[
  {
    "trace_id": "1e72bd4d-1ada-45de-8098-5886b7a5c46f",
    "function_name": "prepare_multi_label_classification_response",
    "file_path": "inference/core/models/inference_models_adapters.py",
    "speedup_x": 68464.46,
    "review_quality": "high",
    "pre_optimization_commit": "0804376ceb9a26d63f7e94874b384232350c1fe0",
    "resolution_method": "db_code_match",
    "source": "db_events",
    "original_function_code": "def prepare_multi_label_classification_response(\n    post_processed_predictions: List[MultiLabelClassificationPrediction],\n    image_sizes: List[Tuple[int, int]],\n    class_names: List[str],\n    confidence_threshold: float,\n) -> List[MultiLabelClassificationInferenceResponse]:\n    results = []\n    for prediction, image_size in zip(post_processed_predictions, image_sizes):\n        image_predictions_dict = dict()\n        predicted_classes = []\n        for class_id, confidence in zip(\n            prediction.class_ids.cpu().tolist(), prediction.confidence.cpu().tolist()\n        ):\n            cls_name = class_names[class_id]\n            image_predictions_dict[cls_name] = {\n                \"confidence\": confidence,\n                \"class_id\": class_id,\n            }\n            if confidence > confidence_threshold:\n                predicted_classes.append(cls_name)\n        results.append(\n            MultiLabelClassificationInferenceResponse(\n                predictions=image_predictions_dict,\n                predicted_classes=predicted_classes,\n                image=InferenceResponseImage(width=image_size[1], height=image_size[0]),\n                # essentially pushing a dummy values as I have no intention breaking the new API for the sake of delivering value that has no practical use\n            )\n        )\n    return results\n",
    "optimized_function_code": "from typing import List, Tuple\n\nfrom inference.core.entities.responses.inference import (\n    InferenceResponseImage, MultiLabelClassificationInferenceResponse)\nfrom inference_models import MultiLabelClassificationPrediction\n\n\ndef _tensor_to_list(t):\n    \"\"\"\n    Convert a tensor-like object to a Python list while avoiding unnecessary .cpu() calls.\n    Handles PyTorch tensors (with .device and .cpu), numpy arrays, and general iterables.\n    \"\"\"\n    # Fast-path for objects that aren't torch tensors (no .device attribute)\n    if not hasattr(t, \"device\"):\n        try:\n            return t.tolist()\n        except Exception:\n            return list(t)\n\n    # Detach if available to avoid potential graph retention\n    if hasattr(t, \"detach\"):\n        try:\n            t = t.detach()\n        except Exception:\n            pass\n\n    # Only move to CPU if tensor is not already on CPU\n    try:\n        if getattr(t, \"device\").type != \"cpu\":\n            t = t.cpu()\n    except Exception:\n        # If something goes wrong with device introspection, fall back to cpu() attempt\n        try:\n            t = t.cpu()\n        except Exception:\n            pass\n\n    return t.tolist()\n\ndef prepare_multi_label_classification_response(\n    post_processed_predictions: List[MultiLabelClassificationPrediction],\n    image_sizes: List[Tuple[int, int]],\n    class_names: List[str],\n    confidence_threshold: float,\n) -> List[MultiLabelClassificationInferenceResponse]:\n    results = []\n    for prediction, image_size in zip(post_processed_predictions, image_sizes):\n        image_predictions_dict = dict()\n        predicted_classes = []\n\n        # Convert tensors/arrays to Python lists only once per prediction\n        class_ids_list = _tensor_to_list(prediction.class_ids)\n        confidences_list = _tensor_to_list(prediction.confidence)\n\n        # Single-pass loop to populate both the predictions dict and predicted classes\n        for class_id, confidence in zip(class_ids_list, confidences_list):\n            cls_name = class_names[class_id]\n            image_predictions_dict[cls_name] = {\n                \"confidence\": confidence,\n                \"class_id\": class_id,\n            }\n            if confidence > confidence_threshold:\n                predicted_classes.append(cls_name)\n        results.append(\n            MultiLabelClassificationInferenceResponse(\n                predictions=image_predictions_dict,\n                predicted_classes=predicted_classes,\n                image=InferenceResponseImage(width=image_size[1], height=image_size[0]),\n                # essentially pushing a dummy values as I have no intention breaking the new API for the sake of delivering value that has no practical use\n            )\n        )\n    return results",
    "optimized_raw_markdown": "```python:inference/core/models/inference_models_adapters.py\nfrom typing import List, Tuple\n\nfrom inference.core.entities.responses.inference import (\n    InferenceResponseImage, MultiLabelClassificationInferenceResponse)\nfrom inference_models import MultiLabelClassificationPrediction\n\n\ndef _tensor_to_list(t):\n    \"\"\"\n    Convert a tensor-like object to a Python list while avoiding unnecessary .cpu() calls.\n    Handles PyTorch tensors (with .device and .cpu), numpy arrays, and general iterables.\n    \"\"\"\n    # Fast-path for objects that aren't torch tensors (no .device attribute)\n    if not hasattr(t, \"device\"):\n        try:\n            return t.tolist()\n        except Exception:\n            return list(t)\n\n    # Detach if available to avoid potential graph retention\n    if hasattr(t, \"detach\"):\n        try:\n            t = t.detach()\n        except Exception:\n            pass\n\n    # Only move to CPU if tensor is not already on CPU\n    try:\n        if getattr(t, \"device\").type != \"cpu\":\n            t = t.cpu()\n    except Exception:\n        # If something goes wrong with device introspection, fall back to cpu() attempt\n        try:\n            t = t.cpu()\n        except Exception:\n            pass\n\n    return t.tolist()\n\ndef prepare_multi_label_classification_response(\n    post_processed_predictions: List[MultiLabelClassificationPrediction],\n    image_sizes: List[Tuple[int, int]],\n    class_names: List[str],\n    confidence_threshold: float,\n) -> List[MultiLabelClassificationInferenceResponse]:\n    results = []\n    for prediction, image_size in zip(post_processed_predictions, image_sizes):\n        image_predictions_dict = dict()\n        predicted_classes = []\n\n        # Convert tensors/arrays to Python lists only once per prediction\n        class_ids_list = _tensor_to_list(prediction.class_ids)\n        confidences_list = _tensor_to_list(prediction.confidence)\n\n        # Single-pass loop to populate both the predictions dict and predicted classes\n        for class_id, confidence in zip(class_ids_list, confidences_list):\n            cls_name = class_names[class_id]\n            image_predictions_dict[cls_name] = {\n                \"confidence\": confidence,\n                \"class_id\": class_id,\n            }\n            if confidence > confidence_threshold:\n                predicted_classes.append(cls_name)\n        results.append(\n            MultiLabelClassificationInferenceResponse(\n                predictions=image_predictions_dict,\n                predicted_classes=predicted_classes,\n                image=InferenceResponseImage(width=image_size[1], height=image_size[0]),\n                # essentially pushing a dummy values as I have no intention breaking the new API for the sake of delivering value that has no practical use\n            )\n        )\n    return results\n```",
    "optimized_function_only": "def prepare_multi_label_classification_response(\n    post_processed_predictions: List[MultiLabelClassificationPrediction],\n    image_sizes: List[Tuple[int, int]],\n    class_names: List[str],\n    confidence_threshold: float,\n) -> List[MultiLabelClassificationInferenceResponse]:\n    results = []\n    for prediction, image_size in zip(post_processed_predictions, image_sizes):\n        image_predictions_dict = dict()\n        predicted_classes = []\n\n        # Convert tensors/arrays to Python lists only once per prediction\n        class_ids_list = _tensor_to_list(prediction.class_ids)\n        confidences_list = _tensor_to_list(prediction.confidence)\n\n        # Single-pass loop to populate both the predictions dict and predicted classes\n        for class_id, confidence in zip(class_ids_list, confidences_list):\n            cls_name = class_names[class_id]\n            image_predictions_dict[cls_name] = {\n                \"confidence\": confidence,\n                \"class_id\": class_id,\n            }\n            if confidence > confidence_threshold:\n                predicted_classes.append(cls_name)\n        results.append(\n            MultiLabelClassificationInferenceResponse(\n                predictions=image_predictions_dict,\n                predicted_classes=predicted_classes,\n                image=InferenceResponseImage(width=image_size[1], height=image_size[0]),\n                # essentially pushing a dummy values as I have no intention breaking the new API for the sake of delivering value that has no practical use\n            )\n        )\n    return results",
    "original_file_content": "import base64\nimport io\nfrom io import BytesIO\nfrom time import perf_counter\nfrom typing import Any, List, Optional, Tuple, Union\n\nimport numpy as np\nimport torch\nfrom PIL import Image, ImageDraw, ImageFont\n\nfrom inference.core.entities.requests import (\n    ClassificationInferenceRequest,\n    InferenceRequest,\n)\nfrom inference.core.entities.responses.inference import (\n    ClassificationInferenceResponse,\n    InferenceResponse,\n    InferenceResponseImage,\n    InstanceSegmentationInferenceResponse,\n    InstanceSegmentationPrediction,\n    Keypoint,\n    KeypointsDetectionInferenceResponse,\n    KeypointsPrediction,\n    MultiLabelClassificationInferenceResponse,\n    ObjectDetectionInferenceResponse,\n    ObjectDetectionPrediction,\n    Point,\n    SemanticSegmentationInferenceResponse,\n    SemanticSegmentationPrediction,\n)\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n    API_KEY,\n    DISABLED_INFERENCE_MODELS_BACKENDS,\n    RFDETR_ONNX_MAX_RESOLUTION,\n    VALID_INFERENCE_MODELS_BACKENDS,\n)\nfrom inference.core.models.base import Model\nfrom inference.core.roboflow_api import get_extra_weights_provider_headers\nfrom inference.core.utils.image_utils import load_image_bgr, load_image_rgb\nfrom inference.core.utils.postprocess import masks2poly\nfrom inference.core.utils.visualisation import draw_detection_predictions\nfrom inference.models.aliases import resolve_roboflow_model_alias\nfrom inference_models import (\n    AutoModel,\n    ClassificationModel,\n    ClassificationPrediction,\n    Detections,\n    InstanceDetections,\n    InstanceSegmentationModel,\n    KeyPoints,\n    KeyPointsDetectionModel,\n    MultiLabelClassificationModel,\n    MultiLabelClassificationPrediction,\n    ObjectDetectionModel,\n    PreProcessingOverrides,\n    SemanticSegmentationModel,\n)\nfrom inference_models.models.base.semantic_segmentation import (\n    SemanticSegmentationResult,\n)\nfrom inference_models.models.base.types import PreprocessingMetadata\n\nDEFAULT_COLOR_PALETTE = [\n    \"#A351FB\",\n    \"#FF4040\",\n    \"#FFA1A0\",\n    \"#FF7633\",\n    \"#FFB633\",\n    \"#D1D435\",\n    \"#4CFB12\",\n    \"#94CF1A\",\n    \"#40DE8A\",\n    \"#1B9640\",\n    \"#00D6C1\",\n    \"#2E9CAA\",\n    \"#00C4FF\",\n    \"#364797\",\n    \"#6675FF\",\n    \"#0019EF\",\n    \"#863AFF\",\n    \"#530087\",\n    \"#CD3AFF\",\n    \"#FF97CA\",\n    \"#FF39C9\",\n]\n\n\nclass InferenceModelsObjectDetectionAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n        model_id = resolve_roboflow_model_alias(model_id=model_id)\n\n        self.task_type = \"object-detection\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n        backend = list(\n            VALID_INFERENCE_MODELS_BACKENDS.difference(\n                DISABLED_INFERENCE_MODELS_BACKENDS\n            )\n        )\n        self._model: ObjectDetectionModel = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            backend=backend,\n            rf_detr_max_input_resolution=RFDETR_ONNX_MAX_RESOLUTION,\n            **kwargs,\n        )\n        self.class_names = list(self._model.class_names)\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        pre_processing_overrides = PreProcessingOverrides(\n            disable_contrast_enhancement=kwargs.get(\"disable_preproc_contrast\", False),\n            disable_grayscale=kwargs.get(\"disable_preproc_grayscale\", False),\n            disable_static_crop=kwargs.get(\"disable_preproc_static_crop\", False),\n        )\n        kwargs[\"pre_processing_overrides\"] = pre_processing_overrides\n        return kwargs\n\n    def preprocess(self, image: Any, **kwargs):\n        is_batch = isinstance(image, list)\n        images = image if is_batch else [image]\n        np_images: List[np.ndarray] = [\n            load_image_bgr(\n                v,\n                disable_preproc_auto_orient=kwargs.get(\n                    \"disable_preproc_auto_orient\", False\n                ),\n            )\n            for v in images\n        ]\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.pre_process(np_images, **mapped_kwargs)\n\n    def predict(self, img_in, **kwargs):\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.forward(img_in, **mapped_kwargs)\n\n    def postprocess(\n        self,\n        predictions: List[Detections],\n        preprocess_return_metadata: PreprocessingMetadata,\n        **kwargs,\n    ) -> List[ObjectDetectionInferenceResponse]:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        detections_list = self._model.post_process(\n            predictions, preprocess_return_metadata, **mapped_kwargs\n        )\n\n        responses: List[ObjectDetectionInferenceResponse] = []\n        for preproc_metadata, det in zip(preprocess_return_metadata, detections_list):\n            H = preproc_metadata.original_size.height\n            W = preproc_metadata.original_size.width\n\n            xyxy = det.xyxy.detach().cpu().numpy()\n            confs = det.confidence.detach().cpu().numpy()\n            class_ids = det.class_id.detach().cpu().numpy()\n\n            predictions: List[ObjectDetectionPrediction] = []\n\n            for (x1, y1, x2, y2), conf, class_id in zip(xyxy, confs, class_ids):\n                cx = (float(x1) + float(x2)) / 2.0\n                cy = (float(y1) + float(y2)) / 2.0\n                w = float(x2) - float(x1)\n                h = float(y2) - float(y1)\n                class_id_int = int(class_id)\n                class_name = (\n                    self.class_names[class_id_int]\n                    if 0 <= class_id_int < len(self.class_names)\n                    else str(class_id_int)\n                )\n                if (\n                    kwargs.get(\"class_filter\")\n                    and class_name not in kwargs[\"class_filter\"]\n                ):\n                    continue\n                predictions.append(\n                    ObjectDetectionPrediction(\n                        x=cx,\n                        y=cy,\n                        width=w,\n                        height=h,\n                        confidence=float(conf),\n                        **{\"class\": class_name},\n                        class_id=class_id_int,\n                    )\n                )\n\n            responses.append(\n                ObjectDetectionInferenceResponse(\n                    predictions=predictions,\n                    image=InferenceResponseImage(width=W, height=H),\n                )\n            )\n        return responses\n\n    def clear_cache(self, delete_from_disk: bool = True) -> None:\n        \"\"\"Clears any cache if necessary. TODO: Implement this to delete the cache from the experimental model.\n\n        Args:\n            delete_from_disk (bool, optional): Whether to delete cached files from disk. Defaults to True.\n        \"\"\"\n        pass\n\n    def draw_predictions(\n        self,\n        inference_request: InferenceRequest,\n        inference_response: InferenceResponse,\n    ) -> bytes:\n        \"\"\"Draw predictions from an inference response onto the original image provided by an inference request\n\n        Args:\n            inference_request (ObjectDetectionInferenceRequest): The inference request containing the image on which to draw predictions\n            inference_response (ObjectDetectionInferenceResponse): The inference response containing predictions to be drawn\n\n        Returns:\n            str: A base64 encoded image string\n        \"\"\"\n        class_id_2_color = {\n            i: DEFAULT_COLOR_PALETTE[i % len(DEFAULT_COLOR_PALETTE)]\n            for i, class_name in enumerate(self._model.class_names)\n        }\n        return draw_detection_predictions(\n            inference_request=inference_request,\n            inference_response=inference_response,\n            colors=class_id_2_color,\n        )\n\n\nclass InferenceModelsInstanceSegmentationAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n        model_id = resolve_roboflow_model_alias(model_id=model_id)\n\n        self.task_type = \"instance-segmentation\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n        backend = list(\n            VALID_INFERENCE_MODELS_BACKENDS.difference(\n                DISABLED_INFERENCE_MODELS_BACKENDS\n            )\n        )\n        self._model: InstanceSegmentationModel = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            backend=backend,\n            rf_detr_max_input_resolution=RFDETR_ONNX_MAX_RESOLUTION,\n            **kwargs,\n        )\n        self.class_names = list(self._model.class_names)\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        pre_processing_overrides = PreProcessingOverrides(\n            disable_contrast_enhancement=kwargs.get(\"disable_preproc_contrast\", False),\n            disable_grayscale=kwargs.get(\"disable_preproc_grayscale\", False),\n            disable_static_crop=kwargs.get(\"disable_preproc_static_crop\", False),\n        )\n        kwargs[\"pre_processing_overrides\"] = pre_processing_overrides\n        return kwargs\n\n    def preprocess(self, image: Any, **kwargs):\n        is_batch = isinstance(image, list)\n        images = image if is_batch else [image]\n        np_images: List[np.ndarray] = [\n            load_image_bgr(\n                v,\n                disable_preproc_auto_orient=kwargs.get(\n                    \"disable_preproc_auto_orient\", False\n                ),\n            )\n            for v in images\n        ]\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.pre_process(np_images, **mapped_kwargs)\n\n    def predict(self, img_in, **kwargs):\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.forward(img_in, **mapped_kwargs)\n\n    def postprocess(\n        self,\n        predictions: List[InstanceDetections],\n        preprocess_return_metadata: PreprocessingMetadata,\n        **kwargs,\n    ) -> List[InstanceSegmentationInferenceResponse]:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        detections_list = self._model.post_process(\n            predictions, preprocess_return_metadata, **mapped_kwargs\n        )\n\n        responses: List[InstanceSegmentationInferenceResponse] = []\n        for preproc_metadata, det in zip(preprocess_return_metadata, detections_list):\n            H = preproc_metadata.original_size.height\n            W = preproc_metadata.original_size.width\n\n            xyxy = det.xyxy.detach().cpu().numpy()\n            confs = det.confidence.detach().cpu().numpy()\n            masks = det.mask.detach().cpu().numpy()\n            polys = masks2poly(masks)\n            class_ids = det.class_id.detach().cpu().numpy()\n\n            predictions: List[InstanceSegmentationPrediction] = []\n\n            for (x1, y1, x2, y2), mask_as_poly, conf, class_id in zip(\n                xyxy, polys, confs, class_ids\n            ):\n                cx = (float(x1) + float(x2)) / 2.0\n                cy = (float(y1) + float(y2)) / 2.0\n                w = float(x2) - float(x1)\n                h = float(y2) - float(y1)\n                class_id_int = int(class_id)\n                class_name = (\n                    self.class_names[class_id_int]\n                    if 0 <= class_id_int < len(self.class_names)\n                    else str(class_id_int)\n                )\n                if (\n                    kwargs.get(\"class_filter\")\n                    and class_name not in kwargs[\"class_filter\"]\n                ):\n                    continue\n                predictions.append(\n                    InstanceSegmentationPrediction(\n                        x=cx,\n                        y=cy,\n                        width=w,\n                        height=h,\n                        confidence=float(conf),\n                        points=[\n                            Point(x=point[0], y=point[1]) for point in mask_as_poly\n                        ],\n                        **{\"class\": class_name},\n                        class_id=class_id_int,\n                    )\n                )\n\n            responses.append(\n                InstanceSegmentationInferenceResponse(\n                    predictions=predictions,\n                    image=InferenceResponseImage(width=W, height=H),\n                )\n            )\n        return responses\n\n    def clear_cache(self, delete_from_disk: bool = True) -> None:\n        \"\"\"Clears any cache if necessary. TODO: Implement this to delete the cache from the experimental model.\n\n        Args:\n            delete_from_disk (bool, optional): Whether to delete cached files from disk. Defaults to True.\n        \"\"\"\n        pass\n\n    def draw_predictions(\n        self,\n        inference_request: InferenceRequest,\n        inference_response: InferenceResponse,\n    ) -> bytes:\n        \"\"\"Draw predictions from an inference response onto the original image provided by an inference request\n\n        Args:\n            inference_request (ObjectDetectionInferenceRequest): The inference request containing the image on which to draw predictions\n            inference_response (ObjectDetectionInferenceResponse): The inference response containing predictions to be drawn\n\n        Returns:\n            str: A base64 encoded image string\n        \"\"\"\n        class_id_2_color = {\n            i: DEFAULT_COLOR_PALETTE[i % len(DEFAULT_COLOR_PALETTE)]\n            for i, class_name in enumerate(self._model.class_names)\n        }\n        return draw_detection_predictions(\n            inference_request=inference_request,\n            inference_response=inference_response,\n            colors=class_id_2_color,\n        )\n\n\nclass InferenceModelsKeyPointsDetectionAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n        model_id = resolve_roboflow_model_alias(model_id=model_id)\n\n        self.task_type = \"keypoint-detection\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n        backend = list(\n            VALID_INFERENCE_MODELS_BACKENDS.difference(\n                DISABLED_INFERENCE_MODELS_BACKENDS\n            )\n        )\n        self._model: KeyPointsDetectionModel = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            backend=backend,\n            **kwargs,\n        )\n        self.class_names = list(self._model.class_names)\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        if \"request\" in kwargs:\n            keypoint_confidence_threshold = kwargs[\"request\"].keypoint_confidence\n            kwargs[\"key_points_threshold\"] = keypoint_confidence_threshold\n        pre_processing_overrides = PreProcessingOverrides(\n            disable_contrast_enhancement=kwargs.get(\"disable_preproc_contrast\", False),\n            disable_grayscale=kwargs.get(\"disable_preproc_grayscale\", False),\n            disable_static_crop=kwargs.get(\"disable_preproc_static_crop\", False),\n        )\n        kwargs[\"pre_processing_overrides\"] = pre_processing_overrides\n        return kwargs\n\n    def preprocess(self, image: Any, **kwargs):\n        is_batch = isinstance(image, list)\n        images = image if is_batch else [image]\n        np_images: List[np.ndarray] = [\n            load_image_bgr(\n                v,\n                disable_preproc_auto_orient=kwargs.get(\n                    \"disable_preproc_auto_orient\", False\n                ),\n            )\n            for v in images\n        ]\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.pre_process(np_images, **mapped_kwargs)\n\n    def predict(self, img_in, **kwargs):\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.forward(img_in, **mapped_kwargs)\n\n    def postprocess(\n        self,\n        predictions: Tuple[List[KeyPoints], Optional[List[Detections]]],\n        preprocess_return_metadata: PreprocessingMetadata,\n        **kwargs,\n    ) -> List[KeypointsDetectionInferenceResponse]:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        keypoints_list, detections_list = self._model.post_process(\n            predictions, preprocess_return_metadata, **mapped_kwargs\n        )\n        if detections_list is None:\n            raise RuntimeError(\n                \"Keypoints detection model does not provide instances detection - this is not supported for \"\n                \"models from `inference-models` package which are adapted to work with `inference`.\"\n            )\n        key_points_classes = self._model.key_points_classes\n        responses: List[KeypointsDetectionInferenceResponse] = []\n        for preproc_metadata, keypoints, det in zip(\n            preprocess_return_metadata, keypoints_list, detections_list\n        ):\n\n            H = preproc_metadata.original_size.height\n            W = preproc_metadata.original_size.width\n\n            xyxy = det.xyxy.detach().cpu().numpy()\n            confs = det.confidence.detach().cpu().numpy()\n            class_ids = det.class_id.detach().cpu().numpy()\n            keypoints_xy = keypoints.xy.detach().cpu().tolist()\n            keypoints_class_id = keypoints.class_id.detach().cpu().tolist()\n            keypoints_confidence = keypoints.confidence.detach().cpu().tolist()\n            predictions: List[KeypointsPrediction] = []\n\n            for (\n                (x1, y1, x2, y2),\n                conf,\n                class_id,\n                instance_keypoints_xy,\n                instance_keypoints_class_id,\n                instance_keypoints_confidence,\n            ) in zip(\n                xyxy,\n                confs,\n                class_ids,\n                keypoints_xy,\n                keypoints_class_id,\n                keypoints_confidence,\n            ):\n                cx = (float(x1) + float(x2)) / 2.0\n                cy = (float(y1) + float(y2)) / 2.0\n                w = float(x2) - float(x1)\n                h = float(y2) - float(y1)\n                class_id_int = int(class_id)\n                class_name = (\n                    self.class_names[class_id_int]\n                    if 0 <= class_id_int < len(self.class_names)\n                    else str(class_id_int)\n                )\n                if (\n                    kwargs.get(\"class_filter\")\n                    and class_name not in kwargs[\"class_filter\"]\n                ):\n                    continue\n                predictions.append(\n                    KeypointsPrediction(\n                        x=cx,\n                        y=cy,\n                        width=w,\n                        height=h,\n                        confidence=float(conf),\n                        **{\"class\": class_name},\n                        class_id=class_id_int,\n                        keypoints=model_keypoints_to_response(\n                            instance_keypoints_xy=instance_keypoints_xy,\n                            instance_keypoints_confidence=instance_keypoints_confidence,\n                            instance_keypoints_class_id=instance_keypoints_class_id,\n                            key_points_classes=key_points_classes,\n                        ),\n                    )\n                )\n\n            responses.append(\n                KeypointsDetectionInferenceResponse(\n                    predictions=predictions,\n                    image=InferenceResponseImage(width=W, height=H),\n                )\n            )\n\n        return responses\n\n    def clear_cache(self, delete_from_disk: bool = True) -> None:\n        \"\"\"Clears any cache if necessary. TODO: Implement this to delete the cache from the experimental model.\n\n        Args:\n            delete_from_disk (bool, optional): Whether to delete cached files from disk. Defaults to True.\n        \"\"\"\n        pass\n\n    def draw_predictions(\n        self,\n        inference_request: InferenceRequest,\n        inference_response: InferenceResponse,\n    ) -> bytes:\n        \"\"\"Draw predictions from an inference response onto the original image provided by an inference request\n\n        Args:\n            inference_request (ObjectDetectionInferenceRequest): The inference request containing the image on which to draw predictions\n            inference_response (ObjectDetectionInferenceResponse): The inference response containing predictions to be drawn\n\n        Returns:\n            str: A base64 encoded image string\n        \"\"\"\n        class_id_2_color = {\n            i: DEFAULT_COLOR_PALETTE[i % len(DEFAULT_COLOR_PALETTE)]\n            for i, class_name in enumerate(self._model.class_names)\n        }\n        return draw_detection_predictions(\n            inference_request=inference_request,\n            inference_response=inference_response,\n            colors=class_id_2_color,\n        )\n\n\ndef model_keypoints_to_response(\n    instance_keypoints_xy: List[\n        List[Union[float, int]]\n    ],  # (num_key_points_foc_class_of_object, 2)\n    instance_keypoints_confidence: List[float],  # (instance_key_points, )\n    instance_keypoints_class_id: int,\n    key_points_classes: List[List[str]],\n) -> List[Keypoint]:\n    keypoint_classes = key_points_classes[instance_keypoints_class_id]\n    results = []\n    for keypoint_class_id, ((x, y), confidence, keypoint_class_name) in enumerate(\n        zip(instance_keypoints_xy, instance_keypoints_confidence, keypoint_classes)\n    ):\n        if confidence <= 0.0:\n            continue\n        keypoint = Keypoint(\n            x=x,\n            y=y,\n            confidence=confidence,\n            class_id=keypoint_class_id,\n            **{\"class\": keypoint_class_name},\n        )\n        results.append(keypoint)\n    return results\n\n\nclass InferenceModelsClassificationAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n        model_id = resolve_roboflow_model_alias(model_id=model_id)\n\n        self.task_type = \"classification\"\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n        backend = list(\n            VALID_INFERENCE_MODELS_BACKENDS.difference(\n                DISABLED_INFERENCE_MODELS_BACKENDS\n            )\n        )\n        self._model: Union[ClassificationModel, MultiLabelClassificationModel] = (\n            AutoModel.from_pretrained(\n                model_id_or_path=model_id,\n                api_key=self.api_key,\n                allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n                allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n                weights_provider_extra_headers=extra_weights_provider_headers,\n                backend=backend,\n                **kwargs,\n            )\n        )\n        self.class_names = list(self._model.class_names)\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        pre_processing_overrides = PreProcessingOverrides(\n            disable_contrast_enhancement=kwargs.get(\"disable_preproc_contrast\", False),\n            disable_grayscale=kwargs.get(\"disable_preproc_grayscale\", False),\n            disable_static_crop=kwargs.get(\"disable_preproc_static_crop\", False),\n        )\n        kwargs[\"pre_processing_overrides\"] = pre_processing_overrides\n        return kwargs\n\n    def preprocess(self, image: Any, **kwargs):\n        is_batch = isinstance(image, list)\n        images = image if is_batch else [image]\n        np_images: List[np.ndarray] = [\n            load_image_bgr(\n                v,\n                disable_preproc_auto_orient=kwargs.get(\n                    \"disable_preproc_auto_orient\", False\n                ),\n            )\n            for v in images\n        ]\n        images_shapes = [i.shape[:2] for i in np_images]\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.pre_process(np_images, **mapped_kwargs), images_shapes\n\n    def predict(self, img_in, **kwargs):\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.forward(img_in, **mapped_kwargs)\n\n    def postprocess(\n        self,\n        predictions: Tuple[List[KeyPoints], Optional[List[Detections]]],\n        returned_metadata: List[Tuple[int, int]],\n        **kwargs,\n    ) -> Union[\n        List[MultiLabelClassificationInferenceResponse],\n        List[ClassificationInferenceResponse],\n    ]:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        post_processed_predictions = self._model.post_process(\n            predictions, **mapped_kwargs\n        )\n        if isinstance(post_processed_predictions, list):\n            # multi-label classification\n            return prepare_multi_label_classification_response(\n                post_processed_predictions,\n                image_sizes=returned_metadata,\n                class_names=self.class_names,\n                confidence_threshold=kwargs.get(\"confidence\", 0.5),\n            )\n        else:\n            # single-label classification\n            return prepare_classification_response(\n                post_processed_predictions,\n                image_sizes=returned_metadata,\n                class_names=self.class_names,\n                confidence_threshold=kwargs.get(\"confidence\", 0.5),\n            )\n\n    def clear_cache(self, delete_from_disk: bool = True) -> None:\n        \"\"\"Clears any cache if necessary. TODO: Implement this to delete the cache from the experimental model.\n\n        Args:\n            delete_from_disk (bool, optional): Whether to delete cached files from disk. Defaults to True.\n        \"\"\"\n        pass\n\n    def infer_from_request(\n        self,\n        request: ClassificationInferenceRequest,\n    ) -> Union[List[InferenceResponse], InferenceResponse]:\n        \"\"\"\n        Handle an inference request to produce an appropriate response.\n\n        Args:\n            request (ClassificationInferenceRequest): The request object encapsulating the image(s) and relevant parameters.\n\n        Returns:\n            Union[List[InferenceResponse], InferenceResponse]: The response object(s) containing the predictions, visualization, and other pertinent details. If a list of images was provided, a list of responses is returned. Otherwise, a single response is returned.\n\n        Notes:\n            - Starts a timer at the beginning to calculate inference time.\n            - Processes the image(s) through the `infer` method.\n            - Generates the appropriate response object(s) using `make_response`.\n            - Calculates and sets the time taken for inference.\n            - If visualization is requested, the predictions are drawn on the image.\n        \"\"\"\n        t1 = perf_counter()\n        responses = self.infer(**request.dict(), return_image_dims=True)\n        for response in responses:\n            response.time = perf_counter() - t1\n            response.inference_id = getattr(request, \"id\", None)\n\n        if request.visualize_predictions:\n            for response in responses:\n                response.visualization = draw_predictions(\n                    request, response, self.class_names\n                )\n\n        if not isinstance(request.image, list):\n            responses = responses[0]\n\n        return responses\n\n\ndef prepare_multi_label_classification_response(\n    post_processed_predictions: List[MultiLabelClassificationPrediction],\n    image_sizes: List[Tuple[int, int]],\n    class_names: List[str],\n    confidence_threshold: float,\n) -> List[MultiLabelClassificationInferenceResponse]:\n    results = []\n    for prediction, image_size in zip(post_processed_predictions, image_sizes):\n        image_predictions_dict = dict()\n        predicted_classes = []\n        for class_id, confidence in zip(\n            prediction.class_ids.cpu().tolist(), prediction.confidence.cpu().tolist()\n        ):\n            cls_name = class_names[class_id]\n            image_predictions_dict[cls_name] = {\n                \"confidence\": confidence,\n                \"class_id\": class_id,\n            }\n            if confidence > confidence_threshold:\n                predicted_classes.append(cls_name)\n        results.append(\n            MultiLabelClassificationInferenceResponse(\n                predictions=image_predictions_dict,\n                predicted_classes=predicted_classes,\n                image=InferenceResponseImage(width=image_size[1], height=image_size[0]),\n                # essentially pushing a dummy values as I have no intention breaking the new API for the sake of delivering value that has no practical use\n            )\n        )\n    return results\n\n\ndef prepare_classification_response(\n    post_processed_predictions: ClassificationPrediction,\n    image_sizes: List[Tuple[int, int]],\n    class_names: List[str],\n    confidence_threshold: float,\n) -> List[ClassificationInferenceResponse]:\n    responses = []\n    for classes_confidence, image_size in zip(\n        post_processed_predictions.confidence.cpu().tolist(), image_sizes\n    ):\n        individual_classes_predictions = []\n        for i, cls_name in enumerate(class_names):\n            class_score = float(classes_confidence[i])\n            if class_score < confidence_threshold:\n                continue\n            class_prediction = {\n                \"class_id\": i,\n                \"class\": cls_name,\n                \"confidence\": round(class_score, 4),\n            }\n            individual_classes_predictions.append(class_prediction)\n        individual_classes_predictions = sorted(\n            individual_classes_predictions, key=lambda x: x[\"confidence\"], reverse=True\n        )\n        response = ClassificationInferenceResponse(\n            image=InferenceResponseImage(width=image_size[1], height=image_size[0]),\n            # essentially pushing a dummy values as I have no intention breaking the new API for the sake of delivering value that has no practical use\n            predictions=individual_classes_predictions,\n            top=(\n                individual_classes_predictions[0][\"class\"]\n                if individual_classes_predictions\n                else \"\"\n            ),\n            confidence=(\n                individual_classes_predictions[0][\"confidence\"]\n                if individual_classes_predictions\n                else 0.0\n            ),\n        )\n        responses.append(response)\n    return responses\n\n\ndef draw_predictions(inference_request, inference_response, class_names: List[str]):\n    \"\"\"Draw prediction visuals on an image.\n\n    This method overlays the predictions on the input image, including drawing rectangles and text to visualize the predicted classes.\n\n    Args:\n        inference_request: The request object containing the image and parameters.\n        inference_response: The response object containing the predictions and other details.\n        class_names: List of class names corresponding to the model's classes.\n\n    Returns:\n        bytes: The bytes of the visualized image in JPEG format.\n    \"\"\"\n    image = load_image_rgb(inference_request.image)\n    image = Image.fromarray(image)\n    draw = ImageDraw.Draw(image)\n    font = ImageFont.load_default()\n    class_id_2_color = {\n        i: DEFAULT_COLOR_PALETTE[i % len(DEFAULT_COLOR_PALETTE)]\n        for i, class_name in enumerate(class_names)\n    }\n    if isinstance(inference_response.predictions, list):\n        prediction = inference_response.predictions[0]\n        color = class_id_2_color.get(prediction.class_id, \"#4892EA\")\n        draw.rectangle(\n            [0, 0, image.size[1], image.size[0]],\n            outline=color,\n            width=inference_request.visualization_stroke_width,\n        )\n        text = f\"{prediction.class_id} - {prediction.class_name} {prediction.confidence:.2f}\"\n        text_size = font.getbbox(text)\n\n        # set button size + 10px margins\n        button_size = (text_size[2] + 20, text_size[3] + 20)\n        button_img = Image.new(\"RGBA\", button_size, color)\n        # put text on button with 10px margins\n        button_draw = ImageDraw.Draw(button_img)\n        button_draw.text((10, 10), text, font=font, fill=(255, 255, 255, 255))\n\n        # put button on source image in position (0, 0)\n        image.paste(button_img, (0, 0))\n    else:\n        if len(inference_response.predictions) > 0:\n            box_color = \"#4892EA\"\n            draw.rectangle(\n                [0, 0, image.size[1], image.size[0]],\n                outline=box_color,\n                width=inference_request.visualization_stroke_width,\n            )\n        row = 0\n        predictions = [\n            (cls_name, pred)\n            for cls_name, pred in inference_response.predictions.items()\n        ]\n        predictions = sorted(predictions, key=lambda x: x[1].confidence, reverse=True)\n        for i, (cls_name, pred) in enumerate(predictions):\n            color = class_id_2_color.get(cls_name, \"#4892EA\")\n            text = f\"{cls_name} {pred.confidence:.2f}\"\n            text_size = font.getbbox(text)\n\n            # set button size + 10px margins\n            button_size = (text_size[2] + 20, text_size[3] + 20)\n            button_img = Image.new(\"RGBA\", button_size, color)\n            # put text on button with 10px margins\n            button_draw = ImageDraw.Draw(button_img)\n            button_draw.text((10, 10), text, font=font, fill=(255, 255, 255, 255))\n\n            # put button on source image in position (0, 0)\n            image.paste(button_img, (0, row))\n            row += button_size[1]\n\n    buffered = BytesIO()\n    image = image.convert(\"RGB\")\n    image.save(buffered, format=\"JPEG\")\n    return buffered.getvalue()\n\n\nclass InferenceModelsSemanticSegmentationAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n        model_id = resolve_roboflow_model_alias(model_id=model_id)\n\n        self.task_type = \"semantic-segmentation\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n        backend = list(\n            VALID_INFERENCE_MODELS_BACKENDS.difference(\n                DISABLED_INFERENCE_MODELS_BACKENDS\n            )\n        )\n        self._model: SemanticSegmentationModel = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            backend=backend,\n            **kwargs,\n        )\n        self.class_names = list(self._model.class_names)\n\n    @property\n    def class_map(self):\n        # match segment.roboflow.com\n        return {str(k): v for k, v in enumerate(self.class_names)}\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        pre_processing_overrides = PreProcessingOverrides(\n            disable_contrast_enhancement=kwargs.get(\"disable_preproc_contrast\", False),\n            disable_grayscale=kwargs.get(\"disable_preproc_grayscale\", False),\n            disable_static_crop=kwargs.get(\"disable_preproc_static_crop\", False),\n        )\n        kwargs[\"pre_processing_overrides\"] = pre_processing_overrides\n        return kwargs\n\n    def preprocess(self, image: Any, **kwargs):\n        is_batch = isinstance(image, list)\n        images = image if is_batch else [image]\n        np_images: List[np.ndarray] = [\n            load_image_bgr(\n                v,\n                disable_preproc_auto_orient=kwargs.get(\n                    \"disable_preproc_auto_orient\", False\n                ),\n            )\n            for v in images\n        ]\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.pre_process(np_images, **mapped_kwargs)\n\n    def predict(self, img_in, **kwargs):\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.forward(img_in, **mapped_kwargs)\n\n    def postprocess(\n        self,\n        predictions: torch.Tensor,\n        preprocess_return_metadata: PreprocessingMetadata,\n        **kwargs,\n    ) -> List[SemanticSegmentationInferenceResponse]:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        segmentation_results = self._model.post_process(\n            predictions, preprocess_return_metadata, **mapped_kwargs\n        )\n\n        responses: List[SemanticSegmentationInferenceResponse] = []\n        for preproc_metadata, segmentation in zip(\n            preprocess_return_metadata, segmentation_results\n        ):\n            height = preproc_metadata.original_size.height\n            width = preproc_metadata.original_size.width\n            response_image = InferenceResponseImage(width=width, height=height)\n            # WARNING! This way of conversion is hazardous - first of all, if background class is not in class names,\n            # for certain pre-processing, we end up with -1 values which will be wrapped to 255 - second of all,\n            # we can support only 256 classes - those constraints should be fine until inference 2.0\n            response_predictions = SemanticSegmentationPrediction(\n                segmentation_mask=self.img_to_b64_str(\n                    segmentation.segmentation_map.to(torch.uint8)\n                ),\n                confidence_mask=self.img_to_b64_str(\n                    (segmentation.confidence * 255).to(torch.uint8)\n                ),\n                class_map=self.class_map,\n                image=dict(response_image),\n            )\n            response = SemanticSegmentationInferenceResponse(\n                predictions=response_predictions,\n                image=response_image,\n            )\n            responses.append(response)\n        return responses\n\n    def clear_cache(self, delete_from_disk: bool = True) -> None:\n        \"\"\"Clears any cache if necessary. TODO: Implement this to delete the cache from the experimental model.\n\n        Args:\n            delete_from_disk (bool, optional): Whether to delete cached files from disk. Defaults to True.\n        \"\"\"\n        pass\n\n    def img_to_b64_str(self, img: torch.Tensor) -> str:\n        if img.dtype != torch.uint8:\n            raise ValueError(\n                f\"img_to_b64_str requires uint8 tensor but got dtype {img.dtype}\"\n            )\n\n        img = Image.fromarray(img.cpu().numpy())\n        buffered = io.BytesIO()\n        img.save(buffered, format=\"PNG\")\n\n        img_str = base64.b64encode(buffered.getvalue())\n        img_str = img_str.decode(\"ascii\")\n\n        return img_str\n\n    def draw_predictions(\n        self,\n        inference_request: InferenceRequest,\n        inference_response: InferenceResponse,\n    ) -> bytes:\n        raise NotImplementedError(\n            \"draw_predictions(...) is not implemented for semantic segmentation models - responses contain \"\n            \"visualization already.\"\n        )\n",
    "patch": null
  },
  {
    "trace_id": "d5f456ec-4dbc-412c-836e-489db172e66e",
    "function_name": "InferenceModelsDepthAnythingV3Adapter.predict",
    "file_path": "inference/models/depth_anything_v3/depth_anything_v3_inference_models.py",
    "speedup_x": 390.52,
    "review_quality": "high",
    "pre_optimization_commit": "7648e452a70ff1aad09f017a0eb2ea4022b7e177",
    "resolution_method": "db_code_match",
    "source": "db_events",
    "original_function_code": "    def predict(self, inputs: np.ndarray, **kwargs) -> Tuple[dict]:\n        predictions = self._model(inputs)[0]\n        depth_map = predictions.to(torch.float32).cpu().numpy()\n        # Normalize depth values\n        depth_min = depth_map.min()\n        depth_max = depth_map.max()\n        if depth_max == depth_min:\n            raise ValueError(\"Depth map has no variation (min equals max)\")\n        normalized_depth = (depth_map - depth_min) / (depth_max - depth_min)\n\n        # Create visualization\n        depth_for_viz = (normalized_depth * 255.0).astype(np.uint8)\n        cmap = plt.get_cmap(\"viridis\")\n        colored_depth = (cmap(depth_for_viz)[:, :, :3] * 255).astype(np.uint8)\n\n        # Convert numpy array to WorkflowImageData\n        parent_metadata = ImageParentMetadata(parent_id=f\"{uuid4()}\")\n        colored_depth_image = WorkflowImageData(\n            numpy_image=colored_depth, parent_metadata=parent_metadata\n        )\n        result = {\n            \"image\": colored_depth_image,\n            \"normalized_depth\": normalized_depth,\n        }\n        return (result,)\n",
    "optimized_function_code": "# Copyright (c) 2025 Roboflow, Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\n\nfrom typing import Tuple\nfrom uuid import uuid4\n\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport torch\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES, API_KEY)\nfrom inference.core.models.base import Model\nfrom inference.core.models.inference_models_adapters import \\\n    get_extra_weights_provider_headers\nfrom inference.core.workflows.execution_engine.entities.base import (\n    ImageParentMetadata, WorkflowImageData)\nfrom inference_models import AutoModel\nfrom inference_models.models.depth_anything_v3.depth_anything_v3_torch import \\\n    DepthAnythingV3Torch\n\n\nclass InferenceModelsDepthAnythingV3Adapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n\n        self.task_type = \"depth-estimation\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers()\n\n        self._model: DepthAnythingV3Torch = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            extra_weights_provider_headers=extra_weights_provider_headers,\n            **kwargs,\n        )\n\n        \n        # Pre-compute colormap LUT for faster application\n        self._viridis_lut = (plt.get_cmap(\"viridis\")(np.arange(256))[:, :3] * 255).astype(np.uint8)\n\n    def predict(self, inputs: np.ndarray, **kwargs) -> Tuple[dict]:\n        predictions = self._model(inputs)[0]\n        depth_map = predictions.cpu().numpy()\n        # Normalize depth values\n        # Normalize depth values\n        depth_min = depth_map.min()\n        depth_max = depth_map.max()\n        if depth_max == depth_min:\n            raise ValueError(\"Depth map has no variation (min equals max)\")\n        normalized_depth = (depth_map - depth_min) / (depth_max - depth_min)\n\n        # Create visualization\n        depth_for_viz = (normalized_depth * 255.0).astype(np.uint8)\n        \n        # Apply colormap using pre-computed LUT\n        colored_depth = self._viridis_lut[depth_for_viz]\n\n        # Convert numpy array to WorkflowImageData\n\n        # Convert numpy array to WorkflowImageData\n        parent_metadata = ImageParentMetadata(parent_id=f\"{uuid4()}\")\n        colored_depth_image = WorkflowImageData(\n            numpy_image=colored_depth, parent_metadata=parent_metadata\n        )\n        result = {\n            \"image\": colored_depth_image,\n            \"normalized_depth\": normalized_depth,\n        }\n        return (result,)",
    "optimized_raw_markdown": "```python:inference/models/depth_anything_v3/depth_anything_v3_inference_models.py\n# Copyright (c) 2025 Roboflow, Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\n\nfrom typing import Tuple\nfrom uuid import uuid4\n\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport torch\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES, API_KEY)\nfrom inference.core.models.base import Model\nfrom inference.core.models.inference_models_adapters import \\\n    get_extra_weights_provider_headers\nfrom inference.core.workflows.execution_engine.entities.base import (\n    ImageParentMetadata, WorkflowImageData)\nfrom inference_models import AutoModel\nfrom inference_models.models.depth_anything_v3.depth_anything_v3_torch import \\\n    DepthAnythingV3Torch\n\n\nclass InferenceModelsDepthAnythingV3Adapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n\n        self.task_type = \"depth-estimation\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers()\n\n        self._model: DepthAnythingV3Torch = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            extra_weights_provider_headers=extra_weights_provider_headers,\n            **kwargs,\n        )\n\n        \n        # Pre-compute colormap LUT for faster application\n        self._viridis_lut = (plt.get_cmap(\"viridis\")(np.arange(256))[:, :3] * 255).astype(np.uint8)\n\n    def predict(self, inputs: np.ndarray, **kwargs) -> Tuple[dict]:\n        predictions = self._model(inputs)[0]\n        depth_map = predictions.cpu().numpy()\n        # Normalize depth values\n        # Normalize depth values\n        depth_min = depth_map.min()\n        depth_max = depth_map.max()\n        if depth_max == depth_min:\n            raise ValueError(\"Depth map has no variation (min equals max)\")\n        normalized_depth = (depth_map - depth_min) / (depth_max - depth_min)\n\n        # Create visualization\n        depth_for_viz = (normalized_depth * 255.0).astype(np.uint8)\n        \n        # Apply colormap using pre-computed LUT\n        colored_depth = self._viridis_lut[depth_for_viz]\n\n        # Convert numpy array to WorkflowImageData\n\n        # Convert numpy array to WorkflowImageData\n        parent_metadata = ImageParentMetadata(parent_id=f\"{uuid4()}\")\n        colored_depth_image = WorkflowImageData(\n            numpy_image=colored_depth, parent_metadata=parent_metadata\n        )\n        result = {\n            \"image\": colored_depth_image,\n            \"normalized_depth\": normalized_depth,\n        }\n        return (result,)\n```",
    "optimized_function_only": "    def predict(self, inputs: np.ndarray, **kwargs) -> Tuple[dict]:\n        predictions = self._model(inputs)[0]\n        depth_map = predictions.cpu().numpy()\n        # Normalize depth values\n        # Normalize depth values\n        depth_min = depth_map.min()\n        depth_max = depth_map.max()\n        if depth_max == depth_min:\n            raise ValueError(\"Depth map has no variation (min equals max)\")\n        normalized_depth = (depth_map - depth_min) / (depth_max - depth_min)\n\n        # Create visualization\n        depth_for_viz = (normalized_depth * 255.0).astype(np.uint8)\n        \n        # Apply colormap using pre-computed LUT\n        colored_depth = self._viridis_lut[depth_for_viz]\n\n        # Convert numpy array to WorkflowImageData\n\n        # Convert numpy array to WorkflowImageData\n        parent_metadata = ImageParentMetadata(parent_id=f\"{uuid4()}\")\n        colored_depth_image = WorkflowImageData(\n            numpy_image=colored_depth, parent_metadata=parent_metadata\n        )\n        result = {\n            \"image\": colored_depth_image,\n            \"normalized_depth\": normalized_depth,\n        }\n        return (result,)",
    "original_file_content": "# Copyright (c) 2025 Roboflow, Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom typing import Any, List, Tuple\nfrom uuid import uuid4\n\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport torch\n\nfrom inference.core.entities.responses import (\n    InferenceResponseImage,\n    LMMInferenceResponse,\n)\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n    API_KEY,\n    DISABLED_INFERENCE_MODELS_BACKENDS,\n    VALID_INFERENCE_MODELS_BACKENDS,\n)\nfrom inference.core.models.base import Model\nfrom inference.core.models.types import PreprocessReturnMetadata\nfrom inference.core.roboflow_api import get_extra_weights_provider_headers\nfrom inference.core.utils.image_utils import load_image_bgr\nfrom inference.core.workflows.execution_engine.entities.base import (\n    ImageParentMetadata,\n    WorkflowImageData,\n)\nfrom inference_models import AutoModel\nfrom inference_models.models.depth_anything_v3.depth_anything_v3_torch import (\n    DepthAnythingV3Torch,\n)\n\n\nclass InferenceModelsDepthAnythingV3Adapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n\n        self.task_type = \"depth-estimation\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n        backend = list(\n            VALID_INFERENCE_MODELS_BACKENDS.difference(\n                DISABLED_INFERENCE_MODELS_BACKENDS\n            )\n        )\n        self._model: DepthAnythingV3Torch = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            backend=backend,\n            **kwargs,\n        )\n\n    def preprocess(self, image: Any, **kwargs):\n        if isinstance(image, list):\n            raise ValueError(\"DepthAnythingV3 does not support batched inference.\")\n        np_image = load_image_bgr(\n            image,\n            disable_preproc_auto_orient=kwargs.get(\n                \"disable_preproc_auto_orient\", False\n            ),\n        )\n        return np_image, PreprocessReturnMetadata(\n            {\"image_dims\": (np_image.shape[1], np_image.shape[0])}\n        )\n\n    def predict(self, inputs: np.ndarray, **kwargs) -> Tuple[dict]:\n        predictions = self._model(inputs)[0]\n        depth_map = predictions.to(torch.float32).cpu().numpy()\n        # Normalize depth values\n        depth_min = depth_map.min()\n        depth_max = depth_map.max()\n        if depth_max == depth_min:\n            raise ValueError(\"Depth map has no variation (min equals max)\")\n        normalized_depth = (depth_map - depth_min) / (depth_max - depth_min)\n\n        # Create visualization\n        depth_for_viz = (normalized_depth * 255.0).astype(np.uint8)\n        cmap = plt.get_cmap(\"viridis\")\n        colored_depth = (cmap(depth_for_viz)[:, :, :3] * 255).astype(np.uint8)\n\n        # Convert numpy array to WorkflowImageData\n        parent_metadata = ImageParentMetadata(parent_id=f\"{uuid4()}\")\n        colored_depth_image = WorkflowImageData(\n            numpy_image=colored_depth, parent_metadata=parent_metadata\n        )\n        result = {\n            \"image\": colored_depth_image,\n            \"normalized_depth\": normalized_depth,\n        }\n        return (result,)\n\n    def postprocess(\n        self,\n        predictions: torch.Tensor,\n        preprocess_return_metadata: PreprocessReturnMetadata,\n        **kwargs,\n    ) -> List[LMMInferenceResponse]:\n        text = predictions[0]\n        image_dims = preprocess_return_metadata[\"image_dims\"]\n        response = LMMInferenceResponse(\n            response=text,\n            image=InferenceResponseImage(width=image_dims[0], height=image_dims[1]),\n        )\n        return [response]\n\n    def clear_cache(self, delete_from_disk: bool = True) -> None:\n        pass\n",
    "patch": null
  },
  {
    "trace_id": "5eae77af-0ed6-4197-bf2e-f37216264e90",
    "function_name": "measure_memory_for_eviction",
    "file_path": "inference/core/cache/memory.py",
    "speedup_x": 18.13,
    "review_quality": "high",
    "pre_optimization_commit": "HEAD",
    "resolution_method": "db_code_only",
    "source": "db_events",
    "original_function_code": "def measure_memory_for_eviction(detailed: bool = False) -> Optional[MemorySnapshot]:\n    \"\"\"\n    Measure memory state for eviction event.\n\n    Only captures gpu_free before eviction. The after state is measured\n    separately after the model is removed.\n\n    Args:\n        detailed: If True, capture memory state\n\n    Returns:\n        MemorySnapshot with gpu_free_before, or None if not detailed\n    \"\"\"\n    if not detailed:\n        return None\n\n    state = _measure_detailed_state()\n    return MemorySnapshot(\n        gpu_free=state.get(\"gpu_free\"),\n    )\n",
    "optimized_function_code": "from typing import Optional\n\nfrom inference.core.structured_logging.events import MemorySnapshot\n\n\ndef measure_memory_for_eviction(detailed: bool = False) -> Optional[MemorySnapshot]:\n    \"\"\"\n    Measure memory state for eviction event.\n\n    Only captures gpu_free before eviction. The after state is measured\n    separately after the model is removed.\n\n    Args:\n        detailed: If True, capture memory state\n\n    Returns:\n        MemorySnapshot with gpu_free_before, or None if not detailed\n    \"\"\"\n    if not detailed:\n        return None\n\n    # GPU memory (expensive - requires GPU synchronization)\n    gpu_free = None\n    try:\n        import torch\n\n        if torch.cuda.is_available():\n            gpu_free, _ = torch.cuda.mem_get_info()\n    except ImportError:\n        pass\n\n    return MemorySnapshot(gpu_free=gpu_free)\n\n\n\n\ndef _measure_detailed_state() -> dict:\n    \"\"\"\n    Capture full memory state (expensive operation).\n\n    This includes GPU memory (requires sync) and system memory (syscalls).\n    Only call when STRUCTURED_LOGGING_DETAILED_MEMORY is enabled.\n    \"\"\"\n    state = {}\n\n    # GPU memory (expensive - requires GPU synchronization)\n    try:\n        import torch\n\n        if torch.cuda.is_available():\n            gpu_free, gpu_total = torch.cuda.mem_get_info()\n            state[\"gpu_allocated\"] = torch.cuda.memory_allocated()\n            state[\"gpu_reserved\"] = torch.cuda.memory_reserved()\n            state[\"gpu_free\"] = gpu_free\n            state[\"gpu_total\"] = gpu_total\n    except ImportError:\n        pass\n\n    # System memory (moderate cost - syscalls)\n    try:\n        import psutil\n\n        state[\"process_rss_bytes\"] = psutil.Process().memory_info().rss\n        state[\"system_available_bytes\"] = psutil.virtual_memory().available\n    except ImportError:\n        pass\n\n    return state",
    "optimized_raw_markdown": "```python:inference/core/structured_logging/memory.py\nfrom typing import Optional\n\nfrom inference.core.structured_logging.events import MemorySnapshot\n\n\ndef measure_memory_for_eviction(detailed: bool = False) -> Optional[MemorySnapshot]:\n    \"\"\"\n    Measure memory state for eviction event.\n\n    Only captures gpu_free before eviction. The after state is measured\n    separately after the model is removed.\n\n    Args:\n        detailed: If True, capture memory state\n\n    Returns:\n        MemorySnapshot with gpu_free_before, or None if not detailed\n    \"\"\"\n    if not detailed:\n        return None\n\n    # GPU memory (expensive - requires GPU synchronization)\n    gpu_free = None\n    try:\n        import torch\n\n        if torch.cuda.is_available():\n            gpu_free, _ = torch.cuda.mem_get_info()\n    except ImportError:\n        pass\n\n    return MemorySnapshot(gpu_free=gpu_free)\n\n\n\n\ndef _measure_detailed_state() -> dict:\n    \"\"\"\n    Capture full memory state (expensive operation).\n\n    This includes GPU memory (requires sync) and system memory (syscalls).\n    Only call when STRUCTURED_LOGGING_DETAILED_MEMORY is enabled.\n    \"\"\"\n    state = {}\n\n    # GPU memory (expensive - requires GPU synchronization)\n    try:\n        import torch\n\n        if torch.cuda.is_available():\n            gpu_free, gpu_total = torch.cuda.mem_get_info()\n            state[\"gpu_allocated\"] = torch.cuda.memory_allocated()\n            state[\"gpu_reserved\"] = torch.cuda.memory_reserved()\n            state[\"gpu_free\"] = gpu_free\n            state[\"gpu_total\"] = gpu_total\n    except ImportError:\n        pass\n\n    # System memory (moderate cost - syscalls)\n    try:\n        import psutil\n\n        state[\"process_rss_bytes\"] = psutil.Process().memory_info().rss\n        state[\"system_available_bytes\"] = psutil.virtual_memory().available\n    except ImportError:\n        pass\n\n    return state\n```",
    "optimized_function_only": "def measure_memory_for_eviction(detailed: bool = False) -> Optional[MemorySnapshot]:\n    \"\"\"\n    Measure memory state for eviction event.\n\n    Only captures gpu_free before eviction. The after state is measured\n    separately after the model is removed.\n\n    Args:\n        detailed: If True, capture memory state\n\n    Returns:\n        MemorySnapshot with gpu_free_before, or None if not detailed\n    \"\"\"\n    if not detailed:\n        return None\n\n    # GPU memory (expensive - requires GPU synchronization)\n    gpu_free = None\n    try:\n        import torch\n\n        if torch.cuda.is_available():\n            gpu_free, _ = torch.cuda.mem_get_info()\n    except ImportError:\n        pass\n\n    return MemorySnapshot(gpu_free=gpu_free)\n",
    "original_file_content": "from inference.core.structured_logging.events import MemorySnapshot\nfrom typing import Optional\n\ndef measure_memory_for_eviction(detailed: bool = False) -> Optional[MemorySnapshot]:\n    \"\"\"\n    Measure memory state for eviction event.\n\n    Only captures gpu_free before eviction. The after state is measured\n    separately after the model is removed.\n\n    Args:\n        detailed: If True, capture memory state\n\n    Returns:\n        MemorySnapshot with gpu_free_before, or None if not detailed\n    \"\"\"\n    if not detailed:\n        return None\n\n    state = _measure_detailed_state()\n    return MemorySnapshot(\n        gpu_free=state.get(\"gpu_free\"),\n    )\n\n\ndef _measure_detailed_state() -> dict:\n    \"\"\"\n    Capture full memory state (expensive operation).\n\n    This includes GPU memory (requires sync) and system memory (syscalls).\n    Only call when STRUCTURED_LOGGING_DETAILED_MEMORY is enabled.\n    \"\"\"\n    state = {}\n\n    # GPU memory (expensive - requires GPU synchronization)\n    try:\n        import torch\n\n        if torch.cuda.is_available():\n            gpu_free, gpu_total = torch.cuda.mem_get_info()\n            state.update(\n                {\n                    \"gpu_allocated\": torch.cuda.memory_allocated(),\n                    \"gpu_reserved\": torch.cuda.memory_reserved(),\n                    \"gpu_free\": gpu_free,\n                    \"gpu_total\": gpu_total,\n                }\n            )\n    except ImportError:\n        pass\n\n    # System memory (moderate cost - syscalls)\n    try:\n        import psutil\n\n        state[\"process_rss_bytes\"] = psutil.Process().memory_info().rss\n        state[\"system_available_bytes\"] = psutil.virtual_memory().available\n    except ImportError:\n        pass\n\n    return state",
    "patch": null
  },
  {
    "trace_id": "e1342861-7c06-4eb7-9ac1-354e5c9b35ae",
    "function_name": "DetectionEventLogBlockV1._evict_oldest_video",
    "file_path": "inference/core/workflows/core_steps/analytics/detection_event_log/v1.py",
    "speedup_x": 14.92,
    "review_quality": "medium",
    "pre_optimization_commit": "320928cb553fbad49b455eede555b3a7463de775",
    "resolution_method": "db_code_match",
    "source": "db_events",
    "original_function_code": "    def _evict_oldest_video(self) -> None:\n        \"\"\"Remove the oldest video stream data when MAX_VIDEOS is exceeded.\"\"\"\n        if len(self._event_logs) <= MAX_VIDEOS:\n            return\n\n        # Find the video with the oldest last access time\n        oldest_video_id = min(self._last_access, key=self._last_access.get)\n\n        # Remove all data for this video\n        self._event_logs.pop(oldest_video_id, None)\n        self._last_flush_frame.pop(oldest_video_id, None)\n        self._frame_count.pop(oldest_video_id, None)\n        self._last_access.pop(oldest_video_id, None)\n",
    "optimized_function_code": "import heapq\nfrom typing import Dict\n\nfrom inference.core.workflows.prototypes.block import WorkflowBlock\n\nMAX_VIDEOS = 100  # Maximum number of video streams to track before evicting oldest\n\n\nclass DetectionEventLogBlockV1(WorkflowBlock):\n\n    def __init__(self):\n        # Dict[video_id, Dict[tracker_id, DetectionEvent]]\n        self._event_logs: Dict[str, Dict[int, DetectionEvent]] = {}\n        # Dict[video_id, last_flush_frame]\n        self._last_flush_frame: Dict[str, int] = {}\n        # Dict[video_id, frame_count] - internal frame counter (increments each run)\n        self._frame_count: Dict[str, int] = {}\n        # Dict[video_id, last_access_frame] - tracks when each video was last accessed (global frame count)\n        self._last_access: Dict[str, int] = {}\n        # Global frame counter for tracking video access order\n        # Min-heap of (last_access_frame, video_id) for efficient eviction\n        self._access_heap: list = []\n        # Global frame counter for tracking video access order\n        self._global_frame: int = 0\n\n    def _evict_oldest_video(self) -> None:\n        \"\"\"Remove the oldest video stream data when MAX_VIDEOS is exceeded.\"\"\"\n        if len(self._event_logs) <= MAX_VIDEOS:\n            return\n\n        # Pop from heap until we find a valid video (handles stale entries)\n        while self._access_heap:\n            _, oldest_video_id = heapq.heappop(self._access_heap)\n            \n            # Check if this video still exists (heap may contain stale entries)\n            if oldest_video_id in self._event_logs:\n                # Remove all data for this video\n                del self._event_logs[oldest_video_id]\n                del self._last_flush_frame[oldest_video_id]\n                del self._frame_count[oldest_video_id]\n                del self._last_access[oldest_video_id]\n                break",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/analytics/detection_event_log/v1.py\nimport heapq\nfrom typing import Dict\n\nfrom inference.core.workflows.prototypes.block import WorkflowBlock\n\nMAX_VIDEOS = 100  # Maximum number of video streams to track before evicting oldest\n\n\nclass DetectionEventLogBlockV1(WorkflowBlock):\n\n    def __init__(self):\n        # Dict[video_id, Dict[tracker_id, DetectionEvent]]\n        self._event_logs: Dict[str, Dict[int, DetectionEvent]] = {}\n        # Dict[video_id, last_flush_frame]\n        self._last_flush_frame: Dict[str, int] = {}\n        # Dict[video_id, frame_count] - internal frame counter (increments each run)\n        self._frame_count: Dict[str, int] = {}\n        # Dict[video_id, last_access_frame] - tracks when each video was last accessed (global frame count)\n        self._last_access: Dict[str, int] = {}\n        # Global frame counter for tracking video access order\n        # Min-heap of (last_access_frame, video_id) for efficient eviction\n        self._access_heap: list = []\n        # Global frame counter for tracking video access order\n        self._global_frame: int = 0\n\n    def _evict_oldest_video(self) -> None:\n        \"\"\"Remove the oldest video stream data when MAX_VIDEOS is exceeded.\"\"\"\n        if len(self._event_logs) <= MAX_VIDEOS:\n            return\n\n        # Pop from heap until we find a valid video (handles stale entries)\n        while self._access_heap:\n            _, oldest_video_id = heapq.heappop(self._access_heap)\n            \n            # Check if this video still exists (heap may contain stale entries)\n            if oldest_video_id in self._event_logs:\n                # Remove all data for this video\n                del self._event_logs[oldest_video_id]\n                del self._last_flush_frame[oldest_video_id]\n                del self._frame_count[oldest_video_id]\n                del self._last_access[oldest_video_id]\n                break\n```",
    "optimized_function_only": "    def _evict_oldest_video(self) -> None:\n        \"\"\"Remove the oldest video stream data when MAX_VIDEOS is exceeded.\"\"\"\n        if len(self._event_logs) <= MAX_VIDEOS:\n            return\n\n        # Pop from heap until we find a valid video (handles stale entries)\n        while self._access_heap:\n            _, oldest_video_id = heapq.heappop(self._access_heap)\n            \n            # Check if this video still exists (heap may contain stale entries)\n            if oldest_video_id in self._event_logs:\n                # Remove all data for this video\n                del self._event_logs[oldest_video_id]\n                del self._last_flush_frame[oldest_video_id]\n                del self._frame_count[oldest_video_id]\n                del self._last_access[oldest_video_id]\n                break",
    "original_file_content": "import logging\nfrom dataclasses import asdict, dataclass\nfrom typing import Any, Dict, List, Literal, Optional, Type, Union\n\nimport numpy as np\nimport supervision as sv\nfrom pydantic import ConfigDict, Field\n\nfrom inference.core import logger\nfrom inference.core.workflows.execution_engine.entities.base import (\n    OutputDefinition,\n    VideoMetadata,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    DICTIONARY_KIND,\n    FLOAT_KIND,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    INTEGER_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    Selector,\n    WorkflowImageSelector,\n    WorkflowParameterSelector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nOUTPUT_KEY = \"event_log\"\nDETECTIONS_OUTPUT_KEY = \"detections\"\nMAX_VIDEOS = 100  # Maximum number of video streams to track before evicting oldest\n\n\n@dataclass\nclass DetectionEvent:\n    \"\"\"Stores event data for a tracked detection.\"\"\"\n\n    tracker_id: int\n    class_name: str\n    first_seen_frame: int\n    first_seen_timestamp: float\n    last_seen_frame: int\n    last_seen_timestamp: float\n    frame_count: int = 1\n    logged: bool = False\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Detection Event Log\",\n            \"version\": \"v1\",\n            \"short_description\": \"Tracks detection events over time, logging when objects first appear and persist.\",\n            \"long_description\": (\n                \"This block maintains a log of detection events from tracked objects. \"\n                \"It records when each object was first seen, its class, and the last time it was seen.\"\n                \"Objects must be seen for a minimum number of frames (frame_threshold) before being logged. \"\n                \"Stale events (not seen for stale_frames) are removed during periodic cleanup (every flush_interval frames).\"\n            ),\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"analytics\",\n            \"ui_manifest\": {\n                \"section\": \"analytics\",\n                \"icon\": \"fal fa-list-timeline\",\n                \"blockPriority\": 3,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/detection_event_log@v1\"]\n\n    image: WorkflowImageSelector = Field(\n        description=\"Reference to the image for video metadata (frame number, timestamp).\",\n        examples=[\"$inputs.image\"],\n    )\n\n    detections: Selector(\n        kind=[\n            OBJECT_DETECTION_PREDICTION_KIND,\n            INSTANCE_SEGMENTATION_PREDICTION_KIND,\n        ]\n    ) = Field(\n        description=\"Tracked detections from byte tracker (must have tracker_id).\",\n        examples=[\"$steps.byte_tracker.tracked_detections\"],\n    )\n\n    frame_threshold: Union[int, WorkflowParameterSelector(kind=[INTEGER_KIND])] = Field(\n        default=30,\n        description=\"Number of frames an object must be seen before being logged.\",\n        examples=[5, 10],\n        ge=1,\n    )\n\n    flush_interval: Union[int, WorkflowParameterSelector(kind=[INTEGER_KIND])] = Field(\n        default=30,\n        description=\"How often (in frames) to run the cleanup operation for stale events.\",\n        examples=[30, 60],\n        ge=1,\n    )\n\n    stale_frames: Union[int, WorkflowParameterSelector(kind=[INTEGER_KIND])] = Field(\n        default=300,\n        description=\"Remove events that haven't been seen for this many frames.\",\n        examples=[150, 300],\n        ge=1,\n    )\n\n    reference_timestamp: Optional[\n        Union[float, WorkflowParameterSelector(kind=[FLOAT_KIND])]\n    ] = Field(\n        default=None,\n        description=\"Unix timestamp when the video started. When provided, absolute timestamps (first_seen_timestamp, last_seen_timestamp) are included in output, calculated as relative time + reference_timestamp.\",\n        examples=[1726570875.0],\n    )\n\n    fallback_fps: Union[float, WorkflowParameterSelector(kind=[FLOAT_KIND])] = Field(\n        default=1.0,\n        description=\"Fallback FPS to use when video metadata does not provide FPS information. Used to calculate relative timestamps.\",\n        examples=[1.0, 30.0],\n        gt=0,\n    )\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(\n                name=OUTPUT_KEY,\n                kind=[DICTIONARY_KIND],\n            ),\n            OutputDefinition(\n                name=DETECTIONS_OUTPUT_KEY,\n                kind=[\n                    OBJECT_DETECTION_PREDICTION_KIND,\n                    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n                ],\n            ),\n            OutputDefinition(\n                name=\"total_logged\",\n                kind=[INTEGER_KIND],\n            ),\n            OutputDefinition(\n                name=\"total_pending\",\n                kind=[INTEGER_KIND],\n            ),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass DetectionEventLogBlockV1(WorkflowBlock):\n    \"\"\"\n    Block that tracks detection events over time.\n\n    Maintains a dictionary of tracked objects with:\n    - First seen timestamp and frame\n    - Last seen timestamp and frame\n    - Class name\n    - Frame count (number of frames the object has been seen)\n\n    Only logs objects that have been seen for at least frame_threshold frames.\n    Runs cleanup every flush_interval frames, removing events not seen for stale_frames.\n    \"\"\"\n\n    def __init__(self):\n        # Dict[video_id, Dict[tracker_id, DetectionEvent]]\n        self._event_logs: Dict[str, Dict[int, DetectionEvent]] = {}\n        # Dict[video_id, last_flush_frame]\n        self._last_flush_frame: Dict[str, int] = {}\n        # Dict[video_id, frame_count] - internal frame counter (increments each run)\n        self._frame_count: Dict[str, int] = {}\n        # Dict[video_id, last_access_frame] - tracks when each video was last accessed (global frame count)\n        self._last_access: Dict[str, int] = {}\n        # Global frame counter for tracking video access order\n        self._global_frame: int = 0\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def _get_relative_time(\n        self, current_frame: int, metadata: VideoMetadata, fallback_fps: float\n    ) -> float:\n        \"\"\"Calculate relative time in seconds since video started.\n\n        Uses frame number and FPS when available, otherwise uses fallback_fps.\n        Frame 1 corresponds to 0.0 seconds.\n        \"\"\"\n        fps = metadata.fps if metadata.fps and metadata.fps != 0 else fallback_fps\n        return (current_frame - 1) / fps\n\n    def _evict_oldest_video(self) -> None:\n        \"\"\"Remove the oldest video stream data when MAX_VIDEOS is exceeded.\"\"\"\n        if len(self._event_logs) <= MAX_VIDEOS:\n            return\n\n        # Find the video with the oldest last access time\n        oldest_video_id = min(self._last_access, key=self._last_access.get)\n\n        # Remove all data for this video\n        self._event_logs.pop(oldest_video_id, None)\n        self._last_flush_frame.pop(oldest_video_id, None)\n        self._frame_count.pop(oldest_video_id, None)\n        self._last_access.pop(oldest_video_id, None)\n\n    def _remove_stale_events(\n        self,\n        event_log: Dict[int, DetectionEvent],\n        current_frame: int,\n        stale_frames: int,\n    ) -> List[DetectionEvent]:\n        \"\"\"Remove events that haven't been seen for stale_frames.\n\n        Returns list of removed events for logging purposes.\n        \"\"\"\n        stale_tracker_ids = []\n        removed_events = []\n\n        for tracker_id, event in event_log.items():\n            frames_since_seen = current_frame - event.last_seen_frame\n            if frames_since_seen > stale_frames:\n                stale_tracker_ids.append(tracker_id)\n                removed_events.append(event)\n\n        for tracker_id in stale_tracker_ids:\n            del event_log[tracker_id]\n\n        return removed_events\n\n    def run(\n        self,\n        image: WorkflowImageData,\n        detections: sv.Detections,\n        frame_threshold: int,\n        flush_interval: int,\n        stale_frames: int,\n        fallback_fps: float = 1.0,\n        reference_timestamp: Optional[float] = None,\n    ) -> BlockResult:\n        \"\"\"Process detections and update the event log.\n\n        Args:\n            image: Workflow image data containing video metadata.\n            detections: Tracked detections with tracker_id from ByteTracker.\n            frame_threshold: Minimum frames an object must be seen before logging.\n            flush_interval: How often to run stale event cleanup.\n            stale_frames: Remove events not seen for this many frames.\n            fallback_fps: FPS to use when video metadata doesn't provide FPS.\n            reference_timestamp: Optional Unix timestamp when video started. When provided,\n                absolute timestamps are included in output.\n\n        Returns:\n            Dictionary containing event_log, detections, total_logged, and total_pending.\n        \"\"\"\n        metadata = image.video_metadata\n        video_id = metadata.video_identifier\n\n        # Track global frame count and video access for eviction\n        self._global_frame += 1\n        self._last_access[video_id] = self._global_frame\n\n        # Increment internal frame counter\n        current_frame = self._frame_count.get(video_id, 0) + 1\n        self._frame_count[video_id] = current_frame\n\n        current_time = self._get_relative_time(current_frame, metadata, fallback_fps)\n\n        # Initialize event log for this video if needed\n        event_log = self._event_logs.setdefault(video_id, {})\n\n        # Evict oldest video if we've exceeded MAX_VIDEOS (after adding current video)\n        self._evict_oldest_video()\n\n        # Initialize last flush frame if not set\n        if video_id not in self._last_flush_frame:\n            self._last_flush_frame[video_id] = current_frame\n\n        # Check if it's time to run cleanup\n        last_flush = self._last_flush_frame.get(video_id, 0)\n        if (current_frame - last_flush) >= flush_interval:\n            self._remove_stale_events(event_log, current_frame, stale_frames)\n            self._last_flush_frame[video_id] = current_frame\n\n        # Process detections\n        if detections.tracker_id is None or len(detections.tracker_id) == 0:\n            # No tracked detections, return current log\n            event_log_dict, total_logged, total_pending = self._format_event_log(\n                event_log, frame_threshold, reference_timestamp\n            )\n            return {\n                OUTPUT_KEY: event_log_dict,\n                DETECTIONS_OUTPUT_KEY: detections,\n                \"total_logged\": total_logged,\n                \"total_pending\": total_pending,\n            }\n\n        # Get class names\n        class_names = detections.data.get(\"class_name\", [])\n        if (\n            len(class_names) == 0\n            and hasattr(detections, \"class_id\")\n            and detections.class_id is not None\n        ):\n            class_names = [f\"class_{cid}\" for cid in detections.class_id]\n\n        # Update event log for each tracked detection\n        for i, tracker_id in enumerate(detections.tracker_id):\n            tracker_id = int(tracker_id)\n            class_name = str(class_names[i]) if len(class_names) > 0 else \"unknown\"\n\n            if tracker_id in event_log:\n                # Update existing event\n                event = event_log[tracker_id]\n                event.last_seen_frame = current_frame\n                event.last_seen_timestamp = current_time\n                event.frame_count += 1\n\n                # Mark as logged once threshold is reached\n                if event.frame_count >= frame_threshold and not event.logged:\n                    event.logged = True\n                    logger.debug(\n                        f\"Object {tracker_id} ({event.class_name}) logged after {event.frame_count} frames\"\n                    )\n            else:\n                # Create new event\n                event_log[tracker_id] = DetectionEvent(\n                    tracker_id=tracker_id,\n                    class_name=class_name,\n                    first_seen_frame=current_frame,\n                    first_seen_timestamp=current_time,\n                    last_seen_frame=current_frame,\n                    last_seen_timestamp=current_time,\n                    frame_count=1,\n                    logged=False,\n                )\n\n        event_log_dict, total_logged, total_pending = self._format_event_log(\n            event_log, frame_threshold, reference_timestamp\n        )\n        return {\n            OUTPUT_KEY: event_log_dict,\n            DETECTIONS_OUTPUT_KEY: detections,\n            \"total_logged\": total_logged,\n            \"total_pending\": total_pending,\n        }\n\n    def _format_event_log(\n        self,\n        event_log: Dict[int, DetectionEvent],\n        frame_threshold: int,\n        reference_timestamp: Optional[float] = None,\n    ) -> tuple:\n        \"\"\"Format the event log for output.\n\n        Returns:\n            Tuple of (event_log_dict, total_logged, total_pending)\n        \"\"\"\n        logged_events = {}\n        pending_events = {}\n\n        for tracker_id, event in event_log.items():\n            event_data = asdict(event)\n            del event_data[\"logged\"]\n\n            # Internal timestamps are relative (seconds since video start)\n            # Rename to *_relative in output\n            first_seen_relative = event_data.pop(\"first_seen_timestamp\")\n            last_seen_relative = event_data.pop(\"last_seen_timestamp\")\n            event_data[\"first_seen_relative\"] = first_seen_relative\n            event_data[\"last_seen_relative\"] = last_seen_relative\n\n            # Add absolute timestamps if reference_timestamp is provided\n            if reference_timestamp is not None:\n                event_data[\"first_seen_timestamp\"] = (\n                    first_seen_relative + reference_timestamp\n                )\n                event_data[\"last_seen_timestamp\"] = (\n                    last_seen_relative + reference_timestamp\n                )\n\n            if event.frame_count >= frame_threshold:\n                logged_events[str(tracker_id)] = event_data\n            else:\n                pending_events[str(tracker_id)] = event_data\n\n        event_log_dict = {\n            \"logged\": logged_events,\n            \"pending\": pending_events,\n        }\n\n        return event_log_dict, len(logged_events), len(pending_events)\n",
    "patch": null
  },
  {
    "trace_id": "82993793-3bb9-4fd7-ba69-e855ea486f4d",
    "function_name": "_extract_detail",
    "file_path": "inference/enterprise/workflows/enterprise_blocks/sinks/event_writer/v1.py",
    "speedup_x": 12.46,
    "review_quality": "high",
    "pre_optimization_commit": "ad7d91d0150bee8f45dc26ae83f7c499503c8a4d",
    "resolution_method": "db_code_match",
    "source": "db_events",
    "original_function_code": "def _extract_detail(response: requests.Response) -> str:\n    \"\"\"Try to extract 'detail' from a JSON error response.\"\"\"\n    try:\n        return str(response.json().get(\"detail\", response.text))\n    except Exception:\n        return response.text\n",
    "optimized_function_code": "import requests\n\n\ndef _extract_detail(response: requests.Response) -> str:\n    \"\"\"Try to extract 'detail' from a JSON error response.\"\"\"\n    try:\n        # Quickly determine whether the body could be a JSON object:\n        # only JSON objects (first non-space char == '{') can meaningfully\n        # supply a .get(\"detail\", ...) result. If it's not an object, avoid\n        # the expensive response.json() call and return the raw text,\n        # which mirrors the original function's fallback behavior.\n        text = response.text\n        stripped = text.lstrip()\n        if not stripped or stripped[0] != \"{\":\n            return text\n\n        obj = response.json()\n        # If obj is a mapping-like dict, use .get as originally done.\n        if isinstance(obj, dict):\n            return str(obj.get(\"detail\", text))\n        # If it's not a dict but happens to provide .get, try it safely.\n        try:\n            return str(obj.get(\"detail\", text))\n        except Exception:\n            return text\n    except Exception:\n        return response.text",
    "optimized_raw_markdown": "```python:inference/enterprise/workflows/enterprise_blocks/sinks/event_writer/v1.py\nimport requests\n\n\ndef _extract_detail(response: requests.Response) -> str:\n    \"\"\"Try to extract 'detail' from a JSON error response.\"\"\"\n    try:\n        # Quickly determine whether the body could be a JSON object:\n        # only JSON objects (first non-space char == '{') can meaningfully\n        # supply a .get(\"detail\", ...) result. If it's not an object, avoid\n        # the expensive response.json() call and return the raw text,\n        # which mirrors the original function's fallback behavior.\n        text = response.text\n        stripped = text.lstrip()\n        if not stripped or stripped[0] != \"{\":\n            return text\n\n        obj = response.json()\n        # If obj is a mapping-like dict, use .get as originally done.\n        if isinstance(obj, dict):\n            return str(obj.get(\"detail\", text))\n        # If it's not a dict but happens to provide .get, try it safely.\n        try:\n            return str(obj.get(\"detail\", text))\n        except Exception:\n            return text\n    except Exception:\n        return response.text\n```",
    "optimized_function_only": "def _extract_detail(response: requests.Response) -> str:\n    \"\"\"Try to extract 'detail' from a JSON error response.\"\"\"\n    try:\n        # Quickly determine whether the body could be a JSON object:\n        # only JSON objects (first non-space char == '{') can meaningfully\n        # supply a .get(\"detail\", ...) result. If it's not an object, avoid\n        # the expensive response.json() call and return the raw text,\n        # which mirrors the original function's fallback behavior.\n        text = response.text\n        stripped = text.lstrip()\n        if not stripped or stripped[0] != \"{\":\n            return text\n\n        obj = response.json()\n        # If obj is a mapping-like dict, use .get as originally done.\n        if isinstance(obj, dict):\n            return str(obj.get(\"detail\", text))\n        # If it's not a dict but happens to provide .get, try it safely.\n        try:\n            return str(obj.get(\"detail\", text))\n        except Exception:\n            return text\n    except Exception:\n        return response.text",
    "original_file_content": "import logging\nimport os\nfrom concurrent.futures import ThreadPoolExecutor\nfrom datetime import datetime, timezone\nfrom functools import partial\nfrom typing import Any, Dict, List, Literal, Optional, Tuple, Type, Union\nfrom urllib.parse import urljoin\n\nimport cv2\nimport numpy as np\nimport requests\nfrom fastapi import BackgroundTasks\nfrom pydantic import ConfigDict, Field\n\nfrom inference.core.workflows.execution_engine.entities.base import (\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    BOOLEAN_KIND,\n    CLASSIFICATION_PREDICTION_KIND,\n    IMAGE_KIND,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    INTEGER_KIND,\n    KEYPOINT_DETECTION_PREDICTION_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    STRING_KIND,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nLONG_DESCRIPTION = \"\"\"\nThe **Event Writer** block sends structured events to the Event Ingestion Service\nusing the v2 API.\n\n## Supported Event Schemas\n\n* **Quality Check** \u2014 pass/fail inspection results\n* **Inventory Count** \u2014 item counts at a location\n* **Safety Alert** \u2014 safety incidents with severity levels\n* **Custom** \u2014 free-form events with an arbitrary value field\n\n## Images\n\nEach event includes one image entry. You must provide an **output image** (the\nprimary display image, typically a visualization). You can optionally attach an\n**input image** (the original frame before any annotation).\n\n## Annotations\n\nYou can optionally pass object detection, classification, instance segmentation,\nor keypoint predictions from upstream model blocks. These are stored as\nstructured annotations on the image within the event.\n\n## Execution Modes\n\n* **Fire-and-forget** (`fire_and_forget=True`, default) \u2014 the HTTP request is\n  dispatched in the background so the workflow continues immediately. The\n  `event_id` output will be empty.\n* **Synchronous** (`fire_and_forget=False`) \u2014 the block waits for the response\n  and returns the created `event_id`.\n\n## Rate Limiting\n\nUse the **Rate Limiter** workflow block upstream of this block to control how\noften events are sent.\n\n## Authentication\n\nIf the Event Ingestion Service requires an API key, set the\n`EVENT_INGESTION_API_KEY` environment variable on the inference server.\nRequests are sent unauthenticated when the variable is not set.\n\"\"\"\n\nQUALITY_CHECK_RELEVANT = {\n    \"event_schema\": {\"values\": [\"quality_check\"], \"required\": True},\n}\nINVENTORY_COUNT_RELEVANT = {\n    \"event_schema\": {\"values\": [\"inventory_count\"], \"required\": True},\n}\nSAFETY_ALERT_RELEVANT = {\n    \"event_schema\": {\"values\": [\"safety_alert\"], \"required\": True},\n}\nCUSTOM_RELEVANT = {\n    \"event_schema\": {\"values\": [\"custom\"], \"required\": True},\n}\nALL_DATA_SCHEMAS_RELEVANT = {\n    \"event_schema\": {\n        \"values\": [\"quality_check\", \"inventory_count\", \"safety_alert\", \"custom\"],\n    },\n}\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Event Writer\",\n            \"version\": \"v1\",\n            \"short_description\": \"Write structured events to the Event Ingestion Service.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Roboflow Enterprise License\",\n            \"block_type\": \"sink\",\n            \"ui_manifest\": {\n                \"section\": \"industrial\",\n                \"icon\": \"fal fa-calendar-check\",\n                \"blockPriority\": 5,\n                \"enterprise_only\": True,\n                \"local_only\": True,\n            },\n        }\n    )\n    type: Literal[\"roboflow_enterprise/event_writer_sink@v1\"]\n\n    # --- Connection ---\n    event_ingestion_url: Union[Selector(kind=[STRING_KIND]), str] = Field(\n        default=\"http://localhost:8001\",\n        description=\"Base URL of the Event Ingestion Service.\",\n        examples=[\"http://localhost:8001\", \"$inputs.event_ingestion_url\"],\n    )\n\n    # --- Schema selector ---\n    event_schema: Literal[\n        \"quality_check\", \"inventory_count\", \"safety_alert\", \"custom\"\n    ] = Field(\n        description=\"The event schema to use.\",\n        json_schema_extra={\"always_visible\": True},\n    )\n\n    # --- Images ---\n    output_image: Selector(kind=[IMAGE_KIND]) = Field(\n        description=\"The output/visualization image. Sent as the primary display image.\",\n        json_schema_extra={\"always_visible\": True},\n    )\n    input_image: Optional[Selector(kind=[IMAGE_KIND])] = Field(\n        default=None,\n        description=\"The original input image (optional). Sent as the source image.\",\n    )\n    image_label: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Label for the image entry.\",\n        examples=[\"defect-analysis\", \"$inputs.image_label\"],\n    )\n\n    # --- Custom metadata ---\n    custom_metadata: Dict[\n        str,\n        Union[\n            Selector(),\n            str,\n            float,\n            bool,\n            int,\n        ],\n    ] = Field(\n        default_factory=dict,\n        description=\"Flat key-value metadata (max 100 keys, values must be str/int/float/bool).\",\n        examples=[{\"line\": \"A1\", \"shift\": \"morning\"}],\n        json_schema_extra={\"always_visible\": True},\n    )\n\n    # --- Quality Check fields ---\n    qc_result: Optional[\n        Union[Selector(kind=[STRING_KIND]), Literal[\"pass\", \"fail\"]]\n    ] = Field(\n        default=None,\n        description=\"Quality check result: pass or fail.\",\n        examples=[\"pass\", \"fail\", \"$steps.qc_logic.result\"],\n        json_schema_extra={\n            \"relevant_for\": QUALITY_CHECK_RELEVANT,\n            \"always_visible\": True,\n        },\n    )\n\n    # --- External ID (shared across schemas) ---\n    external_id: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"External identifier for correlation with other systems (max 1000 chars).\",\n        examples=[\"batch-2025-001\", \"$inputs.external_id\"],\n        json_schema_extra={\n            \"relevant_for\": ALL_DATA_SCHEMAS_RELEVANT,\n        },\n    )\n\n    # --- Inventory Count fields ---\n    location: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Location identifier for inventory count.\",\n        examples=[\"warehouse-A\", \"$inputs.location\"],\n        json_schema_extra={\"relevant_for\": INVENTORY_COUNT_RELEVANT},\n    )\n    item_count: Optional[Union[Selector(kind=[INTEGER_KIND]), int]] = Field(\n        default=None,\n        description=\"Number of items counted.\",\n        examples=[42, \"$steps.counter.count\"],\n        json_schema_extra={\"relevant_for\": INVENTORY_COUNT_RELEVANT},\n    )\n    item_type: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Type of item being counted.\",\n        examples=[\"widget\", \"$inputs.item_type\"],\n        json_schema_extra={\"relevant_for\": INVENTORY_COUNT_RELEVANT},\n    )\n\n    # --- Safety Alert fields ---\n    alert_type: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Alert type identifier (alphanumeric, underscores, hyphens).\",\n        examples=[\"no_hardhat\", \"$steps.classifier.top_class\"],\n        json_schema_extra={\"relevant_for\": SAFETY_ALERT_RELEVANT},\n    )\n    severity: Optional[\n        Union[Selector(kind=[STRING_KIND]), Literal[\"low\", \"medium\", \"high\"]]\n    ] = Field(\n        default=None,\n        description=\"Severity level for the safety alert.\",\n        examples=[\"high\", \"$inputs.severity\"],\n        json_schema_extra={\"relevant_for\": SAFETY_ALERT_RELEVANT},\n    )\n    alert_description: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Description of the safety alert (max 10000 chars).\",\n        examples=[\"Worker detected without hardhat in zone B\"],\n        json_schema_extra={\"relevant_for\": SAFETY_ALERT_RELEVANT},\n    )\n\n    # --- Custom Event fields ---\n    custom_value: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Arbitrary value for custom events (max 10000 chars).\",\n        examples=[\"anomaly detected at 14:32\"],\n        json_schema_extra={\"relevant_for\": CUSTOM_RELEVANT},\n    )\n\n    # --- Annotation pass-through ---\n    object_detections: Optional[Selector(kind=[OBJECT_DETECTION_PREDICTION_KIND])] = (\n        Field(\n            default=None,\n            description=\"Object detection predictions to attach to the image.\",\n            json_schema_extra={\"additional_section\": True},\n        )\n    )\n    classifications: Optional[Selector(kind=[CLASSIFICATION_PREDICTION_KIND])] = Field(\n        default=None,\n        description=\"Classification predictions to attach to the image.\",\n        json_schema_extra={\"additional_section\": True},\n    )\n    instance_segmentations: Optional[\n        Selector(kind=[INSTANCE_SEGMENTATION_PREDICTION_KIND])\n    ] = Field(\n        default=None,\n        description=\"Instance segmentation predictions to attach to the image.\",\n        json_schema_extra={\"additional_section\": True},\n    )\n    keypoint_detections: Optional[\n        Selector(kind=[KEYPOINT_DETECTION_PREDICTION_KIND])\n    ] = Field(\n        default=None,\n        description=\"Keypoint detection predictions to attach to the image.\",\n        json_schema_extra={\"additional_section\": True},\n    )\n\n    # --- Execution control ---\n    fire_and_forget: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=True,\n        description=\"If True, send the event asynchronously (no event_id returned). \"\n        \"If False, wait for the response and return the event_id.\",\n        examples=[True, False, \"$inputs.fire_and_forget\"],\n    )\n    disable_sink: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=False,\n        description=\"If True, skip sending the event entirely.\",\n        examples=[False, \"$inputs.disable_event_writer\"],\n    )\n    request_timeout: Union[int, Selector(kind=[INTEGER_KIND])] = Field(\n        default=5,\n        description=\"HTTP request timeout in seconds.\",\n        examples=[5, 10],\n    )\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"error_status\", kind=[BOOLEAN_KIND]),\n            OutputDefinition(name=\"event_id\", kind=[STRING_KIND]),\n            OutputDefinition(name=\"message\", kind=[STRING_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass EventWriterSinkBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        background_tasks: Optional[BackgroundTasks],\n        thread_pool_executor: Optional[ThreadPoolExecutor],\n    ):\n        self._background_tasks = background_tasks\n        self._thread_pool_executor = thread_pool_executor\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"background_tasks\", \"thread_pool_executor\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        event_ingestion_url: str,\n        event_schema: str,\n        output_image: WorkflowImageData,\n        fire_and_forget: bool,\n        disable_sink: bool,\n        request_timeout: int,\n        input_image: Optional[WorkflowImageData] = None,\n        image_label: Optional[str] = None,\n        custom_metadata: Optional[Dict[str, Any]] = None,\n        qc_result: Optional[str] = None,\n        external_id: Optional[str] = None,\n        location: Optional[str] = None,\n        item_count: Optional[int] = None,\n        item_type: Optional[str] = None,\n        alert_type: Optional[str] = None,\n        severity: Optional[str] = None,\n        alert_description: Optional[str] = None,\n        custom_value: Optional[str] = None,\n        object_detections: Optional[Any] = None,\n        classifications: Optional[Any] = None,\n        instance_segmentations: Optional[Any] = None,\n        keypoint_detections: Optional[Any] = None,\n    ) -> BlockResult:\n        if disable_sink:\n            return {\n                \"error_status\": False,\n                \"event_id\": \"\",\n                \"message\": \"Sink was disabled by parameter `disable_sink`\",\n            }\n\n        event_data = _build_event_data(\n            event_schema=event_schema,\n            qc_result=qc_result,\n            external_id=external_id,\n            location=location,\n            item_count=item_count,\n            item_type=item_type,\n            alert_type=alert_type,\n            severity=severity,\n            alert_description=alert_description,\n            custom_value=custom_value,\n        )\n\n        image_entry = _build_image_entry(\n            output_image=output_image,\n            input_image=input_image,\n            image_label=image_label,\n            object_detections=object_detections,\n            classifications=classifications,\n            instance_segmentations=instance_segmentations,\n            keypoint_detections=keypoint_detections,\n        )\n\n        payload: Dict[str, Any] = {\n            \"inference_timestamp\": datetime.now(timezone.utc).isoformat(),\n            \"event_schema\": event_schema,\n            \"event_data\": event_data,\n            \"images\": [image_entry],\n            \"displayImagePosition\": 0,\n        }\n        if custom_metadata:\n            payload[\"custom_metadata\"] = custom_metadata\n\n        request_handler = partial(\n            _execute_event_request,\n            url=urljoin(event_ingestion_url, \"/v2/events\"),\n            payload=payload,\n            api_key=os.environ.get(\"EVENT_INGESTION_API_KEY\"),\n            timeout=request_timeout,\n        )\n\n        if fire_and_forget and self._background_tasks:\n            self._background_tasks.add_task(request_handler)\n            return {\n                \"error_status\": False,\n                \"event_id\": \"\",\n                \"message\": \"Event sent in background task\",\n            }\n        if fire_and_forget and self._thread_pool_executor:\n            self._thread_pool_executor.submit(request_handler)\n            return {\n                \"error_status\": False,\n                \"event_id\": \"\",\n                \"message\": \"Event sent in background task\",\n            }\n\n        error_status, message, event_id = request_handler()\n        return {\n            \"error_status\": error_status,\n            \"event_id\": event_id,\n            \"message\": message,\n        }\n\n\ndef _build_event_data(\n    event_schema: str,\n    qc_result: Optional[str] = None,\n    external_id: Optional[str] = None,\n    location: Optional[str] = None,\n    item_count: Optional[int] = None,\n    item_type: Optional[str] = None,\n    alert_type: Optional[str] = None,\n    severity: Optional[str] = None,\n    alert_description: Optional[str] = None,\n    custom_value: Optional[str] = None,\n) -> Dict[str, Any]:\n    \"\"\"Build schema-specific event_data dict with camelCase keys, stripping None values.\"\"\"\n    if event_schema == \"quality_check\":\n        data = {\"result\": qc_result, \"externalId\": external_id}\n    elif event_schema == \"inventory_count\":\n        data = {\n            \"location\": location,\n            \"itemCount\": item_count,\n            \"itemType\": item_type,\n            \"externalId\": external_id,\n        }\n    elif event_schema == \"safety_alert\":\n        data = {\n            \"alertType\": alert_type,\n            \"severity\": severity,\n            \"description\": alert_description,\n            \"externalId\": external_id,\n        }\n    elif event_schema == \"custom\":\n        data = {\"externalId\": external_id, \"value\": custom_value}\n    else:\n        data = {}\n    # Strip None values \u2014 event_data schemas use extra=\"forbid\"\n    return {k: v for k, v in data.items() if v is not None}\n\n\ndef _detections_to_v2_object_detections(detections: Any) -> List[Dict[str, Any]]:\n    \"\"\"Convert Supervision Detections to v2 objectDetections format.\n\n    Uses center-based absolute pixel coordinates to match the main Roboflow\n    annotation format: x,y = center of box, width,height = full dimensions.\n    \"\"\"\n    if detections is None:\n        return []\n    results = []\n    try:\n        xyxy = detections.xyxy\n        confidence = detections.confidence\n        class_names = detections.data.get(\"class_name\", [])\n        for i in range(len(xyxy)):\n            x1, y1, x2, y2 = xyxy[i]\n            w = float(x2 - x1)\n            h = float(y2 - y1)\n            results.append(\n                {\n                    \"class\": class_names[i] if i < len(class_names) else \"unknown\",\n                    \"x\": float((x1 + x2) / 2),\n                    \"y\": float((y1 + y2) / 2),\n                    \"width\": w,\n                    \"height\": h,\n                    \"confidence\": (\n                        float(confidence[i]) if confidence is not None else 0.0\n                    ),\n                }\n            )\n    except Exception as e:\n        logging.warning(f\"Failed to convert object detections: {e}\")\n    return results\n\n\ndef _detections_to_v2_instance_segmentations(detections: Any) -> List[Dict[str, Any]]:\n    \"\"\"Convert Supervision Detections with masks to v2 instanceSegmentations format.\"\"\"\n    if detections is None:\n        return []\n    results = []\n    try:\n        xyxy = detections.xyxy\n        confidence = detections.confidence\n        class_names = detections.data.get(\"class_name\", [])\n        masks = detections.mask\n        for i in range(len(xyxy)):\n            x1, y1, x2, y2 = xyxy[i]\n            w = float(x2 - x1)\n            h = float(y2 - y1)\n            entry = {\n                \"class\": class_names[i] if i < len(class_names) else \"unknown\",\n                \"x\": float((x1 + x2) / 2),\n                \"y\": float((y1 + y2) / 2),\n                \"width\": w,\n                \"height\": h,\n                \"confidence\": float(confidence[i]) if confidence is not None else 0.0,\n                \"points\": [],\n            }\n            if masks is not None and i < len(masks):\n                mask = masks[i].astype(np.uint8)\n                contours, _ = cv2.findContours(\n                    mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE\n                )\n                if contours:\n                    largest = max(contours, key=cv2.contourArea)\n                    entry[\"points\"] = [\n                        [float(pt[0][0]), float(pt[0][1])] for pt in largest\n                    ]\n            if len(entry[\"points\"]) >= 3:\n                results.append(entry)\n    except Exception as e:\n        logging.warning(f\"Failed to convert instance segmentations: {e}\")\n    return results\n\n\ndef _classifications_to_v2(predictions: Any) -> List[Dict[str, Any]]:\n    \"\"\"Convert classification predictions to v2 classifications format.\"\"\"\n    if predictions is None:\n        return []\n    results = []\n    try:\n        if isinstance(predictions, dict):\n            class_names = predictions.get(\"class_name\", [])\n            confidences = predictions.get(\"confidence\", [])\n            for i in range(len(class_names)):\n                results.append(\n                    {\n                        \"class\": class_names[i],\n                        \"confidence\": (\n                            float(confidences[i]) if i < len(confidences) else 0.0\n                        ),\n                    }\n                )\n        elif hasattr(predictions, \"data\"):\n            class_names = predictions.data.get(\"class_name\", [])\n            confidences = predictions.confidence\n            for i in range(len(class_names)):\n                results.append(\n                    {\n                        \"class\": class_names[i],\n                        \"confidence\": (\n                            float(confidences[i])\n                            if confidences is not None and i < len(confidences)\n                            else 0.0\n                        ),\n                    }\n                )\n    except Exception as e:\n        logging.warning(f\"Failed to convert classifications: {e}\")\n    return results\n\n\ndef _keypoints_to_v2(detections: Any) -> List[Dict[str, Any]]:\n    \"\"\"Convert keypoint detection predictions to v2 keypoints format.\"\"\"\n    if detections is None:\n        return []\n    results = []\n    try:\n        xyxy = detections.xyxy\n        confidence = detections.confidence\n        class_names = detections.data.get(\"class_name\", [])\n        keypoints_xy = detections.data.get(\"keypoints_xy\")\n        for i in range(len(xyxy)):\n            x1, y1, x2, y2 = xyxy[i]\n            w = float(x2 - x1)\n            h = float(y2 - y1)\n            entry = {\n                \"class\": class_names[i] if i < len(class_names) else \"unknown\",\n                \"x\": float((x1 + x2) / 2),\n                \"y\": float((y1 + y2) / 2),\n                \"width\": w,\n                \"height\": h,\n                \"confidence\": float(confidence[i]) if confidence is not None else 0.0,\n                \"keypoints\": [],\n            }\n            if keypoints_xy is not None and i < len(keypoints_xy):\n                kps = keypoints_xy[i]\n                for j, kp in enumerate(kps):\n                    entry[\"keypoints\"].append(\n                        {\n                            \"id\": j,\n                            \"x\": float(kp[0]),\n                            \"y\": float(kp[1]),\n                        }\n                    )\n            if entry[\"keypoints\"]:\n                results.append(entry)\n    except Exception as e:\n        logging.warning(f\"Failed to convert keypoint detections: {e}\")\n    return results\n\n\ndef _build_image_entry(\n    output_image: WorkflowImageData,\n    input_image: Optional[WorkflowImageData] = None,\n    image_label: Optional[str] = None,\n    object_detections: Optional[Any] = None,\n    classifications: Optional[Any] = None,\n    instance_segmentations: Optional[Any] = None,\n    keypoint_detections: Optional[Any] = None,\n) -> Dict[str, Any]:\n    \"\"\"Build the single image object for the v2 API payload.\"\"\"\n    entry: Dict[str, Any] = {\n        \"base64Image\": output_image.base64_image,\n    }\n    if input_image is not None:\n        entry[\"inputBase64Image\"] = input_image.base64_image\n    if image_label is not None:\n        entry[\"label\"] = image_label\n\n    od = _detections_to_v2_object_detections(object_detections)\n    if od:\n        entry[\"objectDetections\"] = od\n\n    cl = _classifications_to_v2(classifications)\n    if cl:\n        entry[\"classifications\"] = cl\n\n    seg = _detections_to_v2_instance_segmentations(instance_segmentations)\n    if seg:\n        entry[\"instanceSegmentations\"] = seg\n\n    kp = _keypoints_to_v2(keypoint_detections)\n    if kp:\n        entry[\"keypoints\"] = kp\n\n    return entry\n\n\ndef _execute_event_request(\n    url: str,\n    payload: Dict[str, Any],\n    api_key: Optional[str],\n    timeout: int,\n) -> Tuple[bool, str, str]:\n    \"\"\"POST the event to the ingestion service.\n\n    Returns:\n        (error_status, message, event_id)\n    \"\"\"\n    try:\n        headers: Dict[str, str] = {\"Content-Type\": \"application/json\"}\n        if api_key:\n            headers[\"X-API-Key\"] = api_key\n\n        response = requests.post(url, json=payload, headers=headers, timeout=timeout)\n\n        if response.status_code == 201:\n            data = response.json()\n            event_id = str(data.get(\"id\", \"\"))\n            return False, \"Event created successfully\", event_id\n\n        if response.status_code == 529:\n            detail = _extract_detail(response)\n            return (\n                True,\n                f\"Event Ingestion Service at capacity (529). \"\n                f\"The device is experiencing backpressure. Detail: {detail}\",\n                \"\",\n            )\n\n        detail = _extract_detail(response)\n        return True, f\"HTTP {response.status_code}: {detail}\", \"\"\n    except requests.exceptions.Timeout:\n        return True, f\"Request timed out after {timeout}s\", \"\"\n    except Exception as e:\n        logging.warning(f\"Event writer request failed: {e}\")\n        return True, f\"Request failed: {e}\", \"\"\n\n\ndef _extract_detail(response: requests.Response) -> str:\n    \"\"\"Try to extract 'detail' from a JSON error response.\"\"\"\n    try:\n        return str(response.json().get(\"detail\", response.text))\n    except Exception:\n        return response.text\n",
    "patch": null
  },
  {
    "trace_id": "b286ddf1-eb23-4b9f-a5bf-b2f06950bb7f",
    "function_name": "HaloVisualizationBlockV1.getAnnotator",
    "file_path": "inference/core/workflows/core_steps/visualizations/halo/v2.py",
    "speedup_x": 10.57,
    "review_quality": "high",
    "pre_optimization_commit": "HEAD",
    "resolution_method": "db_code_only",
    "source": "db_events",
    "original_function_code": "    def getAnnotator(\n        self,\n        color_palette: str,\n        palette_size: int,\n        custom_colors: List[str],\n        color_axis: str,\n        opacity: float,\n        kernel_size: int,\n    ) -> sv.annotators.base.BaseAnnotator:\n        key = \"_\".join(\n            map(\n                str,\n                [\n                    color_palette,\n                    palette_size,\n                    color_axis,\n                    opacity,\n                    kernel_size,\n                ],\n            )\n        )\n\n        if key not in self.annotatorCache:\n            palette = self.getPalette(color_palette, palette_size, custom_colors)\n\n            self.annotatorCache[key] = HaloAnnotator(\n                color=palette,\n                color_lookup=getattr(sv.ColorLookup, color_axis),\n                opacity=opacity,\n            )\n\n        return self.annotatorCache[key]",
    "optimized_function_code": "import supervision as sv\nfrom inference.core.workflows.core_steps.visualizations.common.base_colorable import ColorableVisualizationBlock\nfrom supervision import HaloAnnotator\nfrom typing import List\n\nclass HaloVisualizationBlockV1(ColorableVisualizationBlock):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.annotatorCache = {}\n\n    def getAnnotator(\n        self,\n        color_palette: str,\n        palette_size: int,\n        custom_colors: List[str],\n        color_axis: str,\n        opacity: float,\n        kernel_size: int,\n    ) -> sv.annotators.base.BaseAnnotator:\n        key = \"_\".join(\n            map(\n                str,\n                [\n                    color_palette,\n                    palette_size,\n                    color_axis,\n                    opacity,\n                    kernel_size,\n                ],\n            )\n        )\n\n        if key not in self.annotatorCache:\n            palette = self.getPalette(color_palette, palette_size, custom_colors)\n\n            self.annotatorCache[key] = HaloAnnotator(\n                color=palette,\n                color_lookup=getattr(sv.ColorLookup, color_axis),\n                opacity=opacity,\n            )\n\n        return self.annotatorCache[key]",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/visualizations/common/base_colorable.py\nfrom abc import ABC\n\nimport supervision as sv\nfrom inference.core.workflows.core_steps.visualizations.common.base import \\\n    PredictionsVisualizationBlock\nfrom inference.core.workflows.core_steps.visualizations.common.utils import \\\n    str_to_color\n\n\nclass ColorableVisualizationBlock(PredictionsVisualizationBlock, ABC):\n    @classmethod\n    def getPalette(self, color_palette, palette_size, custom_colors):\n        # Initialize caches on the class object if they don't exist.\n        # _palette_cache maps keys describing a palette -> sv.ColorPalette\n        # _color_cache maps individual color string -> sv.Color\n        if not hasattr(self, \"_palette_cache\"):\n            self._palette_cache = {}\n        if not hasattr(self, \"_color_cache\"):\n            self._color_cache = {}\n\n        # Fast path for custom palettes: cache by the exact tuple of custom_colors\n        if color_palette == \"CUSTOM\":\n            # Use tuple(custom_colors) as a stable, hashable key\n            custom_key = (\"CUSTOM\", tuple(custom_colors))\n            if custom_key in self._palette_cache:\n                return self._palette_cache[custom_key]\n\n            # Convert colors, reusing any previously converted color objects\n            converted = []\n            color_cache = self._color_cache  # local reference for repeated access\n            for color in custom_colors:\n                if color in color_cache:\n                    converted.append(color_cache[color])\n                else:\n                    cobj = str_to_color(color)\n                    color_cache[color] = cobj\n                    converted.append(cobj)\n\n            palette = sv.ColorPalette(colors=converted)\n            self._palette_cache[custom_key] = palette\n            return palette\n\n        # If palette is a predefined attribute on sv.ColorPalette, return it directly\n        if hasattr(sv.ColorPalette, color_palette):\n            return getattr(sv.ColorPalette, color_palette)\n        else:\n            palette_name = color_palette.replace(\"Matplotlib \", \"\")\n\n            if palette_name in [\n                \"Greys_R\",\n                \"Purples_R\",\n                \"Blues_R\",\n                \"Greens_R\",\n                \"Oranges_R\",\n                \"Reds_R\",\n                \"Wistia\",\n                \"Pastel1\",\n                \"Pastel2\",\n                \"Paired\",\n                \"Accent\",\n                \"Dark2\",\n                \"Set1\",\n                \"Set2\",\n                \"Set3\",\n            ]:\n                palette_name = palette_name.capitalize()\n            else:\n                palette_name = palette_name.lower()\n\n            # Cache matplotlib-derived palettes by (name, size) to avoid repeated construction\n            mpl_key = (\"MATPLOTLIB\", palette_name, int(palette_size))\n            if mpl_key in self._palette_cache:\n                return self._palette_cache[mpl_key]\n\n            palette = sv.ColorPalette.from_matplotlib(palette_name, int(palette_size))\n            self._palette_cache[mpl_key] = palette\n            return palette\n```\n```python:inference/core/workflows/core_steps/visualizations/halo/v2.py\nimport supervision as sv\nfrom inference.core.workflows.core_steps.visualizations.common.base_colorable import ColorableVisualizationBlock\nfrom supervision import HaloAnnotator\nfrom typing import List\n\nclass HaloVisualizationBlockV1(ColorableVisualizationBlock):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.annotatorCache = {}\n\n    def getAnnotator(\n        self,\n        color_palette: str,\n        palette_size: int,\n        custom_colors: List[str],\n        color_axis: str,\n        opacity: float,\n        kernel_size: int,\n    ) -> sv.annotators.base.BaseAnnotator:\n        key = \"_\".join(\n            map(\n                str,\n                [\n                    color_palette,\n                    palette_size,\n                    color_axis,\n                    opacity,\n                    kernel_size,\n                ],\n            )\n        )\n\n        if key not in self.annotatorCache:\n            palette = self.getPalette(color_palette, palette_size, custom_colors)\n\n            self.annotatorCache[key] = HaloAnnotator(\n                color=palette,\n                color_lookup=getattr(sv.ColorLookup, color_axis),\n                opacity=opacity,\n            )\n\n        return self.annotatorCache[key]\n```",
    "optimized_function_only": "    def getAnnotator(\n        self,\n        color_palette: str,\n        palette_size: int,\n        custom_colors: List[str],\n        color_axis: str,\n        opacity: float,\n        kernel_size: int,\n    ) -> sv.annotators.base.BaseAnnotator:\n        key = \"_\".join(\n            map(\n                str,\n                [\n                    color_palette,\n                    palette_size,\n                    color_axis,\n                    opacity,\n                    kernel_size,\n                ],\n            )\n        )\n\n        if key not in self.annotatorCache:\n            palette = self.getPalette(color_palette, palette_size, custom_colors)\n\n            self.annotatorCache[key] = HaloAnnotator(\n                color=palette,\n                color_lookup=getattr(sv.ColorLookup, color_axis),\n                opacity=opacity,\n            )\n\n        return self.annotatorCache[key]",
    "original_file_content": "import supervision as sv\nfrom inference.core.workflows.core_steps.visualizations.common.base_colorable import ColorableVisualizationBlock\nfrom supervision import HaloAnnotator\nfrom typing import List\n\nclass HaloVisualizationBlockV1(ColorableVisualizationBlock):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.annotatorCache = {}\n\n    def getAnnotator(\n        self,\n        color_palette: str,\n        palette_size: int,\n        custom_colors: List[str],\n        color_axis: str,\n        opacity: float,\n        kernel_size: int,\n    ) -> sv.annotators.base.BaseAnnotator:\n        key = \"_\".join(\n            map(\n                str,\n                [\n                    color_palette,\n                    palette_size,\n                    color_axis,\n                    opacity,\n                    kernel_size,\n                ],\n            )\n        )\n\n        if key not in self.annotatorCache:\n            palette = self.getPalette(color_palette, palette_size, custom_colors)\n\n            self.annotatorCache[key] = HaloAnnotator(\n                color=palette,\n                color_lookup=getattr(sv.ColorLookup, color_axis),\n                opacity=opacity,\n            )\n\n        return self.annotatorCache[key]",
    "patch": null
  },
  {
    "trace_id": "7c450cb5-caf6-41b4-809c-0f4dd70b5c8a",
    "function_name": "InferenceModelsDepthAnythingV2Adapter.predict",
    "file_path": "inference/models/depth_anything_v2/depth_anything_v2_inference_models.py",
    "speedup_x": 4.03,
    "review_quality": "high",
    "pre_optimization_commit": "7d46e2fbacd49d1b0d31ef1e4fcd8a6e72927505",
    "resolution_method": "db_code_match",
    "source": "db_events",
    "original_function_code": "    def predict(self, inputs: np.ndarray, **kwargs) -> Tuple[dict]:\n        predictions = self._model(inputs)[0]\n        depth_map = predictions.to(torch.float32).cpu().numpy()\n        # Normalize depth values\n        depth_min = depth_map.min()\n        depth_max = depth_map.max()\n        if depth_max == depth_min:\n            raise ValueError(\"Depth map has no variation (min equals max)\")\n        normalized_depth = (depth_map - depth_min) / (depth_max - depth_min)\n\n        # Create visualization\n        depth_for_viz = (normalized_depth * 255.0).astype(np.uint8)\n        cmap = plt.get_cmap(\"viridis\")\n        colored_depth = (cmap(depth_for_viz)[:, :, :3] * 255).astype(np.uint8)\n\n        # Convert numpy array to WorkflowImageData\n        parent_metadata = ImageParentMetadata(parent_id=f\"{uuid4()}\")\n        colored_depth_image = WorkflowImageData(\n            numpy_image=colored_depth, parent_metadata=parent_metadata\n        )\n        result = {\n            \"image\": colored_depth_image,\n            \"normalized_depth\": normalized_depth,\n        }\n        return (result,)\n",
    "optimized_function_code": "from typing import Tuple\nfrom uuid import uuid4\n\nimport cv2\nimport numpy as np\nimport torch\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES, API_KEY)\nfrom inference.core.models.base import Model\nfrom inference.core.models.inference_models_adapters import \\\n    get_extra_weights_provider_headers\nfrom inference.core.workflows.execution_engine.entities.base import (\n    ImageParentMetadata, WorkflowImageData)\nfrom inference_models import AutoModel\nfrom inference_models.models.depth_anything_v2.depth_anything_v2_hf import \\\n    DepthAnythingV2HF\n\n\nclass InferenceModelsDepthAnythingV2Adapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n\n        self.task_type = \"depth-estimation\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers()\n\n        self._model: DepthAnythingV2HF = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            extra_weights_provider_headers=extra_weights_provider_headers,\n            **kwargs,\n        )\n\n    def predict(self, inputs: np.ndarray, **kwargs) -> Tuple[dict]:\n        predictions = self._model(inputs)[0]\n        depth_map = predictions.to(torch.float32).cpu().numpy()\n        # Normalize depth values\n        depth_min = depth_map.min()\n        depth_max = depth_map.max()\n        if depth_max == depth_min:\n            raise ValueError(\"Depth map has no variation (min equals max)\")\n        normalized_depth = (depth_map - depth_min) / (depth_max - depth_min)\n\n        # Create visualization\n        depth_for_viz = (normalized_depth * 255.0).astype(np.uint8)\n        colored_depth = cv2.applyColorMap(depth_for_viz, cv2.COLORMAP_VIRIDIS)\n        colored_depth = cv2.cvtColor(colored_depth, cv2.COLOR_BGR2RGB)\n\n        # Convert numpy array to WorkflowImageData\n\n        # Convert numpy array to WorkflowImageData\n        parent_metadata = ImageParentMetadata(parent_id=f\"{uuid4()}\")\n        colored_depth_image = WorkflowImageData(\n            numpy_image=colored_depth, parent_metadata=parent_metadata\n        )\n        result = {\n            \"image\": colored_depth_image,\n            \"normalized_depth\": normalized_depth,\n        }\n        return (result,)",
    "optimized_raw_markdown": "```python:inference/models/depth_anything_v2/depth_anything_v2_inference_models.py\nfrom typing import Tuple\nfrom uuid import uuid4\n\nimport cv2\nimport numpy as np\nimport torch\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES, API_KEY)\nfrom inference.core.models.base import Model\nfrom inference.core.models.inference_models_adapters import \\\n    get_extra_weights_provider_headers\nfrom inference.core.workflows.execution_engine.entities.base import (\n    ImageParentMetadata, WorkflowImageData)\nfrom inference_models import AutoModel\nfrom inference_models.models.depth_anything_v2.depth_anything_v2_hf import \\\n    DepthAnythingV2HF\n\n\nclass InferenceModelsDepthAnythingV2Adapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n\n        self.task_type = \"depth-estimation\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers()\n\n        self._model: DepthAnythingV2HF = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            extra_weights_provider_headers=extra_weights_provider_headers,\n            **kwargs,\n        )\n\n    def predict(self, inputs: np.ndarray, **kwargs) -> Tuple[dict]:\n        predictions = self._model(inputs)[0]\n        depth_map = predictions.to(torch.float32).cpu().numpy()\n        # Normalize depth values\n        depth_min = depth_map.min()\n        depth_max = depth_map.max()\n        if depth_max == depth_min:\n            raise ValueError(\"Depth map has no variation (min equals max)\")\n        normalized_depth = (depth_map - depth_min) / (depth_max - depth_min)\n\n        # Create visualization\n        depth_for_viz = (normalized_depth * 255.0).astype(np.uint8)\n        colored_depth = cv2.applyColorMap(depth_for_viz, cv2.COLORMAP_VIRIDIS)\n        colored_depth = cv2.cvtColor(colored_depth, cv2.COLOR_BGR2RGB)\n\n        # Convert numpy array to WorkflowImageData\n\n        # Convert numpy array to WorkflowImageData\n        parent_metadata = ImageParentMetadata(parent_id=f\"{uuid4()}\")\n        colored_depth_image = WorkflowImageData(\n            numpy_image=colored_depth, parent_metadata=parent_metadata\n        )\n        result = {\n            \"image\": colored_depth_image,\n            \"normalized_depth\": normalized_depth,\n        }\n        return (result,)\n```",
    "optimized_function_only": "    def predict(self, inputs: np.ndarray, **kwargs) -> Tuple[dict]:\n        predictions = self._model(inputs)[0]\n        depth_map = predictions.to(torch.float32).cpu().numpy()\n        # Normalize depth values\n        depth_min = depth_map.min()\n        depth_max = depth_map.max()\n        if depth_max == depth_min:\n            raise ValueError(\"Depth map has no variation (min equals max)\")\n        normalized_depth = (depth_map - depth_min) / (depth_max - depth_min)\n\n        # Create visualization\n        depth_for_viz = (normalized_depth * 255.0).astype(np.uint8)\n        colored_depth = cv2.applyColorMap(depth_for_viz, cv2.COLORMAP_VIRIDIS)\n        colored_depth = cv2.cvtColor(colored_depth, cv2.COLOR_BGR2RGB)\n\n        # Convert numpy array to WorkflowImageData\n\n        # Convert numpy array to WorkflowImageData\n        parent_metadata = ImageParentMetadata(parent_id=f\"{uuid4()}\")\n        colored_depth_image = WorkflowImageData(\n            numpy_image=colored_depth, parent_metadata=parent_metadata\n        )\n        result = {\n            \"image\": colored_depth_image,\n            \"normalized_depth\": normalized_depth,\n        }\n        return (result,)",
    "original_file_content": "from typing import Any, List, Tuple\nfrom uuid import uuid4\n\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport torch\n\nfrom inference.core.entities.responses import (\n    InferenceResponseImage,\n    LMMInferenceResponse,\n)\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n    API_KEY,\n)\nfrom inference.core.models.base import Model\nfrom inference.core.models.inference_models_adapters import (\n    get_extra_weights_provider_headers,\n)\nfrom inference.core.models.types import PreprocessReturnMetadata\nfrom inference.core.utils.image_utils import load_image_bgr\nfrom inference.core.workflows.execution_engine.entities.base import (\n    ImageParentMetadata,\n    WorkflowImageData,\n)\nfrom inference_models import AutoModel\nfrom inference_models.models.depth_anything_v2.depth_anything_v2_hf import (\n    DepthAnythingV2HF,\n)\n\n\nclass InferenceModelsDepthAnythingV2Adapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n\n        self.task_type = \"depth-estimation\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers()\n\n        self._model: DepthAnythingV2HF = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            extra_weights_provider_headers=extra_weights_provider_headers,\n            **kwargs,\n        )\n\n    def preprocess(self, image: Any, **kwargs):\n        if isinstance(image, list):\n            raise ValueError(\"DepthAnythingV2 does not support batched inference.\")\n\n        np_image = load_image_bgr(\n            image,\n            disable_preproc_auto_orient=kwargs.get(\n                \"disable_preproc_auto_orient\", False\n            ),\n        )\n        return np_image, PreprocessReturnMetadata(\n            {\"image_dims\": (np_image.shape[1], np_image.shape[0])}\n        )\n\n    def predict(self, inputs: np.ndarray, **kwargs) -> Tuple[dict]:\n        predictions = self._model(inputs)[0]\n        depth_map = predictions.to(torch.float32).cpu().numpy()\n        # Normalize depth values\n        depth_min = depth_map.min()\n        depth_max = depth_map.max()\n        if depth_max == depth_min:\n            raise ValueError(\"Depth map has no variation (min equals max)\")\n        normalized_depth = (depth_map - depth_min) / (depth_max - depth_min)\n\n        # Create visualization\n        depth_for_viz = (normalized_depth * 255.0).astype(np.uint8)\n        cmap = plt.get_cmap(\"viridis\")\n        colored_depth = (cmap(depth_for_viz)[:, :, :3] * 255).astype(np.uint8)\n\n        # Convert numpy array to WorkflowImageData\n        parent_metadata = ImageParentMetadata(parent_id=f\"{uuid4()}\")\n        colored_depth_image = WorkflowImageData(\n            numpy_image=colored_depth, parent_metadata=parent_metadata\n        )\n        result = {\n            \"image\": colored_depth_image,\n            \"normalized_depth\": normalized_depth,\n        }\n        return (result,)\n\n    def postprocess(\n        self,\n        predictions: torch.Tensor,\n        preprocess_return_metadata: PreprocessReturnMetadata,\n        **kwargs,\n    ) -> List[LMMInferenceResponse]:\n        text = predictions[0]\n        image_dims = preprocess_return_metadata[\"image_dims\"]\n        response = LMMInferenceResponse(\n            response=text,\n            image=InferenceResponseImage(width=image_dims[0], height=image_dims[1]),\n        )\n        return [response]\n\n    def clear_cache(self, delete_from_disk: bool = True) -> None:\n        \"\"\"Clears any cache if necessary. TODO: Implement this to delete the cache from the experimental model.\n\n        Args:\n            delete_from_disk (bool, optional): Whether to delete cached files from disk. Defaults to True.\n        \"\"\"\n        pass\n",
    "patch": null
  },
  {
    "trace_id": "9215f881-deaa-4cde-96d1-f35e9d5a37be",
    "function_name": "_should_filter_block",
    "file_path": "inference/core/workflows/core_steps/loader.py",
    "speedup_x": 3.93,
    "review_quality": "high",
    "pre_optimization_commit": "HEAD",
    "resolution_method": "db_code_only",
    "source": "db_events",
    "original_function_code": "def _should_filter_block(block_class: Type[WorkflowBlock]) -> bool:\n    \"\"\"\n    Check if a block should be filtered out based on configuration.\n    \n    Returns True if the block should be filtered (removed), False if it should be kept.\n    \"\"\"\n    if not WORKFLOW_SELECTIVE_BLOCKS_DISABLE:\n        return False\n    \n    try:\n        # Get block manifest to check block type\n        manifest_class = block_class.get_manifest()\n        schema = manifest_class.model_json_schema()\n        json_schema_extra = schema.get(\"json_schema_extra\", {})\n        block_type = json_schema_extra.get(\"block_type\", \"\")\n        \n        # Check if block type category is disabled\n        if block_type and block_type.lower() in WORKFLOW_DISABLED_BLOCK_TYPES:\n            return True\n        \n        # Get the block identifier for pattern matching\n        # We'll check multiple identifiers to be thorough:\n        # 1. The block class name\n        # 2. The full module path\n        # 3. The block name from schema if available\n        block_class_name = block_class.__name__.lower()\n        block_module = block_class.__module__.lower()\n        block_name = json_schema_extra.get(\"name\", \"\").lower()\n        \n        # Check patterns against various identifiers\n        for pattern in WORKFLOW_DISABLED_BLOCK_PATTERNS:\n            pattern_lower = pattern.lower()\n            if (pattern_lower in block_class_name or \n                pattern_lower in block_module or\n                pattern_lower in block_name):\n                return True\n                \n    except Exception:\n        # If we can't determine block info, don't filter it\n        # This ensures we don't accidentally filter blocks due to errors\n        pass\n    \n    return False",
    "optimized_function_code": "from typing import Type\n\nfrom inference.core.env import (WORKFLOW_DISABLED_BLOCK_PATTERNS,\n                                WORKFLOW_DISABLED_BLOCK_TYPES,\n                                WORKFLOW_SELECTIVE_BLOCKS_DISABLE)\nfrom inference.core.workflows.prototypes.block import WorkflowBlock\n\n\ndef _should_filter_block(block_class: Type[WorkflowBlock]) -> bool:\n    \"\"\"\n    Check if a block should be filtered out based on configuration.\n    \n    Returns True if the block should be filtered (removed), False if it should be kept.\n    \"\"\"\n    if not WORKFLOW_SELECTIVE_BLOCKS_DISABLE:\n        return False\n    \n\n    # If there are no configured disabled types or patterns, nothing to do.\n    if not WORKFLOW_DISABLED_BLOCK_PATTERNS and not WORKFLOW_DISABLED_BLOCK_TYPES:\n        return False\n\n    # Compute inexpensive identifiers first to avoid calling manifest when possible\n    block_class_name = block_class.__name__.lower()\n    block_module = block_class.__module__.lower()\n\n    patterns = WORKFLOW_DISABLED_BLOCK_PATTERNS\n    disabled_types = WORKFLOW_DISABLED_BLOCK_TYPES\n\n    # Precompute lowered patterns once to avoid repeated .lower() in loops.\n    patterns_lower = [p.lower() for p in patterns] if patterns else []\n\n    # Check patterns against class name and module first (cheap checks).\n    for pattern_lower in patterns_lower:\n        if pattern_lower in block_class_name or pattern_lower in block_module:\n            return True\n\n    # If we still haven't decided and there are no type filters and no pattern\n    # checks that require manifest name, we can return False early.\n    if not disabled_types and not patterns:\n        return False\n\n    # Need manifest (expensive). Wrap only this part in try/except to preserve original behavior.\n    try:\n        # Get block manifest to check block type\n        manifest_class = block_class.get_manifest()\n        schema = manifest_class.model_json_schema()\n        json_schema_extra = schema.get(\"json_schema_extra\", {})\n        block_type = json_schema_extra.get(\"block_type\", \"\")\n\n        # Check if block type category is disabled\n        if block_type and disabled_types:\n            disabled_types_lower = {t.lower() for t in disabled_types}\n            if block_type.lower() in disabled_types_lower:\n                return True\n                \n\n        # Check pattern against manifest \"name\" if available and patterns exist\n        if patterns_lower:\n            block_name = json_schema_extra.get(\"name\", \"\")\n            if block_name:\n                block_name_lower = block_name.lower()\n                for pattern_lower in patterns_lower:\n                    if pattern_lower in block_name_lower:\n                        return True\n\n    except Exception:\n        # If we can't determine block info, don't filter it\n        # This ensures we don't accidentally filter blocks due to errors\n        pass\n    \n    return False",
    "optimized_raw_markdown": "```python:inference/core/workflows/prototypes/block.py\nfrom abc import ABC, abstractmethod\nfrom inference.core.workflows.errors import BlockInterfaceError\nfrom typing import Type\n\nclass WorkflowBlock(ABC):\n\n    @classmethod\n    @abstractmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        raise BlockInterfaceError(\n            public_message=\"Class method `get_manifest()` must be implemented for any entity \"\n            \"deriving from WorkflowBlockManifest.\",\n            context=\"getting_block_manifest\",\n        )\n```\n```python:inference/core/workflows/core_steps/loader.py\nfrom typing import Type\n\nfrom inference.core.env import (WORKFLOW_DISABLED_BLOCK_PATTERNS,\n                                WORKFLOW_DISABLED_BLOCK_TYPES,\n                                WORKFLOW_SELECTIVE_BLOCKS_DISABLE)\nfrom inference.core.workflows.prototypes.block import WorkflowBlock\n\n\ndef _should_filter_block(block_class: Type[WorkflowBlock]) -> bool:\n    \"\"\"\n    Check if a block should be filtered out based on configuration.\n    \n    Returns True if the block should be filtered (removed), False if it should be kept.\n    \"\"\"\n    if not WORKFLOW_SELECTIVE_BLOCKS_DISABLE:\n        return False\n    \n\n    # If there are no configured disabled types or patterns, nothing to do.\n    if not WORKFLOW_DISABLED_BLOCK_PATTERNS and not WORKFLOW_DISABLED_BLOCK_TYPES:\n        return False\n\n    # Compute inexpensive identifiers first to avoid calling manifest when possible\n    block_class_name = block_class.__name__.lower()\n    block_module = block_class.__module__.lower()\n\n    patterns = WORKFLOW_DISABLED_BLOCK_PATTERNS\n    disabled_types = WORKFLOW_DISABLED_BLOCK_TYPES\n\n    # Precompute lowered patterns once to avoid repeated .lower() in loops.\n    patterns_lower = [p.lower() for p in patterns] if patterns else []\n\n    # Check patterns against class name and module first (cheap checks).\n    for pattern_lower in patterns_lower:\n        if pattern_lower in block_class_name or pattern_lower in block_module:\n            return True\n\n    # If we still haven't decided and there are no type filters and no pattern\n    # checks that require manifest name, we can return False early.\n    if not disabled_types and not patterns:\n        return False\n\n    # Need manifest (expensive). Wrap only this part in try/except to preserve original behavior.\n    try:\n        # Get block manifest to check block type\n        manifest_class = block_class.get_manifest()\n        schema = manifest_class.model_json_schema()\n        json_schema_extra = schema.get(\"json_schema_extra\", {})\n        block_type = json_schema_extra.get(\"block_type\", \"\")\n\n        # Check if block type category is disabled\n        if block_type and disabled_types:\n            disabled_types_lower = {t.lower() for t in disabled_types}\n            if block_type.lower() in disabled_types_lower:\n                return True\n                \n\n        # Check pattern against manifest \"name\" if available and patterns exist\n        if patterns_lower:\n            block_name = json_schema_extra.get(\"name\", \"\")\n            if block_name:\n                block_name_lower = block_name.lower()\n                for pattern_lower in patterns_lower:\n                    if pattern_lower in block_name_lower:\n                        return True\n\n    except Exception:\n        # If we can't determine block info, don't filter it\n        # This ensures we don't accidentally filter blocks due to errors\n        pass\n    \n    return False\n```",
    "optimized_function_only": "def _should_filter_block(block_class: Type[WorkflowBlock]) -> bool:\n    \"\"\"\n    Check if a block should be filtered out based on configuration.\n    \n    Returns True if the block should be filtered (removed), False if it should be kept.\n    \"\"\"\n    if not WORKFLOW_SELECTIVE_BLOCKS_DISABLE:\n        return False\n    \n\n    # If there are no configured disabled types or patterns, nothing to do.\n    if not WORKFLOW_DISABLED_BLOCK_PATTERNS and not WORKFLOW_DISABLED_BLOCK_TYPES:\n        return False\n\n    # Compute inexpensive identifiers first to avoid calling manifest when possible\n    block_class_name = block_class.__name__.lower()\n    block_module = block_class.__module__.lower()\n\n    patterns = WORKFLOW_DISABLED_BLOCK_PATTERNS\n    disabled_types = WORKFLOW_DISABLED_BLOCK_TYPES\n\n    # Precompute lowered patterns once to avoid repeated .lower() in loops.\n    patterns_lower = [p.lower() for p in patterns] if patterns else []\n\n    # Check patterns against class name and module first (cheap checks).\n    for pattern_lower in patterns_lower:\n        if pattern_lower in block_class_name or pattern_lower in block_module:\n            return True\n\n    # If we still haven't decided and there are no type filters and no pattern\n    # checks that require manifest name, we can return False early.\n    if not disabled_types and not patterns:\n        return False\n\n    # Need manifest (expensive). Wrap only this part in try/except to preserve original behavior.\n    try:\n        # Get block manifest to check block type\n        manifest_class = block_class.get_manifest()\n        schema = manifest_class.model_json_schema()\n        json_schema_extra = schema.get(\"json_schema_extra\", {})\n        block_type = json_schema_extra.get(\"block_type\", \"\")\n\n        # Check if block type category is disabled\n        if block_type and disabled_types:\n            disabled_types_lower = {t.lower() for t in disabled_types}\n            if block_type.lower() in disabled_types_lower:\n                return True\n                \n\n        # Check pattern against manifest \"name\" if available and patterns exist\n        if patterns_lower:\n            block_name = json_schema_extra.get(\"name\", \"\")\n            if block_name:\n                block_name_lower = block_name.lower()\n                for pattern_lower in patterns_lower:\n                    if pattern_lower in block_name_lower:\n                        return True\n\n    except Exception:\n        # If we can't determine block info, don't filter it\n        # This ensures we don't accidentally filter blocks due to errors\n        pass\n    \n    return False",
    "original_file_content": "from inference.core.env import WORKFLOW_DISABLED_BLOCK_PATTERNS, WORKFLOW_DISABLED_BLOCK_TYPES, WORKFLOW_SELECTIVE_BLOCKS_DISABLE\nfrom inference.core.workflows.prototypes.block import WorkflowBlock\nfrom typing import Type\n\ndef _should_filter_block(block_class: Type[WorkflowBlock]) -> bool:\n    \"\"\"\n    Check if a block should be filtered out based on configuration.\n    \n    Returns True if the block should be filtered (removed), False if it should be kept.\n    \"\"\"\n    if not WORKFLOW_SELECTIVE_BLOCKS_DISABLE:\n        return False\n    \n    try:\n        # Get block manifest to check block type\n        manifest_class = block_class.get_manifest()\n        schema = manifest_class.model_json_schema()\n        json_schema_extra = schema.get(\"json_schema_extra\", {})\n        block_type = json_schema_extra.get(\"block_type\", \"\")\n        \n        # Check if block type category is disabled\n        if block_type and block_type.lower() in WORKFLOW_DISABLED_BLOCK_TYPES:\n            return True\n        \n        # Get the block identifier for pattern matching\n        # We'll check multiple identifiers to be thorough:\n        # 1. The block class name\n        # 2. The full module path\n        # 3. The block name from schema if available\n        block_class_name = block_class.__name__.lower()\n        block_module = block_class.__module__.lower()\n        block_name = json_schema_extra.get(\"name\", \"\").lower()\n        \n        # Check patterns against various identifiers\n        for pattern in WORKFLOW_DISABLED_BLOCK_PATTERNS:\n            pattern_lower = pattern.lower()\n            if (pattern_lower in block_class_name or \n                pattern_lower in block_module or\n                pattern_lower in block_name):\n                return True\n                \n    except Exception:\n        # If we can't determine block info, don't filter it\n        # This ensures we don't accidentally filter blocks due to errors\n        pass\n    \n    return False",
    "patch": null
  },
  {
    "trace_id": "2ff1f9c1-0d7b-481a-a5b6-51c00b4eb519",
    "function_name": "DetectionEventLogBlockV1.run",
    "file_path": "inference/core/workflows/core_steps/analytics/detection_event_log/v1.py",
    "speedup_x": 2.4,
    "review_quality": "high",
    "pre_optimization_commit": "10079df8d89971ef2493e294d6d7d99038802b5e",
    "resolution_method": "db_code_match",
    "source": "db_events",
    "original_function_code": "    def run(\n        self,\n        image: WorkflowImageData,\n        detections: sv.Detections,\n        frame_threshold: int,\n        flush_interval: int,\n        stale_frames: int,\n        fallback_fps: float = 1.0,\n        reference_timestamp: Optional[float] = None,\n    ) -> BlockResult:\n        \"\"\"Process detections and update the event log.\n\n        Args:\n            image: Workflow image data containing video metadata.\n            detections: Tracked detections with tracker_id from ByteTracker.\n            frame_threshold: Minimum frames an object must be seen before logging.\n            flush_interval: How often to run stale event cleanup.\n            stale_frames: Remove events not seen for this many frames.\n            fallback_fps: FPS to use when video metadata doesn't provide FPS.\n            reference_timestamp: Unused, kept for backward compatibility.\n\n        Returns:\n            Dictionary containing event_log, detections, total_logged, and total_pending.\n        \"\"\"\n        metadata = image.video_metadata\n        video_id = metadata.video_identifier\n\n        # Track global frame count and video access for eviction\n        self._global_frame += 1\n        self._last_access[video_id] = self._global_frame\n\n        # Increment internal frame counter\n        current_frame = self._frame_count.get(video_id, 0) + 1\n        self._frame_count[video_id] = current_frame\n\n        current_time = self._get_relative_time(\n            video_id, current_frame, metadata, fallback_fps\n        )\n\n        # Use frame_timestamp for absolute time when available (reflects actual capture\n        # time, not inference processing time). Falls back to time.time().\n        current_absolute_time = (\n            metadata.frame_timestamp.timestamp()\n            if metadata.frame_timestamp is not None\n            else time.time()\n        )\n\n        # Initialize event log for this video if needed\n        event_log = self._event_logs.setdefault(video_id, {})\n\n        # Evict oldest video if we've exceeded MAX_VIDEOS (after adding current video)\n        self._evict_oldest_video()\n\n        # Initialize last flush frame if not set\n        if video_id not in self._last_flush_frame:\n            self._last_flush_frame[video_id] = current_frame\n\n        # Check if it's time to run cleanup\n        complete_events_list = []\n        last_flush = self._last_flush_frame.get(video_id, 0)\n        if (current_frame - last_flush) >= flush_interval:\n            complete_events_list = self._remove_stale_events(\n                event_log, current_frame, stale_frames, frame_threshold\n            )\n            self._last_flush_frame[video_id] = current_frame\n\n        # Format complete events\n        complete_events = self._format_complete_events(complete_events_list)\n\n        # Process detections\n        if detections.tracker_id is None or len(detections.tracker_id) == 0:\n            # No tracked detections, return current log\n            event_log_dict, total_logged, total_pending = self._format_event_log(\n                event_log, frame_threshold\n            )\n            return {\n                OUTPUT_KEY: event_log_dict,\n                DETECTIONS_OUTPUT_KEY: detections,\n                \"total_logged\": total_logged,\n                \"total_pending\": total_pending,\n                \"complete_events\": complete_events,\n            }\n\n        # Get class names\n        class_names = detections.data.get(\"class_name\", [])\n        if (\n            len(class_names) == 0\n            and hasattr(detections, \"class_id\")\n            and detections.class_id is not None\n        ):\n            class_names = [f\"class_{cid}\" for cid in detections.class_id]\n\n        # Update event log for each tracked detection\n        for i, tracker_id in enumerate(detections.tracker_id):\n            tracker_id = int(tracker_id)\n            class_name = str(class_names[i]) if len(class_names) > 0 else \"unknown\"\n\n            if tracker_id in event_log:\n                # Update existing event\n                event = event_log[tracker_id]\n                event.last_seen_frame = current_frame\n                event.last_seen_timestamp = current_absolute_time\n                event.last_seen_relative = current_time\n                event.frame_count += 1\n\n                # Mark as logged once threshold is reached\n                if event.frame_count >= frame_threshold and not event.logged:\n                    event.logged = True\n                    logger.debug(\n                        f\"Object {tracker_id} ({event.class_name}) logged after {event.frame_count} frames\"\n                    )\n            else:\n                # Create new event\n                event_log[tracker_id] = DetectionEvent(\n                    tracker_id=tracker_id,\n                    class_name=class_name,\n                    first_seen_frame=current_frame,\n                    first_seen_timestamp=current_absolute_time,\n                    last_seen_frame=current_frame,\n                    last_seen_timestamp=current_absolute_time,\n                    first_seen_relative=current_time,\n                    last_seen_relative=current_time,\n                    frame_count=1,\n                    logged=False,\n                )\n\n        event_log_dict, total_logged, total_pending = self._format_event_log(\n            event_log, frame_threshold\n        )\n        return {\n            OUTPUT_KEY: event_log_dict,\n            DETECTIONS_OUTPUT_KEY: detections,\n            \"total_logged\": total_logged,\n            \"total_pending\": total_pending,\n            \"complete_events\": complete_events,\n        }\n",
    "optimized_function_code": "import time\nimport supervision as sv\nfrom dataclasses import dataclass\nfrom inference.core import logger\nfrom inference.core.workflows.execution_engine.entities.base import VideoMetadata, WorkflowImageData\nfrom inference.core.workflows.prototypes.block import BlockResult, WorkflowBlock\nfrom typing import Any, Dict, List, Optional\n\nOUTPUT_KEY = \"event_log\"\nDETECTIONS_OUTPUT_KEY = \"detections\"\nMAX_VIDEOS = 100  # Maximum number of video streams to track before evicting oldest\n\n\n@dataclass\nclass DetectionEvent:\n    \"\"\"Stores event data for a tracked detection.\"\"\"\n\n    tracker_id: int\n    class_name: str\n    first_seen_frame: int\n    first_seen_timestamp: float  # Unix wall-clock time (frame_timestamp or time.time())\n    last_seen_frame: int\n    last_seen_timestamp: float  # Unix wall-clock time (frame_timestamp or time.time())\n    first_seen_relative: float = 0.0  # seconds since video start\n    last_seen_relative: float = 0.0  # seconds since video start\n    frame_count: int = 1\n    logged: bool = False\n\n\nclass DetectionEventLogBlockV1(WorkflowBlock):\n\n    def __init__(self):\n        # Dict[video_id, Dict[tracker_id, DetectionEvent]]\n        self._event_logs: Dict[str, Dict[int, DetectionEvent]] = {}\n        # Dict[video_id, last_flush_frame]\n        self._last_flush_frame: Dict[str, int] = {}\n        # Dict[video_id, frame_count] - internal frame counter (increments each run)\n        self._frame_count: Dict[str, int] = {}\n        # Dict[video_id, last_access_frame] - tracks when each video was last accessed (global frame count)\n        self._last_access: Dict[str, int] = {}\n        # Dict[video_id, first_frame_timestamp] - stores the first frame's wall-clock timestamp\n        # Used as the anchor for frame_timestamp-based relative time calculation\n        self._first_frame_timestamps: Dict[str, float] = {}\n        # Global frame counter for tracking video access order\n        self._global_frame: int = 0\n\n    def _get_relative_time(\n        self,\n        video_id: str,\n        current_frame: int,\n        metadata: VideoMetadata,\n        fallback_fps: float,\n    ) -> float:\n        \"\"\"Calculate relative time in seconds since video started.\n\n        Uses frame_timestamp from metadata when available for accurate timing,\n        even when inference doesn't run at the camera's reported FPS (e.g. due\n        to dropped frames or processing lag). Falls back to internal frame\n        counter / FPS when frame_timestamp is not available.\n        \"\"\"\n        if metadata.frame_timestamp is not None:\n            frame_ts = metadata.frame_timestamp.timestamp()\n            if video_id not in self._first_frame_timestamps:\n                self._first_frame_timestamps[video_id] = frame_ts\n            return frame_ts - self._first_frame_timestamps[video_id]\n\n        # Fallback: use internal frame counter and FPS\n        fps = metadata.fps if metadata.fps and metadata.fps != 0 else fallback_fps\n        return (current_frame - 1) / fps\n\n    def _evict_oldest_video(self) -> None:\n        \"\"\"Remove the oldest video stream data when MAX_VIDEOS is exceeded.\"\"\"\n        if len(self._event_logs) <= MAX_VIDEOS:\n            return\n\n        # Find the video with the oldest last access time\n        oldest_video_id = min(self._last_access, key=self._last_access.get)\n\n        # Remove all data for this video\n        self._event_logs.pop(oldest_video_id, None)\n        self._last_flush_frame.pop(oldest_video_id, None)\n        self._frame_count.pop(oldest_video_id, None)\n        self._last_access.pop(oldest_video_id, None)\n        self._first_frame_timestamps.pop(oldest_video_id, None)\n\n    def _remove_stale_events(\n        self,\n        event_log: Dict[int, DetectionEvent],\n        current_frame: int,\n        stale_frames: int,\n        frame_threshold: int,\n    ) -> List[DetectionEvent]:\n        \"\"\"Remove events that haven't been seen for stale_frames.\n\n        Returns list of removed LOGGED events (events that met frame_threshold).\n        These are \"complete\" events - objects that were tracked long enough\n        to be logged and have now left the scene.\n        \"\"\"\n        stale_tracker_ids = []\n        complete_events = []\n\n        for tracker_id, event in event_log.items():\n            frames_since_seen = current_frame - event.last_seen_frame\n            if frames_since_seen > stale_frames:\n                stale_tracker_ids.append(tracker_id)\n                # Only return logged events as \"complete\" - pending events are just discarded\n                if event.frame_count >= frame_threshold:\n                    complete_events.append(event)\n\n        for tracker_id in stale_tracker_ids:\n            del event_log[tracker_id]\n\n        return complete_events\n\n    def run(\n        self,\n        image: WorkflowImageData,\n        detections: sv.Detections,\n        frame_threshold: int,\n        flush_interval: int,\n        stale_frames: int,\n        fallback_fps: float = 1.0,\n        reference_timestamp: Optional[float] = None,\n    ) -> BlockResult:\n        \"\"\"Process detections and update the event log.\n\n        Args:\n            image: Workflow image data containing video metadata.\n            detections: Tracked detections with tracker_id from ByteTracker.\n            frame_threshold: Minimum frames an object must be seen before logging.\n            flush_interval: How often to run stale event cleanup.\n            stale_frames: Remove events not seen for this many frames.\n            fallback_fps: FPS to use when video metadata doesn't provide FPS.\n            reference_timestamp: Unused, kept for backward compatibility.\n\n        Returns:\n            Dictionary containing event_log, detections, total_logged, and total_pending.\n        \"\"\"\n        metadata = image.video_metadata\n        video_id = metadata.video_identifier\n\n        # Track global frame count and video access for eviction\n        self._global_frame += 1\n        self._last_access[video_id] = self._global_frame\n\n        # Increment internal frame counter\n        current_frame = self._frame_count.get(video_id, 0) + 1\n        self._frame_count[video_id] = current_frame\n\n        current_time = self._get_relative_time(\n            video_id, current_frame, metadata, fallback_fps\n        )\n\n        # Use frame_timestamp for absolute time when available (reflects actual capture\n        # time, not inference processing time). Falls back to time.time().\n        current_absolute_time = (\n            metadata.frame_timestamp.timestamp()\n            if metadata.frame_timestamp is not None\n            else time.time()\n        )\n\n        # Initialize event log for this video if needed\n        event_log = self._event_logs.setdefault(video_id, {})\n\n        # Evict oldest video if we've exceeded MAX_VIDEOS (after adding current video)\n        self._evict_oldest_video()\n\n        # Initialize last flush frame if not set\n        if video_id not in self._last_flush_frame:\n            self._last_flush_frame[video_id] = current_frame\n\n        # Check if it's time to run cleanup\n        complete_events_list = []\n        last_flush = self._last_flush_frame.get(video_id, 0)\n        if (current_frame - last_flush) >= flush_interval:\n            complete_events_list = self._remove_stale_events(\n                event_log, current_frame, stale_frames, frame_threshold\n            )\n            self._last_flush_frame[video_id] = current_frame\n\n        # Format complete events\n        complete_events = self._format_complete_events(complete_events_list)\n\n        # Process detections\n        if detections.tracker_id is None or len(detections.tracker_id) == 0:\n            # No tracked detections, return current log\n            event_log_dict, total_logged, total_pending = self._format_event_log(\n                event_log, frame_threshold\n            )\n            return {\n                OUTPUT_KEY: event_log_dict,\n                DETECTIONS_OUTPUT_KEY: detections,\n                \"total_logged\": total_logged,\n                \"total_pending\": total_pending,\n                \"complete_events\": complete_events,\n            }\n\n        # Get class names\n        class_names = detections.data.get(\"class_name\", [])\n        if (\n            len(class_names) == 0\n            and hasattr(detections, \"class_id\")\n            and detections.class_id is not None\n        ):\n            class_names = [f\"class_{cid}\" for cid in detections.class_id]\n\n        # Update event log for each tracked detection\n        for i, tracker_id in enumerate(detections.tracker_id):\n            tracker_id = int(tracker_id)\n            class_name = str(class_names[i]) if len(class_names) > 0 else \"unknown\"\n\n            if tracker_id in event_log:\n                # Update existing event\n                event = event_log[tracker_id]\n                event.last_seen_frame = current_frame\n                event.last_seen_timestamp = current_absolute_time\n                event.last_seen_relative = current_time\n                event.frame_count += 1\n\n                # Mark as logged once threshold is reached\n                if event.frame_count >= frame_threshold and not event.logged:\n                    event.logged = True\n                    logger.debug(\n                        f\"Object {tracker_id} ({event.class_name}) logged after {event.frame_count} frames\"\n                    )\n            else:\n                # Create new event\n                event_log[tracker_id] = DetectionEvent(\n                    tracker_id=tracker_id,\n                    class_name=class_name,\n                    first_seen_frame=current_frame,\n                    first_seen_timestamp=current_absolute_time,\n                    last_seen_frame=current_frame,\n                    last_seen_timestamp=current_absolute_time,\n                    first_seen_relative=current_time,\n                    last_seen_relative=current_time,\n                    frame_count=1,\n                    logged=False,\n                )\n\n        event_log_dict, total_logged, total_pending = self._format_event_log(\n            event_log, frame_threshold\n        )\n        return {\n            OUTPUT_KEY: event_log_dict,\n            DETECTIONS_OUTPUT_KEY: detections,\n            \"total_logged\": total_logged,\n            \"total_pending\": total_pending,\n            \"complete_events\": complete_events,\n        }\n\n    def _format_complete_events(\n        self,\n        complete_events: List[DetectionEvent],\n    ) -> Dict[str, Any]:\n        \"\"\"Format complete events for output.\n\n        Args:\n            complete_events: List of DetectionEvent objects that have completed (gone stale).\n\n        Returns:\n            Dictionary with tracker_id as key and event data as value.\n        \"\"\"\n        formatted = {}\n        for event in complete_events:\n            event_data = event.__dict__.copy()\n            del event_data[\"logged\"]\n            formatted[str(event.tracker_id)] = event_data\n\n        return formatted\n\n    def _format_event_log(\n        self,\n        event_log: Dict[int, DetectionEvent],\n        frame_threshold: int,\n    ) -> tuple:\n        \"\"\"Format the event log for output.\n\n        Returns:\n            Tuple of (event_log_dict, total_logged, total_pending)\n        \"\"\"\n        logged_events = {}\n        pending_events = {}\n\n        for tracker_id, event in event_log.items():\n            event_data = event.__dict__.copy()\n            del event_data[\"logged\"]\n\n            if event.frame_count >= frame_threshold:\n                logged_events[str(tracker_id)] = event_data\n            else:\n                pending_events[str(tracker_id)] = event_data\n\n        event_log_dict = {\n            \"logged\": logged_events,\n            \"pending\": pending_events,\n        }\n\n        return event_log_dict, len(logged_events), len(pending_events)",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/analytics/detection_event_log/v1.py\nimport time\nimport supervision as sv\nfrom dataclasses import dataclass\nfrom inference.core import logger\nfrom inference.core.workflows.execution_engine.entities.base import VideoMetadata, WorkflowImageData\nfrom inference.core.workflows.prototypes.block import BlockResult, WorkflowBlock\nfrom typing import Any, Dict, List, Optional\n\nOUTPUT_KEY = \"event_log\"\nDETECTIONS_OUTPUT_KEY = \"detections\"\nMAX_VIDEOS = 100  # Maximum number of video streams to track before evicting oldest\n\n\n@dataclass\nclass DetectionEvent:\n    \"\"\"Stores event data for a tracked detection.\"\"\"\n\n    tracker_id: int\n    class_name: str\n    first_seen_frame: int\n    first_seen_timestamp: float  # Unix wall-clock time (frame_timestamp or time.time())\n    last_seen_frame: int\n    last_seen_timestamp: float  # Unix wall-clock time (frame_timestamp or time.time())\n    first_seen_relative: float = 0.0  # seconds since video start\n    last_seen_relative: float = 0.0  # seconds since video start\n    frame_count: int = 1\n    logged: bool = False\n\n\nclass DetectionEventLogBlockV1(WorkflowBlock):\n\n    def __init__(self):\n        # Dict[video_id, Dict[tracker_id, DetectionEvent]]\n        self._event_logs: Dict[str, Dict[int, DetectionEvent]] = {}\n        # Dict[video_id, last_flush_frame]\n        self._last_flush_frame: Dict[str, int] = {}\n        # Dict[video_id, frame_count] - internal frame counter (increments each run)\n        self._frame_count: Dict[str, int] = {}\n        # Dict[video_id, last_access_frame] - tracks when each video was last accessed (global frame count)\n        self._last_access: Dict[str, int] = {}\n        # Dict[video_id, first_frame_timestamp] - stores the first frame's wall-clock timestamp\n        # Used as the anchor for frame_timestamp-based relative time calculation\n        self._first_frame_timestamps: Dict[str, float] = {}\n        # Global frame counter for tracking video access order\n        self._global_frame: int = 0\n\n    def _get_relative_time(\n        self,\n        video_id: str,\n        current_frame: int,\n        metadata: VideoMetadata,\n        fallback_fps: float,\n    ) -> float:\n        \"\"\"Calculate relative time in seconds since video started.\n\n        Uses frame_timestamp from metadata when available for accurate timing,\n        even when inference doesn't run at the camera's reported FPS (e.g. due\n        to dropped frames or processing lag). Falls back to internal frame\n        counter / FPS when frame_timestamp is not available.\n        \"\"\"\n        if metadata.frame_timestamp is not None:\n            frame_ts = metadata.frame_timestamp.timestamp()\n            if video_id not in self._first_frame_timestamps:\n                self._first_frame_timestamps[video_id] = frame_ts\n            return frame_ts - self._first_frame_timestamps[video_id]\n\n        # Fallback: use internal frame counter and FPS\n        fps = metadata.fps if metadata.fps and metadata.fps != 0 else fallback_fps\n        return (current_frame - 1) / fps\n\n    def _evict_oldest_video(self) -> None:\n        \"\"\"Remove the oldest video stream data when MAX_VIDEOS is exceeded.\"\"\"\n        if len(self._event_logs) <= MAX_VIDEOS:\n            return\n\n        # Find the video with the oldest last access time\n        oldest_video_id = min(self._last_access, key=self._last_access.get)\n\n        # Remove all data for this video\n        self._event_logs.pop(oldest_video_id, None)\n        self._last_flush_frame.pop(oldest_video_id, None)\n        self._frame_count.pop(oldest_video_id, None)\n        self._last_access.pop(oldest_video_id, None)\n        self._first_frame_timestamps.pop(oldest_video_id, None)\n\n    def _remove_stale_events(\n        self,\n        event_log: Dict[int, DetectionEvent],\n        current_frame: int,\n        stale_frames: int,\n        frame_threshold: int,\n    ) -> List[DetectionEvent]:\n        \"\"\"Remove events that haven't been seen for stale_frames.\n\n        Returns list of removed LOGGED events (events that met frame_threshold).\n        These are \"complete\" events - objects that were tracked long enough\n        to be logged and have now left the scene.\n        \"\"\"\n        stale_tracker_ids = []\n        complete_events = []\n\n        for tracker_id, event in event_log.items():\n            frames_since_seen = current_frame - event.last_seen_frame\n            if frames_since_seen > stale_frames:\n                stale_tracker_ids.append(tracker_id)\n                # Only return logged events as \"complete\" - pending events are just discarded\n                if event.frame_count >= frame_threshold:\n                    complete_events.append(event)\n\n        for tracker_id in stale_tracker_ids:\n            del event_log[tracker_id]\n\n        return complete_events\n\n    def run(\n        self,\n        image: WorkflowImageData,\n        detections: sv.Detections,\n        frame_threshold: int,\n        flush_interval: int,\n        stale_frames: int,\n        fallback_fps: float = 1.0,\n        reference_timestamp: Optional[float] = None,\n    ) -> BlockResult:\n        \"\"\"Process detections and update the event log.\n\n        Args:\n            image: Workflow image data containing video metadata.\n            detections: Tracked detections with tracker_id from ByteTracker.\n            frame_threshold: Minimum frames an object must be seen before logging.\n            flush_interval: How often to run stale event cleanup.\n            stale_frames: Remove events not seen for this many frames.\n            fallback_fps: FPS to use when video metadata doesn't provide FPS.\n            reference_timestamp: Unused, kept for backward compatibility.\n\n        Returns:\n            Dictionary containing event_log, detections, total_logged, and total_pending.\n        \"\"\"\n        metadata = image.video_metadata\n        video_id = metadata.video_identifier\n\n        # Track global frame count and video access for eviction\n        self._global_frame += 1\n        self._last_access[video_id] = self._global_frame\n\n        # Increment internal frame counter\n        current_frame = self._frame_count.get(video_id, 0) + 1\n        self._frame_count[video_id] = current_frame\n\n        current_time = self._get_relative_time(\n            video_id, current_frame, metadata, fallback_fps\n        )\n\n        # Use frame_timestamp for absolute time when available (reflects actual capture\n        # time, not inference processing time). Falls back to time.time().\n        current_absolute_time = (\n            metadata.frame_timestamp.timestamp()\n            if metadata.frame_timestamp is not None\n            else time.time()\n        )\n\n        # Initialize event log for this video if needed\n        event_log = self._event_logs.setdefault(video_id, {})\n\n        # Evict oldest video if we've exceeded MAX_VIDEOS (after adding current video)\n        self._evict_oldest_video()\n\n        # Initialize last flush frame if not set\n        if video_id not in self._last_flush_frame:\n            self._last_flush_frame[video_id] = current_frame\n\n        # Check if it's time to run cleanup\n        complete_events_list = []\n        last_flush = self._last_flush_frame.get(video_id, 0)\n        if (current_frame - last_flush) >= flush_interval:\n            complete_events_list = self._remove_stale_events(\n                event_log, current_frame, stale_frames, frame_threshold\n            )\n            self._last_flush_frame[video_id] = current_frame\n\n        # Format complete events\n        complete_events = self._format_complete_events(complete_events_list)\n\n        # Process detections\n        if detections.tracker_id is None or len(detections.tracker_id) == 0:\n            # No tracked detections, return current log\n            event_log_dict, total_logged, total_pending = self._format_event_log(\n                event_log, frame_threshold\n            )\n            return {\n                OUTPUT_KEY: event_log_dict,\n                DETECTIONS_OUTPUT_KEY: detections,\n                \"total_logged\": total_logged,\n                \"total_pending\": total_pending,\n                \"complete_events\": complete_events,\n            }\n\n        # Get class names\n        class_names = detections.data.get(\"class_name\", [])\n        if (\n            len(class_names) == 0\n            and hasattr(detections, \"class_id\")\n            and detections.class_id is not None\n        ):\n            class_names = [f\"class_{cid}\" for cid in detections.class_id]\n\n        # Update event log for each tracked detection\n        for i, tracker_id in enumerate(detections.tracker_id):\n            tracker_id = int(tracker_id)\n            class_name = str(class_names[i]) if len(class_names) > 0 else \"unknown\"\n\n            if tracker_id in event_log:\n                # Update existing event\n                event = event_log[tracker_id]\n                event.last_seen_frame = current_frame\n                event.last_seen_timestamp = current_absolute_time\n                event.last_seen_relative = current_time\n                event.frame_count += 1\n\n                # Mark as logged once threshold is reached\n                if event.frame_count >= frame_threshold and not event.logged:\n                    event.logged = True\n                    logger.debug(\n                        f\"Object {tracker_id} ({event.class_name}) logged after {event.frame_count} frames\"\n                    )\n            else:\n                # Create new event\n                event_log[tracker_id] = DetectionEvent(\n                    tracker_id=tracker_id,\n                    class_name=class_name,\n                    first_seen_frame=current_frame,\n                    first_seen_timestamp=current_absolute_time,\n                    last_seen_frame=current_frame,\n                    last_seen_timestamp=current_absolute_time,\n                    first_seen_relative=current_time,\n                    last_seen_relative=current_time,\n                    frame_count=1,\n                    logged=False,\n                )\n\n        event_log_dict, total_logged, total_pending = self._format_event_log(\n            event_log, frame_threshold\n        )\n        return {\n            OUTPUT_KEY: event_log_dict,\n            DETECTIONS_OUTPUT_KEY: detections,\n            \"total_logged\": total_logged,\n            \"total_pending\": total_pending,\n            \"complete_events\": complete_events,\n        }\n\n    def _format_complete_events(\n        self,\n        complete_events: List[DetectionEvent],\n    ) -> Dict[str, Any]:\n        \"\"\"Format complete events for output.\n\n        Args:\n            complete_events: List of DetectionEvent objects that have completed (gone stale).\n\n        Returns:\n            Dictionary with tracker_id as key and event data as value.\n        \"\"\"\n        formatted = {}\n        for event in complete_events:\n            event_data = event.__dict__.copy()\n            del event_data[\"logged\"]\n            formatted[str(event.tracker_id)] = event_data\n\n        return formatted\n\n    def _format_event_log(\n        self,\n        event_log: Dict[int, DetectionEvent],\n        frame_threshold: int,\n    ) -> tuple:\n        \"\"\"Format the event log for output.\n\n        Returns:\n            Tuple of (event_log_dict, total_logged, total_pending)\n        \"\"\"\n        logged_events = {}\n        pending_events = {}\n\n        for tracker_id, event in event_log.items():\n            event_data = event.__dict__.copy()\n            del event_data[\"logged\"]\n\n            if event.frame_count >= frame_threshold:\n                logged_events[str(tracker_id)] = event_data\n            else:\n                pending_events[str(tracker_id)] = event_data\n\n        event_log_dict = {\n            \"logged\": logged_events,\n            \"pending\": pending_events,\n        }\n\n        return event_log_dict, len(logged_events), len(pending_events)\n```",
    "optimized_function_only": "    def run(\n        self,\n        image: WorkflowImageData,\n        detections: sv.Detections,\n        frame_threshold: int,\n        flush_interval: int,\n        stale_frames: int,\n        fallback_fps: float = 1.0,\n        reference_timestamp: Optional[float] = None,\n    ) -> BlockResult:\n        \"\"\"Process detections and update the event log.\n\n        Args:\n            image: Workflow image data containing video metadata.\n            detections: Tracked detections with tracker_id from ByteTracker.\n            frame_threshold: Minimum frames an object must be seen before logging.\n            flush_interval: How often to run stale event cleanup.\n            stale_frames: Remove events not seen for this many frames.\n            fallback_fps: FPS to use when video metadata doesn't provide FPS.\n            reference_timestamp: Unused, kept for backward compatibility.\n\n        Returns:\n            Dictionary containing event_log, detections, total_logged, and total_pending.\n        \"\"\"\n        metadata = image.video_metadata\n        video_id = metadata.video_identifier\n\n        # Track global frame count and video access for eviction\n        self._global_frame += 1\n        self._last_access[video_id] = self._global_frame\n\n        # Increment internal frame counter\n        current_frame = self._frame_count.get(video_id, 0) + 1\n        self._frame_count[video_id] = current_frame\n\n        current_time = self._get_relative_time(\n            video_id, current_frame, metadata, fallback_fps\n        )\n\n        # Use frame_timestamp for absolute time when available (reflects actual capture\n        # time, not inference processing time). Falls back to time.time().\n        current_absolute_time = (\n            metadata.frame_timestamp.timestamp()\n            if metadata.frame_timestamp is not None\n            else time.time()\n        )\n\n        # Initialize event log for this video if needed\n        event_log = self._event_logs.setdefault(video_id, {})\n\n        # Evict oldest video if we've exceeded MAX_VIDEOS (after adding current video)\n        self._evict_oldest_video()\n\n        # Initialize last flush frame if not set\n        if video_id not in self._last_flush_frame:\n            self._last_flush_frame[video_id] = current_frame\n\n        # Check if it's time to run cleanup\n        complete_events_list = []\n        last_flush = self._last_flush_frame.get(video_id, 0)\n        if (current_frame - last_flush) >= flush_interval:\n            complete_events_list = self._remove_stale_events(\n                event_log, current_frame, stale_frames, frame_threshold\n            )\n            self._last_flush_frame[video_id] = current_frame\n\n        # Format complete events\n        complete_events = self._format_complete_events(complete_events_list)\n\n        # Process detections\n        if detections.tracker_id is None or len(detections.tracker_id) == 0:\n            # No tracked detections, return current log\n            event_log_dict, total_logged, total_pending = self._format_event_log(\n                event_log, frame_threshold\n            )\n            return {\n                OUTPUT_KEY: event_log_dict,\n                DETECTIONS_OUTPUT_KEY: detections,\n                \"total_logged\": total_logged,\n                \"total_pending\": total_pending,\n                \"complete_events\": complete_events,\n            }\n\n        # Get class names\n        class_names = detections.data.get(\"class_name\", [])\n        if (\n            len(class_names) == 0\n            and hasattr(detections, \"class_id\")\n            and detections.class_id is not None\n        ):\n            class_names = [f\"class_{cid}\" for cid in detections.class_id]\n\n        # Update event log for each tracked detection\n        for i, tracker_id in enumerate(detections.tracker_id):\n            tracker_id = int(tracker_id)\n            class_name = str(class_names[i]) if len(class_names) > 0 else \"unknown\"\n\n            if tracker_id in event_log:\n                # Update existing event\n                event = event_log[tracker_id]\n                event.last_seen_frame = current_frame\n                event.last_seen_timestamp = current_absolute_time\n                event.last_seen_relative = current_time\n                event.frame_count += 1\n\n                # Mark as logged once threshold is reached\n                if event.frame_count >= frame_threshold and not event.logged:\n                    event.logged = True\n                    logger.debug(\n                        f\"Object {tracker_id} ({event.class_name}) logged after {event.frame_count} frames\"\n                    )\n            else:\n                # Create new event\n                event_log[tracker_id] = DetectionEvent(\n                    tracker_id=tracker_id,\n                    class_name=class_name,\n                    first_seen_frame=current_frame,\n                    first_seen_timestamp=current_absolute_time,\n                    last_seen_frame=current_frame,\n                    last_seen_timestamp=current_absolute_time,\n                    first_seen_relative=current_time,\n                    last_seen_relative=current_time,\n                    frame_count=1,\n                    logged=False,\n                )\n\n        event_log_dict, total_logged, total_pending = self._format_event_log(\n            event_log, frame_threshold\n        )\n        return {\n            OUTPUT_KEY: event_log_dict,\n            DETECTIONS_OUTPUT_KEY: detections,\n            \"total_logged\": total_logged,\n            \"total_pending\": total_pending,\n            \"complete_events\": complete_events,\n        }\n",
    "original_file_content": "import time\nfrom dataclasses import asdict, dataclass\nfrom typing import Tuple, Any, Dict, List, Literal, Optional, Type, Union\n\nimport numpy as np\nimport supervision as sv\nfrom pydantic import ConfigDict, Field\n\nfrom inference.core import logger\nfrom inference.core.workflows.execution_engine.entities.base import (\n    OutputDefinition,\n    VideoMetadata,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    DICTIONARY_KIND,\n    FLOAT_KIND,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    INTEGER_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    Selector,\n    WorkflowImageSelector,\n    WorkflowParameterSelector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\nimport heapq\n\nOUTPUT_KEY = \"event_log\"\nDETECTIONS_OUTPUT_KEY = \"detections\"\nMAX_VIDEOS = 100  # Maximum number of video streams to track before evicting oldest\n\n\n@dataclass\nclass DetectionEvent:\n    \"\"\"Stores event data for a tracked detection.\"\"\"\n\n    tracker_id: int\n    class_name: str\n    first_seen_frame: int\n    first_seen_timestamp: float  # Unix wall-clock time (frame_timestamp or time.time())\n    last_seen_frame: int\n    last_seen_timestamp: float  # Unix wall-clock time (frame_timestamp or time.time())\n    first_seen_relative: float = 0.0  # seconds since video start\n    last_seen_relative: float = 0.0  # seconds since video start\n    frame_count: int = 1\n    logged: bool = False\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Detection Event Log\",\n            \"version\": \"v1\",\n            \"short_description\": \"Tracks detection events over time, logging when objects first appear and persist.\",\n            \"long_description\": (\n                \"This block maintains a log of detection events from tracked objects. \"\n                \"For each tracked object it records: class name, first and last seen frame numbers, \"\n                \"absolute wall-clock timestamps (Unix epoch floats derived from frame_timestamp metadata, \"\n                \"or time.time() as fallback), and relative timestamps in seconds since the video started. \"\n                \"Objects must be seen for a minimum number of frames (frame_threshold) before being moved \"\n                \"from 'pending' to 'logged' status. \"\n                \"Stale events (not seen for stale_frames frames) are removed during periodic cleanup \"\n                \"(every flush_interval frames). When a logged event goes stale it is emitted in the \"\n                \"complete_events output, which contains the full event data for objects that were tracked \"\n                \"long enough to be logged and have since left the scene. \"\n                \"The reference_timestamp parameter is deprecated and no longer used.\"\n            ),\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"analytics\",\n            \"ui_manifest\": {\n                \"section\": \"analytics\",\n                \"icon\": \"fal fa-list-timeline\",\n                \"blockPriority\": 3,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/detection_event_log@v1\"]\n\n    image: WorkflowImageSelector = Field(\n        description=\"Reference to the image for video metadata (frame number, timestamp).\",\n        examples=[\"$inputs.image\"],\n    )\n\n    detections: Selector(\n        kind=[\n            OBJECT_DETECTION_PREDICTION_KIND,\n            INSTANCE_SEGMENTATION_PREDICTION_KIND,\n        ]\n    ) = Field(\n        description=\"Tracked detections from byte tracker (must have tracker_id).\",\n        examples=[\"$steps.byte_tracker.tracked_detections\"],\n    )\n\n    frame_threshold: Union[int, WorkflowParameterSelector(kind=[INTEGER_KIND])] = Field(\n        default=30,\n        description=\"Number of frames an object must be seen before being logged.\",\n        examples=[5, 10],\n        ge=1,\n    )\n\n    flush_interval: Union[int, WorkflowParameterSelector(kind=[INTEGER_KIND])] = Field(\n        default=30,\n        description=\"How often (in frames) to run the cleanup operation for stale events.\",\n        examples=[30, 60],\n        ge=1,\n    )\n\n    stale_frames: Union[int, WorkflowParameterSelector(kind=[INTEGER_KIND])] = Field(\n        default=300,\n        description=\"Remove events that haven't been seen for this many frames.\",\n        examples=[150, 300],\n        ge=1,\n    )\n\n    reference_timestamp: Optional[Union[float, Selector(kind=[FLOAT_KIND])]] = Field(\n        default=None,\n        description=\"Deprecated, no longer used. Absolute timestamps are now taken directly from frame_timestamp metadata (or time.time() as fallback).\",\n        examples=[1726570875.0],\n    )\n\n    fallback_fps: Union[float, WorkflowParameterSelector(kind=[FLOAT_KIND])] = Field(\n        default=1.0,\n        description=\"Fallback FPS to use when video metadata does not provide FPS information. Used to calculate relative timestamps.\",\n        examples=[1.0, 30.0],\n        gt=0,\n    )\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(\n                name=OUTPUT_KEY,\n                kind=[DICTIONARY_KIND],\n            ),\n            OutputDefinition(\n                name=DETECTIONS_OUTPUT_KEY,\n                kind=[\n                    OBJECT_DETECTION_PREDICTION_KIND,\n                    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n                ],\n            ),\n            OutputDefinition(\n                name=\"total_logged\",\n                kind=[INTEGER_KIND],\n            ),\n            OutputDefinition(\n                name=\"total_pending\",\n                kind=[INTEGER_KIND],\n            ),\n            OutputDefinition(\n                name=\"complete_events\",\n                kind=[DICTIONARY_KIND],\n            ),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass DetectionEventLogBlockV1(WorkflowBlock):\n    \"\"\"\n    Block that tracks detection events over time.\n\n    Maintains a dictionary of tracked objects with:\n    - First seen timestamp and frame\n    - Last seen timestamp and frame\n    - Class name\n    - Frame count (number of frames the object has been seen)\n\n    Only logs objects that have been seen for at least frame_threshold frames.\n    Runs cleanup every flush_interval frames, removing events not seen for stale_frames.\n    \"\"\"\n\n    def __init__(self):\n        # Dict[video_id, Dict[tracker_id, DetectionEvent]]\n        self._event_logs: Dict[str, Dict[int, DetectionEvent]] = {}\n        # Dict[video_id, last_flush_frame]\n        self._last_flush_frame: Dict[str, int] = {}\n        # Dict[video_id, frame_count] - internal frame counter (increments each run)\n        self._frame_count: Dict[str, int] = {}\n        # Dict[video_id, last_access_frame] - tracks when each video was last accessed (global frame count)\n        self._last_access: Dict[str, int] = {}\n        # Dict[video_id, first_frame_timestamp] - stores the first frame's wall-clock timestamp\n        # Used as the anchor for frame_timestamp-based relative time calculation\n        self._first_frame_timestamps: Dict[str, float] = {}\n        # Global frame counter for tracking video access order\n        self._global_frame: int = 0\n        # Min-heap of (last_access_frame, video_id) for efficient oldest video lookup\n        self._access_heap: List[Tuple[int, str]] = []\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def _get_relative_time(\n        self,\n        video_id: str,\n        current_frame: int,\n        metadata: VideoMetadata,\n        fallback_fps: float,\n    ) -> float:\n        \"\"\"Calculate relative time in seconds since video started.\n\n        Uses frame_timestamp from metadata when available for accurate timing,\n        even when inference doesn't run at the camera's reported FPS (e.g. due\n        to dropped frames or processing lag). Falls back to internal frame\n        counter / FPS when frame_timestamp is not available.\n        \"\"\"\n        if metadata.frame_timestamp is not None:\n            frame_ts = metadata.frame_timestamp.timestamp()\n            if video_id not in self._first_frame_timestamps:\n                self._first_frame_timestamps[video_id] = frame_ts\n            return frame_ts - self._first_frame_timestamps[video_id]\n\n        # Fallback: use internal frame counter and FPS\n        fps = metadata.fps if metadata.fps and metadata.fps != 0 else fallback_fps\n        return (current_frame - 1) / fps\n\n    def _evict_oldest_video(self) -> None:\n        \"\"\"Remove the oldest video stream data when MAX_VIDEOS is exceeded.\"\"\"\n        if len(self._event_logs) <= MAX_VIDEOS:\n            return\n\n        # Rebuild heap if out of sync with current state\n        if len(self._access_heap) < len(self._last_access):\n            self._access_heap[:] = [\n                (frame, vid) for vid, frame in self._last_access.items()\n            ]\n            heapq.heapify(self._access_heap)\n\n        # Pop stale entries until we find a valid current entry\n        while self._access_heap:\n            frame, vid = heapq.heappop(self._access_heap)\n            if self._last_access.get(vid) == frame and vid in self._event_logs:\n                oldest_video_id = vid\n                break\n        else:\n            # If heap is empty but we have event_logs, use fallback\n            oldest_video_id = min(self._last_access, key=self._last_access.get)\n\n        # Remove all data for this video\n        self._event_logs.pop(oldest_video_id, None)\n        self._last_flush_frame.pop(oldest_video_id, None)\n        self._frame_count.pop(oldest_video_id, None)\n        self._last_access.pop(oldest_video_id, None)\n        self._first_frame_timestamps.pop(oldest_video_id, None)\n\n    def _remove_stale_events(\n        self,\n        event_log: Dict[int, DetectionEvent],\n        current_frame: int,\n        stale_frames: int,\n        frame_threshold: int,\n    ) -> List[DetectionEvent]:\n        \"\"\"Remove events that haven't been seen for stale_frames.\n\n        Returns list of removed LOGGED events (events that met frame_threshold).\n        These are \"complete\" events - objects that were tracked long enough\n        to be logged and have now left the scene.\n        \"\"\"\n        stale_tracker_ids = []\n        complete_events = []\n\n        for tracker_id, event in event_log.items():\n            frames_since_seen = current_frame - event.last_seen_frame\n            if frames_since_seen > stale_frames:\n                stale_tracker_ids.append(tracker_id)\n                # Only return logged events as \"complete\" - pending events are just discarded\n                if event.frame_count >= frame_threshold:\n                    complete_events.append(event)\n\n        for tracker_id in stale_tracker_ids:\n            del event_log[tracker_id]\n\n        return complete_events\n\n    def run(\n        self,\n        image: WorkflowImageData,\n        detections: sv.Detections,\n        frame_threshold: int,\n        flush_interval: int,\n        stale_frames: int,\n        fallback_fps: float = 1.0,\n        reference_timestamp: Optional[float] = None,\n    ) -> BlockResult:\n        \"\"\"Process detections and update the event log.\n\n        Args:\n            image: Workflow image data containing video metadata.\n            detections: Tracked detections with tracker_id from ByteTracker.\n            frame_threshold: Minimum frames an object must be seen before logging.\n            flush_interval: How often to run stale event cleanup.\n            stale_frames: Remove events not seen for this many frames.\n            fallback_fps: FPS to use when video metadata doesn't provide FPS.\n            reference_timestamp: Unused, kept for backward compatibility.\n\n        Returns:\n            Dictionary containing event_log, detections, total_logged, and total_pending.\n        \"\"\"\n        metadata = image.video_metadata\n        video_id = metadata.video_identifier\n\n        # Track global frame count and video access for eviction\n        self._global_frame += 1\n        self._last_access[video_id] = self._global_frame\n\n        # Increment internal frame counter\n        current_frame = self._frame_count.get(video_id, 0) + 1\n        self._frame_count[video_id] = current_frame\n\n        current_time = self._get_relative_time(\n            video_id, current_frame, metadata, fallback_fps\n        )\n\n        # Use frame_timestamp for absolute time when available (reflects actual capture\n        # time, not inference processing time). Falls back to time.time().\n        current_absolute_time = (\n            metadata.frame_timestamp.timestamp()\n            if metadata.frame_timestamp is not None\n            else time.time()\n        )\n\n        # Initialize event log for this video if needed\n        event_log = self._event_logs.setdefault(video_id, {})\n\n        # Evict oldest video if we've exceeded MAX_VIDEOS (after adding current video)\n        self._evict_oldest_video()\n\n        # Initialize last flush frame if not set\n        if video_id not in self._last_flush_frame:\n            self._last_flush_frame[video_id] = current_frame\n\n        # Check if it's time to run cleanup\n        complete_events_list = []\n        last_flush = self._last_flush_frame.get(video_id, 0)\n        if (current_frame - last_flush) >= flush_interval:\n            complete_events_list = self._remove_stale_events(\n                event_log, current_frame, stale_frames, frame_threshold\n            )\n            self._last_flush_frame[video_id] = current_frame\n\n        # Format complete events\n        complete_events = self._format_complete_events(complete_events_list)\n\n        # Process detections\n        if detections.tracker_id is None or len(detections.tracker_id) == 0:\n            # No tracked detections, return current log\n            event_log_dict, total_logged, total_pending = self._format_event_log(\n                event_log, frame_threshold\n            )\n            return {\n                OUTPUT_KEY: event_log_dict,\n                DETECTIONS_OUTPUT_KEY: detections,\n                \"total_logged\": total_logged,\n                \"total_pending\": total_pending,\n                \"complete_events\": complete_events,\n            }\n\n        # Get class names\n        class_names = detections.data.get(\"class_name\", [])\n        if (\n            len(class_names) == 0\n            and hasattr(detections, \"class_id\")\n            and detections.class_id is not None\n        ):\n            class_names = [f\"class_{cid}\" for cid in detections.class_id]\n\n        # Update event log for each tracked detection\n        for i, tracker_id in enumerate(detections.tracker_id):\n            tracker_id = int(tracker_id)\n            class_name = str(class_names[i]) if len(class_names) > 0 else \"unknown\"\n\n            if tracker_id in event_log:\n                # Update existing event\n                event = event_log[tracker_id]\n                event.last_seen_frame = current_frame\n                event.last_seen_timestamp = current_absolute_time\n                event.last_seen_relative = current_time\n                event.frame_count += 1\n\n                # Mark as logged once threshold is reached\n                if event.frame_count >= frame_threshold and not event.logged:\n                    event.logged = True\n                    logger.debug(\n                        f\"Object {tracker_id} ({event.class_name}) logged after {event.frame_count} frames\"\n                    )\n            else:\n                # Create new event\n                event_log[tracker_id] = DetectionEvent(\n                    tracker_id=tracker_id,\n                    class_name=class_name,\n                    first_seen_frame=current_frame,\n                    first_seen_timestamp=current_absolute_time,\n                    last_seen_frame=current_frame,\n                    last_seen_timestamp=current_absolute_time,\n                    first_seen_relative=current_time,\n                    last_seen_relative=current_time,\n                    frame_count=1,\n                    logged=False,\n                )\n\n        event_log_dict, total_logged, total_pending = self._format_event_log(\n            event_log, frame_threshold\n        )\n        return {\n            OUTPUT_KEY: event_log_dict,\n            DETECTIONS_OUTPUT_KEY: detections,\n            \"total_logged\": total_logged,\n            \"total_pending\": total_pending,\n            \"complete_events\": complete_events,\n        }\n\n    def _format_complete_events(\n        self,\n        complete_events: List[DetectionEvent],\n    ) -> Dict[str, Any]:\n        \"\"\"Format complete events for output.\n\n        Args:\n            complete_events: List of DetectionEvent objects that have completed (gone stale).\n\n        Returns:\n            Dictionary with tracker_id as key and event data as value.\n        \"\"\"\n        formatted = {}\n        for event in complete_events:\n            event_data = event.__dict__.copy()\n            del event_data[\"logged\"]\n            formatted[str(event.tracker_id)] = event_data\n\n        return formatted\n\n    def _format_event_log(\n        self,\n        event_log: Dict[int, DetectionEvent],\n        frame_threshold: int,\n    ) -> tuple:\n        \"\"\"Format the event log for output.\n\n        Returns:\n            Tuple of (event_log_dict, total_logged, total_pending)\n        \"\"\"\n        logged_events = {}\n        pending_events = {}\n\n        for tracker_id, event in event_log.items():\n            event_data = event.__dict__.copy()\n            del event_data[\"logged\"]\n\n            if event.frame_count >= frame_threshold:\n                logged_events[str(tracker_id)] = event_data\n            else:\n                pending_events[str(tracker_id)] = event_data\n\n        event_log_dict = {\n            \"logged\": logged_events,\n            \"pending\": pending_events,\n        }\n\n        return event_log_dict, len(logged_events), len(pending_events)\n",
    "patch": null
  },
  {
    "trace_id": "cc10c2fb-62c2-4ae0-b7f9-9b5a65e4f5a6",
    "function_name": "InferenceModelsClipAdapter.compare",
    "file_path": "inference/models/clip/clip_inference_models.py",
    "speedup_x": 2.37,
    "review_quality": "high",
    "pre_optimization_commit": "7648e452a70ff1aad09f017a0eb2ea4022b7e177",
    "resolution_method": "db_code_match",
    "source": "db_events",
    "original_function_code": "    def compare(\n        self,\n        subject: Any,\n        prompt: Any,\n        subject_type: str = \"image\",\n        prompt_type: Union[str, List[str], Dict[str, Any]] = \"text\",\n        **kwargs,\n    ) -> Union[List[float], Dict[str, float]]:\n        \"\"\"\n        Compares the subject with the prompt to calculate similarity scores.\n\n        Args:\n            subject (Any): The subject data to be compared. Can be either an image or text.\n            prompt (Any): The prompt data to be compared against the subject. Can be a single value (image/text), list of values, or dictionary of values.\n            subject_type (str, optional): Specifies the type of the subject data. Must be either \"image\" or \"text\". Defaults to \"image\".\n            prompt_type (Union[str, List[str], Dict[str, Any]], optional): Specifies the type of the prompt data. Can be \"image\", \"text\", list of these types, or a dictionary containing these types. Defaults to \"text\".\n            **kwargs: Additional keyword arguments.\n\n        Returns:\n            Union[List[float], Dict[str, float]]: A list or dictionary containing cosine similarity scores between the subject and prompt(s). If prompt is a dictionary, returns a dictionary with keys corresponding to the original prompt dictionary's keys.\n\n        Raises:\n            ValueError: If subject_type or prompt_type is neither \"image\" nor \"text\".\n            ValueError: If the number of prompts exceeds the maximum batch size.\n        \"\"\"\n\n        if subject_type == \"image\":\n            subject_embeddings = self.embed_image(subject)\n        elif subject_type == \"text\":\n            subject_embeddings = self.embed_text(subject)\n        else:\n            raise ValueError(\n                \"subject_type must be either 'image' or 'text', but got {request.subject_type}\"\n            )\n\n        if isinstance(prompt, dict) and not (\"type\" in prompt and \"value\" in prompt):\n            prompt_keys = prompt.keys()\n            prompt = [prompt[k] for k in prompt_keys]\n            prompt_obj = \"dict\"\n        else:\n            prompt = prompt\n            if not isinstance(prompt, list):\n                prompt = [prompt]\n            prompt_obj = \"list\"\n\n        if len(prompt) > CLIP_MAX_BATCH_SIZE:\n            raise ValueError(\n                f\"The maximum number of prompts that can be compared at once is {CLIP_MAX_BATCH_SIZE}\"\n            )\n\n        if prompt_type == \"image\":\n            prompt_embeddings = self.embed_image(prompt)\n        elif prompt_type == \"text\":\n            prompt_embeddings = self.embed_text(prompt)\n        else:\n            raise ValueError(\n                \"prompt_type must be either 'image' or 'text', but got {request.prompt_type}\"\n            )\n\n        similarities = [\n            cosine_similarity(subject_embeddings, p) for p in prompt_embeddings\n        ]\n\n        if prompt_obj == \"dict\":\n            similarities = dict(zip(prompt_keys, similarities))\n\n        return similarities\n",
    "optimized_function_code": "from time import perf_counter\nfrom typing import Any, Dict, List, Union\n\nimport numpy as np\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES, API_KEY, CLIP_MAX_BATCH_SIZE,\n    CLIP_MODEL_ID)\nfrom inference.core.models.base import Model\nfrom inference_models import AutoModel\nfrom inference_models.models.clip.clip_onnx import ClipOnnx\nfrom inference_models.models.clip.clip_pytorch import ClipTorch\n\n\nclass InferenceModelsClipAdapter(Model):\n\n    def __init__(\n        self,\n        model_id: str = CLIP_MODEL_ID,\n        api_key: str = None,\n        **kwargs,\n    ):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n        self.task_type = \"embedding\"\n        self._model: Union[ClipOnnx, ClipTorch] = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            **kwargs,\n        )\n\n    def compare(\n        self,\n        subject: Any,\n        prompt: Any,\n        subject_type: str = \"image\",\n        prompt_type: Union[str, List[str], Dict[str, Any]] = \"text\",\n        **kwargs,\n    ) -> Union[List[float], Dict[str, float]]:\n        \"\"\"\n        Compares the subject with the prompt to calculate similarity scores.\n\n        Args:\n            subject (Any): The subject data to be compared. Can be either an image or text.\n            prompt (Any): The prompt data to be compared against the subject. Can be a single value (image/text), list of values, or dictionary of values.\n            subject_type (str, optional): Specifies the type of the subject data. Must be either \"image\" or \"text\". Defaults to \"image\".\n            prompt_type (Union[str, List[str], Dict[str, Any]], optional): Specifies the type of the prompt data. Can be \"image\", \"text\", list of these types, or a dictionary containing these types. Defaults to \"text\".\n            **kwargs: Additional keyword arguments.\n\n        Returns:\n            Union[List[float], Dict[str, float]]: A list or dictionary containing cosine similarity scores between the subject and prompt(s). If prompt is a dictionary, returns a dictionary with keys corresponding to the original prompt dictionary's keys.\n\n        Raises:\n            ValueError: If subject_type or prompt_type is neither \"image\" nor \"text\".\n            ValueError: If the number of prompts exceeds the maximum batch size.\n        \"\"\"\n\n        if subject_type == \"image\":\n            subject_embeddings = self.embed_image(subject)\n        elif subject_type == \"text\":\n            subject_embeddings = self.embed_text(subject)\n        else:\n            raise ValueError(\n                \"subject_type must be either 'image' or 'text', but got {request.subject_type}\"\n            )\n\n        if isinstance(prompt, dict) and not (\"type\" in prompt and \"value\" in prompt):\n            prompt_keys = prompt.keys()\n            prompt = [prompt[k] for k in prompt_keys]\n            prompt_obj = \"dict\"\n        else:\n            prompt = prompt\n            if not isinstance(prompt, list):\n                prompt = [prompt]\n            prompt_obj = \"list\"\n\n        if len(prompt) > CLIP_MAX_BATCH_SIZE:\n            raise ValueError(\n                f\"The maximum number of prompts that can be compared at once is {CLIP_MAX_BATCH_SIZE}\"\n            )\n\n        if prompt_type == \"image\":\n            prompt_embeddings = self.embed_image(prompt)\n        elif prompt_type == \"text\":\n            prompt_embeddings = self.embed_text(prompt)\n        else:\n            raise ValueError(\n                \"prompt_type must be either 'image' or 'text', but got {request.prompt_type}\"\n            )\n\n        # Vectorized cosine similarity computation to avoid Python-level loop and many function calls.\n        # Preserve shape/return behavior: for each prompt return either a scalar (if subject was 1D)\n        # or a 1D numpy array (if subject had multiple embeddings).\n        subj_arr = np.asarray(subject_embeddings)\n        prom_arr = np.asarray(prompt_embeddings)\n\n        subj_was_1d = subj_arr.ndim == 1\n        prom_was_1d = prom_arr.ndim == 1\n\n        if subj_was_1d:\n            a = subj_arr.reshape(1, -1)\n        else:\n            a = subj_arr\n\n        if prom_was_1d:\n            b = prom_arr.reshape(1, -1)\n        else:\n            b = prom_arr\n\n        # Compute dot products and norms in a vectorized manner.\n        dot = a @ b.T  # shape (S, M)\n        a_norm = np.linalg.norm(a, axis=1)\n        b_norm = np.linalg.norm(b, axis=1)\n        denom = a_norm[:, None] * b_norm[None, :]\n        sim_mat = dot / denom\n\n        M = sim_mat.shape[1]\n        if subj_was_1d:\n            similarities = [sim_mat[0, j] for j in range(M)]\n        else:\n            similarities = [sim_mat[:, j] for j in range(M)]\n\n\n        if prompt_obj == \"dict\":\n            similarities = dict(zip(prompt_keys, similarities))\n\n        return similarities\n\n    def embed_image(\n        self,\n        image: Any,\n        **kwargs,\n    ) -> np.ndarray:\n        \"\"\"\n        Embeds an image or a list of images using the Clip model.\n\n        Args:\n            image (Any): The image or list of images to be embedded. Image can be in any format that is acceptable by the preproc_image method.\n            **kwargs: Additional keyword arguments.\n\n        Returns:\n            np.ndarray: The embeddings of the image(s) as a numpy array.\n\n        Raises:\n            ValueError: If the number of images in the list exceeds the maximum batch size.\n\n        Notes:\n            The function measures performance using perf_counter and also has support for ONNX session to get embeddings.\n        \"\"\"\n\n        if isinstance(image, list):\n            if len(image) > CLIP_MAX_BATCH_SIZE:\n                raise ValueError(\n                    f\"The maximum number of images that can be embedded at once is {CLIP_MAX_BATCH_SIZE}\"\n                )\n            imgs = [self.preproc_image(i) for i in image]\n            img_in = np.concatenate(imgs, axis=0)\n        else:\n            img_in = self.preproc_image(image)\n        embeddings = self._model.embed_images(images=img_in)\n        return embeddings.cpu().numpy()\n\n    def embed_text(\n        self,\n        text: Union[str, List[str]],\n        **kwargs,\n    ) -> np.ndarray:\n        \"\"\"\n        Embeds a text or a list of texts using the Clip model.\n\n        Args:\n            text (Union[str, List[str]]): The text string or list of text strings to be embedded.\n            **kwargs: Additional keyword arguments.\n\n        Returns:\n            np.ndarray: The embeddings of the text or texts as a numpy array.\n\n        Raises:\n            ValueError: If the number of text strings in the list exceeds the maximum batch size.\n\n        Notes:\n            The function utilizes an ONNX session to compute embeddings and measures the embedding time with perf_counter.\n        \"\"\"\n        if isinstance(text, list):\n            texts = text\n        else:\n            texts = [text]\n        embeddings = self._model.embed_text(texts=texts)\n        return embeddings.cpu().numpy()",
    "optimized_raw_markdown": "```python:inference/models/clip/clip_inference_models.py\nfrom time import perf_counter\nfrom typing import Any, Dict, List, Union\n\nimport numpy as np\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES, API_KEY, CLIP_MAX_BATCH_SIZE,\n    CLIP_MODEL_ID)\nfrom inference.core.models.base import Model\nfrom inference_models import AutoModel\nfrom inference_models.models.clip.clip_onnx import ClipOnnx\nfrom inference_models.models.clip.clip_pytorch import ClipTorch\n\n\nclass InferenceModelsClipAdapter(Model):\n\n    def __init__(\n        self,\n        model_id: str = CLIP_MODEL_ID,\n        api_key: str = None,\n        **kwargs,\n    ):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n        self.task_type = \"embedding\"\n        self._model: Union[ClipOnnx, ClipTorch] = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            **kwargs,\n        )\n\n    def compare(\n        self,\n        subject: Any,\n        prompt: Any,\n        subject_type: str = \"image\",\n        prompt_type: Union[str, List[str], Dict[str, Any]] = \"text\",\n        **kwargs,\n    ) -> Union[List[float], Dict[str, float]]:\n        \"\"\"\n        Compares the subject with the prompt to calculate similarity scores.\n\n        Args:\n            subject (Any): The subject data to be compared. Can be either an image or text.\n            prompt (Any): The prompt data to be compared against the subject. Can be a single value (image/text), list of values, or dictionary of values.\n            subject_type (str, optional): Specifies the type of the subject data. Must be either \"image\" or \"text\". Defaults to \"image\".\n            prompt_type (Union[str, List[str], Dict[str, Any]], optional): Specifies the type of the prompt data. Can be \"image\", \"text\", list of these types, or a dictionary containing these types. Defaults to \"text\".\n            **kwargs: Additional keyword arguments.\n\n        Returns:\n            Union[List[float], Dict[str, float]]: A list or dictionary containing cosine similarity scores between the subject and prompt(s). If prompt is a dictionary, returns a dictionary with keys corresponding to the original prompt dictionary's keys.\n\n        Raises:\n            ValueError: If subject_type or prompt_type is neither \"image\" nor \"text\".\n            ValueError: If the number of prompts exceeds the maximum batch size.\n        \"\"\"\n\n        if subject_type == \"image\":\n            subject_embeddings = self.embed_image(subject)\n        elif subject_type == \"text\":\n            subject_embeddings = self.embed_text(subject)\n        else:\n            raise ValueError(\n                \"subject_type must be either 'image' or 'text', but got {request.subject_type}\"\n            )\n\n        if isinstance(prompt, dict) and not (\"type\" in prompt and \"value\" in prompt):\n            prompt_keys = prompt.keys()\n            prompt = [prompt[k] for k in prompt_keys]\n            prompt_obj = \"dict\"\n        else:\n            prompt = prompt\n            if not isinstance(prompt, list):\n                prompt = [prompt]\n            prompt_obj = \"list\"\n\n        if len(prompt) > CLIP_MAX_BATCH_SIZE:\n            raise ValueError(\n                f\"The maximum number of prompts that can be compared at once is {CLIP_MAX_BATCH_SIZE}\"\n            )\n\n        if prompt_type == \"image\":\n            prompt_embeddings = self.embed_image(prompt)\n        elif prompt_type == \"text\":\n            prompt_embeddings = self.embed_text(prompt)\n        else:\n            raise ValueError(\n                \"prompt_type must be either 'image' or 'text', but got {request.prompt_type}\"\n            )\n\n        # Vectorized cosine similarity computation to avoid Python-level loop and many function calls.\n        # Preserve shape/return behavior: for each prompt return either a scalar (if subject was 1D)\n        # or a 1D numpy array (if subject had multiple embeddings).\n        subj_arr = np.asarray(subject_embeddings)\n        prom_arr = np.asarray(prompt_embeddings)\n\n        subj_was_1d = subj_arr.ndim == 1\n        prom_was_1d = prom_arr.ndim == 1\n\n        if subj_was_1d:\n            a = subj_arr.reshape(1, -1)\n        else:\n            a = subj_arr\n\n        if prom_was_1d:\n            b = prom_arr.reshape(1, -1)\n        else:\n            b = prom_arr\n\n        # Compute dot products and norms in a vectorized manner.\n        dot = a @ b.T  # shape (S, M)\n        a_norm = np.linalg.norm(a, axis=1)\n        b_norm = np.linalg.norm(b, axis=1)\n        denom = a_norm[:, None] * b_norm[None, :]\n        sim_mat = dot / denom\n\n        M = sim_mat.shape[1]\n        if subj_was_1d:\n            similarities = [sim_mat[0, j] for j in range(M)]\n        else:\n            similarities = [sim_mat[:, j] for j in range(M)]\n\n\n        if prompt_obj == \"dict\":\n            similarities = dict(zip(prompt_keys, similarities))\n\n        return similarities\n\n    def embed_image(\n        self,\n        image: Any,\n        **kwargs,\n    ) -> np.ndarray:\n        \"\"\"\n        Embeds an image or a list of images using the Clip model.\n\n        Args:\n            image (Any): The image or list of images to be embedded. Image can be in any format that is acceptable by the preproc_image method.\n            **kwargs: Additional keyword arguments.\n\n        Returns:\n            np.ndarray: The embeddings of the image(s) as a numpy array.\n\n        Raises:\n            ValueError: If the number of images in the list exceeds the maximum batch size.\n\n        Notes:\n            The function measures performance using perf_counter and also has support for ONNX session to get embeddings.\n        \"\"\"\n\n        if isinstance(image, list):\n            if len(image) > CLIP_MAX_BATCH_SIZE:\n                raise ValueError(\n                    f\"The maximum number of images that can be embedded at once is {CLIP_MAX_BATCH_SIZE}\"\n                )\n            imgs = [self.preproc_image(i) for i in image]\n            img_in = np.concatenate(imgs, axis=0)\n        else:\n            img_in = self.preproc_image(image)\n        embeddings = self._model.embed_images(images=img_in)\n        return embeddings.cpu().numpy()\n\n    def embed_text(\n        self,\n        text: Union[str, List[str]],\n        **kwargs,\n    ) -> np.ndarray:\n        \"\"\"\n        Embeds a text or a list of texts using the Clip model.\n\n        Args:\n            text (Union[str, List[str]]): The text string or list of text strings to be embedded.\n            **kwargs: Additional keyword arguments.\n\n        Returns:\n            np.ndarray: The embeddings of the text or texts as a numpy array.\n\n        Raises:\n            ValueError: If the number of text strings in the list exceeds the maximum batch size.\n\n        Notes:\n            The function utilizes an ONNX session to compute embeddings and measures the embedding time with perf_counter.\n        \"\"\"\n        if isinstance(text, list):\n            texts = text\n        else:\n            texts = [text]\n        embeddings = self._model.embed_text(texts=texts)\n        return embeddings.cpu().numpy()\n```",
    "optimized_function_only": "    def compare(\n        self,\n        subject: Any,\n        prompt: Any,\n        subject_type: str = \"image\",\n        prompt_type: Union[str, List[str], Dict[str, Any]] = \"text\",\n        **kwargs,\n    ) -> Union[List[float], Dict[str, float]]:\n        \"\"\"\n        Compares the subject with the prompt to calculate similarity scores.\n\n        Args:\n            subject (Any): The subject data to be compared. Can be either an image or text.\n            prompt (Any): The prompt data to be compared against the subject. Can be a single value (image/text), list of values, or dictionary of values.\n            subject_type (str, optional): Specifies the type of the subject data. Must be either \"image\" or \"text\". Defaults to \"image\".\n            prompt_type (Union[str, List[str], Dict[str, Any]], optional): Specifies the type of the prompt data. Can be \"image\", \"text\", list of these types, or a dictionary containing these types. Defaults to \"text\".\n            **kwargs: Additional keyword arguments.\n\n        Returns:\n            Union[List[float], Dict[str, float]]: A list or dictionary containing cosine similarity scores between the subject and prompt(s). If prompt is a dictionary, returns a dictionary with keys corresponding to the original prompt dictionary's keys.\n\n        Raises:\n            ValueError: If subject_type or prompt_type is neither \"image\" nor \"text\".\n            ValueError: If the number of prompts exceeds the maximum batch size.\n        \"\"\"\n\n        if subject_type == \"image\":\n            subject_embeddings = self.embed_image(subject)\n        elif subject_type == \"text\":\n            subject_embeddings = self.embed_text(subject)\n        else:\n            raise ValueError(\n                \"subject_type must be either 'image' or 'text', but got {request.subject_type}\"\n            )\n\n        if isinstance(prompt, dict) and not (\"type\" in prompt and \"value\" in prompt):\n            prompt_keys = prompt.keys()\n            prompt = [prompt[k] for k in prompt_keys]\n            prompt_obj = \"dict\"\n        else:\n            prompt = prompt\n            if not isinstance(prompt, list):\n                prompt = [prompt]\n            prompt_obj = \"list\"\n\n        if len(prompt) > CLIP_MAX_BATCH_SIZE:\n            raise ValueError(\n                f\"The maximum number of prompts that can be compared at once is {CLIP_MAX_BATCH_SIZE}\"\n            )\n\n        if prompt_type == \"image\":\n            prompt_embeddings = self.embed_image(prompt)\n        elif prompt_type == \"text\":\n            prompt_embeddings = self.embed_text(prompt)\n        else:\n            raise ValueError(\n                \"prompt_type must be either 'image' or 'text', but got {request.prompt_type}\"\n            )\n\n        # Vectorized cosine similarity computation to avoid Python-level loop and many function calls.\n        # Preserve shape/return behavior: for each prompt return either a scalar (if subject was 1D)\n        # or a 1D numpy array (if subject had multiple embeddings).\n        subj_arr = np.asarray(subject_embeddings)\n        prom_arr = np.asarray(prompt_embeddings)\n\n        subj_was_1d = subj_arr.ndim == 1\n        prom_was_1d = prom_arr.ndim == 1\n\n        if subj_was_1d:\n            a = subj_arr.reshape(1, -1)\n        else:\n            a = subj_arr\n\n        if prom_was_1d:\n            b = prom_arr.reshape(1, -1)\n        else:\n            b = prom_arr\n\n        # Compute dot products and norms in a vectorized manner.\n        dot = a @ b.T  # shape (S, M)\n        a_norm = np.linalg.norm(a, axis=1)\n        b_norm = np.linalg.norm(b, axis=1)\n        denom = a_norm[:, None] * b_norm[None, :]\n        sim_mat = dot / denom\n\n        M = sim_mat.shape[1]\n        if subj_was_1d:\n            similarities = [sim_mat[0, j] for j in range(M)]\n        else:\n            similarities = [sim_mat[:, j] for j in range(M)]\n\n\n        if prompt_obj == \"dict\":\n            similarities = dict(zip(prompt_keys, similarities))\n\n        return similarities\n",
    "original_file_content": "from time import perf_counter\nfrom typing import Any, Dict, List, Tuple, Union\n\nimport numpy as np\nimport onnxruntime\n\nfrom inference.core.entities.requests.clip import (\n    ClipCompareRequest,\n    ClipImageEmbeddingRequest,\n    ClipInferenceRequest,\n    ClipTextEmbeddingRequest,\n)\nfrom inference.core.entities.requests.inference import InferenceRequestImage\nfrom inference.core.entities.responses.clip import (\n    ClipCompareResponse,\n    ClipEmbeddingResponse,\n)\nfrom inference.core.entities.responses.inference import InferenceResponse\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n    API_KEY,\n    CLIP_MAX_BATCH_SIZE,\n    CLIP_MODEL_ID,\n    DISABLED_INFERENCE_MODELS_BACKENDS,\n    VALID_INFERENCE_MODELS_BACKENDS,\n)\nfrom inference.core.models.base import Model\nfrom inference.core.models.types import PreprocessReturnMetadata\nfrom inference.core.roboflow_api import get_extra_weights_provider_headers\nfrom inference.core.utils.image_utils import load_image_bgr\nfrom inference.core.utils.postprocess import cosine_similarity\nfrom inference_models import AutoModel\nfrom inference_models.models.clip.clip_onnx import ClipOnnx\nfrom inference_models.models.clip.clip_pytorch import ClipTorch\n\n\nclass InferenceModelsClipAdapter(Model):\n    \"\"\"Roboflow ONNX ClipModel model.\n\n    This class is responsible for handling the ONNX ClipModel model, including\n    loading the model, preprocessing the input, and performing inference.\n\n    Attributes:\n        visual_onnx_session (onnxruntime.InferenceSession): ONNX Runtime session for visual inference.\n        textual_onnx_session (onnxruntime.InferenceSession): ONNX Runtime session for textual inference.\n        resolution (int): The resolution of the input image.\n        clip_preprocess (function): Function to preprocess the image.\n    \"\"\"\n\n    def __init__(\n        self,\n        model_id: str = CLIP_MODEL_ID,\n        api_key: str = None,\n        **kwargs,\n    ):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n        self.task_type = \"embedding\"\n        weights_provider_extra_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n        backend = list(\n            VALID_INFERENCE_MODELS_BACKENDS.difference(\n                DISABLED_INFERENCE_MODELS_BACKENDS\n            )\n        )\n        self._model: Union[ClipOnnx, ClipTorch] = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=weights_provider_extra_headers,\n            backend=backend,\n            **kwargs,\n        )\n\n    def compare(\n        self,\n        subject: Any,\n        prompt: Any,\n        subject_type: str = \"image\",\n        prompt_type: Union[str, List[str], Dict[str, Any]] = \"text\",\n        **kwargs,\n    ) -> Union[List[float], Dict[str, float]]:\n        \"\"\"\n        Compares the subject with the prompt to calculate similarity scores.\n\n        Args:\n            subject (Any): The subject data to be compared. Can be either an image or text.\n            prompt (Any): The prompt data to be compared against the subject. Can be a single value (image/text), list of values, or dictionary of values.\n            subject_type (str, optional): Specifies the type of the subject data. Must be either \"image\" or \"text\". Defaults to \"image\".\n            prompt_type (Union[str, List[str], Dict[str, Any]], optional): Specifies the type of the prompt data. Can be \"image\", \"text\", list of these types, or a dictionary containing these types. Defaults to \"text\".\n            **kwargs: Additional keyword arguments.\n\n        Returns:\n            Union[List[float], Dict[str, float]]: A list or dictionary containing cosine similarity scores between the subject and prompt(s). If prompt is a dictionary, returns a dictionary with keys corresponding to the original prompt dictionary's keys.\n\n        Raises:\n            ValueError: If subject_type or prompt_type is neither \"image\" nor \"text\".\n            ValueError: If the number of prompts exceeds the maximum batch size.\n        \"\"\"\n\n        if subject_type == \"image\":\n            subject_embeddings = self.embed_image(subject)\n        elif subject_type == \"text\":\n            subject_embeddings = self.embed_text(subject)\n        else:\n            raise ValueError(\n                \"subject_type must be either 'image' or 'text', but got {request.subject_type}\"\n            )\n\n        if isinstance(prompt, dict) and not (\"type\" in prompt and \"value\" in prompt):\n            prompt_keys = prompt.keys()\n            prompt = [prompt[k] for k in prompt_keys]\n            prompt_obj = \"dict\"\n        else:\n            prompt = prompt\n            if not isinstance(prompt, list):\n                prompt = [prompt]\n            prompt_obj = \"list\"\n\n        if len(prompt) > CLIP_MAX_BATCH_SIZE:\n            raise ValueError(\n                f\"The maximum number of prompts that can be compared at once is {CLIP_MAX_BATCH_SIZE}\"\n            )\n\n        if prompt_type == \"image\":\n            prompt_embeddings = self.embed_image(prompt)\n        elif prompt_type == \"text\":\n            prompt_embeddings = self.embed_text(prompt)\n        else:\n            raise ValueError(\n                \"prompt_type must be either 'image' or 'text', but got {request.prompt_type}\"\n            )\n\n        similarities = [\n            cosine_similarity(subject_embeddings, p) for p in prompt_embeddings\n        ]\n\n        if prompt_obj == \"dict\":\n            similarities = dict(zip(prompt_keys, similarities))\n\n        return similarities\n\n    def make_compare_response(\n        self, similarities: Union[List[float], Dict[str, float]]\n    ) -> ClipCompareResponse:\n        \"\"\"\n        Creates a ClipCompareResponse object from the provided similarity data.\n\n        Args:\n            similarities (Union[List[float], Dict[str, float]]): A list or dictionary containing similarity scores.\n\n        Returns:\n            ClipCompareResponse: An instance of the ClipCompareResponse with the given similarity scores.\n\n        Example:\n            Assuming `ClipCompareResponse` expects a dictionary of string-float pairs:\n\n            >>> make_compare_response({\"image1\": 0.98, \"image2\": 0.76})\n            ClipCompareResponse(similarity={\"image1\": 0.98, \"image2\": 0.76})\n        \"\"\"\n        response = ClipCompareResponse(similarity=similarities)\n        return response\n\n    def embed_image(\n        self,\n        image: Any,\n        **kwargs,\n    ) -> np.ndarray:\n        \"\"\"\n        Embeds an image or a list of images using the Clip model.\n\n        Args:\n            image (Any): The image or list of images to be embedded. Image can be in any format that is acceptable by the preproc_image method.\n            **kwargs: Additional keyword arguments.\n\n        Returns:\n            np.ndarray: The embeddings of the image(s) as a numpy array.\n\n        Raises:\n            ValueError: If the number of images in the list exceeds the maximum batch size.\n\n        Notes:\n            The function measures performance using perf_counter and also has support for ONNX session to get embeddings.\n        \"\"\"\n        t1 = perf_counter()\n\n        if isinstance(image, list):\n            if len(image) > CLIP_MAX_BATCH_SIZE:\n                raise ValueError(\n                    f\"The maximum number of images that can be embedded at once is {CLIP_MAX_BATCH_SIZE}\"\n                )\n            imgs = [self.preproc_image(i) for i in image]\n            img_in = np.concatenate(imgs, axis=0)\n        else:\n            img_in = self.preproc_image(image)\n        embeddings = self._model.embed_images(images=img_in)\n        return embeddings.cpu().numpy()\n\n    def predict(self, img_in: np.ndarray, **kwargs) -> Tuple[np.ndarray]:\n        embeddings = self._model.embed_images(images=img_in)\n        return (embeddings.cpu().numpy(),)\n\n    def make_embed_image_response(\n        self, embeddings: np.ndarray\n    ) -> ClipEmbeddingResponse:\n        \"\"\"\n        Converts the given embeddings into a ClipEmbeddingResponse object.\n\n        Args:\n            embeddings (np.ndarray): A numpy array containing the embeddings for an image or images.\n\n        Returns:\n            ClipEmbeddingResponse: An instance of the ClipEmbeddingResponse with the provided embeddings converted to a list.\n\n        Example:\n            >>> embeddings_array = np.array([[0.5, 0.3, 0.2], [0.1, 0.9, 0.0]])\n            >>> make_embed_image_response(embeddings_array)\n            ClipEmbeddingResponse(embeddings=[[0.5, 0.3, 0.2], [0.1, 0.9, 0.0]])\n        \"\"\"\n        response = ClipEmbeddingResponse(embeddings=embeddings.tolist())\n\n        return response\n\n    def embed_text(\n        self,\n        text: Union[str, List[str]],\n        **kwargs,\n    ) -> np.ndarray:\n        \"\"\"\n        Embeds a text or a list of texts using the Clip model.\n\n        Args:\n            text (Union[str, List[str]]): The text string or list of text strings to be embedded.\n            **kwargs: Additional keyword arguments.\n\n        Returns:\n            np.ndarray: The embeddings of the text or texts as a numpy array.\n\n        Raises:\n            ValueError: If the number of text strings in the list exceeds the maximum batch size.\n\n        Notes:\n            The function utilizes an ONNX session to compute embeddings and measures the embedding time with perf_counter.\n        \"\"\"\n        if isinstance(text, list):\n            texts = text\n        else:\n            texts = [text]\n        embeddings = self._model.embed_text(texts=texts)\n        return embeddings.cpu().numpy()\n\n    def make_embed_text_response(self, embeddings: np.ndarray) -> ClipEmbeddingResponse:\n        \"\"\"\n        Converts the given text embeddings into a ClipEmbeddingResponse object.\n\n        Args:\n            embeddings (np.ndarray): A numpy array containing the embeddings for a text or texts.\n\n        Returns:\n            ClipEmbeddingResponse: An instance of the ClipEmbeddingResponse with the provided embeddings converted to a list.\n\n        Example:\n            >>> embeddings_array = np.array([[0.8, 0.1, 0.1], [0.4, 0.5, 0.1]])\n            >>> make_embed_text_response(embeddings_array)\n            ClipEmbeddingResponse(embeddings=[[0.8, 0.1, 0.1], [0.4, 0.5, 0.1]])\n        \"\"\"\n        response = ClipEmbeddingResponse(embeddings=embeddings.tolist())\n        return response\n\n    def infer_from_request(\n        self, request: ClipInferenceRequest\n    ) -> ClipEmbeddingResponse:\n        \"\"\"Routes the request to the appropriate inference function.\n\n        Args:\n            request (ClipInferenceRequest): The request object containing the inference details.\n\n        Returns:\n            ClipEmbeddingResponse: The response object containing the embeddings.\n        \"\"\"\n        t1 = perf_counter()\n        if isinstance(request, ClipImageEmbeddingRequest):\n            infer_func = self.embed_image\n            make_response_func = self.make_embed_image_response\n        elif isinstance(request, ClipTextEmbeddingRequest):\n            infer_func = self.embed_text\n            make_response_func = self.make_embed_text_response\n        elif isinstance(request, ClipCompareRequest):\n            infer_func = self.compare\n            make_response_func = self.make_compare_response\n        else:\n            raise ValueError(\n                f\"Request type {type(request)} is not a valid ClipInferenceRequest\"\n            )\n        data = infer_func(**request.dict())\n        response = make_response_func(data)\n        response.time = perf_counter() - t1\n        return response\n\n    def make_response(self, embeddings, *args, **kwargs) -> InferenceResponse:\n        return [self.make_embed_image_response(embeddings)]\n\n    def postprocess(\n        self,\n        predictions: Tuple[np.ndarray],\n        preprocess_return_metadata: PreprocessReturnMetadata,\n        **kwargs,\n    ) -> Any:\n        return [self.make_embed_image_response(predictions[0])]\n\n    def infer(self, image: Any, **kwargs) -> Any:\n        \"\"\"Embeds an image\n        - image:\n            can be a BGR numpy array, filepath, InferenceRequestImage, PIL Image, byte-string, etc.\n        \"\"\"\n        return super().infer(image, **kwargs)\n\n    def preproc_image(self, image: InferenceRequestImage) -> np.ndarray:\n        \"\"\"Preprocesses an inference request image.\n\n        Args:\n            image (InferenceRequestImage): The object containing information necessary to load the image for inference.\n\n        Returns:\n            np.ndarray: A numpy array of the preprocessed image pixel data.\n        \"\"\"\n        return load_image_bgr(image)\n\n    def preprocess(\n        self, image: Any, **kwargs\n    ) -> Tuple[np.ndarray, PreprocessReturnMetadata]:\n        return self.preproc_image(image), PreprocessReturnMetadata({})\n",
    "patch": null
  },
  {
    "trace_id": "84cb6370-3148-40ef-b4f4-e436de3160f7",
    "function_name": "clamp_box",
    "file_path": "inference/core/workflows/core_steps/visualizations/text_display/utils.py",
    "speedup_x": 1.8,
    "review_quality": "high",
    "pre_optimization_commit": "a58f6b10343b08a41f49e931daa24e353fabf7a9",
    "resolution_method": "db_code_match",
    "source": "db_events",
    "original_function_code": "def clamp_box(\n    box_x: int, box_y: int, box_w: int, box_h: int, img_w: int, img_h: int\n) -> Tuple[int, int]:\n    \"\"\"Clamp box position to image bounds.\"\"\"\n    box_x = 0 if box_w > img_w else max(0, min(box_x, img_w - box_w))\n    box_y = 0 if box_h > img_h else max(0, min(box_y, img_h - box_h))\n    return box_x, box_y\n",
    "optimized_function_code": "from __future__ import annotations\n\nfrom typing import Tuple\n\n\ndef clamp_box(\n    box_x: int, box_y: int, box_w: int, box_h: int, img_w: int, img_h: int\n) -> Tuple[int, int]:\n    \"\"\"Clamp box position to image bounds.\"\"\"\n    if box_w > img_w:\n        box_x = 0\n    elif box_x < 0:\n        box_x = 0\n    elif box_x > img_w - box_w:\n        box_x = img_w - box_w\n\n    if box_h > img_h:\n        box_y = 0\n    elif box_y < 0:\n        box_y = 0\n    elif box_y > img_h - box_h:\n        box_y = img_h - box_h\n\n    return box_x, box_y",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/visualizations/text_display/utils.py\nfrom __future__ import annotations\n\nfrom typing import Tuple\n\n\ndef clamp_box(\n    box_x: int, box_y: int, box_w: int, box_h: int, img_w: int, img_h: int\n) -> Tuple[int, int]:\n    \"\"\"Clamp box position to image bounds.\"\"\"\n    if box_w > img_w:\n        box_x = 0\n    elif box_x < 0:\n        box_x = 0\n    elif box_x > img_w - box_w:\n        box_x = img_w - box_w\n\n    if box_h > img_h:\n        box_y = 0\n    elif box_y < 0:\n        box_y = 0\n    elif box_y > img_h - box_h:\n        box_y = img_h - box_h\n\n    return box_x, box_y\n```",
    "optimized_function_only": "def clamp_box(\n    box_x: int, box_y: int, box_w: int, box_h: int, img_w: int, img_h: int\n) -> Tuple[int, int]:\n    \"\"\"Clamp box position to image bounds.\"\"\"\n    if box_w > img_w:\n        box_x = 0\n    elif box_x < 0:\n        box_x = 0\n    elif box_x > img_w - box_w:\n        box_x = img_w - box_w\n\n    if box_h > img_h:\n        box_y = 0\n    elif box_y < 0:\n        box_y = 0\n    elif box_y > img_h - box_h:\n        box_y = img_h - box_h\n\n    return box_x, box_y",
    "original_file_content": "from __future__ import annotations\n\nfrom dataclasses import dataclass\nfrom typing import Dict, Final, List, Optional, Tuple\n\nimport cv2\nimport numpy as np\n\nANCHORS: Final[Dict[str, Tuple[float, float]]] = {\n    \"top_left\": (0.0, 0.0),\n    \"top_center\": (0.5, 0.0),\n    \"top_right\": (1.0, 0.0),\n    \"center_left\": (0.0, 0.5),\n    \"center\": (0.5, 0.5),\n    \"center_right\": (1.0, 0.5),\n    \"bottom_left\": (0.0, 1.0),\n    \"bottom_center\": (0.5, 1.0),\n    \"bottom_right\": (1.0, 1.0),\n}\n\n\ndef calculate_relative_position(\n    anchor: str,\n    offset_x: int,\n    offset_y: int,\n    box_width: int,\n    box_height: int,\n    img_width: int,\n    img_height: int,\n) -> Tuple[int, int]:\n    \"\"\"Calculate the top-left corner position for a box positioned relative to an image anchor.\n\n    Args:\n        anchor: Anchor point name (e.g., \"top_left\", \"center\", \"bottom_right\")\n        offset_x: Horizontal offset from anchor point (positive = right)\n        offset_y: Vertical offset from anchor point (positive = down)\n        box_width: Width of the box to position\n        box_height: Height of the box to position\n        img_width: Width of the image\n        img_height: Height of the image\n\n    Returns:\n        Tuple of (x, y) coordinates for the top-left corner of the box\n\n    Raises:\n        ValueError: If anchor is not recognized\n    \"\"\"\n    key = anchor.lower()\n    try:\n        ax, ay = ANCHORS[key]\n    except KeyError as e:\n        raise ValueError(\n            f\"Unknown anchor: {anchor!r}. Must be one of {sorted(ANCHORS.keys())}\"\n        ) from e\n\n    anchor_x = int(round(ax * img_width))\n    anchor_y = int(round(ay * img_height))\n\n    box_x = anchor_x - int(round(ax * box_width)) + offset_x\n    box_y = anchor_y - int(round(ay * box_height)) + offset_y\n\n    return box_x, box_y\n\n\n@dataclass(frozen=True)\nclass TextLayout:\n    lines: List[str]\n    line_widths: List[int]\n    max_width: int\n    ref_height: int\n    line_advance: int\n    line_spacing: int\n    box_x: int\n    box_y: int\n    box_w: int\n    box_h: int\n\n\ndef clamp_box(\n    box_x: int, box_y: int, box_w: int, box_h: int, img_w: int, img_h: int\n) -> Tuple[int, int]:\n    \"\"\"Clamp box position to image bounds.\"\"\"\n    box_x = 0 if box_w > img_w else max(0, min(box_x, img_w - box_w))\n    box_y = 0 if box_h > img_h else max(0, min(box_y, img_h - box_h))\n    return box_x, box_y\n\n\ndef align_offset(text_align: str, max_width: int, line_width: int) -> int:\n    \"\"\"Calculate horizontal offset for text alignment.\"\"\"\n    if text_align == \"center\":\n        return (max_width - line_width) // 2\n    elif text_align == \"right\":\n        return max_width - line_width\n    else:  # left\n        return 0\n\n\ndef compute_layout(\n    *,\n    formatted_text: str,\n    font,\n    font_scale: float,\n    font_thickness: int,\n    padding: int,\n    position_mode: str,\n    position_x: int,\n    position_y: int,\n    anchor: str,\n    offset_x: int,\n    offset_y: int,\n    img_w: int,\n    img_h: int,\n) -> TextLayout:\n    \"\"\"Compute text layout including dimensions and position.\"\"\"\n    lines = formatted_text.split(\"\\n\") if formatted_text else [\"\"]\n    (_, ref_h), ref_base = cv2.getTextSize(\"Ag\", font, font_scale, font_thickness)\n    line_advance = ref_h + ref_base\n    line_spacing = max(1, int(round(0.25 * line_advance)))\n\n    line_widths = [\n        (\n            cv2.getTextSize(line, font, font_scale, font_thickness)[0][0]\n            if line.strip()\n            else 0\n        )\n        for line in lines\n    ]\n    max_width = max(line_widths, default=0)\n\n    num_lines = len(lines)\n    total_h = num_lines * line_advance + max(0, num_lines - 1) * line_spacing\n\n    box_w = max_width + 2 * padding\n    box_h = total_h + 2 * padding\n\n    if position_mode == \"absolute\":\n        box_x, box_y = position_x, position_y\n    else:\n        box_x, box_y = calculate_relative_position(\n            anchor=anchor,\n            offset_x=offset_x,\n            offset_y=offset_y,\n            box_width=box_w,\n            box_height=box_h,\n            img_width=img_w,\n            img_height=img_h,\n        )\n\n    box_x, box_y = clamp_box(box_x, box_y, box_w, box_h, img_w, img_h)\n\n    return TextLayout(\n        lines=lines,\n        line_widths=line_widths,\n        max_width=max_width,\n        ref_height=ref_h,\n        line_advance=line_advance,\n        line_spacing=line_spacing,\n        box_x=box_x,\n        box_y=box_y,\n        box_w=box_w,\n        box_h=box_h,\n    )\n\n\ndef draw_text_lines(\n    img: np.ndarray,\n    *,\n    layout: TextLayout,\n    padding: int,\n    text_align: str,\n    font,\n    font_scale: float,\n    font_thickness: int,\n    color_bgr: Tuple[int, int, int],\n) -> None:\n    \"\"\"Draw text lines on the image.\"\"\"\n    img_h, img_w = img.shape[:2]\n    current_y = layout.box_y + padding\n    base_x = layout.box_x + padding\n\n    for i, line in enumerate(layout.lines):\n        if line.strip():\n            w = layout.line_widths[i]\n            text_x = base_x + align_offset(text_align, layout.max_width, w)\n            text_y = current_y + layout.ref_height\n\n            if text_y > 0 and current_y < img_h and text_x < img_w:\n                cv2.putText(\n                    img,\n                    line,\n                    (text_x, text_y),\n                    font,\n                    font_scale,\n                    color_bgr,\n                    font_thickness,\n                    cv2.LINE_AA,\n                )\n\n        current_y += layout.line_advance\n        if i < len(layout.lines) - 1:\n            current_y += layout.line_spacing\n\n\ndef draw_rounded_rectangle(\n    img: np.ndarray,\n    pt1: Tuple[int, int],\n    pt2: Tuple[int, int],\n    color: Tuple[int, int, int],\n    radius: int,\n) -> None:\n    \"\"\"Draw a filled rounded rectangle on an image.\"\"\"\n    x1, y1 = pt1\n    x2, y2 = pt2\n\n    # Early return for invalid coordinates\n    if x2 <= x1 or y2 <= y1:\n        return\n\n    max_radius = min((x2 - x1) // 2, (y2 - y1) // 2)\n    radius = min(radius, max_radius)\n\n    if radius <= 0:\n        cv2.rectangle(img, pt1, pt2, color, -1)\n        return\n\n    cv2.rectangle(img, (x1 + radius, y1), (x2 - radius, y2), color, -1)\n    cv2.rectangle(img, (x1, y1 + radius), (x2, y2 - radius), color, -1)\n\n    cv2.ellipse(\n        img, (x1 + radius, y1 + radius), (radius, radius), 180, 0, 90, color, -1\n    )\n    cv2.ellipse(\n        img, (x2 - radius, y1 + radius), (radius, radius), 270, 0, 90, color, -1\n    )\n    cv2.ellipse(img, (x1 + radius, y2 - radius), (radius, radius), 90, 0, 90, color, -1)\n    cv2.ellipse(img, (x2 - radius, y2 - radius), (radius, radius), 0, 0, 90, color, -1)\n\n\ndef draw_background_with_alpha(\n    img: np.ndarray,\n    pt1: Tuple[int, int],\n    pt2: Tuple[int, int],\n    color: Tuple[int, int, int],\n    alpha: float,\n    border_radius: int,\n) -> None:\n    \"\"\"Draw a filled rectangle with alpha blending using overlay compositing.\n\n    Uses proper overlay-based alpha blending for smooth antialiased edges,\n    especially important for rounded rectangles.\n\n    Process:\n    1. Extract the affected region\n    2. Create overlay and draw shape on it\n    3. Alpha-blend overlay with original region\n    4. Write blended result back\n    \"\"\"\n    x1, y1 = pt1\n    x2, y2 = pt2\n\n    # Clamp to image bounds\n    img_h, img_w = img.shape[:2]\n    x1_clamped = max(0, x1)\n    y1_clamped = max(0, y1)\n    x2_clamped = min(img_w, x2)\n    y2_clamped = min(img_h, y2)\n\n    if x2_clamped <= x1_clamped or y2_clamped <= y1_clamped:\n        return\n\n    # Extract the region of interest\n    roi = img[y1_clamped:y2_clamped, x1_clamped:x2_clamped]\n\n    # Create overlay for just this region\n    overlay = roi.copy()\n\n    roi_w = x2_clamped - x1_clamped\n    roi_h = y2_clamped - y1_clamped\n\n    # Draw the shape onto the overlay (coordinates relative\n    # to ROI and OpenCV uses inclusive coordinates,\n    # so max index is size - 1\n    if border_radius > 0:\n        draw_rounded_rectangle(\n            img=overlay,\n            pt1=(0, 0),\n            pt2=(roi_w - 1, roi_h - 1),\n            color=color,\n            radius=border_radius,\n        )\n    else:\n        cv2.rectangle(\n            overlay,\n            (0, 0),\n            (roi_w - 1, roi_h - 1),\n            color,\n            -1,\n        )\n\n    # Alpha blend: result = overlay * alpha + original * (1 - alpha)\n    blended = cv2.addWeighted(overlay, alpha, roi, 1 - alpha, 0)\n\n    # Write blended result back to image\n    img[y1_clamped:y2_clamped, x1_clamped:x2_clamped] = blended\n\n\ndef draw_background(\n    img: np.ndarray,\n    x1: int,\n    y1: int,\n    x2: int,\n    y2: int,\n    bg_color_bgr: Optional[Tuple[int, int, int]],\n    background_opacity: float,\n    border_radius: int,\n) -> None:\n    \"\"\"Draw background rectangle with optional transparency and rounded corners.\"\"\"\n    if bg_color_bgr is None or x2 <= x1 or y2 <= y1:\n        return\n\n    if background_opacity > 0.0:\n        if background_opacity < 1.0:\n            # Alpha blending required\n            draw_background_with_alpha(\n                img=img,\n                pt1=(x1, y1),\n                pt2=(x2, y2),\n                color=bg_color_bgr,\n                alpha=background_opacity,\n                border_radius=border_radius,\n            )\n        else:\n            # Fully opaque - use direct drawing\n            # OpenCV uses inclusive coordinates, so subtract 1 from exclusive end coords\n            if border_radius > 0:\n                draw_rounded_rectangle(\n                    img=img,\n                    pt1=(x1, y1),\n                    pt2=(x2 - 1, y2 - 1),\n                    color=bg_color_bgr,\n                    radius=border_radius,\n                )\n            else:\n                cv2.rectangle(\n                    img,\n                    (x1, y1),\n                    (x2 - 1, y2 - 1),\n                    bg_color_bgr,\n                    -1,\n                )\n",
    "patch": null
  },
  {
    "trace_id": "4f1c2423-b3a1-43f2-8bb6-c15e9a23bfbe",
    "function_name": "with_route_exceptions_async",
    "file_path": "inference/core/interfaces/http/error_handlers.py",
    "speedup_x": 5.1953170300693055,
    "review_quality": "high",
    "pre_optimization_commit": "607c853289559d1117ee503cf7c703552e1306a7",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def with_route_exceptions_async(route):\n    \"\"\"\n    A decorator that wraps a FastAPI route to handle specific exceptions. If an exception\n    is caught, it returns a JSON response with the error message.\n\n    Args:\n        route (Callable): The FastAPI route to be wrapped.\n\n    Returns:\n        Callable: The wrapped route.\n    \"\"\"\n\n    @wraps(route)\n    async def wrapped_route(*args, **kwargs):\n        try:\n            try:\n                return await route(*args, **kwargs)\n            except Exception as error:\n                record_error(error)\n                record_error_metric(type(error).__name__)\n                raise\n        except ContentTypeInvalid as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Invalid Content-Type header provided with request.\"\n                },\n            )\n        except ContentTypeMissing as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\"message\": \"Content-Type header not provided with request.\"},\n            )\n        except InputImageLoadError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": f\"Could not load input image. Cause: {error.get_public_error_details()}\"\n                },\n            )\n        except ModelInputError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": f\"Error with model input. Cause: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except InvalidModelIDError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\"message\": \"Invalid Model ID sent in request.\"},\n            )\n        except InvalidMaskDecodeArgument as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Invalid mask decode argument sent. tradeoff_factor must be in [0.0, 1.0], \"\n                    \"mask_decode_mode: must be one of ['accurate', 'fast', 'tradeoff']\"\n                },\n            )\n        except MissingApiKeyError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Required Roboflow API key is missing. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except (\n            WorkflowSyntaxError,\n            InvalidReferenceTargetError,\n            ExecutionGraphStructureError,\n            StepInputDimensionalityError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=error.blocks_errors,\n            )\n            resp = JSONResponse(status_code=400, content=content.model_dump())\n        except (\n            WorkflowDefinitionError,\n            ReferenceTypeError,\n            RuntimeInputError,\n            InvalidInputTypeError,\n            OperationTypeNotRecognisedError,\n            DynamicBlockError,\n            WorkflowExecutionEngineVersionError,\n            NotSupportedExecutionEngineError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"context\": error.context,\n                    \"inner_error_type\": error.inner_error_type,\n                    \"inner_error_message\": str(error.inner_error),\n                },\n            )\n        except (\n            ProcessesManagerInvalidPayload,\n            MalformedPayloadError,\n            MessageToBigError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except (\n            RoboflowAPINotAuthorizedError,\n            ProcessesManagerAuthorisationError,\n            UnauthorizedModelAccessError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=401,\n                content={\n                    \"message\": \"Unauthorized access to roboflow API - check API key and make sure the key is valid for \"\n                    \"workspace you use. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except PaymentRequiredError as error:\n            logger.warning(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=402,\n                content={\n                    \"message\": \"Not enough credits to perform this request. Verify your workspace billing page.\"\n                },\n            )\n        except RoboflowAPIForbiddenError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=403,\n                content={\n                    \"message\": \"Unauthorized access to roboflow API - check API key and make sure the key is valid and \"\n                    \"have required scopes. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except RoboflowAPIUsagePausedError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=423,\n                content={\n                    \"message\": \"Roboflow API usage is paused. Please contact your workspace administrator to re-enable api keys.\"\n                },\n            )\n        except (RoboflowAPINotNotFoundError, ModelNotFoundError) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=404,\n                content={\n                    \"message\": \"Requested Roboflow resource not found. Make sure that workspace, project or model \"\n                    \"you referred in request exists.\"\n                },\n            )\n        except ProcessesManagerNotFoundError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=404,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except ModelPackageNegotiationError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Could not negotiate model package - {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except (\n            InvalidEnvironmentVariableError,\n            MissingServiceSecretError,\n            ServiceConfigurationError,\n            EnvironmentConfigurationError,\n            InvalidEnvVariable,\n            JetsonTypeResolutionError,\n            MissingDependencyError,\n            InvalidParameterError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500, content={\"message\": \"Service misconfiguration.\"}\n            )\n        except (\n            PreProcessingError,\n            PostProcessingError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": \"Model configuration related to pre- or post-processing is invalid.\"\n                },\n            )\n        except ModelArtefactError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500, content={\"message\": \"Model package is broken.\"}\n            )\n        except ModelLoadingError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Model loading failed: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except (UntrustedFileError, FileHashSumMissmatch) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Issue with model package file: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except ModelRetrievalError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Could not retrieve model {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except OnnxProviderNotAvailable as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=501,\n                content={\n                    \"message\": \"Could not find requested ONNX Runtime Provider. Check that you are using \"\n                    \"the correct docker image on a supported device.\"\n                },\n            )\n        except (\n            MalformedRoboflowAPIResponseError,\n            RoboflowAPIUnsuccessfulRequestError,\n            WorkspaceLoadError,\n            MalformedWorkflowResponseError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=502,\n                content={\"message\": \"Internal error. Request to Roboflow API failed.\"},\n            )\n        except InferenceModelNotFound as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\"message\": \"Model is temporarily not ready - retry request.\"},\n                headers={\"Retry-After\": \"1\"},\n            )\n        except RoboflowAPIConnectionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\n                    \"message\": \"Internal error. Could not connect to Roboflow API.\"\n                },\n            )\n        except ModelManagerLockAcquisitionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\n                    \"message\": \"Could not acquire model manager lock due to other request performing \"\n                    \"blocking operation. Try again....\"\n                },\n                headers={\"Retry-After\": \"1\"},\n            )\n        except RoboflowAPITimeoutError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=504,\n                content={\n                    \"message\": \"Timeout when attempting to connect to Roboflow API.\"\n                },\n            )\n        except ClientCausedStepExecutionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=error.block_id,\n                    ),\n                ],\n            )\n            resp = JSONResponse(\n                status_code=error.status_code,\n                content=content.model_dump(),\n            )\n        except StepExecutionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=error.block_id,\n                        block_type=error.block_type,\n                    ),\n                ],\n            )\n            resp = JSONResponse(\n                status_code=500,\n                content=content.model_dump(),\n            )\n        except WorkflowError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"context\": error.context,\n                    \"inner_error_type\": error.inner_error_type,\n                    \"inner_error_message\": str(error.inner_error),\n                },\n            )\n        except (\n            ProcessesManagerClientError,\n            CommunicationProtocolError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except WebRTCConfigurationError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": str(error),\n                    \"error_type\": \"WebRTCConfigurationError\",\n                },\n            )\n        except CreditsExceededError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=402,\n                content={\n                    \"message\": \"Not enough credits to perform this request.\",\n                    \"error_type\": \"CreditsExceededError\",\n                },\n            )\n        except WorkspaceStreamQuotaError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=429,\n                content={\n                    \"message\": str(error),\n                    \"error_type\": \"WorkspaceStreamQuotaError\",\n                },\n            )\n        except Exception as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(status_code=500, content={\"message\": \"Internal error.\"})\n        return resp\n\n    return wrapped_route\n",
    "optimized_function_code": "from functools import wraps\nfrom inference.core import logger\nfrom inference.core.entities.responses.workflows import WorkflowErrorResponse\nfrom inference.core.exceptions import ContentTypeInvalid, ContentTypeMissing, CreditsExceededError, InferenceModelNotFound, InputImageLoadError, InvalidEnvironmentVariableError, InvalidMaskDecodeArgument, InvalidModelIDError, MalformedRoboflowAPIResponseError, MalformedWorkflowResponseError, MissingApiKeyError, MissingServiceSecretError, ModelArtefactError, ModelManagerLockAcquisitionError, OnnxProviderNotAvailable, PaymentRequiredError, PostProcessingError, PreProcessingError, RoboflowAPIConnectionError, RoboflowAPIForbiddenError, RoboflowAPINotAuthorizedError, RoboflowAPINotNotFoundError, RoboflowAPITimeoutError, RoboflowAPIUnsuccessfulRequestError, RoboflowAPIUsagePausedError, ServiceConfigurationError, WebRTCConfigurationError, WorkspaceLoadError, WorkspaceStreamQuotaError\nfrom inference.core.interfaces.stream_manager.api.errors import ProcessesManagerAuthorisationError, ProcessesManagerClientError, ProcessesManagerInvalidPayload, ProcessesManagerNotFoundError\nfrom inference.core.interfaces.stream_manager.manager_app.errors import CommunicationProtocolError, MalformedPayloadError, MessageToBigError\nfrom inference.core.telemetry import record_error, record_error_metric\nfrom inference.core.workflows.core_steps.common.query_language.errors import InvalidInputTypeError, OperationTypeNotRecognisedError\nfrom inference.core.workflows.errors import ClientCausedStepExecutionError, DynamicBlockError, ExecutionGraphStructureError, InvalidReferenceTargetError, NotSupportedExecutionEngineError, ReferenceTypeError, RuntimeInputError, StepExecutionError, StepInputDimensionalityError, WorkflowBlockError, WorkflowDefinitionError, WorkflowError, WorkflowExecutionEngineVersionError, WorkflowSyntaxError\nfrom inference_models.errors import EnvironmentConfigurationError, FileHashSumMissmatch, InvalidEnvVariable, InvalidParameterError, JetsonTypeResolutionError, MissingDependencyError, ModelInputError, ModelLoadingError, ModelNotFoundError, ModelPackageNegotiationError, ModelRetrievalError, UnauthorizedModelAccessError, UntrustedFileError\nfrom starlette.responses import JSONResponse\n\ndef with_route_exceptions_async(route):\n    \"\"\"\n    A decorator that wraps a FastAPI route to handle specific exceptions. If an exception\n    is caught, it returns a JSON response with the error message.\n\n    Args:\n        route (Callable): The FastAPI route to be wrapped.\n\n    Returns:\n        Callable: The wrapped route.\n    \"\"\"\n\n    async def wrapped_route(*args, **kwargs):\n        try:\n            try:\n                return await route(*args, **kwargs)\n            except Exception as error:\n                record_error(error)\n                record_error_metric(type(error).__name__)\n                raise\n        except ContentTypeInvalid as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Invalid Content-Type header provided with request.\"\n                },\n            )\n        except ContentTypeMissing as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\"message\": \"Content-Type header not provided with request.\"},\n            )\n        except InputImageLoadError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": f\"Could not load input image. Cause: {error.get_public_error_details()}\"\n                },\n            )\n        except ModelInputError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": f\"Error with model input. Cause: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except InvalidModelIDError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\"message\": \"Invalid Model ID sent in request.\"},\n            )\n        except InvalidMaskDecodeArgument as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Invalid mask decode argument sent. tradeoff_factor must be in [0.0, 1.0], \"\n                    \"mask_decode_mode: must be one of ['accurate', 'fast', 'tradeoff']\"\n                },\n            )\n        except MissingApiKeyError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Required Roboflow API key is missing. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except (\n            WorkflowSyntaxError,\n            InvalidReferenceTargetError,\n            ExecutionGraphStructureError,\n            StepInputDimensionalityError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=error.blocks_errors,\n            )\n            resp = JSONResponse(status_code=400, content=content.model_dump())\n        except (\n            WorkflowDefinitionError,\n            ReferenceTypeError,\n            RuntimeInputError,\n            InvalidInputTypeError,\n            OperationTypeNotRecognisedError,\n            DynamicBlockError,\n            WorkflowExecutionEngineVersionError,\n            NotSupportedExecutionEngineError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"context\": error.context,\n                    \"inner_error_type\": error.inner_error_type,\n                    \"inner_error_message\": str(error.inner_error),\n                },\n            )\n        except (\n            ProcessesManagerInvalidPayload,\n            MalformedPayloadError,\n            MessageToBigError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except (\n            RoboflowAPINotAuthorizedError,\n            ProcessesManagerAuthorisationError,\n            UnauthorizedModelAccessError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=401,\n                content={\n                    \"message\": \"Unauthorized access to roboflow API - check API key and make sure the key is valid for \"\n                    \"workspace you use. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except PaymentRequiredError as error:\n            logger.warning(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=402,\n                content={\n                    \"message\": \"Not enough credits to perform this request. Verify your workspace billing page.\"\n                },\n            )\n        except RoboflowAPIForbiddenError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=403,\n                content={\n                    \"message\": \"Unauthorized access to roboflow API - check API key and make sure the key is valid and \"\n                    \"have required scopes. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except RoboflowAPIUsagePausedError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=423,\n                content={\n                    \"message\": \"Roboflow API usage is paused. Please contact your workspace administrator to re-enable api keys.\"\n                },\n            )\n        except (RoboflowAPINotNotFoundError, ModelNotFoundError) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=404,\n                content={\n                    \"message\": \"Requested Roboflow resource not found. Make sure that workspace, project or model \"\n                    \"you referred in request exists.\"\n                },\n            )\n        except ProcessesManagerNotFoundError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=404,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except ModelPackageNegotiationError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Could not negotiate model package - {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except (\n            InvalidEnvironmentVariableError,\n            MissingServiceSecretError,\n            ServiceConfigurationError,\n            EnvironmentConfigurationError,\n            InvalidEnvVariable,\n            JetsonTypeResolutionError,\n            MissingDependencyError,\n            InvalidParameterError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500, content={\"message\": \"Service misconfiguration.\"}\n            )\n        except (\n            PreProcessingError,\n            PostProcessingError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": \"Model configuration related to pre- or post-processing is invalid.\"\n                },\n            )\n        except ModelArtefactError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500, content={\"message\": \"Model package is broken.\"}\n            )\n        except ModelLoadingError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Model loading failed: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except (UntrustedFileError, FileHashSumMissmatch) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Issue with model package file: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except ModelRetrievalError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Could not retrieve model {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except OnnxProviderNotAvailable as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=501,\n                content={\n                    \"message\": \"Could not find requested ONNX Runtime Provider. Check that you are using \"\n                    \"the correct docker image on a supported device.\"\n                },\n            )\n        except (\n            MalformedRoboflowAPIResponseError,\n            RoboflowAPIUnsuccessfulRequestError,\n            WorkspaceLoadError,\n            MalformedWorkflowResponseError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=502,\n                content={\"message\": \"Internal error. Request to Roboflow API failed.\"},\n            )\n        except InferenceModelNotFound as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\"message\": \"Model is temporarily not ready - retry request.\"},\n                headers={\"Retry-After\": \"1\"},\n            )\n        except RoboflowAPIConnectionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\n                    \"message\": \"Internal error. Could not connect to Roboflow API.\"\n                },\n            )\n        except ModelManagerLockAcquisitionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\n                    \"message\": \"Could not acquire model manager lock due to other request performing \"\n                    \"blocking operation. Try again....\"\n                },\n                headers={\"Retry-After\": \"1\"},\n            )\n        except RoboflowAPITimeoutError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=504,\n                content={\n                    \"message\": \"Timeout when attempting to connect to Roboflow API.\"\n                },\n            )\n        except ClientCausedStepExecutionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=error.block_id,\n                    ),\n                ],\n            )\n            resp = JSONResponse(\n                status_code=error.status_code,\n                content=content.model_dump(),\n            )\n        except StepExecutionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=error.block_id,\n                        block_type=error.block_type,\n                    ),\n                ],\n            )\n            resp = JSONResponse(\n                status_code=500,\n                content=content.model_dump(),\n            )\n        except WorkflowError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"context\": error.context,\n                    \"inner_error_type\": error.inner_error_type,\n                    \"inner_error_message\": str(error.inner_error),\n                },\n            )\n        except (\n            ProcessesManagerClientError,\n            CommunicationProtocolError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except WebRTCConfigurationError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": str(error),\n                    \"error_type\": \"WebRTCConfigurationError\",\n                },\n            )\n        except CreditsExceededError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=402,\n                content={\n                    \"message\": \"Not enough credits to perform this request.\",\n                    \"error_type\": \"CreditsExceededError\",\n                },\n            )\n        except WorkspaceStreamQuotaError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=429,\n                content={\n                    \"message\": str(error),\n                    \"error_type\": \"WorkspaceStreamQuotaError\",\n                },\n            )\n        except Exception as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(status_code=500, content={\"message\": \"Internal error.\"})\n        return resp\n\n    wrapped_route.__wrapped__ = route\n    return wrapped_route",
    "optimized_raw_markdown": "```python:inference/core/interfaces/http/error_handlers.py\nfrom functools import wraps\nfrom inference.core import logger\nfrom inference.core.entities.responses.workflows import WorkflowErrorResponse\nfrom inference.core.exceptions import ContentTypeInvalid, ContentTypeMissing, CreditsExceededError, InferenceModelNotFound, InputImageLoadError, InvalidEnvironmentVariableError, InvalidMaskDecodeArgument, InvalidModelIDError, MalformedRoboflowAPIResponseError, MalformedWorkflowResponseError, MissingApiKeyError, MissingServiceSecretError, ModelArtefactError, ModelManagerLockAcquisitionError, OnnxProviderNotAvailable, PaymentRequiredError, PostProcessingError, PreProcessingError, RoboflowAPIConnectionError, RoboflowAPIForbiddenError, RoboflowAPINotAuthorizedError, RoboflowAPINotNotFoundError, RoboflowAPITimeoutError, RoboflowAPIUnsuccessfulRequestError, RoboflowAPIUsagePausedError, ServiceConfigurationError, WebRTCConfigurationError, WorkspaceLoadError, WorkspaceStreamQuotaError\nfrom inference.core.interfaces.stream_manager.api.errors import ProcessesManagerAuthorisationError, ProcessesManagerClientError, ProcessesManagerInvalidPayload, ProcessesManagerNotFoundError\nfrom inference.core.interfaces.stream_manager.manager_app.errors import CommunicationProtocolError, MalformedPayloadError, MessageToBigError\nfrom inference.core.telemetry import record_error, record_error_metric\nfrom inference.core.workflows.core_steps.common.query_language.errors import InvalidInputTypeError, OperationTypeNotRecognisedError\nfrom inference.core.workflows.errors import ClientCausedStepExecutionError, DynamicBlockError, ExecutionGraphStructureError, InvalidReferenceTargetError, NotSupportedExecutionEngineError, ReferenceTypeError, RuntimeInputError, StepExecutionError, StepInputDimensionalityError, WorkflowBlockError, WorkflowDefinitionError, WorkflowError, WorkflowExecutionEngineVersionError, WorkflowSyntaxError\nfrom inference_models.errors import EnvironmentConfigurationError, FileHashSumMissmatch, InvalidEnvVariable, InvalidParameterError, JetsonTypeResolutionError, MissingDependencyError, ModelInputError, ModelLoadingError, ModelNotFoundError, ModelPackageNegotiationError, ModelRetrievalError, UnauthorizedModelAccessError, UntrustedFileError\nfrom starlette.responses import JSONResponse\n\ndef with_route_exceptions_async(route):\n    \"\"\"\n    A decorator that wraps a FastAPI route to handle specific exceptions. If an exception\n    is caught, it returns a JSON response with the error message.\n\n    Args:\n        route (Callable): The FastAPI route to be wrapped.\n\n    Returns:\n        Callable: The wrapped route.\n    \"\"\"\n\n    async def wrapped_route(*args, **kwargs):\n        try:\n            try:\n                return await route(*args, **kwargs)\n            except Exception as error:\n                record_error(error)\n                record_error_metric(type(error).__name__)\n                raise\n        except ContentTypeInvalid as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Invalid Content-Type header provided with request.\"\n                },\n            )\n        except ContentTypeMissing as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\"message\": \"Content-Type header not provided with request.\"},\n            )\n        except InputImageLoadError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": f\"Could not load input image. Cause: {error.get_public_error_details()}\"\n                },\n            )\n        except ModelInputError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": f\"Error with model input. Cause: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except InvalidModelIDError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\"message\": \"Invalid Model ID sent in request.\"},\n            )\n        except InvalidMaskDecodeArgument as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Invalid mask decode argument sent. tradeoff_factor must be in [0.0, 1.0], \"\n                    \"mask_decode_mode: must be one of ['accurate', 'fast', 'tradeoff']\"\n                },\n            )\n        except MissingApiKeyError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Required Roboflow API key is missing. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except (\n            WorkflowSyntaxError,\n            InvalidReferenceTargetError,\n            ExecutionGraphStructureError,\n            StepInputDimensionalityError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=error.blocks_errors,\n            )\n            resp = JSONResponse(status_code=400, content=content.model_dump())\n        except (\n            WorkflowDefinitionError,\n            ReferenceTypeError,\n            RuntimeInputError,\n            InvalidInputTypeError,\n            OperationTypeNotRecognisedError,\n            DynamicBlockError,\n            WorkflowExecutionEngineVersionError,\n            NotSupportedExecutionEngineError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"context\": error.context,\n                    \"inner_error_type\": error.inner_error_type,\n                    \"inner_error_message\": str(error.inner_error),\n                },\n            )\n        except (\n            ProcessesManagerInvalidPayload,\n            MalformedPayloadError,\n            MessageToBigError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except (\n            RoboflowAPINotAuthorizedError,\n            ProcessesManagerAuthorisationError,\n            UnauthorizedModelAccessError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=401,\n                content={\n                    \"message\": \"Unauthorized access to roboflow API - check API key and make sure the key is valid for \"\n                    \"workspace you use. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except PaymentRequiredError as error:\n            logger.warning(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=402,\n                content={\n                    \"message\": \"Not enough credits to perform this request. Verify your workspace billing page.\"\n                },\n            )\n        except RoboflowAPIForbiddenError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=403,\n                content={\n                    \"message\": \"Unauthorized access to roboflow API - check API key and make sure the key is valid and \"\n                    \"have required scopes. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except RoboflowAPIUsagePausedError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=423,\n                content={\n                    \"message\": \"Roboflow API usage is paused. Please contact your workspace administrator to re-enable api keys.\"\n                },\n            )\n        except (RoboflowAPINotNotFoundError, ModelNotFoundError) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=404,\n                content={\n                    \"message\": \"Requested Roboflow resource not found. Make sure that workspace, project or model \"\n                    \"you referred in request exists.\"\n                },\n            )\n        except ProcessesManagerNotFoundError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=404,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except ModelPackageNegotiationError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Could not negotiate model package - {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except (\n            InvalidEnvironmentVariableError,\n            MissingServiceSecretError,\n            ServiceConfigurationError,\n            EnvironmentConfigurationError,\n            InvalidEnvVariable,\n            JetsonTypeResolutionError,\n            MissingDependencyError,\n            InvalidParameterError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500, content={\"message\": \"Service misconfiguration.\"}\n            )\n        except (\n            PreProcessingError,\n            PostProcessingError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": \"Model configuration related to pre- or post-processing is invalid.\"\n                },\n            )\n        except ModelArtefactError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500, content={\"message\": \"Model package is broken.\"}\n            )\n        except ModelLoadingError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Model loading failed: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except (UntrustedFileError, FileHashSumMissmatch) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Issue with model package file: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except ModelRetrievalError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Could not retrieve model {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except OnnxProviderNotAvailable as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=501,\n                content={\n                    \"message\": \"Could not find requested ONNX Runtime Provider. Check that you are using \"\n                    \"the correct docker image on a supported device.\"\n                },\n            )\n        except (\n            MalformedRoboflowAPIResponseError,\n            RoboflowAPIUnsuccessfulRequestError,\n            WorkspaceLoadError,\n            MalformedWorkflowResponseError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=502,\n                content={\"message\": \"Internal error. Request to Roboflow API failed.\"},\n            )\n        except InferenceModelNotFound as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\"message\": \"Model is temporarily not ready - retry request.\"},\n                headers={\"Retry-After\": \"1\"},\n            )\n        except RoboflowAPIConnectionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\n                    \"message\": \"Internal error. Could not connect to Roboflow API.\"\n                },\n            )\n        except ModelManagerLockAcquisitionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\n                    \"message\": \"Could not acquire model manager lock due to other request performing \"\n                    \"blocking operation. Try again....\"\n                },\n                headers={\"Retry-After\": \"1\"},\n            )\n        except RoboflowAPITimeoutError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=504,\n                content={\n                    \"message\": \"Timeout when attempting to connect to Roboflow API.\"\n                },\n            )\n        except ClientCausedStepExecutionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=error.block_id,\n                    ),\n                ],\n            )\n            resp = JSONResponse(\n                status_code=error.status_code,\n                content=content.model_dump(),\n            )\n        except StepExecutionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=error.block_id,\n                        block_type=error.block_type,\n                    ),\n                ],\n            )\n            resp = JSONResponse(\n                status_code=500,\n                content=content.model_dump(),\n            )\n        except WorkflowError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"context\": error.context,\n                    \"inner_error_type\": error.inner_error_type,\n                    \"inner_error_message\": str(error.inner_error),\n                },\n            )\n        except (\n            ProcessesManagerClientError,\n            CommunicationProtocolError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except WebRTCConfigurationError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": str(error),\n                    \"error_type\": \"WebRTCConfigurationError\",\n                },\n            )\n        except CreditsExceededError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=402,\n                content={\n                    \"message\": \"Not enough credits to perform this request.\",\n                    \"error_type\": \"CreditsExceededError\",\n                },\n            )\n        except WorkspaceStreamQuotaError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=429,\n                content={\n                    \"message\": str(error),\n                    \"error_type\": \"WorkspaceStreamQuotaError\",\n                },\n            )\n        except Exception as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(status_code=500, content={\"message\": \"Internal error.\"})\n        return resp\n\n    wrapped_route.__wrapped__ = route\n    return wrapped_route\n```",
    "optimized_function_only": "def with_route_exceptions_async(route):\n    \"\"\"\n    A decorator that wraps a FastAPI route to handle specific exceptions. If an exception\n    is caught, it returns a JSON response with the error message.\n\n    Args:\n        route (Callable): The FastAPI route to be wrapped.\n\n    Returns:\n        Callable: The wrapped route.\n    \"\"\"\n\n    async def wrapped_route(*args, **kwargs):\n        try:\n            try:\n                return await route(*args, **kwargs)\n            except Exception as error:\n                record_error(error)\n                record_error_metric(type(error).__name__)\n                raise\n        except ContentTypeInvalid as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Invalid Content-Type header provided with request.\"\n                },\n            )\n        except ContentTypeMissing as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\"message\": \"Content-Type header not provided with request.\"},\n            )\n        except InputImageLoadError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": f\"Could not load input image. Cause: {error.get_public_error_details()}\"\n                },\n            )\n        except ModelInputError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": f\"Error with model input. Cause: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except InvalidModelIDError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\"message\": \"Invalid Model ID sent in request.\"},\n            )\n        except InvalidMaskDecodeArgument as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Invalid mask decode argument sent. tradeoff_factor must be in [0.0, 1.0], \"\n                    \"mask_decode_mode: must be one of ['accurate', 'fast', 'tradeoff']\"\n                },\n            )\n        except MissingApiKeyError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Required Roboflow API key is missing. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except (\n            WorkflowSyntaxError,\n            InvalidReferenceTargetError,\n            ExecutionGraphStructureError,\n            StepInputDimensionalityError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=error.blocks_errors,\n            )\n            resp = JSONResponse(status_code=400, content=content.model_dump())\n        except (\n            WorkflowDefinitionError,\n            ReferenceTypeError,\n            RuntimeInputError,\n            InvalidInputTypeError,\n            OperationTypeNotRecognisedError,\n            DynamicBlockError,\n            WorkflowExecutionEngineVersionError,\n            NotSupportedExecutionEngineError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"context\": error.context,\n                    \"inner_error_type\": error.inner_error_type,\n                    \"inner_error_message\": str(error.inner_error),\n                },\n            )\n        except (\n            ProcessesManagerInvalidPayload,\n            MalformedPayloadError,\n            MessageToBigError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except (\n            RoboflowAPINotAuthorizedError,\n            ProcessesManagerAuthorisationError,\n            UnauthorizedModelAccessError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=401,\n                content={\n                    \"message\": \"Unauthorized access to roboflow API - check API key and make sure the key is valid for \"\n                    \"workspace you use. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except PaymentRequiredError as error:\n            logger.warning(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=402,\n                content={\n                    \"message\": \"Not enough credits to perform this request. Verify your workspace billing page.\"\n                },\n            )\n        except RoboflowAPIForbiddenError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=403,\n                content={\n                    \"message\": \"Unauthorized access to roboflow API - check API key and make sure the key is valid and \"\n                    \"have required scopes. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except RoboflowAPIUsagePausedError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=423,\n                content={\n                    \"message\": \"Roboflow API usage is paused. Please contact your workspace administrator to re-enable api keys.\"\n                },\n            )\n        except (RoboflowAPINotNotFoundError, ModelNotFoundError) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=404,\n                content={\n                    \"message\": \"Requested Roboflow resource not found. Make sure that workspace, project or model \"\n                    \"you referred in request exists.\"\n                },\n            )\n        except ProcessesManagerNotFoundError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=404,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except ModelPackageNegotiationError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Could not negotiate model package - {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except (\n            InvalidEnvironmentVariableError,\n            MissingServiceSecretError,\n            ServiceConfigurationError,\n            EnvironmentConfigurationError,\n            InvalidEnvVariable,\n            JetsonTypeResolutionError,\n            MissingDependencyError,\n            InvalidParameterError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500, content={\"message\": \"Service misconfiguration.\"}\n            )\n        except (\n            PreProcessingError,\n            PostProcessingError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": \"Model configuration related to pre- or post-processing is invalid.\"\n                },\n            )\n        except ModelArtefactError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500, content={\"message\": \"Model package is broken.\"}\n            )\n        except ModelLoadingError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Model loading failed: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except (UntrustedFileError, FileHashSumMissmatch) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Issue with model package file: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except ModelRetrievalError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Could not retrieve model {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except OnnxProviderNotAvailable as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=501,\n                content={\n                    \"message\": \"Could not find requested ONNX Runtime Provider. Check that you are using \"\n                    \"the correct docker image on a supported device.\"\n                },\n            )\n        except (\n            MalformedRoboflowAPIResponseError,\n            RoboflowAPIUnsuccessfulRequestError,\n            WorkspaceLoadError,\n            MalformedWorkflowResponseError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=502,\n                content={\"message\": \"Internal error. Request to Roboflow API failed.\"},\n            )\n        except InferenceModelNotFound as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\"message\": \"Model is temporarily not ready - retry request.\"},\n                headers={\"Retry-After\": \"1\"},\n            )\n        except RoboflowAPIConnectionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\n                    \"message\": \"Internal error. Could not connect to Roboflow API.\"\n                },\n            )\n        except ModelManagerLockAcquisitionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\n                    \"message\": \"Could not acquire model manager lock due to other request performing \"\n                    \"blocking operation. Try again....\"\n                },\n                headers={\"Retry-After\": \"1\"},\n            )\n        except RoboflowAPITimeoutError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=504,\n                content={\n                    \"message\": \"Timeout when attempting to connect to Roboflow API.\"\n                },\n            )\n        except ClientCausedStepExecutionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=error.block_id,\n                    ),\n                ],\n            )\n            resp = JSONResponse(\n                status_code=error.status_code,\n                content=content.model_dump(),\n            )\n        except StepExecutionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=error.block_id,\n                        block_type=error.block_type,\n                    ),\n                ],\n            )\n            resp = JSONResponse(\n                status_code=500,\n                content=content.model_dump(),\n            )\n        except WorkflowError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"context\": error.context,\n                    \"inner_error_type\": error.inner_error_type,\n                    \"inner_error_message\": str(error.inner_error),\n                },\n            )\n        except (\n            ProcessesManagerClientError,\n            CommunicationProtocolError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except WebRTCConfigurationError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": str(error),\n                    \"error_type\": \"WebRTCConfigurationError\",\n                },\n            )\n        except CreditsExceededError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=402,\n                content={\n                    \"message\": \"Not enough credits to perform this request.\",\n                    \"error_type\": \"CreditsExceededError\",\n                },\n            )\n        except WorkspaceStreamQuotaError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=429,\n                content={\n                    \"message\": str(error),\n                    \"error_type\": \"WorkspaceStreamQuotaError\",\n                },\n            )\n        except Exception as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(status_code=500, content={\"message\": \"Internal error.\"})\n        return resp\n\n    wrapped_route.__wrapped__ = route\n    return wrapped_route",
    "original_file_content": "from functools import wraps\n\nfrom starlette.responses import JSONResponse\n\nfrom inference.core import logger\nfrom inference.core.entities.responses.workflows import WorkflowErrorResponse\nfrom inference.core.exceptions import (\n    ContentTypeInvalid,\n    ContentTypeMissing,\n    CreditsExceededError,\n    InferenceModelNotFound,\n    InputImageLoadError,\n    InvalidEnvironmentVariableError,\n    InvalidMaskDecodeArgument,\n    InvalidModelIDError,\n    MalformedRoboflowAPIResponseError,\n    MalformedWorkflowResponseError,\n    MissingApiKeyError,\n    MissingServiceSecretError,\n    ModelArtefactError,\n    ModelManagerLockAcquisitionError,\n    OnnxProviderNotAvailable,\n    PaymentRequiredError,\n    PostProcessingError,\n    PreProcessingError,\n    RoboflowAPIConnectionError,\n    RoboflowAPIForbiddenError,\n    RoboflowAPINotAuthorizedError,\n    RoboflowAPINotNotFoundError,\n    RoboflowAPITimeoutError,\n    RoboflowAPIUnsuccessfulRequestError,\n    RoboflowAPIUsagePausedError,\n    ServiceConfigurationError,\n    WebRTCConfigurationError,\n    WorkspaceLoadError,\n    WorkspaceStreamQuotaError,\n)\nfrom inference.core.interfaces.stream_manager.api.errors import (\n    ProcessesManagerAuthorisationError,\n    ProcessesManagerClientError,\n    ProcessesManagerInvalidPayload,\n    ProcessesManagerNotFoundError,\n)\nfrom inference.core.interfaces.stream_manager.manager_app.errors import (\n    CommunicationProtocolError,\n    MalformedPayloadError,\n    MessageToBigError,\n)\nfrom inference.core.telemetry import record_error, record_error_metric\nfrom inference.core.workflows.core_steps.common.query_language.errors import (\n    InvalidInputTypeError,\n    OperationTypeNotRecognisedError,\n)\nfrom inference.core.workflows.errors import (\n    ClientCausedStepExecutionError,\n    DynamicBlockError,\n    ExecutionGraphStructureError,\n    InvalidReferenceTargetError,\n    NotSupportedExecutionEngineError,\n    ReferenceTypeError,\n    RuntimeInputError,\n    StepExecutionError,\n    StepInputDimensionalityError,\n    WorkflowBlockError,\n    WorkflowDefinitionError,\n    WorkflowError,\n    WorkflowExecutionEngineVersionError,\n    WorkflowSyntaxError,\n)\nfrom inference_models.errors import (\n    EnvironmentConfigurationError,\n    FileHashSumMissmatch,\n    InvalidEnvVariable,\n    InvalidParameterError,\n    JetsonTypeResolutionError,\n    MissingDependencyError,\n    ModelInputError,\n    ModelLoadingError,\n    ModelNotFoundError,\n    ModelPackageNegotiationError,\n    ModelRetrievalError,\n    UnauthorizedModelAccessError,\n    UntrustedFileError,\n)\n\n\ndef with_route_exceptions(route):\n    \"\"\"\n    A decorator that wraps a FastAPI route to handle specific exceptions. If an exception\n    is caught, it returns a JSON response with the error message.\n\n    Args:\n        route (Callable): The FastAPI route to be wrapped.\n\n    Returns:\n        Callable: The wrapped route.\n    \"\"\"\n\n    @wraps(route)\n    def wrapped_route(*args, **kwargs):\n        try:\n            try:\n                return route(*args, **kwargs)\n            except Exception as error:\n                record_error(error)\n                record_error_metric(type(error).__name__)\n                raise\n        except ContentTypeInvalid as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Invalid Content-Type header provided with request.\"\n                },\n            )\n        except ContentTypeMissing as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\"message\": \"Content-Type header not provided with request.\"},\n            )\n        except InputImageLoadError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": f\"Could not load input image. Cause: {error.get_public_error_details()}\"\n                },\n            )\n        except ModelInputError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": f\"Error with model input. Cause: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except InvalidModelIDError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\"message\": \"Invalid Model ID sent in request.\"},\n            )\n        except InvalidMaskDecodeArgument as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Invalid mask decode argument sent. tradeoff_factor must be in [0.0, 1.0], \"\n                    \"mask_decode_mode: must be one of ['accurate', 'fast', 'tradeoff']\"\n                },\n            )\n        except MissingApiKeyError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Required Roboflow API key is missing. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except (\n            WorkflowSyntaxError,\n            InvalidReferenceTargetError,\n            ExecutionGraphStructureError,\n            StepInputDimensionalityError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=error.blocks_errors,\n            )\n            resp = JSONResponse(status_code=400, content=content.model_dump())\n        except (\n            WorkflowDefinitionError,\n            ReferenceTypeError,\n            RuntimeInputError,\n            InvalidInputTypeError,\n            OperationTypeNotRecognisedError,\n            DynamicBlockError,\n            WorkflowExecutionEngineVersionError,\n            NotSupportedExecutionEngineError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"context\": error.context,\n                    \"inner_error_type\": error.inner_error_type,\n                    \"inner_error_message\": str(error.inner_error),\n                },\n            )\n        except (\n            ProcessesManagerInvalidPayload,\n            MalformedPayloadError,\n            MessageToBigError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except (\n            RoboflowAPINotAuthorizedError,\n            ProcessesManagerAuthorisationError,\n            UnauthorizedModelAccessError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=401,\n                content={\n                    \"message\": \"Unauthorized access to roboflow API - check API key and make sure the key is valid for \"\n                    \"workspace you use. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except PaymentRequiredError as error:\n            logger.warning(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=402,\n                content={\n                    \"message\": \"Not enough credits to perform this request. Verify your workspace billing page.\"\n                },\n            )\n        except RoboflowAPIForbiddenError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=403,\n                content={\n                    \"message\": \"Unauthorized access to roboflow API - check API key and make sure the key is valid and \"\n                    \"have required scopes. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except RoboflowAPIUsagePausedError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=423,\n                content={\n                    \"message\": \"Roboflow API usage is paused. Please contact your workspace administrator to re-enable api keys.\"\n                },\n            )\n        except (RoboflowAPINotNotFoundError, ModelNotFoundError) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=404,\n                content={\n                    \"message\": \"Requested Roboflow resource not found. Make sure that workspace, project or model \"\n                    \"you referred in request exists.\"\n                },\n            )\n        except ProcessesManagerNotFoundError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=404,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except ModelPackageNegotiationError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Could not negotiate model package - {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except (\n            InvalidEnvironmentVariableError,\n            MissingServiceSecretError,\n            ServiceConfigurationError,\n            EnvironmentConfigurationError,\n            InvalidEnvVariable,\n            JetsonTypeResolutionError,\n            MissingDependencyError,\n            InvalidParameterError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500, content={\"message\": \"Service misconfiguration.\"}\n            )\n        except (\n            PreProcessingError,\n            PostProcessingError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": \"Model configuration related to pre- or post-processing is invalid.\"\n                },\n            )\n        except ModelArtefactError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500, content={\"message\": \"Model package is broken.\"}\n            )\n        except ModelLoadingError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Model loading failed: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except (UntrustedFileError, FileHashSumMissmatch) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Issue with model package file: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except ModelRetrievalError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Could not retrieve model {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except OnnxProviderNotAvailable as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=501,\n                content={\n                    \"message\": \"Could not find requested ONNX Runtime Provider. Check that you are using \"\n                    \"the correct docker image on a supported device.\"\n                },\n            )\n        except (\n            MalformedRoboflowAPIResponseError,\n            RoboflowAPIUnsuccessfulRequestError,\n            WorkspaceLoadError,\n            MalformedWorkflowResponseError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=502,\n                content={\"message\": \"Internal error. Request to Roboflow API failed.\"},\n            )\n        except InferenceModelNotFound as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\"message\": \"Model is temporarily not ready - retry request.\"},\n                headers={\"Retry-After\": \"1\"},\n            )\n        except RoboflowAPIConnectionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\n                    \"message\": \"Internal error. Could not connect to Roboflow API.\"\n                },\n            )\n        except ModelManagerLockAcquisitionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\n                    \"message\": \"Could not acquire model manager lock due to other request performing \"\n                    \"blocking operation. Try again....\"\n                },\n                headers={\"Retry-After\": \"1\"},\n            )\n        except RoboflowAPITimeoutError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=504,\n                content={\n                    \"message\": \"Timeout when attempting to connect to Roboflow API.\"\n                },\n            )\n        except ClientCausedStepExecutionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=error.block_id,\n                    ),\n                ],\n            )\n            resp = JSONResponse(\n                status_code=error.status_code,\n                content=content.model_dump(),\n            )\n        except StepExecutionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=error.block_id,\n                        block_type=error.block_type,\n                    ),\n                ],\n            )\n            resp = JSONResponse(\n                status_code=500,\n                content=content.model_dump(),\n            )\n        except WorkflowError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"context\": error.context,\n                    \"inner_error_type\": error.inner_error_type,\n                    \"inner_error_message\": str(error.inner_error),\n                },\n            )\n        except (\n            ProcessesManagerClientError,\n            CommunicationProtocolError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except WebRTCConfigurationError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": str(error),\n                    \"error_type\": \"WebRTCConfigurationError\",\n                },\n            )\n        except CreditsExceededError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=402,\n                content={\n                    \"message\": \"Not enough credits to perform this request.\",\n                    \"error_type\": \"CreditsExceededError\",\n                },\n            )\n        except WorkspaceStreamQuotaError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=429,\n                content={\n                    \"message\": str(error),\n                    \"error_type\": \"WorkspaceStreamQuotaError\",\n                },\n            )\n        except Exception as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(status_code=500, content={\"message\": \"Internal error.\"})\n        return resp\n\n    return wrapped_route\n\n\ndef with_route_exceptions_async(route):\n    \"\"\"\n    A decorator that wraps a FastAPI route to handle specific exceptions. If an exception\n    is caught, it returns a JSON response with the error message.\n\n    Args:\n        route (Callable): The FastAPI route to be wrapped.\n\n    Returns:\n        Callable: The wrapped route.\n    \"\"\"\n\n    @wraps(route)\n    async def wrapped_route(*args, **kwargs):\n        try:\n            try:\n                return await route(*args, **kwargs)\n            except Exception as error:\n                record_error(error)\n                record_error_metric(type(error).__name__)\n                raise\n        except ContentTypeInvalid as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Invalid Content-Type header provided with request.\"\n                },\n            )\n        except ContentTypeMissing as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\"message\": \"Content-Type header not provided with request.\"},\n            )\n        except InputImageLoadError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": f\"Could not load input image. Cause: {error.get_public_error_details()}\"\n                },\n            )\n        except ModelInputError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": f\"Error with model input. Cause: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except InvalidModelIDError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\"message\": \"Invalid Model ID sent in request.\"},\n            )\n        except InvalidMaskDecodeArgument as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Invalid mask decode argument sent. tradeoff_factor must be in [0.0, 1.0], \"\n                    \"mask_decode_mode: must be one of ['accurate', 'fast', 'tradeoff']\"\n                },\n            )\n        except MissingApiKeyError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Required Roboflow API key is missing. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except (\n            WorkflowSyntaxError,\n            InvalidReferenceTargetError,\n            ExecutionGraphStructureError,\n            StepInputDimensionalityError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=error.blocks_errors,\n            )\n            resp = JSONResponse(status_code=400, content=content.model_dump())\n        except (\n            WorkflowDefinitionError,\n            ReferenceTypeError,\n            RuntimeInputError,\n            InvalidInputTypeError,\n            OperationTypeNotRecognisedError,\n            DynamicBlockError,\n            WorkflowExecutionEngineVersionError,\n            NotSupportedExecutionEngineError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"context\": error.context,\n                    \"inner_error_type\": error.inner_error_type,\n                    \"inner_error_message\": str(error.inner_error),\n                },\n            )\n        except (\n            ProcessesManagerInvalidPayload,\n            MalformedPayloadError,\n            MessageToBigError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except (\n            RoboflowAPINotAuthorizedError,\n            ProcessesManagerAuthorisationError,\n            UnauthorizedModelAccessError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=401,\n                content={\n                    \"message\": \"Unauthorized access to roboflow API - check API key and make sure the key is valid for \"\n                    \"workspace you use. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except PaymentRequiredError as error:\n            logger.warning(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=402,\n                content={\n                    \"message\": \"Not enough credits to perform this request. Verify your workspace billing page.\"\n                },\n            )\n        except RoboflowAPIForbiddenError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=403,\n                content={\n                    \"message\": \"Unauthorized access to roboflow API - check API key and make sure the key is valid and \"\n                    \"have required scopes. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except RoboflowAPIUsagePausedError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=423,\n                content={\n                    \"message\": \"Roboflow API usage is paused. Please contact your workspace administrator to re-enable api keys.\"\n                },\n            )\n        except (RoboflowAPINotNotFoundError, ModelNotFoundError) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=404,\n                content={\n                    \"message\": \"Requested Roboflow resource not found. Make sure that workspace, project or model \"\n                    \"you referred in request exists.\"\n                },\n            )\n        except ProcessesManagerNotFoundError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=404,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except ModelPackageNegotiationError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Could not negotiate model package - {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except (\n            InvalidEnvironmentVariableError,\n            MissingServiceSecretError,\n            ServiceConfigurationError,\n            EnvironmentConfigurationError,\n            InvalidEnvVariable,\n            JetsonTypeResolutionError,\n            MissingDependencyError,\n            InvalidParameterError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500, content={\"message\": \"Service misconfiguration.\"}\n            )\n        except (\n            PreProcessingError,\n            PostProcessingError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": \"Model configuration related to pre- or post-processing is invalid.\"\n                },\n            )\n        except ModelArtefactError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500, content={\"message\": \"Model package is broken.\"}\n            )\n        except ModelLoadingError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Model loading failed: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except (UntrustedFileError, FileHashSumMissmatch) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Issue with model package file: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except ModelRetrievalError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Could not retrieve model {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except OnnxProviderNotAvailable as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=501,\n                content={\n                    \"message\": \"Could not find requested ONNX Runtime Provider. Check that you are using \"\n                    \"the correct docker image on a supported device.\"\n                },\n            )\n        except (\n            MalformedRoboflowAPIResponseError,\n            RoboflowAPIUnsuccessfulRequestError,\n            WorkspaceLoadError,\n            MalformedWorkflowResponseError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=502,\n                content={\"message\": \"Internal error. Request to Roboflow API failed.\"},\n            )\n        except InferenceModelNotFound as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\"message\": \"Model is temporarily not ready - retry request.\"},\n                headers={\"Retry-After\": \"1\"},\n            )\n        except RoboflowAPIConnectionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\n                    \"message\": \"Internal error. Could not connect to Roboflow API.\"\n                },\n            )\n        except ModelManagerLockAcquisitionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\n                    \"message\": \"Could not acquire model manager lock due to other request performing \"\n                    \"blocking operation. Try again....\"\n                },\n                headers={\"Retry-After\": \"1\"},\n            )\n        except RoboflowAPITimeoutError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=504,\n                content={\n                    \"message\": \"Timeout when attempting to connect to Roboflow API.\"\n                },\n            )\n        except ClientCausedStepExecutionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=error.block_id,\n                    ),\n                ],\n            )\n            resp = JSONResponse(\n                status_code=error.status_code,\n                content=content.model_dump(),\n            )\n        except StepExecutionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=error.block_id,\n                        block_type=error.block_type,\n                    ),\n                ],\n            )\n            resp = JSONResponse(\n                status_code=500,\n                content=content.model_dump(),\n            )\n        except WorkflowError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"context\": error.context,\n                    \"inner_error_type\": error.inner_error_type,\n                    \"inner_error_message\": str(error.inner_error),\n                },\n            )\n        except (\n            ProcessesManagerClientError,\n            CommunicationProtocolError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except WebRTCConfigurationError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": str(error),\n                    \"error_type\": \"WebRTCConfigurationError\",\n                },\n            )\n        except CreditsExceededError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=402,\n                content={\n                    \"message\": \"Not enough credits to perform this request.\",\n                    \"error_type\": \"CreditsExceededError\",\n                },\n            )\n        except WorkspaceStreamQuotaError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=429,\n                content={\n                    \"message\": str(error),\n                    \"error_type\": \"WorkspaceStreamQuotaError\",\n                },\n            )\n        except Exception as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(status_code=500, content={\"message\": \"Internal error.\"})\n        return resp\n\n    return wrapped_route\n",
    "patch": null
  },
  {
    "trace_id": "1d0ad166-f7b4-47bb-abdd-a70b0ee0d792",
    "function_name": "InferenceModelsPerceptionEncoderAdapter.preprocess",
    "file_path": "inference/models/perception_encoder/perception_encoder_inference_models.py",
    "speedup_x": 1.47,
    "review_quality": "high",
    "pre_optimization_commit": "7648e452a70ff1aad09f017a0eb2ea4022b7e177",
    "resolution_method": "db_code_match",
    "source": "db_events",
    "original_function_code": "    def preprocess(\n        self, image: Any, **kwargs\n    ) -> Tuple[torch.Tensor, PreprocessReturnMetadata]:\n        return self.preproc_image(image), PreprocessReturnMetadata({})\n",
    "optimized_function_code": "from typing import Any, Tuple\n\nimport numpy as np\nimport torch\nfrom inference.core.entities.requests.inference import InferenceRequestImage\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES, API_KEY,\n    PERCEPTION_ENCODER_MODEL_ID)\nfrom inference.core.models.base import Model\nfrom inference.core.models.types import PreprocessReturnMetadata\nfrom inference.core.roboflow_api import get_extra_weights_provider_headers\nfrom inference.core.utils.image_utils import load_image_bgr\nfrom inference_models import AutoModel\nfrom inference_models.models.perception_encoder.perception_encoder_pytorch import \\\n    PerceptionEncoderTorch\n\n# Reuse empty metadata to avoid dictionary allocation on every call\n_EMPTY_METADATA = PreprocessReturnMetadata({})\n\nclass InferenceModelsPerceptionEncoderAdapter(Model):\n\n    def __init__(\n        self, model_id: str = PERCEPTION_ENCODER_MODEL_ID, api_key: str = None, **kwargs\n    ):\n        super().__init__()\n        if model_id.startswith(\"perception_encoder/\"):\n            model_id = model_id.replace(\"perception_encoder/\", \"perception-encoder/\")\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n\n        self.task_type = \"embedding\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers()\n\n        self._model: PerceptionEncoderTorch = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            **kwargs,\n        )\n\n    def preproc_image(self, image: InferenceRequestImage) -> np.ndarray:\n        \"\"\"Preprocesses an inference request image.\"\"\"\n        return load_image_bgr(image)\n\n    def preprocess(\n        self, image: Any, **kwargs\n    ) -> Tuple[torch.Tensor, PreprocessReturnMetadata]:\n        return load_image_bgr(image), _EMPTY_METADATA",
    "optimized_raw_markdown": "```python:inference/models/perception_encoder/perception_encoder_inference_models.py\nfrom typing import Any, Tuple\n\nimport numpy as np\nimport torch\nfrom inference.core.entities.requests.inference import InferenceRequestImage\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES, API_KEY,\n    PERCEPTION_ENCODER_MODEL_ID)\nfrom inference.core.models.base import Model\nfrom inference.core.models.types import PreprocessReturnMetadata\nfrom inference.core.roboflow_api import get_extra_weights_provider_headers\nfrom inference.core.utils.image_utils import load_image_bgr\nfrom inference_models import AutoModel\nfrom inference_models.models.perception_encoder.perception_encoder_pytorch import \\\n    PerceptionEncoderTorch\n\n# Reuse empty metadata to avoid dictionary allocation on every call\n_EMPTY_METADATA = PreprocessReturnMetadata({})\n\nclass InferenceModelsPerceptionEncoderAdapter(Model):\n\n    def __init__(\n        self, model_id: str = PERCEPTION_ENCODER_MODEL_ID, api_key: str = None, **kwargs\n    ):\n        super().__init__()\n        if model_id.startswith(\"perception_encoder/\"):\n            model_id = model_id.replace(\"perception_encoder/\", \"perception-encoder/\")\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n\n        self.task_type = \"embedding\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers()\n\n        self._model: PerceptionEncoderTorch = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            **kwargs,\n        )\n\n    def preproc_image(self, image: InferenceRequestImage) -> np.ndarray:\n        \"\"\"Preprocesses an inference request image.\"\"\"\n        return load_image_bgr(image)\n\n    def preprocess(\n        self, image: Any, **kwargs\n    ) -> Tuple[torch.Tensor, PreprocessReturnMetadata]:\n        return load_image_bgr(image), _EMPTY_METADATA\n```",
    "optimized_function_only": "    def preprocess(\n        self, image: Any, **kwargs\n    ) -> Tuple[torch.Tensor, PreprocessReturnMetadata]:\n        return load_image_bgr(image), _EMPTY_METADATA",
    "original_file_content": "from time import perf_counter\nfrom typing import Any, Dict, List, Tuple, Union\n\nimport numpy as np\nimport torch\n\nfrom inference.core.entities.requests.inference import InferenceRequestImage\nfrom inference.core.entities.requests.perception_encoder import (\n    PerceptionEncoderCompareRequest,\n    PerceptionEncoderImageEmbeddingRequest,\n    PerceptionEncoderInferenceRequest,\n    PerceptionEncoderTextEmbeddingRequest,\n)\nfrom inference.core.entities.responses.inference import InferenceResponse\nfrom inference.core.entities.responses.perception_encoder import (\n    PerceptionEncoderCompareResponse,\n    PerceptionEncoderEmbeddingResponse,\n)\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n    API_KEY,\n    CLIP_MAX_BATCH_SIZE,\n    DEVICE,\n    DISABLED_INFERENCE_MODELS_BACKENDS,\n    PERCEPTION_ENCODER_MODEL_ID,\n    VALID_INFERENCE_MODELS_BACKENDS,\n)\nfrom inference.core.models.base import Model\nfrom inference.core.models.types import PreprocessReturnMetadata\nfrom inference.core.roboflow_api import get_extra_weights_provider_headers\nfrom inference.core.utils.image_utils import load_image_bgr\nfrom inference.core.utils.postprocess import cosine_similarity\nfrom inference_models import AutoModel\nfrom inference_models.models.perception_encoder.perception_encoder_pytorch import (\n    PerceptionEncoderTorch,\n)\n\n\nclass InferenceModelsPerceptionEncoderAdapter(Model):\n    \"\"\"Roboflow Perception Encoder model implementation.\n\n    This class is responsible for handling the Percpetion Encoder model, including\n    loading the model, preprocessing the input, and performing inference.\n    \"\"\"\n\n    def __init__(\n        self, model_id: str = PERCEPTION_ENCODER_MODEL_ID, api_key: str = None, **kwargs\n    ):\n        super().__init__()\n        if model_id.startswith(\"perception_encoder/\"):\n            model_id = model_id.replace(\"perception_encoder/\", \"perception-encoder/\")\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n\n        self.task_type = \"embedding\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n        backend = list(\n            VALID_INFERENCE_MODELS_BACKENDS.difference(\n                DISABLED_INFERENCE_MODELS_BACKENDS\n            )\n        )\n        self._model: PerceptionEncoderTorch = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            backend=backend,\n            **kwargs,\n        )\n\n    def preproc_image(self, image: InferenceRequestImage) -> np.ndarray:\n        \"\"\"Preprocesses an inference request image.\"\"\"\n        return load_image_bgr(image)\n\n    def preprocess(\n        self, image: Any, **kwargs\n    ) -> Tuple[torch.Tensor, PreprocessReturnMetadata]:\n        return self.preproc_image(image), PreprocessReturnMetadata({})\n\n    def compare(\n        self,\n        subject: Any,\n        prompt: Any,\n        subject_type: str = \"image\",\n        prompt_type: Union[str, List[str], Dict[str, Any]] = \"text\",\n        **kwargs,\n    ) -> Union[List[float], Dict[str, float]]:\n        \"\"\"\n        Compares the subject with the prompt to calculate similarity scores.\n\n        Args:\n            subject (Any): The subject data to be compared. Can be either an image or text.\n            prompt (Any): The prompt data to be compared against the subject. Can be a single value (image/text), list of values, or dictionary of values.\n            subject_type (str, optional): Specifies the type of the subject data. Must be either \"image\" or \"text\". Defaults to \"image\".\n            prompt_type (Union[str, List[str], Dict[str, Any]], optional): Specifies the type of the prompt data. Can be \"image\", \"text\", list of these types, or a dictionary containing these types. Defaults to \"text\".\n            **kwargs: Additional keyword arguments.\n\n        Returns:\n            Union[List[float], Dict[str, float]]: A list or dictionary containing cosine similarity scores between the subject and prompt(s).\n        \"\"\"\n        if subject_type == \"image\":\n            subject_embeddings = self.embed_image(subject)\n        elif subject_type == \"text\":\n            subject_embeddings = self.embed_text(subject)\n        else:\n            raise ValueError(\n                f\"subject_type must be either 'image' or 'text', but got {subject_type}\"\n            )\n\n        if isinstance(prompt, dict) and not (\"type\" in prompt and \"value\" in prompt):\n            prompt_keys = prompt.keys()\n            prompt = [prompt[k] for k in prompt_keys]\n            prompt_obj = \"dict\"\n        else:\n            if not isinstance(prompt, list):\n                prompt = [prompt]\n            prompt_obj = \"list\"\n\n        if len(prompt) > CLIP_MAX_BATCH_SIZE:\n            raise ValueError(\n                f\"The maximum number of prompts that can be compared at once is {CLIP_MAX_BATCH_SIZE}\"\n            )\n\n        if prompt_type == \"image\":\n            prompt_embeddings = self.embed_image(prompt)\n        elif prompt_type == \"text\":\n            prompt_embeddings = self.embed_text(prompt)\n        else:\n            raise ValueError(\n                f\"prompt_type must be either 'image' or 'text', but got {prompt_type}\"\n            )\n\n        similarities = [\n            cosine_similarity(subject_embeddings, p) for p in prompt_embeddings\n        ]\n\n        if prompt_obj == \"dict\":\n            similarities = dict(zip(prompt_keys, similarities))\n\n        return similarities\n\n    def make_compare_response(\n        self, similarities: Union[List[float], Dict[str, float]]\n    ) -> PerceptionEncoderCompareResponse:\n        \"\"\"Creates a PerceptionEncoderCompareResponse object from the provided similarity data.\"\"\"\n        response = PerceptionEncoderCompareResponse(similarity=similarities)\n        return response\n\n    def embed_image(\n        self,\n        image: Any,\n        **kwargs,\n    ) -> np.ndarray:\n        \"\"\"\n        Embeds an image or a list of images using the PE-CLIP model.\n\n        Args:\n            image (Any): The image or list of images to be embedded.\n            **kwargs: Additional keyword arguments.\n\n        Returns:\n            np.ndarray: The embeddings of the image(s) as a numpy array.\n        \"\"\"\n        if isinstance(image, list):\n            if len(image) > CLIP_MAX_BATCH_SIZE:\n                raise ValueError(\n                    f\"The maximum number of images that can be embedded at once is {CLIP_MAX_BATCH_SIZE}\"\n                )\n            img_in = [self.preproc_image(i) for i in image]\n        else:\n            img_in = [self.preproc_image(image)]\n\n        return self._model.embed_images(img_in).cpu().numpy()\n\n    def embed_text(\n        self,\n        text: Union[str, List[str]],\n        **kwargs,\n    ) -> np.ndarray:\n        \"\"\"\n        Embeds a text or a list of texts using the PE-CLIP model.\n\n        Args:\n            text (Union[str, List[str]]): The text string or list of text strings to be embedded.\n            **kwargs: Additional keyword arguments.\n\n        Returns:\n            np.ndarray: The embeddings of the text or texts as a numpy array.\n        \"\"\"\n        if isinstance(text, list):\n            texts = text\n        else:\n            texts = [text]\n        if len(texts) > CLIP_MAX_BATCH_SIZE:\n            raise ValueError(\n                f\"The maximum number of texts that can be embedded at once is {CLIP_MAX_BATCH_SIZE}\"\n            )\n        return self._model.embed_text(texts).cpu().numpy()\n\n    def predict(self, img_in: np.ndarray, **kwargs) -> Tuple[np.ndarray]:\n        \"\"\"Predict embeddings for an input tensor.\n\n        Args:\n            img_in (torch.Tensor): The input tensor to get embeddings for.\n            **kwargs: Additional keyword arguments.\n\n        Returns:\n            Tuple[np.ndarray]: A tuple containing the embeddings as a numpy array.\n        \"\"\"\n        embeddings = self._model.embed_images(img_in).cpu().numpy()\n        return (embeddings,)\n\n    def make_embed_image_response(\n        self, embeddings: np.ndarray\n    ) -> PerceptionEncoderEmbeddingResponse:\n        \"\"\"Converts the given embeddings into a PerceptionEncoderEmbeddingResponse object.\"\"\"\n        response = PerceptionEncoderEmbeddingResponse(embeddings=embeddings.tolist())\n        return response\n\n    def make_embed_text_response(\n        self, embeddings: np.ndarray\n    ) -> PerceptionEncoderEmbeddingResponse:\n        \"\"\"Converts the given text embeddings into a PerceptionEncoderEmbeddingResponse object.\"\"\"\n        response = PerceptionEncoderEmbeddingResponse(embeddings=embeddings.tolist())\n        return response\n\n    def infer_from_request(\n        self, request: PerceptionEncoderInferenceRequest\n    ) -> PerceptionEncoderEmbeddingResponse:\n        \"\"\"Routes the request to the appropriate inference function.\"\"\"\n        t1 = perf_counter()\n        if isinstance(request, PerceptionEncoderImageEmbeddingRequest):\n            infer_func = self.embed_image\n            make_response_func = self.make_embed_image_response\n        elif isinstance(request, PerceptionEncoderTextEmbeddingRequest):\n            infer_func = self.embed_text\n            make_response_func = self.make_embed_text_response\n        elif isinstance(request, PerceptionEncoderCompareRequest):\n            infer_func = self.compare\n            make_response_func = self.make_compare_response\n        else:\n            raise ValueError(\n                f\"Request type {type(request)} is not a valid PerceptionEncoderInferenceRequest\"\n            )\n        data = infer_func(**request.dict())\n        response = make_response_func(data)\n        response.time = perf_counter() - t1\n        return response\n\n    def make_response(self, embeddings, *args, **kwargs) -> InferenceResponse:\n        return [self.make_embed_image_response(embeddings)]\n\n    def postprocess(\n        self,\n        predictions: Tuple[np.ndarray],\n        preprocess_return_metadata: PreprocessReturnMetadata,\n        **kwargs,\n    ) -> Any:\n        return [self.make_embed_image_response(predictions[0])]\n\n    def infer(self, image: Any, **kwargs) -> Any:\n        \"\"\"Embeds an image\"\"\"\n        return super().infer(image, **kwargs)\n",
    "patch": null
  },
  {
    "trace_id": "b9e42406-788e-4c48-8367-910fefcc8eae",
    "function_name": "retrieve_selectors_from_union_definition",
    "file_path": "inference/core/workflows/execution_engine/introspection/schema_parser.py",
    "speedup_x": 0.98,
    "review_quality": "high",
    "pre_optimization_commit": "5ec77d6306fd9212f2a8990c421720775f9da64e",
    "resolution_method": "db_code_match",
    "source": "db_events",
    "original_function_code": "def retrieve_selectors_from_union_definition(\n    property_name: str,\n    property_description: str,\n    union_definition: dict,\n    is_list_element: bool,\n    is_dict_element: bool,\n    property_dimensionality_offset: int,\n    is_dimensionality_reference_property: bool,\n    inputs_accepting_batches: Set[str],\n    inputs_accepting_batches_and_scalars: Set[str],\n    inputs_enforcing_auto_batch_casting: Set[str],\n) -> Optional[SelectorDefinition]:\n    union_types = (\n        union_definition.get(ANY_OF_KEY, [])\n        + union_definition.get(ONE_OF_KEY, [])\n        + union_definition.get(ALL_OF_KEY, [])\n    )\n    results = []\n    for type_definition in union_types:\n        result = retrieve_selectors_from_simple_property(\n            property_name=property_name,\n            property_description=property_description,\n            property_definition=type_definition,\n            property_dimensionality_offset=property_dimensionality_offset,\n            is_dimensionality_reference_property=is_dimensionality_reference_property,\n            inputs_accepting_batches=inputs_accepting_batches,\n            inputs_accepting_batches_and_scalars=inputs_accepting_batches_and_scalars,\n            inputs_enforcing_auto_batch_casting=inputs_enforcing_auto_batch_casting,\n            is_list_element=is_list_element,\n            is_dict_element=is_dict_element,\n        )\n        if result is None:\n            continue\n        results.append(result)\n    results_references = list(\n        itertools.chain.from_iterable(r.allowed_references for r in results)\n    )\n    results_references_kind_by_selected_element = defaultdict(set)\n    results_references_batch_pointing_by_selected_element = defaultdict(set)\n    for reference in results_references:\n        results_references_kind_by_selected_element[reference.selected_element].update(\n            reference.kind\n        )\n        results_references_batch_pointing_by_selected_element[\n            reference.selected_element\n        ].update(reference.points_to_batch)\n    merged_references = []\n    for (\n        reference_selected_element,\n        kind,\n    ) in results_references_kind_by_selected_element.items():\n        merged_references.append(\n            ReferenceDefinition(\n                selected_element=reference_selected_element,\n                kind=list(kind),\n                points_to_batch=results_references_batch_pointing_by_selected_element[\n                    reference_selected_element\n                ],\n            )\n        )\n    if not merged_references:\n        return None\n    merged_is_list_element = is_list_element or any(r.is_list_element for r in results)\n    merged_is_dict_element = is_dict_element or any(r.is_dict_element for r in results)\n    return SelectorDefinition(\n        property_name=property_name,\n        property_description=property_description,\n        allowed_references=merged_references,\n        is_list_element=merged_is_list_element,\n        is_dict_element=merged_is_dict_element,\n        dimensionality_offset=property_dimensionality_offset,\n        is_dimensionality_reference_property=is_dimensionality_reference_property,\n    )\n",
    "optimized_function_code": "import itertools\nfrom collections import defaultdict\nfrom typing import Optional, Set\n\nfrom inference.core.workflows.execution_engine.entities.types import (\n    KIND_KEY, REFERENCE_KEY, SELECTED_ELEMENT_KEY,\n    SELECTOR_POINTS_TO_BATCH_KEY, Kind)\nfrom inference.core.workflows.execution_engine.introspection.entities import (\n    ReferenceDefinition, SelectorDefinition)\n\nITEMS_KEY = \"items\"\nALL_OF_KEY = \"allOf\"\nANY_OF_KEY = \"anyOf\"\nONE_OF_KEY = \"oneOf\"\n\n\ndef retrieve_selectors_from_simple_property(\n    property_name: str,\n    property_description: str,\n    property_definition: dict,\n    property_dimensionality_offset: int,\n    is_dimensionality_reference_property: bool,\n    inputs_accepting_batches: Set[str],\n    inputs_accepting_batches_and_scalars: Set[str],\n    inputs_enforcing_auto_batch_casting: Set[str],\n    is_list_element: bool = False,\n    is_dict_element: bool = False,\n) -> Optional[SelectorDefinition]:\n    if REFERENCE_KEY in property_definition:\n        declared_points_to_batch = property_definition.get(\n            SELECTOR_POINTS_TO_BATCH_KEY, False\n        )\n        if declared_points_to_batch == \"dynamic\":\n            if property_name in inputs_accepting_batches_and_scalars:\n                if property_name in inputs_enforcing_auto_batch_casting:\n                    points_to_batch = {True}\n                else:\n                    points_to_batch = {True, False}\n            else:\n                points_to_batch = {\n                    property_name in inputs_accepting_batches\n                    or property_name in inputs_enforcing_auto_batch_casting\n                }\n        else:\n            points_to_batch = {declared_points_to_batch}\n        allowed_references = [\n            ReferenceDefinition(\n                selected_element=property_definition[SELECTED_ELEMENT_KEY],\n                kind=[\n                    Kind.model_validate(k)\n                    for k in property_definition.get(KIND_KEY, [])\n                ],\n                points_to_batch=points_to_batch,\n            )\n        ]\n        return SelectorDefinition(\n            property_name=property_name,\n            property_description=property_description,\n            allowed_references=allowed_references,\n            is_list_element=is_list_element,\n            is_dict_element=is_dict_element,\n            dimensionality_offset=property_dimensionality_offset,\n            is_dimensionality_reference_property=is_dimensionality_reference_property,\n        )\n    if ITEMS_KEY in property_definition:\n        if is_list_element or is_dict_element:\n            # ignoring nested references above first level of depth\n            return None\n        return retrieve_selectors_from_simple_property(\n            property_name=property_name,\n            property_description=property_description,\n            property_definition=property_definition[ITEMS_KEY],\n            property_dimensionality_offset=property_dimensionality_offset,\n            is_dimensionality_reference_property=is_dimensionality_reference_property,\n            inputs_accepting_batches=inputs_accepting_batches,\n            inputs_accepting_batches_and_scalars=inputs_accepting_batches_and_scalars,\n            inputs_enforcing_auto_batch_casting=inputs_enforcing_auto_batch_casting,\n            is_list_element=True,\n        )\n    # Inlined property_defines_union check\n    if (\n        ANY_OF_KEY in property_definition\n        or ONE_OF_KEY in property_definition\n        or ALL_OF_KEY in property_definition\n    ):\n        return retrieve_selectors_from_union_definition(\n            property_name=property_name,\n            property_description=property_description,\n            union_definition=property_definition,\n            is_list_element=is_list_element,\n            is_dict_element=is_dict_element,\n            property_dimensionality_offset=property_dimensionality_offset,\n            is_dimensionality_reference_property=is_dimensionality_reference_property,\n            inputs_accepting_batches=inputs_accepting_batches,\n            inputs_accepting_batches_and_scalars=inputs_accepting_batches_and_scalars,\n            inputs_enforcing_auto_batch_casting=inputs_enforcing_auto_batch_casting,\n        )\n    return None\n\n\ndef retrieve_selectors_from_union_definition(\n    property_name: str,\n    property_description: str,\n    union_definition: dict,\n    is_list_element: bool,\n    is_dict_element: bool,\n    property_dimensionality_offset: int,\n    is_dimensionality_reference_property: bool,\n    inputs_accepting_batches: Set[str],\n    inputs_accepting_batches_and_scalars: Set[str],\n    inputs_enforcing_auto_batch_casting: Set[str],\n) -> Optional[SelectorDefinition]:\n    results = []\n    # Process union types more efficiently by iterating once\n    for key in (ANY_OF_KEY, ONE_OF_KEY, ALL_OF_KEY):\n        union_types = union_definition.get(key)\n        if not union_types:\n            continue\n        for type_definition in union_types:\n            result = retrieve_selectors_from_simple_property(\n                property_name=property_name,\n                property_description=property_description,\n                property_definition=type_definition,\n                property_dimensionality_offset=property_dimensionality_offset,\n                is_dimensionality_reference_property=is_dimensionality_reference_property,\n                inputs_accepting_batches=inputs_accepting_batches,\n                inputs_accepting_batches_and_scalars=inputs_accepting_batches_and_scalars,\n                inputs_enforcing_auto_batch_casting=inputs_enforcing_auto_batch_casting,\n                is_list_element=is_list_element,\n                is_dict_element=is_dict_element,\n            )\n            if result is not None:\n                results.append(result)\n    \n    if not results:\n        return None\n    \n    results_references_kind_by_selected_element = defaultdict(set)\n    results_references_batch_pointing_by_selected_element = defaultdict(set)\n    \n    for result in results:\n        for reference in result.allowed_references:\n            results_references_kind_by_selected_element[reference.selected_element].update(\n                reference.kind\n            )\n            results_references_batch_pointing_by_selected_element[\n                reference.selected_element\n            ].update(reference.points_to_batch)\n    \n    merged_references = [\n        ReferenceDefinition(\n            selected_element=reference_selected_element,\n            kind=list(kind),\n            points_to_batch=results_references_batch_pointing_by_selected_element[\n                reference_selected_element\n            ],\n        )\n        for reference_selected_element, kind in results_references_kind_by_selected_element.items()\n    ]\n    \n    merged_is_list_element = is_list_element or any(r.is_list_element for r in results)\n    merged_is_dict_element = is_dict_element or any(r.is_dict_element for r in results)\n    return SelectorDefinition(\n        property_name=property_name,\n        property_description=property_description,\n        allowed_references=merged_references,\n        is_list_element=merged_is_list_element,\n        is_dict_element=merged_is_dict_element,\n        dimensionality_offset=property_dimensionality_offset,\n        is_dimensionality_reference_property=is_dimensionality_reference_property,\n    )",
    "optimized_raw_markdown": "```python:inference/core/workflows/execution_engine/introspection/schema_parser.py\nimport itertools\nfrom collections import defaultdict\nfrom typing import Optional, Set\n\nfrom inference.core.workflows.execution_engine.entities.types import (\n    KIND_KEY, REFERENCE_KEY, SELECTED_ELEMENT_KEY,\n    SELECTOR_POINTS_TO_BATCH_KEY, Kind)\nfrom inference.core.workflows.execution_engine.introspection.entities import (\n    ReferenceDefinition, SelectorDefinition)\n\nITEMS_KEY = \"items\"\nALL_OF_KEY = \"allOf\"\nANY_OF_KEY = \"anyOf\"\nONE_OF_KEY = \"oneOf\"\n\n\ndef retrieve_selectors_from_simple_property(\n    property_name: str,\n    property_description: str,\n    property_definition: dict,\n    property_dimensionality_offset: int,\n    is_dimensionality_reference_property: bool,\n    inputs_accepting_batches: Set[str],\n    inputs_accepting_batches_and_scalars: Set[str],\n    inputs_enforcing_auto_batch_casting: Set[str],\n    is_list_element: bool = False,\n    is_dict_element: bool = False,\n) -> Optional[SelectorDefinition]:\n    if REFERENCE_KEY in property_definition:\n        declared_points_to_batch = property_definition.get(\n            SELECTOR_POINTS_TO_BATCH_KEY, False\n        )\n        if declared_points_to_batch == \"dynamic\":\n            if property_name in inputs_accepting_batches_and_scalars:\n                if property_name in inputs_enforcing_auto_batch_casting:\n                    points_to_batch = {True}\n                else:\n                    points_to_batch = {True, False}\n            else:\n                points_to_batch = {\n                    property_name in inputs_accepting_batches\n                    or property_name in inputs_enforcing_auto_batch_casting\n                }\n        else:\n            points_to_batch = {declared_points_to_batch}\n        allowed_references = [\n            ReferenceDefinition(\n                selected_element=property_definition[SELECTED_ELEMENT_KEY],\n                kind=[\n                    Kind.model_validate(k)\n                    for k in property_definition.get(KIND_KEY, [])\n                ],\n                points_to_batch=points_to_batch,\n            )\n        ]\n        return SelectorDefinition(\n            property_name=property_name,\n            property_description=property_description,\n            allowed_references=allowed_references,\n            is_list_element=is_list_element,\n            is_dict_element=is_dict_element,\n            dimensionality_offset=property_dimensionality_offset,\n            is_dimensionality_reference_property=is_dimensionality_reference_property,\n        )\n    if ITEMS_KEY in property_definition:\n        if is_list_element or is_dict_element:\n            # ignoring nested references above first level of depth\n            return None\n        return retrieve_selectors_from_simple_property(\n            property_name=property_name,\n            property_description=property_description,\n            property_definition=property_definition[ITEMS_KEY],\n            property_dimensionality_offset=property_dimensionality_offset,\n            is_dimensionality_reference_property=is_dimensionality_reference_property,\n            inputs_accepting_batches=inputs_accepting_batches,\n            inputs_accepting_batches_and_scalars=inputs_accepting_batches_and_scalars,\n            inputs_enforcing_auto_batch_casting=inputs_enforcing_auto_batch_casting,\n            is_list_element=True,\n        )\n    # Inlined property_defines_union check\n    if (\n        ANY_OF_KEY in property_definition\n        or ONE_OF_KEY in property_definition\n        or ALL_OF_KEY in property_definition\n    ):\n        return retrieve_selectors_from_union_definition(\n            property_name=property_name,\n            property_description=property_description,\n            union_definition=property_definition,\n            is_list_element=is_list_element,\n            is_dict_element=is_dict_element,\n            property_dimensionality_offset=property_dimensionality_offset,\n            is_dimensionality_reference_property=is_dimensionality_reference_property,\n            inputs_accepting_batches=inputs_accepting_batches,\n            inputs_accepting_batches_and_scalars=inputs_accepting_batches_and_scalars,\n            inputs_enforcing_auto_batch_casting=inputs_enforcing_auto_batch_casting,\n        )\n    return None\n\n\ndef retrieve_selectors_from_union_definition(\n    property_name: str,\n    property_description: str,\n    union_definition: dict,\n    is_list_element: bool,\n    is_dict_element: bool,\n    property_dimensionality_offset: int,\n    is_dimensionality_reference_property: bool,\n    inputs_accepting_batches: Set[str],\n    inputs_accepting_batches_and_scalars: Set[str],\n    inputs_enforcing_auto_batch_casting: Set[str],\n) -> Optional[SelectorDefinition]:\n    results = []\n    # Process union types more efficiently by iterating once\n    for key in (ANY_OF_KEY, ONE_OF_KEY, ALL_OF_KEY):\n        union_types = union_definition.get(key)\n        if not union_types:\n            continue\n        for type_definition in union_types:\n            result = retrieve_selectors_from_simple_property(\n                property_name=property_name,\n                property_description=property_description,\n                property_definition=type_definition,\n                property_dimensionality_offset=property_dimensionality_offset,\n                is_dimensionality_reference_property=is_dimensionality_reference_property,\n                inputs_accepting_batches=inputs_accepting_batches,\n                inputs_accepting_batches_and_scalars=inputs_accepting_batches_and_scalars,\n                inputs_enforcing_auto_batch_casting=inputs_enforcing_auto_batch_casting,\n                is_list_element=is_list_element,\n                is_dict_element=is_dict_element,\n            )\n            if result is not None:\n                results.append(result)\n    \n    if not results:\n        return None\n    \n    results_references_kind_by_selected_element = defaultdict(set)\n    results_references_batch_pointing_by_selected_element = defaultdict(set)\n    \n    for result in results:\n        for reference in result.allowed_references:\n            results_references_kind_by_selected_element[reference.selected_element].update(\n                reference.kind\n            )\n            results_references_batch_pointing_by_selected_element[\n                reference.selected_element\n            ].update(reference.points_to_batch)\n    \n    merged_references = [\n        ReferenceDefinition(\n            selected_element=reference_selected_element,\n            kind=list(kind),\n            points_to_batch=results_references_batch_pointing_by_selected_element[\n                reference_selected_element\n            ],\n        )\n        for reference_selected_element, kind in results_references_kind_by_selected_element.items()\n    ]\n    \n    merged_is_list_element = is_list_element or any(r.is_list_element for r in results)\n    merged_is_dict_element = is_dict_element or any(r.is_dict_element for r in results)\n    return SelectorDefinition(\n        property_name=property_name,\n        property_description=property_description,\n        allowed_references=merged_references,\n        is_list_element=merged_is_list_element,\n        is_dict_element=merged_is_dict_element,\n        dimensionality_offset=property_dimensionality_offset,\n        is_dimensionality_reference_property=is_dimensionality_reference_property,\n    )\n```",
    "optimized_function_only": "def retrieve_selectors_from_union_definition(\n    property_name: str,\n    property_description: str,\n    union_definition: dict,\n    is_list_element: bool,\n    is_dict_element: bool,\n    property_dimensionality_offset: int,\n    is_dimensionality_reference_property: bool,\n    inputs_accepting_batches: Set[str],\n    inputs_accepting_batches_and_scalars: Set[str],\n    inputs_enforcing_auto_batch_casting: Set[str],\n) -> Optional[SelectorDefinition]:\n    results = []\n    # Process union types more efficiently by iterating once\n    for key in (ANY_OF_KEY, ONE_OF_KEY, ALL_OF_KEY):\n        union_types = union_definition.get(key)\n        if not union_types:\n            continue\n        for type_definition in union_types:\n            result = retrieve_selectors_from_simple_property(\n                property_name=property_name,\n                property_description=property_description,\n                property_definition=type_definition,\n                property_dimensionality_offset=property_dimensionality_offset,\n                is_dimensionality_reference_property=is_dimensionality_reference_property,\n                inputs_accepting_batches=inputs_accepting_batches,\n                inputs_accepting_batches_and_scalars=inputs_accepting_batches_and_scalars,\n                inputs_enforcing_auto_batch_casting=inputs_enforcing_auto_batch_casting,\n                is_list_element=is_list_element,\n                is_dict_element=is_dict_element,\n            )\n            if result is not None:\n                results.append(result)\n    \n    if not results:\n        return None\n    \n    results_references_kind_by_selected_element = defaultdict(set)\n    results_references_batch_pointing_by_selected_element = defaultdict(set)\n    \n    for result in results:\n        for reference in result.allowed_references:\n            results_references_kind_by_selected_element[reference.selected_element].update(\n                reference.kind\n            )\n            results_references_batch_pointing_by_selected_element[\n                reference.selected_element\n            ].update(reference.points_to_batch)\n    \n    merged_references = [\n        ReferenceDefinition(\n            selected_element=reference_selected_element,\n            kind=list(kind),\n            points_to_batch=results_references_batch_pointing_by_selected_element[\n                reference_selected_element\n            ],\n        )\n        for reference_selected_element, kind in results_references_kind_by_selected_element.items()\n    ]\n    \n    merged_is_list_element = is_list_element or any(r.is_list_element for r in results)\n    merged_is_dict_element = is_dict_element or any(r.is_dict_element for r in results)\n    return SelectorDefinition(\n        property_name=property_name,\n        property_description=property_description,\n        allowed_references=merged_references,\n        is_list_element=merged_is_list_element,\n        is_dict_element=merged_is_dict_element,\n        dimensionality_offset=property_dimensionality_offset,\n        is_dimensionality_reference_property=is_dimensionality_reference_property,\n    )",
    "original_file_content": "import itertools\nfrom collections import OrderedDict, defaultdict\nfrom dataclasses import replace\nfrom functools import lru_cache\nfrom typing import Dict, Optional, Set, Type\n\nfrom inference.core.workflows.execution_engine.entities.types import (\n    KIND_KEY,\n    REFERENCE_KEY,\n    SELECTED_ELEMENT_KEY,\n    SELECTOR_POINTS_TO_BATCH_KEY,\n    Kind,\n)\nfrom inference.core.workflows.execution_engine.introspection.entities import (\n    BlockManifestMetadata,\n    PrimitiveTypeDefinition,\n    ReferenceDefinition,\n    SelectorDefinition,\n)\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nEXCLUDED_PROPERTIES = {\"type\"}\n\nTYPE_MAPPING = {\n    \"number\": \"float\",\n    \"integer\": \"int\",\n    \"boolean\": \"bool\",\n    \"string\": \"str\",\n    \"null\": \"None\",\n}\n\nSET_TYPE_NAME = \"Set\"\nLIST_TYPE_NAME = \"List\"\nUNION_TYPE_NAME = \"Union\"\nNONE_TYPE_NAME = \"None\"\nOPTIONAL_TYPE_NAME = \"Optional\"\nANY_TYPE_NAME = \"Any\"\nANY_DICT_TYPE_NAME = \"Dict[Any, Any]\"\nDICT_TYPE_NAME_PREFIX = \"Dict\"\nSTR_TYPE_NAME = \"str\"\n\nITEMS_KEY = \"items\"\nUNIQUE_ITEMS_KEY = \"uniqueItems\"\nTUPLE_ITEMS_KEY = \"prefixItems\"\nTYPE_KEY = \"type\"\nREF_KEY = \"$ref\"\nADDITIONAL_PROPERTIES_KEY = \"additionalProperties\"\nPROPERTIES_KEY = \"properties\"\nDESCRIPTION_KEY = \"description\"\nALL_OF_KEY = \"allOf\"\nANY_OF_KEY = \"anyOf\"\nONE_OF_KEY = \"oneOf\"\nOBJECT_TYPE = \"object\"\n\n\ndef clear_cache() -> None:\n    \"\"\"Clear the parse_block_manifest cache.\"\"\"\n    parse_block_manifest.cache_clear()\n\n\n@lru_cache(maxsize=10000)\ndef parse_block_manifest(\n    manifest_type: Type[WorkflowBlockManifest],\n) -> BlockManifestMetadata:\n    # Import here to avoid circular dependency\n    from inference.core.workflows.execution_engine.introspection.blocks_loader import (\n        _cached_model_json_schema,\n    )\n\n    schema = _cached_model_json_schema(manifest_type)\n    inputs_dimensionality_offsets = manifest_type.get_input_dimensionality_offsets()\n    dimensionality_reference_property = (\n        manifest_type.get_dimensionality_reference_property()\n    )\n    inputs_accepting_batches = set(manifest_type.get_parameters_accepting_batches())\n    inputs_accepting_batches_and_scalars = set(\n        manifest_type.get_parameters_accepting_batches_and_scalars()\n    )\n    inputs_enforcing_auto_batch_casting = set(\n        manifest_type.get_parameters_enforcing_auto_batch_casting()\n    )\n    return parse_block_manifest_schema(\n        schema=schema,\n        inputs_dimensionality_offsets=inputs_dimensionality_offsets,\n        dimensionality_reference_property=dimensionality_reference_property,\n        inputs_accepting_batches=inputs_accepting_batches,\n        inputs_accepting_batches_and_scalars=inputs_accepting_batches_and_scalars,\n        inputs_enforcing_auto_batch_casting=inputs_enforcing_auto_batch_casting,\n    )\n\n\ndef parse_block_manifest_schema(\n    schema: dict,\n    inputs_dimensionality_offsets: Dict[str, int],\n    dimensionality_reference_property: Optional[str],\n    inputs_accepting_batches: Set[str],\n    inputs_accepting_batches_and_scalars: Set[str],\n    inputs_enforcing_auto_batch_casting: Set[str],\n) -> BlockManifestMetadata:\n    primitive_types = retrieve_primitives_from_schema(\n        schema=schema,\n    )\n    selectors = retrieve_selectors_from_schema(\n        schema=schema,\n        inputs_dimensionality_offsets=inputs_dimensionality_offsets,\n        dimensionality_reference_property=dimensionality_reference_property,\n        inputs_accepting_batches=inputs_accepting_batches,\n        inputs_accepting_batches_and_scalars=inputs_accepting_batches_and_scalars,\n        inputs_enforcing_auto_batch_casting=inputs_enforcing_auto_batch_casting,\n    )\n    return BlockManifestMetadata(\n        primitive_types=primitive_types,\n        selectors=selectors,\n    )\n\n\ndef retrieve_primitives_from_schema(schema: dict) -> Dict[str, PrimitiveTypeDefinition]:\n    result = []\n    for property_name, property_definition in schema[PROPERTIES_KEY].items():\n        if property_name in EXCLUDED_PROPERTIES:\n            continue\n        property_description = property_definition.get(DESCRIPTION_KEY, \"not available\")\n        primitive_metadata = retrieve_primitive_type_from_property(\n            property_name=property_name,\n            property_description=property_description,\n            property_definition=property_definition,\n        )\n        if primitive_metadata is not None:\n            result.append(primitive_metadata)\n    return OrderedDict((r.property_name, r) for r in result)\n\n\ndef retrieve_primitive_type_from_property(\n    property_name: str,\n    property_description: str,\n    property_definition: dict,\n) -> Optional[PrimitiveTypeDefinition]:\n    if REFERENCE_KEY in property_definition:\n        return None\n    if ITEMS_KEY in property_definition:\n        result = retrieve_primitive_type_from_property(\n            property_name=property_name,\n            property_description=property_description,\n            property_definition=property_definition[ITEMS_KEY],\n        )\n        if result is None:\n            return None\n        high_level_type = (\n            SET_TYPE_NAME\n            if property_definition.get(UNIQUE_ITEMS_KEY, False) is True\n            else LIST_TYPE_NAME\n        )\n        return replace(\n            result, type_annotation=f\"{high_level_type}[{result.type_annotation}]\"\n        )\n    if TUPLE_ITEMS_KEY in property_definition:\n        nested_annotations = [\n            retrieve_primitive_type_from_property(\n                property_name=property_name,\n                property_description=property_description,\n                property_definition=nested_definition,\n            )\n            for nested_definition in property_definition[TUPLE_ITEMS_KEY]\n        ]\n        inner_types = \", \".join(a.type_annotation for a in nested_annotations)\n        return PrimitiveTypeDefinition(\n            property_name=property_name,\n            property_description=property_description,\n            type_annotation=f\"Tuple[{inner_types}]\",\n        )\n    if property_definition.get(TYPE_KEY) in TYPE_MAPPING:\n        type_name = TYPE_MAPPING[property_definition[TYPE_KEY]]\n        return PrimitiveTypeDefinition(\n            property_name=property_name,\n            property_description=property_description,\n            type_annotation=type_name,\n        )\n    if REF_KEY in property_definition:\n        return PrimitiveTypeDefinition(\n            property_name=property_name,\n            property_description=property_description,\n            type_annotation=property_definition[REF_KEY].split(\"/\")[-1],\n        )\n    if property_defines_union(property_definition=property_definition):\n        return retrieve_primitive_type_from_union_property(\n            property_name=property_name,\n            property_description=property_description,\n            union_definition=property_definition,\n        )\n    if property_definition.get(TYPE_KEY) == \"object\":\n        return retrieve_primitive_type_from_dict_property(\n            property_name=property_name,\n            property_description=property_description,\n            property_definition=property_definition,\n        )\n    return PrimitiveTypeDefinition(\n        property_name=property_name,\n        property_description=property_description,\n        type_annotation=ANY_TYPE_NAME,\n    )\n\n\ndef retrieve_primitive_type_from_union_property(\n    property_name: str,\n    property_description: str,\n    union_definition: dict,\n) -> Optional[PrimitiveTypeDefinition]:\n    union_types = (\n        union_definition.get(ANY_OF_KEY, [])\n        + union_definition.get(ONE_OF_KEY, [])\n        + union_definition.get(ALL_OF_KEY, [])\n    )\n    primitive_union_types = [e for e in union_types if REFERENCE_KEY not in e]\n    union_types_metadata = []\n    for union_type in primitive_union_types:\n        union_type_metadata = retrieve_primitive_type_from_property(\n            property_name=property_name,\n            property_description=property_description,\n            property_definition=union_type,\n        )\n        if union_type_metadata is None:\n            continue\n        union_types_metadata.append(union_type_metadata)\n    if not union_types_metadata:\n        return None\n    type_names = {m.type_annotation for m in union_types_metadata}\n    if NONE_TYPE_NAME in type_names:\n        high_level_type = OPTIONAL_TYPE_NAME\n        type_names.remove(NONE_TYPE_NAME)\n    else:\n        high_level_type = UNION_TYPE_NAME\n    final_type_name = \", \".join(list(sorted(type_names)))\n    if len(type_names) == 0:\n        return None\n    if len(type_names) > 1:\n        final_type_name = f\"{high_level_type}[{final_type_name}]\"\n    return PrimitiveTypeDefinition(\n        property_name=property_name,\n        property_description=property_description,\n        type_annotation=final_type_name,\n    )\n\n\ndef retrieve_primitive_type_from_dict_property(\n    property_name: str,\n    property_description: str,\n    property_definition: dict,\n) -> Optional[PrimitiveTypeDefinition]:\n    nested_property_definition = property_definition.get(ADDITIONAL_PROPERTIES_KEY)\n    if isinstance(nested_property_definition, dict):\n        dict_value_type = retrieve_primitive_type_from_property(\n            property_name=property_name,\n            property_description=property_description,\n            property_definition=nested_property_definition,\n        )\n        if dict_value_type is None:\n            return None\n        return PrimitiveTypeDefinition(\n            property_name=property_name,\n            property_description=property_description,\n            type_annotation=f\"{DICT_TYPE_NAME_PREFIX}[{STR_TYPE_NAME}, {dict_value_type.type_annotation}]\",\n        )\n    return PrimitiveTypeDefinition(\n        property_name=property_name,\n        property_description=property_description,\n        type_annotation=ANY_DICT_TYPE_NAME,\n    )\n\n\ndef retrieve_selectors_from_schema(\n    schema: dict,\n    inputs_dimensionality_offsets: Dict[str, int],\n    dimensionality_reference_property: Optional[str],\n    inputs_accepting_batches: Set[str],\n    inputs_accepting_batches_and_scalars: Set[str],\n    inputs_enforcing_auto_batch_casting: Set[str],\n) -> Dict[str, SelectorDefinition]:\n    result = []\n    for property_name, property_definition in schema[PROPERTIES_KEY].items():\n        if property_name in EXCLUDED_PROPERTIES:\n            continue\n        property_dimensionality_offset = inputs_dimensionality_offsets.get(\n            property_name, 0\n        )\n        is_dimensionality_reference_property = (\n            property_name == dimensionality_reference_property\n        )\n        property_description = property_definition.get(DESCRIPTION_KEY, \"not available\")\n        if ITEMS_KEY in property_definition:\n            selector = retrieve_selectors_from_simple_property(\n                property_name=property_name,\n                property_description=property_description,\n                property_definition=property_definition[ITEMS_KEY],\n                property_dimensionality_offset=property_dimensionality_offset,\n                is_dimensionality_reference_property=is_dimensionality_reference_property,\n                is_list_element=True,\n                inputs_accepting_batches=inputs_accepting_batches,\n                inputs_accepting_batches_and_scalars=inputs_accepting_batches_and_scalars,\n                inputs_enforcing_auto_batch_casting=inputs_enforcing_auto_batch_casting,\n            )\n        elif property_definition.get(TYPE_KEY) == OBJECT_TYPE and isinstance(\n            property_definition.get(ADDITIONAL_PROPERTIES_KEY), dict\n        ):\n            selector = retrieve_selectors_from_simple_property(\n                property_name=property_name,\n                property_description=property_description,\n                property_definition=property_definition[ADDITIONAL_PROPERTIES_KEY],\n                property_dimensionality_offset=property_dimensionality_offset,\n                is_dimensionality_reference_property=is_dimensionality_reference_property,\n                is_dict_element=True,\n                inputs_accepting_batches=inputs_accepting_batches,\n                inputs_accepting_batches_and_scalars=inputs_accepting_batches_and_scalars,\n                inputs_enforcing_auto_batch_casting=inputs_enforcing_auto_batch_casting,\n            )\n        else:\n            selector = retrieve_selectors_from_simple_property(\n                property_name=property_name,\n                property_description=property_description,\n                property_definition=property_definition,\n                property_dimensionality_offset=property_dimensionality_offset,\n                is_dimensionality_reference_property=is_dimensionality_reference_property,\n                inputs_accepting_batches=inputs_accepting_batches,\n                inputs_accepting_batches_and_scalars=inputs_accepting_batches_and_scalars,\n                inputs_enforcing_auto_batch_casting=inputs_enforcing_auto_batch_casting,\n            )\n        if selector is not None:\n            result.append(selector)\n    return OrderedDict((r.property_name, r) for r in result)\n\n\ndef retrieve_selectors_from_simple_property(\n    property_name: str,\n    property_description: str,\n    property_definition: dict,\n    property_dimensionality_offset: int,\n    is_dimensionality_reference_property: bool,\n    inputs_accepting_batches: Set[str],\n    inputs_accepting_batches_and_scalars: Set[str],\n    inputs_enforcing_auto_batch_casting: Set[str],\n    is_list_element: bool = False,\n    is_dict_element: bool = False,\n) -> Optional[SelectorDefinition]:\n    if REFERENCE_KEY in property_definition:\n        declared_points_to_batch = property_definition.get(\n            SELECTOR_POINTS_TO_BATCH_KEY, False\n        )\n        if declared_points_to_batch == \"dynamic\":\n            if property_name in inputs_accepting_batches_and_scalars:\n                if property_name in inputs_enforcing_auto_batch_casting:\n                    points_to_batch = {True}\n                else:\n                    points_to_batch = {True, False}\n            else:\n                points_to_batch = {\n                    property_name in inputs_accepting_batches\n                    or property_name in inputs_enforcing_auto_batch_casting\n                }\n        else:\n            points_to_batch = {declared_points_to_batch}\n        allowed_references = [\n            ReferenceDefinition(\n                selected_element=property_definition[SELECTED_ELEMENT_KEY],\n                kind=[\n                    Kind.model_validate(k)\n                    for k in property_definition.get(KIND_KEY, [])\n                ],\n                points_to_batch=points_to_batch,\n            )\n        ]\n        return SelectorDefinition(\n            property_name=property_name,\n            property_description=property_description,\n            allowed_references=allowed_references,\n            is_list_element=is_list_element,\n            is_dict_element=is_dict_element,\n            dimensionality_offset=property_dimensionality_offset,\n            is_dimensionality_reference_property=is_dimensionality_reference_property,\n        )\n    if ITEMS_KEY in property_definition:\n        if is_list_element or is_dict_element:\n            # ignoring nested references above first level of depth\n            return None\n        return retrieve_selectors_from_simple_property(\n            property_name=property_name,\n            property_description=property_description,\n            property_definition=property_definition[ITEMS_KEY],\n            property_dimensionality_offset=property_dimensionality_offset,\n            is_dimensionality_reference_property=is_dimensionality_reference_property,\n            inputs_accepting_batches=inputs_accepting_batches,\n            inputs_accepting_batches_and_scalars=inputs_accepting_batches_and_scalars,\n            inputs_enforcing_auto_batch_casting=inputs_enforcing_auto_batch_casting,\n            is_list_element=True,\n        )\n    if property_defines_union(property_definition=property_definition):\n        return retrieve_selectors_from_union_definition(\n            property_name=property_name,\n            property_description=property_description,\n            union_definition=property_definition,\n            is_list_element=is_list_element,\n            is_dict_element=is_dict_element,\n            property_dimensionality_offset=property_dimensionality_offset,\n            is_dimensionality_reference_property=is_dimensionality_reference_property,\n            inputs_accepting_batches=inputs_accepting_batches,\n            inputs_accepting_batches_and_scalars=inputs_accepting_batches_and_scalars,\n            inputs_enforcing_auto_batch_casting=inputs_enforcing_auto_batch_casting,\n        )\n    return None\n\n\ndef property_defines_union(property_definition: dict) -> bool:\n    return (\n        ANY_OF_KEY in property_definition\n        or ONE_OF_KEY in property_definition\n        or ALL_OF_KEY in property_definition\n    )\n\n\ndef retrieve_selectors_from_union_definition(\n    property_name: str,\n    property_description: str,\n    union_definition: dict,\n    is_list_element: bool,\n    is_dict_element: bool,\n    property_dimensionality_offset: int,\n    is_dimensionality_reference_property: bool,\n    inputs_accepting_batches: Set[str],\n    inputs_accepting_batches_and_scalars: Set[str],\n    inputs_enforcing_auto_batch_casting: Set[str],\n) -> Optional[SelectorDefinition]:\n    union_types = (\n        union_definition.get(ANY_OF_KEY, [])\n        + union_definition.get(ONE_OF_KEY, [])\n        + union_definition.get(ALL_OF_KEY, [])\n    )\n    results = []\n    for type_definition in union_types:\n        result = retrieve_selectors_from_simple_property(\n            property_name=property_name,\n            property_description=property_description,\n            property_definition=type_definition,\n            property_dimensionality_offset=property_dimensionality_offset,\n            is_dimensionality_reference_property=is_dimensionality_reference_property,\n            inputs_accepting_batches=inputs_accepting_batches,\n            inputs_accepting_batches_and_scalars=inputs_accepting_batches_and_scalars,\n            inputs_enforcing_auto_batch_casting=inputs_enforcing_auto_batch_casting,\n            is_list_element=is_list_element,\n            is_dict_element=is_dict_element,\n        )\n        if result is None:\n            continue\n        results.append(result)\n    results_references = list(\n        itertools.chain.from_iterable(r.allowed_references for r in results)\n    )\n    results_references_kind_by_selected_element = defaultdict(set)\n    results_references_batch_pointing_by_selected_element = defaultdict(set)\n    for reference in results_references:\n        results_references_kind_by_selected_element[reference.selected_element].update(\n            reference.kind\n        )\n        results_references_batch_pointing_by_selected_element[\n            reference.selected_element\n        ].update(reference.points_to_batch)\n    merged_references = []\n    for (\n        reference_selected_element,\n        kind,\n    ) in results_references_kind_by_selected_element.items():\n        merged_references.append(\n            ReferenceDefinition(\n                selected_element=reference_selected_element,\n                kind=list(kind),\n                points_to_batch=results_references_batch_pointing_by_selected_element[\n                    reference_selected_element\n                ],\n            )\n        )\n    if not merged_references:\n        return None\n    merged_is_list_element = is_list_element or any(r.is_list_element for r in results)\n    merged_is_dict_element = is_dict_element or any(r.is_dict_element for r in results)\n    return SelectorDefinition(\n        property_name=property_name,\n        property_description=property_description,\n        allowed_references=merged_references,\n        is_list_element=merged_is_list_element,\n        is_dict_element=merged_is_dict_element,\n        dimensionality_offset=property_dimensionality_offset,\n        is_dimensionality_reference_property=is_dimensionality_reference_property,\n    )\n",
    "patch": null
  },
  {
    "trace_id": "10df3dd6-e4cf-4942-b158-b6da262b0036",
    "function_name": "MaskAreaMeasurementBlockV1.run",
    "file_path": "inference/core/workflows/core_steps/classical_cv/mask_area_measurement/v1.py",
    "speedup_x": 0.65,
    "review_quality": "high",
    "pre_optimization_commit": "0cfcffe66b48e56a5177c252b38aad0ef3f98c27",
    "resolution_method": "db_code_match",
    "source": "db_events",
    "original_function_code": "    def run(\n        self,\n        predictions: sv.Detections,\n    ) -> BlockResult:\n        areas = []\n        for i in range(len(predictions)):\n            areas.append(get_detection_area(predictions, i))\n        return {OUTPUT_KEY: areas}\n",
    "optimized_function_code": "import cv2 as cv\nimport numpy as np\nimport supervision as sv\nfrom inference.core.workflows.prototypes.block import BlockResult, WorkflowBlock\n\nOUTPUT_KEY = \"areas\"\n\n\ndef get_detection_area(detection: sv.Detections, index: int) -> float:\n    \"\"\"Compute the area of a single detection in square pixels.\n\n    If a segmentation mask is available, the area is computed from the largest\n    contour found in the mask using ``cv2.contourArea``.  Otherwise the area\n    falls back to bounding-box width * height.\n\n    Args:\n        detection: A supervision Detections object.\n        index: Index of the detection to measure.\n\n    Returns:\n        Area in square pixels.\n    \"\"\"\n    if detection.mask is not None:\n        mask = detection.mask[index].astype(np.uint8)\n        contours, _ = cv.findContours(mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)\n        if contours:\n            largest_contour = max(contours, key=cv.contourArea)\n            area = cv.contourArea(largest_contour)\n            if area > 0:\n                return float(area)\n\n    bbox = detection.xyxy[index]\n    w = bbox[2] - bbox[0]\n    h = bbox[3] - bbox[1]\n    return float(w * h)\n\n\nclass MaskAreaMeasurementBlockV1(WorkflowBlock):\n\n    def run(\n        self,\n        predictions: sv.Detections,\n    ) -> BlockResult:\n        if predictions.mask is not None:\n            areas = []\n            for i in range(len(predictions)):\n                areas.append(get_detection_area(predictions, i))\n        else:\n            xyxy = predictions.xyxy\n            widths = xyxy[:, 2] - xyxy[:, 0]\n            heights = xyxy[:, 3] - xyxy[:, 1]\n            areas = (widths * heights).tolist()\n        return {OUTPUT_KEY: areas}",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/classical_cv/mask_area_measurement/v1.py\nimport cv2 as cv\nimport numpy as np\nimport supervision as sv\nfrom inference.core.workflows.prototypes.block import BlockResult, WorkflowBlock\n\nOUTPUT_KEY = \"areas\"\n\n\ndef get_detection_area(detection: sv.Detections, index: int) -> float:\n    \"\"\"Compute the area of a single detection in square pixels.\n\n    If a segmentation mask is available, the area is computed from the largest\n    contour found in the mask using ``cv2.contourArea``.  Otherwise the area\n    falls back to bounding-box width * height.\n\n    Args:\n        detection: A supervision Detections object.\n        index: Index of the detection to measure.\n\n    Returns:\n        Area in square pixels.\n    \"\"\"\n    if detection.mask is not None:\n        mask = detection.mask[index].astype(np.uint8)\n        contours, _ = cv.findContours(mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)\n        if contours:\n            largest_contour = max(contours, key=cv.contourArea)\n            area = cv.contourArea(largest_contour)\n            if area > 0:\n                return float(area)\n\n    bbox = detection.xyxy[index]\n    w = bbox[2] - bbox[0]\n    h = bbox[3] - bbox[1]\n    return float(w * h)\n\n\nclass MaskAreaMeasurementBlockV1(WorkflowBlock):\n\n    def run(\n        self,\n        predictions: sv.Detections,\n    ) -> BlockResult:\n        if predictions.mask is not None:\n            areas = []\n            for i in range(len(predictions)):\n                areas.append(get_detection_area(predictions, i))\n        else:\n            xyxy = predictions.xyxy\n            widths = xyxy[:, 2] - xyxy[:, 0]\n            heights = xyxy[:, 3] - xyxy[:, 1]\n            areas = (widths * heights).tolist()\n        return {OUTPUT_KEY: areas}\n```",
    "optimized_function_only": "    def run(\n        self,\n        predictions: sv.Detections,\n    ) -> BlockResult:\n        if predictions.mask is not None:\n            areas = []\n            for i in range(len(predictions)):\n                areas.append(get_detection_area(predictions, i))\n        else:\n            xyxy = predictions.xyxy\n            widths = xyxy[:, 2] - xyxy[:, 0]\n            heights = xyxy[:, 3] - xyxy[:, 1]\n            areas = (widths * heights).tolist()\n        return {OUTPUT_KEY: areas}",
    "original_file_content": "from typing import List, Literal, Optional, Type\n\nimport cv2 as cv\nimport numpy as np\nimport supervision as sv\nfrom pydantic import ConfigDict, Field\n\nfrom inference.core.workflows.execution_engine.entities.base import OutputDefinition\nfrom inference.core.workflows.execution_engine.entities.types import (\n    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    LIST_OF_VALUES_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nOUTPUT_KEY = \"areas\"\nSHORT_DESCRIPTION = \"Measure the mask area of detected objects in square pixels.\"\nLONG_DESCRIPTION = \"\"\"\nMeasure the area of detected objects in square pixels. For detections with segmentation masks, the area is computed from the largest contour using `cv2.contourArea`. For bounding-box-only detections, the area is the bounding box width multiplied by height.\n\n## How This Block Works\n\nThis block calculates the area of each detected object in an image, returning a list of area values in square pixels. The block operates in two modes depending on the type of predictions it receives:\n\n1. **Polygon/Mask Area (Instance Segmentation)**: When the input detections include segmentation masks, the block extracts the mask for each detection, finds the largest external contour using OpenCV's `findContours`, and computes its area with `cv2.contourArea`. This provides a precise measurement that follows the actual shape of the object rather than its bounding rectangle.\n\n2. **Bounding Box Area (Object Detection)**: When no segmentation mask is available, the block falls back to computing the area as the bounding box width multiplied by height (`w * h`). This is less precise but works with any object detection model output.\n\nThe block processes all detections in the input and returns a list of area values (one per detection) under the `areas` output key.\n\n## Common Use Cases\n\n- **Size-Based Filtering**: Use area measurements to filter out small noise detections or irrelevant objects. Chain the output with a filtering block to keep only detections above a minimum area threshold, reducing false positives from small artifacts.\n- **Agricultural Analysis**: Measure leaf area, crop coverage, or canopy extent from aerial or close-up imagery. Combine with segmentation models trained on plant structures to quantify growth or health metrics.\n- **Quality Control**: Verify that manufactured components meet size specifications by measuring their area in pixels and comparing against expected ranges. Flag parts that fall outside acceptable tolerances.\n- **Medical Imaging**: Quantify the area of wounds, lesions, skin conditions, or anatomical structures in clinical images. When paired with a calibration reference, pixel areas can be converted to real-world units for clinical documentation.\n- **Inventory and Logistics**: Estimate the footprint of packages, pallets, or items on conveyor belts. Area measurements help classify objects by size category or detect misplaced items that differ from expected dimensions.\n\n## Connecting to Other Blocks\n\nThis block receives detection predictions and produces a list of area values:\n\n- **Upstream -- Detection and Segmentation Models**: Connect the output of an object detection or instance segmentation model to the `predictions` input. Instance segmentation models (which produce masks) yield more accurate area measurements than bounding-box-only detections.\n- **Upstream -- Camera Calibration Block**: If your camera introduces lens distortion, run images through the Camera Calibration block before detection to correct geometric distortions. This ensures that area measurements are not skewed by barrel or pincushion distortion.\n- **Upstream -- Perspective Correction Block**: For images captured at an angle (e.g., overhead cameras that are not perfectly perpendicular), apply the Perspective Correction block before detection. This transforms the image to a top-down view so that area measurements reflect true object footprints rather than perspective-distorted projections.\n- **Downstream -- Filtering Blocks**: Pass the `areas` output to a filtering or condition block (e.g., Continue If, Detection Filter) to keep only detections whose area meets a threshold, enabling size-based filtering workflows.\n- **Downstream -- Analytics and Visualization**: Feed area values into analytics blocks for aggregation, charting, or overlay display. Combine with other measurement blocks (Size Measurement, Distance Measurement) for comprehensive spatial analysis.\n\n## Converting Pixel Areas to Real-World Units\n\nThis block returns areas in **square pixels**. To convert to real-world units (e.g., cm\u00b2, in\u00b2, mm\u00b2), you need a calibration value: the number of pixels per unit of length along one axis (pixels_per_unit).\n\n**Important:** Because area is two-dimensional, you must **square** the pixels_per_unit ratio:\n\n```\narea_real = area_px / (pixels_per_unit ** 2)\n```\n\nFor example, if your calibration is 130 pixels/cm:\n\n```\narea_cm\u00b2 = area_px / (130 ** 2) = area_px / 16900\n```\n\nA common mistake is dividing by `pixels_per_unit` instead of `pixels_per_unit\u00b2`, which produces values that are off by a factor of the ratio itself.\n\n**How to determine pixels_per_unit:** Place an object of known size in the camera's field of view (e.g., a ruler or calibration target). Measure its length in pixels in the image and divide by its real-world length. For instance, if a 10 cm reference object spans 1300 pixels, then `pixels_per_cm = 1300 / 10 = 130`.\n\nYou can perform this conversion downstream using a Dynamic Python Block or a simple post-processing step in your application code.\n\n## Handling Camera Distortion\n\nLens distortion (barrel or pincushion) warps the image so that objects near the edges appear stretched or compressed compared to objects near the center. This directly affects area measurements \u2014 the same real-world object will report different pixel areas depending on where it appears in the frame.\n\n**When distortion matters:**\n- Wide-angle or fisheye lenses with visible barrel distortion\n- Applications requiring consistent area measurements across the entire frame\n- When objects of interest appear near the edges of the image\n\n**When distortion can be ignored:**\n- Objects are always near the center of the frame\n- The lens has minimal distortion (e.g., telecentric or narrow field-of-view lenses)\n- Relative area comparisons (larger vs. smaller) are sufficient and absolute accuracy is not required\n\n**How to correct for it:**\n1. **Camera Calibration Block**: Use the `roboflow_core/camera_calibration@v1` block upstream of your detection model. This block applies OpenCV's `undistort` to remove lens distortion before the image is processed, so that mask areas reflect the true object shape.\n2. **Perspective Correction Block**: If the camera views the scene at an angle (not perpendicular), use the `roboflow_core/perspective_correction@v1` block to warp the image to a top-down view. Without this, objects farther from the camera appear smaller and their measured areas will be understated.\n\nBoth corrections should be applied **before** the detection model runs, so that the segmentation masks and bounding boxes are computed on the corrected image.\n\n## Requirements\n\nThis block requires detection predictions from an object detection or instance segmentation model. No additional environment variables, API keys, or external dependencies are needed beyond the standard OpenCV and NumPy libraries included with inference. For the most accurate area measurements, use instance segmentation models that produce per-object masks. Bounding-box-only detections will yield rectangular area approximations.\n\"\"\"\n\n\nclass MaskAreaMeasurementManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Mask Area Measurement\",\n            \"version\": \"v1\",\n            \"short_description\": SHORT_DESCRIPTION,\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"transformation\",\n            \"ui_manifest\": {\n                \"section\": \"classical_cv\",\n                \"icon\": \"far fa-ruler-combined\",\n                \"blockPriority\": 12,\n                \"opencv\": True,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/mask_area_measurement@v1\"]\n\n    predictions: Selector(\n        kind=[\n            INSTANCE_SEGMENTATION_PREDICTION_KIND,\n            OBJECT_DETECTION_PREDICTION_KIND,\n        ]\n    ) = Field(\n        description=\"Detection predictions to measure areas for.\",\n        examples=[\"$steps.model.predictions\"],\n    )\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=OUTPUT_KEY, kind=[LIST_OF_VALUES_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\ndef get_detection_area(detection: sv.Detections, index: int) -> float:\n    \"\"\"Compute the area of a single detection in square pixels.\n\n    If a segmentation mask is available, the area is computed from the largest\n    contour found in the mask using ``cv2.contourArea``.  Otherwise the area\n    falls back to bounding-box width * height.\n\n    Args:\n        detection: A supervision Detections object.\n        index: Index of the detection to measure.\n\n    Returns:\n        Area in square pixels.\n    \"\"\"\n    if detection.mask is not None:\n        mask = detection.mask[index].astype(np.uint8)\n        contours, _ = cv.findContours(mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)\n        if contours:\n            largest_contour = max(contours, key=cv.contourArea)\n            area = cv.contourArea(largest_contour)\n            if area > 0:\n                return float(area)\n\n    bbox = detection.xyxy[index]\n    w = bbox[2] - bbox[0]\n    h = bbox[3] - bbox[1]\n    return float(w * h)\n\n\nclass MaskAreaMeasurementBlockV1(WorkflowBlock):\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return MaskAreaMeasurementManifest\n\n    def run(\n        self,\n        predictions: sv.Detections,\n    ) -> BlockResult:\n        areas = []\n        for i in range(len(predictions)):\n            areas.append(get_detection_area(predictions, i))\n        return {OUTPUT_KEY: areas}\n",
    "patch": null
  },
  {
    "trace_id": "97d1ea7e-10e0-4723-b296-0090fa39e721",
    "function_name": "_transpose_dict_of_batches_if_needed",
    "file_path": "inference/core/workflows/execution_engine/v1/executor/execution_data_manager/step_input_assembler.py",
    "speedup_x": 0.61,
    "review_quality": "high",
    "pre_optimization_commit": "HEAD",
    "resolution_method": "db_code_only",
    "source": "db_events",
    "original_function_code": "def _transpose_dict_of_batches_if_needed(\n    value: Dict[str, Any],\n) -> Union[Dict[str, Any], Batch]:\n    \"\"\"Transpose a dict-of-Batches into a Batch-of-dicts.\n\n    Compound dict inputs are resolved as {\"key1\": Batch([...]), \"key2\": Batch([...])}.\n    Batch-mode blocks expect Batch[Dict] instead. This function detects dicts containing\n    Batch values and transposes them so each batch element is a complete dict.\n    If no Batch values are present, returns the dict unchanged.\n    \"\"\"\n    batch_entries = {k: v for k, v in value.items() if isinstance(v, Batch)}\n    if not batch_entries:\n        return value\n    non_batch_entries = {k: v for k, v in value.items() if not isinstance(v, Batch)}\n    first_batch = next(iter(batch_entries.values()))\n    indices = first_batch.indices\n    length = len(first_batch)\n    content = []\n    for i in range(length):\n        entry = {}\n        for k, batch_val in batch_entries.items():\n            entry[k] = batch_val[i]\n        entry.update(non_batch_entries)\n        content.append(entry)\n    return Batch(content=content, indices=indices)",
    "optimized_function_code": "from typing import Any, Dict, Union\n\nfrom inference.core.workflows.execution_engine.entities.base import Batch\n\n\ndef _transpose_dict_of_batches_if_needed(\n    value: Dict[str, Any],\n) -> Union[Dict[str, Any], Batch]:\n    \"\"\"Transpose a dict-of-Batches into a Batch-of-dicts.\n\n    Compound dict inputs are resolved as {\"key1\": Batch([...]), \"key2\": Batch([...])}.\n    Batch-mode blocks expect Batch[Dict] instead. This function detects dicts containing\n    Batch values and transposes them so each batch element is a complete dict.\n    If no Batch values are present, returns the dict unchanged.\n    \"\"\"\n    batch_entries = {k: v for k, v in value.items() if isinstance(v, Batch)}\n    if not batch_entries:\n        return value\n    non_batch_entries = {k: v for k, v in value.items() if not isinstance(v, Batch)}\n    first_batch = next(iter(batch_entries.values()))\n    indices = first_batch.indices\n    length = len(first_batch)\n    \n    # Pre-extract batch contents to avoid repeated __getitem__ calls\n    batch_items = [(k, v._content) for k, v in batch_entries.items()]\n    \n    content = []\n    for i in range(length):\n        entry = {k: batch_content[i] for k, batch_content in batch_items}\n        if non_batch_entries:\n            entry.update(non_batch_entries)\n        content.append(entry)\n    return Batch(content=content, indices=indices)",
    "optimized_raw_markdown": "```python:inference/core/workflows/execution_engine/entities/base.py\nfrom __future__ import annotations\n\nfrom typing import Generic, List, Optional, Tuple, TypeVar\n\nB = TypeVar(\"B\")\n\n\nclass Batch(Generic[B]):\n\n    def __init__(self, content: List[B], indices: Optional[List[Tuple[int, ...]]]):\n        self._content = content\n        self._indices = indices\n```\n```python:inference/core/workflows/execution_engine/v1/executor/execution_data_manager/step_input_assembler.py\nfrom typing import Any, Dict, Union\n\nfrom inference.core.workflows.execution_engine.entities.base import Batch\n\n\ndef _transpose_dict_of_batches_if_needed(\n    value: Dict[str, Any],\n) -> Union[Dict[str, Any], Batch]:\n    \"\"\"Transpose a dict-of-Batches into a Batch-of-dicts.\n\n    Compound dict inputs are resolved as {\"key1\": Batch([...]), \"key2\": Batch([...])}.\n    Batch-mode blocks expect Batch[Dict] instead. This function detects dicts containing\n    Batch values and transposes them so each batch element is a complete dict.\n    If no Batch values are present, returns the dict unchanged.\n    \"\"\"\n    batch_entries = {k: v for k, v in value.items() if isinstance(v, Batch)}\n    if not batch_entries:\n        return value\n    non_batch_entries = {k: v for k, v in value.items() if not isinstance(v, Batch)}\n    first_batch = next(iter(batch_entries.values()))\n    indices = first_batch.indices\n    length = len(first_batch)\n    \n    # Pre-extract batch contents to avoid repeated __getitem__ calls\n    batch_items = [(k, v._content) for k, v in batch_entries.items()]\n    \n    content = []\n    for i in range(length):\n        entry = {k: batch_content[i] for k, batch_content in batch_items}\n        if non_batch_entries:\n            entry.update(non_batch_entries)\n        content.append(entry)\n    return Batch(content=content, indices=indices)\n```",
    "optimized_function_only": "def _transpose_dict_of_batches_if_needed(\n    value: Dict[str, Any],\n) -> Union[Dict[str, Any], Batch]:\n    \"\"\"Transpose a dict-of-Batches into a Batch-of-dicts.\n\n    Compound dict inputs are resolved as {\"key1\": Batch([...]), \"key2\": Batch([...])}.\n    Batch-mode blocks expect Batch[Dict] instead. This function detects dicts containing\n    Batch values and transposes them so each batch element is a complete dict.\n    If no Batch values are present, returns the dict unchanged.\n    \"\"\"\n    batch_entries = {k: v for k, v in value.items() if isinstance(v, Batch)}\n    if not batch_entries:\n        return value\n    non_batch_entries = {k: v for k, v in value.items() if not isinstance(v, Batch)}\n    first_batch = next(iter(batch_entries.values()))\n    indices = first_batch.indices\n    length = len(first_batch)\n    \n    # Pre-extract batch contents to avoid repeated __getitem__ calls\n    batch_items = [(k, v._content) for k, v in batch_entries.items()]\n    \n    content = []\n    for i in range(length):\n        entry = {k: batch_content[i] for k, batch_content in batch_items}\n        if non_batch_entries:\n            entry.update(non_batch_entries)\n        content.append(entry)\n    return Batch(content=content, indices=indices)",
    "original_file_content": "from inference.core.workflows.execution_engine.entities.base import Batch\nfrom typing import Any, Dict, Union\n\ndef _transpose_dict_of_batches_if_needed(\n    value: Dict[str, Any],\n) -> Union[Dict[str, Any], Batch]:\n    \"\"\"Transpose a dict-of-Batches into a Batch-of-dicts.\n\n    Compound dict inputs are resolved as {\"key1\": Batch([...]), \"key2\": Batch([...])}.\n    Batch-mode blocks expect Batch[Dict] instead. This function detects dicts containing\n    Batch values and transposes them so each batch element is a complete dict.\n    If no Batch values are present, returns the dict unchanged.\n    \"\"\"\n    batch_entries = {k: v for k, v in value.items() if isinstance(v, Batch)}\n    if not batch_entries:\n        return value\n    non_batch_entries = {k: v for k, v in value.items() if not isinstance(v, Batch)}\n    first_batch = next(iter(batch_entries.values()))\n    indices = first_batch.indices\n    length = len(first_batch)\n    content = []\n    for i in range(length):\n        entry = {}\n        for k, batch_val in batch_entries.items():\n            entry[k] = batch_val[i]\n        entry.update(non_batch_entries)\n        content.append(entry)\n    return Batch(content=content, indices=indices)",
    "patch": null
  },
  {
    "trace_id": "8c040576-154a-4fcc-b903-dcbf8f6e2ead",
    "function_name": "Qwen3VLBlockV1.run",
    "file_path": "inference/core/workflows/core_steps/models/foundation/qwen3vl/v1.py",
    "speedup_x": 0.45,
    "review_quality": "high",
    "pre_optimization_commit": "c20359386c628a08bde69f5f3f780cedd782c50c",
    "resolution_method": "db_code_match",
    "source": "db_events",
    "original_function_code": "    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n        system_prompt: Optional[str],\n    ) -> BlockResult:\n        if self._step_execution_mode == StepExecutionMode.LOCAL:\n            return self.run_locally(\n                images=images,\n                model_version=model_version,\n                prompt=prompt,\n                system_prompt=system_prompt,\n            )\n        elif self._step_execution_mode == StepExecutionMode.REMOTE:\n            return self.run_remotely(\n                images=images,\n                model_version=model_version,\n                prompt=prompt,\n                system_prompt=system_prompt,\n            )\n        else:\n            raise ValueError(\n                f\"Unknown step execution mode: {self._step_execution_mode}\"\n            )\n",
    "optimized_function_code": "##########################################################################\n# Qwen3-VL Workflow Block\n##########################################################################\nfrom typing import Optional\n\nfrom inference.core.entities.requests.inference import LMMInferenceRequest\nfrom inference.core.env import (HOSTED_CORE_MODEL_URL, LOCAL_INFERENCE_API_URL,\n                                WORKFLOWS_REMOTE_API_TARGET)\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.entities import \\\n    StepExecutionMode\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch, WorkflowImageData)\nfrom inference.core.workflows.prototypes.block import (BlockResult,\n                                                       WorkflowBlock)\nfrom inference_sdk import InferenceHTTPClient\n\n\nclass Qwen3VLBlockV1(WorkflowBlock):\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n        system_prompt: Optional[str],\n    ) -> BlockResult:\n        if self._step_execution_mode == StepExecutionMode.LOCAL:\n            return self.run_locally(\n                images=images,\n                model_version=model_version,\n                prompt=prompt,\n                system_prompt=system_prompt,\n            )\n        elif self._step_execution_mode == StepExecutionMode.REMOTE:\n            return self.run_remotely(\n                images=images,\n                model_version=model_version,\n                prompt=prompt,\n                system_prompt=system_prompt,\n            )\n        else:\n            raise ValueError(\n                f\"Unknown step execution mode: {self._step_execution_mode}\"\n            )\n\n    def run_remotely(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n        system_prompt: Optional[str],\n    ) -> BlockResult:\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_CORE_MODEL_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        if WORKFLOWS_REMOTE_API_TARGET == \"hosted\":\n            client.select_api_v0()\n\n        prompt = prompt or \"Describe what's in this image.\"\n        system_prompt = (\n            system_prompt\n            or \"You are a Qwen3-VL model that can answer questions about any image.\"\n        )\n        combined_prompt = prompt + \"<system_prompt>\" + system_prompt\n\n        # Collect inputs into a list so we can batch the HTTP request.\n        inputs = [image.base64_image for image in images]\n\n        if not inputs:\n            return []\n\n        # Perform a batched HTTP call when there are multiple images to reduce network overhead.\n        if len(inputs) == 1:\n            result = client.infer_lmm(\n                inference_input=inputs[0],\n                model_id=model_version,\n                prompt=combined_prompt,\n            )\n            # Normalize single-item result to a list for unified processing.\n            results_iterable = [result]\n        else:\n            results_iterable = client.infer_lmm(\n                inference_input=inputs,\n                model_id=model_version,\n                prompt=combined_prompt,\n            )\n\n        predictions = []\n        # results_iterable may be a list of dicts or a single dict wrapped above.\n        # Iterate and extract \"response\" if present.\n        if isinstance(results_iterable, list):\n            for item in results_iterable:\n                response_text = item.get(\"response\", item)\n                predictions.append({\"parsed_output\": response_text})\n        else:\n            # In case the client returns a non-list for multi inputs (defensive).\n            response_text = results_iterable.get(\"response\", results_iterable)\n            predictions.append({\"parsed_output\": response_text})\n\n        return predictions\n\n    def run_locally(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n        system_prompt: Optional[str],\n    ) -> BlockResult:\n        # Convert each image to the format required by the model.\n        inference_images = [\n            i.to_inference_format(numpy_preferred=False) for i in images\n        ]\n        # Use the provided prompt or default to a generic image description request.\n        prompt = prompt or \"Describe what's in this image.\"\n        system_prompt = (\n            system_prompt\n            or \"You are a Qwen3-VL model that can answer questions about any image.\"\n        )\n        combined_prompt = prompt + \"<system_prompt>\" + system_prompt\n        # Register Qwen3-VL with the model manager.\n        # Register Qwen3-VL with the model manager.\n        self._model_manager.add_model(model_id=model_version, api_key=self._api_key)\n\n        predictions = []\n        for image in inference_images:\n            # Build an LMMInferenceRequest with both prompt and image.\n            # Build an LMMInferenceRequest with both prompt and image.\n            request = LMMInferenceRequest(\n                api_key=self._api_key,\n                model_id=model_version,\n                image=image,\n                source=\"workflow-execution\",\n                prompt=combined_prompt,\n            )\n            # Run inference.\n            prediction = self._model_manager.infer_from_request_sync(\n                model_id=model_version, request=request\n            )\n            response_text = prediction.response\n            predictions.append(\n                {\n                    \"parsed_output\": response_text,\n                }\n            )\n        return predictions",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/models/foundation/qwen3vl/v1.py\n##########################################################################\n# Qwen3-VL Workflow Block\n##########################################################################\nfrom typing import Optional\n\nfrom inference.core.entities.requests.inference import LMMInferenceRequest\nfrom inference.core.env import (HOSTED_CORE_MODEL_URL, LOCAL_INFERENCE_API_URL,\n                                WORKFLOWS_REMOTE_API_TARGET)\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.entities import \\\n    StepExecutionMode\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch, WorkflowImageData)\nfrom inference.core.workflows.prototypes.block import (BlockResult,\n                                                       WorkflowBlock)\nfrom inference_sdk import InferenceHTTPClient\n\n\nclass Qwen3VLBlockV1(WorkflowBlock):\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n        system_prompt: Optional[str],\n    ) -> BlockResult:\n        if self._step_execution_mode == StepExecutionMode.LOCAL:\n            return self.run_locally(\n                images=images,\n                model_version=model_version,\n                prompt=prompt,\n                system_prompt=system_prompt,\n            )\n        elif self._step_execution_mode == StepExecutionMode.REMOTE:\n            return self.run_remotely(\n                images=images,\n                model_version=model_version,\n                prompt=prompt,\n                system_prompt=system_prompt,\n            )\n        else:\n            raise ValueError(\n                f\"Unknown step execution mode: {self._step_execution_mode}\"\n            )\n\n    def run_remotely(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n        system_prompt: Optional[str],\n    ) -> BlockResult:\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_CORE_MODEL_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        if WORKFLOWS_REMOTE_API_TARGET == \"hosted\":\n            client.select_api_v0()\n\n        prompt = prompt or \"Describe what's in this image.\"\n        system_prompt = (\n            system_prompt\n            or \"You are a Qwen3-VL model that can answer questions about any image.\"\n        )\n        combined_prompt = prompt + \"<system_prompt>\" + system_prompt\n\n        # Collect inputs into a list so we can batch the HTTP request.\n        inputs = [image.base64_image for image in images]\n\n        if not inputs:\n            return []\n\n        # Perform a batched HTTP call when there are multiple images to reduce network overhead.\n        if len(inputs) == 1:\n            result = client.infer_lmm(\n                inference_input=inputs[0],\n                model_id=model_version,\n                prompt=combined_prompt,\n            )\n            # Normalize single-item result to a list for unified processing.\n            results_iterable = [result]\n        else:\n            results_iterable = client.infer_lmm(\n                inference_input=inputs,\n                model_id=model_version,\n                prompt=combined_prompt,\n            )\n\n        predictions = []\n        # results_iterable may be a list of dicts or a single dict wrapped above.\n        # Iterate and extract \"response\" if present.\n        if isinstance(results_iterable, list):\n            for item in results_iterable:\n                response_text = item.get(\"response\", item)\n                predictions.append({\"parsed_output\": response_text})\n        else:\n            # In case the client returns a non-list for multi inputs (defensive).\n            response_text = results_iterable.get(\"response\", results_iterable)\n            predictions.append({\"parsed_output\": response_text})\n\n        return predictions\n\n    def run_locally(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n        system_prompt: Optional[str],\n    ) -> BlockResult:\n        # Convert each image to the format required by the model.\n        inference_images = [\n            i.to_inference_format(numpy_preferred=False) for i in images\n        ]\n        # Use the provided prompt or default to a generic image description request.\n        prompt = prompt or \"Describe what's in this image.\"\n        system_prompt = (\n            system_prompt\n            or \"You are a Qwen3-VL model that can answer questions about any image.\"\n        )\n        combined_prompt = prompt + \"<system_prompt>\" + system_prompt\n        # Register Qwen3-VL with the model manager.\n        # Register Qwen3-VL with the model manager.\n        self._model_manager.add_model(model_id=model_version, api_key=self._api_key)\n\n        predictions = []\n        for image in inference_images:\n            # Build an LMMInferenceRequest with both prompt and image.\n            # Build an LMMInferenceRequest with both prompt and image.\n            request = LMMInferenceRequest(\n                api_key=self._api_key,\n                model_id=model_version,\n                image=image,\n                source=\"workflow-execution\",\n                prompt=combined_prompt,\n            )\n            # Run inference.\n            prediction = self._model_manager.infer_from_request_sync(\n                model_id=model_version, request=request\n            )\n            response_text = prediction.response\n            predictions.append(\n                {\n                    \"parsed_output\": response_text,\n                }\n            )\n        return predictions\n```",
    "optimized_function_only": "    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n        system_prompt: Optional[str],\n    ) -> BlockResult:\n        if self._step_execution_mode == StepExecutionMode.LOCAL:\n            return self.run_locally(\n                images=images,\n                model_version=model_version,\n                prompt=prompt,\n                system_prompt=system_prompt,\n            )\n        elif self._step_execution_mode == StepExecutionMode.REMOTE:\n            return self.run_remotely(\n                images=images,\n                model_version=model_version,\n                prompt=prompt,\n                system_prompt=system_prompt,\n            )\n        else:\n            raise ValueError(\n                f\"Unknown step execution mode: {self._step_execution_mode}\"\n            )\n",
    "original_file_content": "import json\nfrom typing import List, Literal, Optional, Type, Union\n\nimport supervision as sv\nfrom pydantic import ConfigDict, Field\n\nfrom inference.core.entities.requests.inference import LMMInferenceRequest\nfrom inference.core.env import (\n    HOSTED_CORE_MODEL_URL,\n    LOCAL_INFERENCE_API_URL,\n    WORKFLOWS_REMOTE_API_TARGET,\n)\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.entities import StepExecutionMode\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    DICTIONARY_KIND,\n    IMAGE_KIND,\n    LANGUAGE_MODEL_OUTPUT_KIND,\n    ROBOFLOW_MODEL_ID_KIND,\n    STRING_KIND,\n    ImageInputField,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\nfrom inference_sdk import InferenceHTTPClient\n\n\n##########################################################################\n# Qwen3-VL Workflow Block Manifest\n##########################################################################\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Qwen3-VL\",\n            \"version\": \"v1\",\n            \"short_description\": \"Run Qwen3-VL on an image.\",\n            \"long_description\": (\n                \"This workflow block runs Qwen3-VL\u2014a vision language model that accepts an image \"\n                \"and an optional text prompt\u2014and returns a text answer based on a conversation template.\"\n            ),\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"model\",\n            \"search_keywords\": [\n                \"Qwen3\",\n                \"qwen3-vl\",\n                \"vision language model\",\n                \"VLM\",\n                \"Alibaba\",\n            ],\n            \"is_vlm_block\": True,\n            \"ui_manifest\": {\n                \"section\": \"model\",\n                \"icon\": \"fal fa-atom\",\n                \"blockPriority\": 5.5,\n            },\n        },\n        protected_namespaces=(),\n    )\n    type: Literal[\"roboflow_core/qwen3vl@v1\"]\n\n    images: Selector(kind=[IMAGE_KIND]) = ImageInputField\n    prompt: Optional[str] = Field(\n        default=None,\n        description=\"Optional text prompt to provide additional context to Qwen3-VL. Otherwise it will just be a default one, which may affect the desired model behavior.\",\n        examples=[\"What is in this image?\"],\n    )\n    model_version: Union[Selector(kind=[ROBOFLOW_MODEL_ID_KIND]), str] = Field(\n        default=\"qwen3vl-2b-instruct\",\n        description=\"The Qwen3-VL model to be used for inference.\",\n        examples=[\"qwen3vl-2b-instruct\"],\n    )\n\n    system_prompt: Optional[str] = Field(\n        default=None,\n        description=\"Optional system prompt to provide additional context to Qwen3-VL.\",\n        examples=[\"You are a helpful assistant.\"],\n    )\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(\n                name=\"parsed_output\",\n                kind=[DICTIONARY_KIND],\n                description=\"A parsed version of the output, provided as a dictionary containing the text.\",\n            ),\n        ]\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        # Only images can be passed in as a list/batch\n        return [\"images\"]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n    @classmethod\n    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        return [\"qwen-pretrains/2\"]\n\n\n##########################################################################\n# Qwen3-VL Workflow Block\n##########################################################################\nclass Qwen3VLBlockV1(WorkflowBlock):\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"model_manager\", \"api_key\", \"step_execution_mode\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n        system_prompt: Optional[str],\n    ) -> BlockResult:\n        if self._step_execution_mode == StepExecutionMode.LOCAL:\n            return self.run_locally(\n                images=images,\n                model_version=model_version,\n                prompt=prompt,\n                system_prompt=system_prompt,\n            )\n        elif self._step_execution_mode == StepExecutionMode.REMOTE:\n            return self.run_remotely(\n                images=images,\n                model_version=model_version,\n                prompt=prompt,\n                system_prompt=system_prompt,\n            )\n        else:\n            raise ValueError(\n                f\"Unknown step execution mode: {self._step_execution_mode}\"\n            )\n\n    def run_remotely(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n        system_prompt: Optional[str],\n    ) -> BlockResult:\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_CORE_MODEL_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        if WORKFLOWS_REMOTE_API_TARGET == \"hosted\":\n            client.select_api_v0()\n\n        prompt = prompt or \"Describe what's in this image.\"\n        system_prompt = (\n            system_prompt\n            or \"You are a Qwen3-VL model that can answer questions about any image.\"\n        )\n        combined_prompt = prompt + \"<system_prompt>\" + system_prompt\n\n        predictions = []\n        for image in images:\n            result = client.infer_lmm(\n                inference_input=image.base64_image,\n                model_id=model_version,\n                prompt=combined_prompt,\n                model_id_in_path=True,\n            )\n            response_text = result.get(\"response\", result)\n            predictions.append({\"parsed_output\": response_text})\n\n        return predictions\n\n    def run_locally(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n        system_prompt: Optional[str],\n    ) -> BlockResult:\n        # Convert each image to the format required by the model.\n        inference_images = [\n            i.to_inference_format(numpy_preferred=False) for i in images\n        ]\n        # Use the provided prompt or default to a generic image description request.\n        prompt = prompt or \"Describe what's in this image.\"\n        system_prompt = (\n            system_prompt\n            or \"You are a Qwen3-VL model that can answer questions about any image.\"\n        )\n        prompts = [prompt + \"<system_prompt>\" + system_prompt] * len(inference_images)\n        # Register Qwen3-VL with the model manager.\n        self._model_manager.add_model(model_id=model_version, api_key=self._api_key)\n\n        predictions = []\n        for image, single_prompt in zip(inference_images, prompts):\n            # Build an LMMInferenceRequest with both prompt and image.\n            request = LMMInferenceRequest(\n                api_key=self._api_key,\n                model_id=model_version,\n                image=image,\n                source=\"workflow-execution\",\n                prompt=single_prompt,\n            )\n            # Run inference.\n            prediction = self._model_manager.infer_from_request_sync(\n                model_id=model_version, request=request\n            )\n            response_text = prediction.response\n            predictions.append(\n                {\n                    \"parsed_output\": response_text,\n                }\n            )\n        return predictions\n",
    "patch": null
  },
  {
    "trace_id": "9342b3af-dd86-4a27-9d2e-3cae51ca4dbd",
    "function_name": "HeatmapVisualizationBlockV1.getAnnotator",
    "file_path": "inference/core/workflows/core_steps/visualizations/heatmap/v1.py",
    "speedup_x": 0.41,
    "review_quality": "high",
    "pre_optimization_commit": "HEAD",
    "resolution_method": "db_code_only",
    "source": "db_events",
    "original_function_code": "    def getAnnotator(\n        self,\n        position: str,\n        opacity: float,\n        radius: int,\n        kernel_size: int,\n        top_hue: int,\n        low_hue: int,\n    ) -> sv.annotators.base.BaseAnnotator:\n        key = \"_\".join(\n            map(\n                str,\n                [\n                    position,\n                    opacity,\n                    radius,\n                    kernel_size,\n                    top_hue,\n                    low_hue,\n                ],\n            )\n        )\n\n        if key not in self.annotatorCache:\n            position_enum = getattr(sv.Position, position)\n            self.annotatorCache[key] = sv.HeatMapAnnotator(\n                position=position_enum,\n                opacity=opacity,\n                radius=radius,\n                kernel_size=kernel_size,\n                top_hue=top_hue,\n                low_hue=low_hue,\n            )\n\n        return self.annotatorCache[key]",
    "optimized_function_code": "from typing import Dict\n\nimport supervision as sv\nfrom inference.core.workflows.core_steps.visualizations.common.base import \\\n    PredictionsVisualizationBlock\n\n\nclass HeatmapVisualizationBlockV1(PredictionsVisualizationBlock):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.annotatorCache = {}\n        # Dictionary to store track history: {video_id: {tracker_id: (x, y)}}\n        self._track_history: Dict[str, Dict[int, tuple]] = {}\n\n    def getAnnotator(\n        self,\n        position: str,\n        opacity: float,\n        radius: int,\n        kernel_size: int,\n        top_hue: int,\n        low_hue: int,\n    ) -> sv.annotators.base.BaseAnnotator:\n        # Build a tuple key of stringified components to avoid creating a joined string\n        key = (\n            position,\n            str(opacity),\n            str(radius),\n            str(kernel_size),\n            str(top_hue),\n            str(low_hue),\n        )\n\n        # Fast-path return if cached\n        annotator = self.annotatorCache.get(key)\n        if annotator is not None:\n            return annotator\n\n        # Cache Position enum lookups to avoid repeated getattr calls\n        pos_cache = getattr(self, \"_position_enum_cache\", None)\n        if pos_cache is None:\n            pos_cache = {}\n            self._position_enum_cache = pos_cache\n\n        position_enum = pos_cache.get(position)\n        if position_enum is None:\n            # Preserve original behavior: if attribute missing, let AttributeError propagate\n            position_enum = getattr(sv.Position, position)\n            pos_cache[position] = position_enum\n\n        annotator = sv.HeatMapAnnotator(\n            position=position_enum,\n            opacity=opacity,\n            radius=radius,\n            kernel_size=kernel_size,\n            top_hue=top_hue,\n            low_hue=low_hue,\n        )\n\n        self.annotatorCache[key] = annotator\n\n        return annotator",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/visualizations/heatmap/v1.py\nfrom typing import Dict\n\nimport supervision as sv\nfrom inference.core.workflows.core_steps.visualizations.common.base import \\\n    PredictionsVisualizationBlock\n\n\nclass HeatmapVisualizationBlockV1(PredictionsVisualizationBlock):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.annotatorCache = {}\n        # Dictionary to store track history: {video_id: {tracker_id: (x, y)}}\n        self._track_history: Dict[str, Dict[int, tuple]] = {}\n\n    def getAnnotator(\n        self,\n        position: str,\n        opacity: float,\n        radius: int,\n        kernel_size: int,\n        top_hue: int,\n        low_hue: int,\n    ) -> sv.annotators.base.BaseAnnotator:\n        # Build a tuple key of stringified components to avoid creating a joined string\n        key = (\n            position,\n            str(opacity),\n            str(radius),\n            str(kernel_size),\n            str(top_hue),\n            str(low_hue),\n        )\n\n        # Fast-path return if cached\n        annotator = self.annotatorCache.get(key)\n        if annotator is not None:\n            return annotator\n\n        # Cache Position enum lookups to avoid repeated getattr calls\n        pos_cache = getattr(self, \"_position_enum_cache\", None)\n        if pos_cache is None:\n            pos_cache = {}\n            self._position_enum_cache = pos_cache\n\n        position_enum = pos_cache.get(position)\n        if position_enum is None:\n            # Preserve original behavior: if attribute missing, let AttributeError propagate\n            position_enum = getattr(sv.Position, position)\n            pos_cache[position] = position_enum\n\n        annotator = sv.HeatMapAnnotator(\n            position=position_enum,\n            opacity=opacity,\n            radius=radius,\n            kernel_size=kernel_size,\n            top_hue=top_hue,\n            low_hue=low_hue,\n        )\n\n        self.annotatorCache[key] = annotator\n\n        return annotator\n```",
    "optimized_function_only": "    def getAnnotator(\n        self,\n        position: str,\n        opacity: float,\n        radius: int,\n        kernel_size: int,\n        top_hue: int,\n        low_hue: int,\n    ) -> sv.annotators.base.BaseAnnotator:\n        # Build a tuple key of stringified components to avoid creating a joined string\n        key = (\n            position,\n            str(opacity),\n            str(radius),\n            str(kernel_size),\n            str(top_hue),\n            str(low_hue),\n        )\n\n        # Fast-path return if cached\n        annotator = self.annotatorCache.get(key)\n        if annotator is not None:\n            return annotator\n\n        # Cache Position enum lookups to avoid repeated getattr calls\n        pos_cache = getattr(self, \"_position_enum_cache\", None)\n        if pos_cache is None:\n            pos_cache = {}\n            self._position_enum_cache = pos_cache\n\n        position_enum = pos_cache.get(position)\n        if position_enum is None:\n            # Preserve original behavior: if attribute missing, let AttributeError propagate\n            position_enum = getattr(sv.Position, position)\n            pos_cache[position] = position_enum\n\n        annotator = sv.HeatMapAnnotator(\n            position=position_enum,\n            opacity=opacity,\n            radius=radius,\n            kernel_size=kernel_size,\n            top_hue=top_hue,\n            low_hue=low_hue,\n        )\n\n        self.annotatorCache[key] = annotator\n\n        return annotator",
    "original_file_content": "import supervision as sv\nfrom inference.core.workflows.core_steps.visualizations.common.base import PredictionsVisualizationBlock\nfrom typing import Dict\n\nclass HeatmapVisualizationBlockV1(PredictionsVisualizationBlock):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.annotatorCache = {}\n        # Dictionary to store track history: {video_id: {tracker_id: (x, y)}}\n        self._track_history: Dict[str, Dict[int, tuple]] = {}\n\n    def getAnnotator(\n        self,\n        position: str,\n        opacity: float,\n        radius: int,\n        kernel_size: int,\n        top_hue: int,\n        low_hue: int,\n    ) -> sv.annotators.base.BaseAnnotator:\n        key = \"_\".join(\n            map(\n                str,\n                [\n                    position,\n                    opacity,\n                    radius,\n                    kernel_size,\n                    top_hue,\n                    low_hue,\n                ],\n            )\n        )\n\n        if key not in self.annotatorCache:\n            position_enum = getattr(sv.Position, position)\n            self.annotatorCache[key] = sv.HeatMapAnnotator(\n                position=position_enum,\n                opacity=opacity,\n                radius=radius,\n                kernel_size=kernel_size,\n                top_hue=top_hue,\n                low_hue=low_hue,\n            )\n\n        return self.annotatorCache[key]",
    "patch": null
  },
  {
    "trace_id": "16124b10-e860-4911-ab38-19c7e2992080",
    "function_name": "VideoFrameProcessor.serialize_outputs_sync",
    "file_path": "inference/core/interfaces/webrtc_worker/webrtc.py",
    "speedup_x": 0.37,
    "review_quality": "high",
    "pre_optimization_commit": "5084f39d5f913daa06247d85a5af244b7a835a09",
    "resolution_method": "db_code_match",
    "source": "db_events",
    "original_function_code": "    def serialize_outputs_sync(\n        fields_to_send: List[str],\n        workflow_output: Dict[str, Any],\n        data_output_mode: DataOutputMode,\n    ) -> Tuple[Dict[str, Any], List[str]]:\n        \"\"\"Serialize workflow outputs in a thread to avoid blocking the event loop.\n\n        Uses low JPEG quality (quality=10) for image compression to reduce\n        frame size from ~1MB to ~50KB for efficient WebRTC transmission.\n        \"\"\"\n        serialized = {}\n        serialization_errors = []\n\n        for field_name in fields_to_send:\n            if field_name not in workflow_output:\n                serialization_errors.append(\n                    f\"Requested output '{field_name}' not found in workflow outputs\"\n                )\n                continue\n\n            output_data = workflow_output[field_name]\n\n            if data_output_mode == DataOutputMode.ALL and isinstance(\n                output_data, WorkflowImageData\n            ):\n                continue\n\n            try:\n                serialized_value = serialize_for_webrtc(output_data)\n                serialized[field_name] = serialized_value\n            except Exception as e:\n                serialization_errors.append(f\"{field_name}: {e}\")\n                serialized[field_name] = {\"__serialization_error__\": str(e)}\n\n        return serialized, serialization_errors\n",
    "optimized_function_code": "# WebRTC image compression quality - lower = smaller file size, quality=10 reduces ~1MB to ~50KB\nimport asyncio\nimport datetime\nfrom typing import Any, Callable, Dict, List, Optional, Tuple\n\nimport supervision as sv\nfrom aiortc import RTCDataChannel\nfrom aiortc.mediastreams import MediaStreamTrack\nfrom inference.core.env import WEBRTC_DATA_CHANNEL_ACK_WINDOW\nfrom inference.core.exceptions import WebRTCConfigurationError\nfrom inference.core.interfaces.camera.entities import VideoFrameProducer\nfrom inference.core.interfaces.stream.inference_pipeline import \\\n    InferencePipeline\nfrom inference.core.interfaces.stream_manager.manager_app.entities import \\\n    WorkflowConfiguration\nfrom inference.core.interfaces.webrtc_worker.entities import DataOutputMode\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.serializers import (\n    serialise_sv_detections, serialize_timestamp)\nfrom inference.core.workflows.execution_engine.entities.base import \\\n    WorkflowImageData\n\nWEBRTC_JPEG_QUALITY = 10\n\n\ndef serialize_for_webrtc(value: Any) -> Any:\n    \"\"\"Recursively serialize, compressing images with JPEG quality=10.\"\"\"\n    value_type = type(value)\n    \n    if value_type is WorkflowImageData:\n        return serialise_image_for_webrtc(value)\n    \n    if value_type is dict:\n        result = {}\n        for k, v in value.items():\n            result[k] = serialize_for_webrtc(v)\n        return result\n    \n    if value_type is list:\n        return [serialize_for_webrtc(v) for v in value]\n    \n    if value_type is sv.Detections:\n        return serialise_sv_detections(value)\n    \n    if value_type is datetime.datetime:\n        return serialize_timestamp(value)\n    return value\n\n\nclass VideoFrameProcessor:\n\n    def __init__(\n        self,\n        asyncio_loop: asyncio.AbstractEventLoop,\n        workflow_configuration: WorkflowConfiguration,\n        api_key: str,\n        model_manager: Optional[ModelManager] = None,\n        data_output: Optional[List[str]] = None,\n        stream_output: Optional[str] = None,\n        has_video_track: bool = True,\n        declared_fps: float = 30,\n        termination_date: Optional[datetime.datetime] = None,\n        terminate_event: Optional[asyncio.Event] = None,\n        heartbeat_callback: Optional[Callable[[], None]] = None,\n        realtime_processing: bool = True,\n        is_preview: bool = False,\n    ):\n        self._loop = asyncio_loop\n        self._termination_date = termination_date\n        self._terminate_event = terminate_event\n        self.track: Optional[MediaStreamTrack] = None\n        self._track_active: bool = False\n        self._av_logging_set: bool = False\n        self._received_frames = 0\n        self._declared_fps = declared_fps\n        self._stop_processing = False\n        self.heartbeat_callback = heartbeat_callback\n\n        self.has_video_track = has_video_track\n        self.stream_output = stream_output\n        self.data_channel: Optional[RTCDataChannel] = None\n\n        # Video file upload support\n        self.video_upload_handler: Optional[VideoFileUploadHandler] = None\n        self._track_ready_event: asyncio.Event = asyncio.Event()\n        self.realtime_processing = realtime_processing\n        self._rotation_code: Optional[int] = None\n\n        # Optional receiver-paced flow control (enabled only after first ACK is received)\n        self._ack_last: int = 0\n        # If ack=1 and window=4, server may produce/send up to frame 5.\n        # Configurable via WEBRTC_DATACHANNEL_ACK_WINDOW env var.\n        self._ack_window: int = WEBRTC_DATA_CHANNEL_ACK_WINDOW\n        self._ack_event: asyncio.Event = asyncio.Event()\n\n        if data_output is None:\n            self.data_output = None\n            self._data_mode = DataOutputMode.NONE\n        elif isinstance(data_output, list):\n            self.data_output = [f for f in data_output if f]\n            if self.data_output == [\"*\"]:\n                self._data_mode = DataOutputMode.ALL\n            elif len(self.data_output) == 0:\n                self._data_mode = DataOutputMode.NONE\n            else:\n                self._data_mode = DataOutputMode.SPECIFIC\n        else:\n            raise WebRTCConfigurationError(\n                f\"data_output must be list or None, got {type(data_output).__name__}\"\n            )\n\n        self._validate_output_fields(workflow_configuration)\n\n        self._inference_pipeline = InferencePipeline.init_with_workflow(\n            video_reference=VideoFrameProducer,\n            workflow_specification=workflow_configuration.workflow_specification,\n            workspace_name=workflow_configuration.workspace_name,\n            workflow_id=workflow_configuration.workflow_id,\n            api_key=api_key,\n            image_input_name=workflow_configuration.image_input_name,\n            workflows_parameters=workflow_configuration.workflows_parameters,\n            workflows_thread_pool_workers=workflow_configuration.workflows_thread_pool_workers,\n            cancel_thread_pool_tasks_on_exit=workflow_configuration.cancel_thread_pool_tasks_on_exit,\n            video_metadata_input_name=workflow_configuration.video_metadata_input_name,\n            model_manager=model_manager,\n            _is_preview=is_preview,\n        )\n\n    @staticmethod\n    def serialize_outputs_sync(\n        fields_to_send: List[str],\n        workflow_output: Dict[str, Any],\n        data_output_mode: DataOutputMode,\n    ) -> Tuple[Dict[str, Any], List[str]]:\n        \"\"\"Serialize workflow outputs in a thread to avoid blocking the event loop.\n        \n        Uses low JPEG quality (quality=10) for image compression to reduce\n        frame size from ~1MB to ~50KB for efficient WebRTC transmission.\n        \"\"\"\n        serialized = {}\n        serialization_errors = []\n\n        for field_name in fields_to_send:\n            if field_name not in workflow_output:\n                serialization_errors.append(\n                    f\"Requested output '{field_name}' not found in workflow outputs\"\n                )\n                continue\n\n            output_data = workflow_output[field_name]\n\n            if data_output_mode == DataOutputMode.ALL and type(output_data) is WorkflowImageData:\n                continue\n\n            try:\n                serialized_value = serialize_for_webrtc(output_data)\n                serialized[field_name] = serialized_value\n            except Exception as e:\n                serialization_errors.append(f\"{field_name}: {e}\")\n                serialized[field_name] = {\"__serialization_error__\": str(e)}\n\n        return serialized, serialization_errors",
    "optimized_raw_markdown": "```python:inference/core/interfaces/webrtc_worker/webrtc.py\n# WebRTC image compression quality - lower = smaller file size, quality=10 reduces ~1MB to ~50KB\nimport asyncio\nimport datetime\nfrom typing import Any, Callable, Dict, List, Optional, Tuple\n\nimport supervision as sv\nfrom aiortc import RTCDataChannel\nfrom aiortc.mediastreams import MediaStreamTrack\nfrom inference.core.env import WEBRTC_DATA_CHANNEL_ACK_WINDOW\nfrom inference.core.exceptions import WebRTCConfigurationError\nfrom inference.core.interfaces.camera.entities import VideoFrameProducer\nfrom inference.core.interfaces.stream.inference_pipeline import \\\n    InferencePipeline\nfrom inference.core.interfaces.stream_manager.manager_app.entities import \\\n    WorkflowConfiguration\nfrom inference.core.interfaces.webrtc_worker.entities import DataOutputMode\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.serializers import (\n    serialise_sv_detections, serialize_timestamp)\nfrom inference.core.workflows.execution_engine.entities.base import \\\n    WorkflowImageData\n\nWEBRTC_JPEG_QUALITY = 10\n\n\ndef serialize_for_webrtc(value: Any) -> Any:\n    \"\"\"Recursively serialize, compressing images with JPEG quality=10.\"\"\"\n    value_type = type(value)\n    \n    if value_type is WorkflowImageData:\n        return serialise_image_for_webrtc(value)\n    \n    if value_type is dict:\n        result = {}\n        for k, v in value.items():\n            result[k] = serialize_for_webrtc(v)\n        return result\n    \n    if value_type is list:\n        return [serialize_for_webrtc(v) for v in value]\n    \n    if value_type is sv.Detections:\n        return serialise_sv_detections(value)\n    \n    if value_type is datetime.datetime:\n        return serialize_timestamp(value)\n    return value\n\n\nclass VideoFrameProcessor:\n\n    def __init__(\n        self,\n        asyncio_loop: asyncio.AbstractEventLoop,\n        workflow_configuration: WorkflowConfiguration,\n        api_key: str,\n        model_manager: Optional[ModelManager] = None,\n        data_output: Optional[List[str]] = None,\n        stream_output: Optional[str] = None,\n        has_video_track: bool = True,\n        declared_fps: float = 30,\n        termination_date: Optional[datetime.datetime] = None,\n        terminate_event: Optional[asyncio.Event] = None,\n        heartbeat_callback: Optional[Callable[[], None]] = None,\n        realtime_processing: bool = True,\n        is_preview: bool = False,\n    ):\n        self._loop = asyncio_loop\n        self._termination_date = termination_date\n        self._terminate_event = terminate_event\n        self.track: Optional[MediaStreamTrack] = None\n        self._track_active: bool = False\n        self._av_logging_set: bool = False\n        self._received_frames = 0\n        self._declared_fps = declared_fps\n        self._stop_processing = False\n        self.heartbeat_callback = heartbeat_callback\n\n        self.has_video_track = has_video_track\n        self.stream_output = stream_output\n        self.data_channel: Optional[RTCDataChannel] = None\n\n        # Video file upload support\n        self.video_upload_handler: Optional[VideoFileUploadHandler] = None\n        self._track_ready_event: asyncio.Event = asyncio.Event()\n        self.realtime_processing = realtime_processing\n        self._rotation_code: Optional[int] = None\n\n        # Optional receiver-paced flow control (enabled only after first ACK is received)\n        self._ack_last: int = 0\n        # If ack=1 and window=4, server may produce/send up to frame 5.\n        # Configurable via WEBRTC_DATACHANNEL_ACK_WINDOW env var.\n        self._ack_window: int = WEBRTC_DATA_CHANNEL_ACK_WINDOW\n        self._ack_event: asyncio.Event = asyncio.Event()\n\n        if data_output is None:\n            self.data_output = None\n            self._data_mode = DataOutputMode.NONE\n        elif isinstance(data_output, list):\n            self.data_output = [f for f in data_output if f]\n            if self.data_output == [\"*\"]:\n                self._data_mode = DataOutputMode.ALL\n            elif len(self.data_output) == 0:\n                self._data_mode = DataOutputMode.NONE\n            else:\n                self._data_mode = DataOutputMode.SPECIFIC\n        else:\n            raise WebRTCConfigurationError(\n                f\"data_output must be list or None, got {type(data_output).__name__}\"\n            )\n\n        self._validate_output_fields(workflow_configuration)\n\n        self._inference_pipeline = InferencePipeline.init_with_workflow(\n            video_reference=VideoFrameProducer,\n            workflow_specification=workflow_configuration.workflow_specification,\n            workspace_name=workflow_configuration.workspace_name,\n            workflow_id=workflow_configuration.workflow_id,\n            api_key=api_key,\n            image_input_name=workflow_configuration.image_input_name,\n            workflows_parameters=workflow_configuration.workflows_parameters,\n            workflows_thread_pool_workers=workflow_configuration.workflows_thread_pool_workers,\n            cancel_thread_pool_tasks_on_exit=workflow_configuration.cancel_thread_pool_tasks_on_exit,\n            video_metadata_input_name=workflow_configuration.video_metadata_input_name,\n            model_manager=model_manager,\n            _is_preview=is_preview,\n        )\n\n    @staticmethod\n    def serialize_outputs_sync(\n        fields_to_send: List[str],\n        workflow_output: Dict[str, Any],\n        data_output_mode: DataOutputMode,\n    ) -> Tuple[Dict[str, Any], List[str]]:\n        \"\"\"Serialize workflow outputs in a thread to avoid blocking the event loop.\n        \n        Uses low JPEG quality (quality=10) for image compression to reduce\n        frame size from ~1MB to ~50KB for efficient WebRTC transmission.\n        \"\"\"\n        serialized = {}\n        serialization_errors = []\n\n        for field_name in fields_to_send:\n            if field_name not in workflow_output:\n                serialization_errors.append(\n                    f\"Requested output '{field_name}' not found in workflow outputs\"\n                )\n                continue\n\n            output_data = workflow_output[field_name]\n\n            if data_output_mode == DataOutputMode.ALL and type(output_data) is WorkflowImageData:\n                continue\n\n            try:\n                serialized_value = serialize_for_webrtc(output_data)\n                serialized[field_name] = serialized_value\n            except Exception as e:\n                serialization_errors.append(f\"{field_name}: {e}\")\n                serialized[field_name] = {\"__serialization_error__\": str(e)}\n\n        return serialized, serialization_errors\n```",
    "optimized_function_only": "    def serialize_outputs_sync(\n        fields_to_send: List[str],\n        workflow_output: Dict[str, Any],\n        data_output_mode: DataOutputMode,\n    ) -> Tuple[Dict[str, Any], List[str]]:\n        \"\"\"Serialize workflow outputs in a thread to avoid blocking the event loop.\n        \n        Uses low JPEG quality (quality=10) for image compression to reduce\n        frame size from ~1MB to ~50KB for efficient WebRTC transmission.\n        \"\"\"\n        serialized = {}\n        serialization_errors = []\n\n        for field_name in fields_to_send:\n            if field_name not in workflow_output:\n                serialization_errors.append(\n                    f\"Requested output '{field_name}' not found in workflow outputs\"\n                )\n                continue\n\n            output_data = workflow_output[field_name]\n\n            if data_output_mode == DataOutputMode.ALL and type(output_data) is WorkflowImageData:\n                continue\n\n            try:\n                serialized_value = serialize_for_webrtc(output_data)\n                serialized[field_name] = serialized_value\n            except Exception as e:\n                serialization_errors.append(f\"{field_name}: {e}\")\n                serialized[field_name] = {\"__serialization_error__\": str(e)}\n\n        return serialized, serialization_errors",
    "original_file_content": "import asyncio\nimport base64\nimport datetime\nimport av\nimport json\nimport logging\nimport queue\nimport struct\nimport threading\nimport time\nfrom typing import Any, Callable, Dict, List, Optional, Tuple\n\nimport supervision as sv\n\nfrom aioice import ice\nfrom aiortc import (\n    RTCConfiguration,\n    RTCDataChannel,\n    RTCIceServer,\n    RTCPeerConnection,\n    RTCSessionDescription,\n    VideoStreamTrack,\n)\nfrom aiortc.contrib.media import MediaPlayer, MediaRelay, PlayerStreamTrack\nfrom aiortc.mediastreams import MediaStreamError, MediaStreamTrack\nfrom aiortc.rtcrtpreceiver import RemoteStreamTrack\nfrom av import VideoFrame\nfrom av import logging as av_logging\nfrom pydantic import ValidationError\n\nfrom inference.core import logger\nfrom inference.core.env import (\n    WEBRTC_DATA_CHANNEL_ACK_WINDOW,\n    WEBRTC_DATA_CHANNEL_BUFFER_DRAINING_DELAY,\n    WEBRTC_DATA_CHANNEL_BUFFER_SIZE_LIMIT,\n    WEBRTC_MODAL_PUBLIC_STUN_SERVERS,\n    WEBRTC_MODAL_RTSP_PLACEHOLDER,\n    WEBRTC_MODAL_RTSP_PLACEHOLDER_URL,\n    WEBRTC_MODAL_SHUTDOWN_RESERVE,\n)\nfrom inference.core.exceptions import (\n    MissingApiKeyError,\n    RoboflowAPINotAuthorizedError,\n    RoboflowAPINotNotFoundError,\n    WebRTCConfigurationError,\n)\nfrom inference.core.interfaces.camera.entities import VideoFrameProducer\nfrom inference.core.interfaces.stream.inference_pipeline import InferencePipeline\nfrom inference.core.interfaces.stream_manager.manager_app.entities import (\n    WebRTCData,\n    WorkflowConfiguration,\n)\nfrom inference.core.interfaces.webrtc_worker.entities import (\n    DataOutputMode,\n    StreamOutputMode,\n    VideoFileUploadState,\n    WebRTCOutput,\n    WebRTCVideoMetadata,\n    WebRTCWorkerRequest,\n    WebRTCWorkerResult,\n)\nfrom inference.core.interfaces.webrtc_worker.utils import (\n    detect_image_output,\n    get_cv2_rotation_code,\n    get_video_rotation,\n    parse_video_file_chunk,\n    process_frame,\n    rotate_video_frame,\n)\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.roboflow_api import get_workflow_specification\nfrom inference.core.workflows.core_steps.common.serializers import (\n    serialise_sv_detections,\n    serialize_timestamp,\n)\nfrom inference.core.utils.image_utils import encode_image_to_jpeg_bytes\nfrom inference.core.workflows.errors import WorkflowError, WorkflowSyntaxError\nfrom inference.core.workflows.execution_engine.entities.base import WorkflowImageData\nfrom inference.usage_tracking.collector import usage_collector\n\nlogging.getLogger(\"aiortc\").setLevel(logging.WARNING)\n\n# WebRTC data channel chunking configuration\nCHUNK_SIZE = 48 * 1024  # 48KB - safe for all WebRTC implementations\n\n# WebRTC image compression quality - lower = smaller file size, quality=10 reduces ~1MB to ~50KB\nWEBRTC_JPEG_QUALITY = 10\n\n\ndef serialise_image_for_webrtc(image: WorkflowImageData) -> Dict[str, Any]:\n    \"\"\"Serialize image with JPEG quality=10 for efficient WebRTC transmission.\"\"\"\n    jpeg_bytes = encode_image_to_jpeg_bytes(\n        image.numpy_image, jpeg_quality=WEBRTC_JPEG_QUALITY\n    )\n    return {\n        \"type\": \"base64\",\n        \"value\": base64.b64encode(jpeg_bytes).decode(\"ascii\"),\n        \"video_metadata\": image.video_metadata.dict() if image.video_metadata else None,\n    }\n\n\ndef serialize_for_webrtc(value: Any) -> Any:\n    \"\"\"Recursively serialize, compressing images with JPEG quality=10.\"\"\"\n    # Fast path for most common types (primitives)\n    value_type = type(value)\n    if value_type in (int, float, str, bool, type(None)):\n        return value\n\n    if isinstance(value, WorkflowImageData):\n        return serialise_image_for_webrtc(value)\n    if isinstance(value, dict):\n        return {k: serialize_for_webrtc(v) for k, v in value.items()}\n    if isinstance(value, list):\n        return [serialize_for_webrtc(v) for v in value]\n    if isinstance(value, sv.Detections):\n        return serialise_sv_detections(value)\n    if isinstance(value, datetime.datetime):\n        return serialize_timestamp(value)\n    return value\n\n\ndef create_chunked_binary_message(\n    frame_id: int, chunk_index: int, total_chunks: int, payload: bytes\n) -> bytes:\n    \"\"\"Create a binary message with standard 12-byte header.\n\n    Format: [frame_id: 4][chunk_index: 4][total_chunks: 4][payload: N]\n    All integers are uint32 little-endian.\n    \"\"\"\n    header = struct.pack(\"<III\", frame_id, chunk_index, total_chunks)\n    return header + payload\n\n\ndef _decode_worker(filepath: str, frame_queue, stop_event):\n    \"\"\"Decode video frames in a thread and put them on the queue.\"\"\"\n\n    try:\n        container = av.open(filepath)\n        stream = container.streams.video[0]\n        stream.thread_type = \"AUTO\"\n\n        for frame in container.decode(stream):\n            if stop_event.is_set():\n                break\n            frame_queue.put(\n                frame,\n                timeout=30,\n            )\n\n        container.close()\n    except Exception as e:\n        frame_queue.put({\"error\": str(e)})\n    finally:\n        frame_queue.put(None)\n\n\nclass ThreadedVideoTrack(MediaStreamTrack):\n    \"\"\"Video track that decodes frames from a queue.\"\"\"\n\n    kind = \"video\"\n\n    def __init__(self, filepath: str, queue_size: int = 10):\n        super().__init__()\n        self._queue = queue.Queue(maxsize=queue_size)\n        self._stop_event = threading.Event()\n        self._decode_thread = threading.Thread(\n            target=_decode_worker,\n            args=(filepath, self._queue, self._stop_event),\n            daemon=True,\n        )\n        self._decode_thread.start()\n\n    async def recv(self) -> VideoFrame:\n        while True:\n            try:\n                data = self._queue.get_nowait()\n                break\n            except queue.Empty:\n                # we use a non-blocking get + sleep to avoid blocking the\n                # event loop.\n                # The queue is typically pre-filled by the decoder thread,\n                # so this sleep rarely triggers during normal operation.\n                await asyncio.sleep(0.01)\n\n        if data is None:\n            self.stop()\n            raise MediaStreamError(\"End of video file\")\n        if isinstance(data, dict):\n            self.stop()\n            raise MediaStreamError(data.get(\"error\", \"Unknown decode error\"))\n\n        return data\n\n    def stop(self):\n        super().stop()\n        self._stop_event.set()\n\n\nclass VideoFileUploadHandler:\n    \"\"\"Handles video file uploads via data channel.\n\n    Protocol: [chunk_index:u32][total_chunks:u32][payload]\n    Auto-completes when all chunks received.\n    \"\"\"\n\n    def __init__(self):\n        self._chunks: Dict[int, bytes] = {}\n        self._total_chunks: Optional[int] = None\n        self._temp_file_path: Optional[str] = None\n        self._state = VideoFileUploadState.IDLE\n        self.upload_complete_event = asyncio.Event()\n\n    @property\n    def temp_file_path(self) -> Optional[str]:\n        return self._temp_file_path\n\n    def handle_chunk(self, chunk_index: int, total_chunks: int, data: bytes) -> None:\n        \"\"\"Handle a chunk. Auto-completes when all chunks received.\"\"\"\n        if self._total_chunks is None:\n            self._total_chunks = total_chunks\n            self._state = VideoFileUploadState.UPLOADING\n            logger.info(f\"Starting video upload: {total_chunks} chunks\")\n\n        self._chunks[chunk_index] = data\n\n        if chunk_index % 100 == 0:\n            logger.info(\n                \"Upload progress: %s/%s chunks\", len(self._chunks), total_chunks\n            )\n\n        # Auto-complete when all chunks received\n        # TODO: Handle the file writing without keeping all chunks in memory\n        if len(self._chunks) == total_chunks:\n            self._write_to_temp_file()\n            self._state = VideoFileUploadState.COMPLETE\n            self.upload_complete_event.set()\n\n    def _write_to_temp_file(self) -> None:\n        \"\"\"Reassemble chunks and write to temp file.\"\"\"\n        import tempfile\n\n        total_size = 0\n        with tempfile.NamedTemporaryFile(mode=\"wb\", suffix=\".mp4\", delete=False) as f:\n            for i in range(self._total_chunks):\n                chunk_data = self._chunks[i]\n                f.write(chunk_data)\n                total_size += len(chunk_data)\n            self._temp_file_path = f.name\n\n        logger.info(\n            \"Video upload complete: {total_size} bytes -> %s\", self._temp_file_path\n        )\n        self._chunks.clear()  # Free memory\n\n    def try_start_processing(self) -> Optional[str]:\n        \"\"\"Atomically check if upload is complete and transition to PROCESSING.\n\n        Returns video path if processing should start, None otherwise.\n        This ensures process_video_file() is only triggered once.\n        \"\"\"\n        if self._state == VideoFileUploadState.COMPLETE:\n            self._state = VideoFileUploadState.PROCESSING\n            return self._temp_file_path\n        return None\n\n    async def cleanup(self) -> None:\n        \"\"\"Clean up temp file.\"\"\"\n        if self._temp_file_path:\n            import os\n\n            path_to_delete = self._temp_file_path\n            self._temp_file_path = None\n            try:\n                await asyncio.to_thread(os.unlink, path_to_delete)\n            except Exception:\n                pass\n\n\nasync def wait_for_buffer_drain(\n    data_channel: RTCDataChannel,\n    timeout: float = 30.0,\n    heartbeat_callback: Optional[Callable[[], None]] = None,\n) -> bool:\n    \"\"\"Wait for data channel buffer to have space, with timeout.\"\"\"\n    start_time = asyncio.get_event_loop().time()\n    while data_channel.bufferedAmount > WEBRTC_DATA_CHANNEL_BUFFER_SIZE_LIMIT:\n        if asyncio.get_event_loop().time() - start_time > timeout:\n            logger.warning(\n                \"Buffer drain timeout, buffered: %s\", data_channel.bufferedAmount\n            )\n            return False\n        if heartbeat_callback:\n            heartbeat_callback()\n        await asyncio.sleep(WEBRTC_DATA_CHANNEL_BUFFER_DRAINING_DELAY)\n    return True\n\n\nasync def send_chunked_data(\n    data_channel: RTCDataChannel,\n    frame_id: int,\n    payload_bytes: bytes,\n    chunk_size: int = CHUNK_SIZE,\n    heartbeat_callback: Optional[Callable[[], None]] = None,\n    buffer_timeout: float = 30.0,\n) -> None:\n    \"\"\"Send payload via data channel with chunking and backpressure.\"\"\"\n    if data_channel.readyState != \"open\":\n        logger.warning(\"Cannot send frame %s: channel not open\", frame_id)\n        return\n\n    total_chunks = (len(payload_bytes) + chunk_size - 1) // chunk_size\n    view = memoryview(payload_bytes)\n    for chunk_index in range(total_chunks):\n        if data_channel.readyState != \"open\":\n            logger.warning(\"Channel closed while sending frame %s\", frame_id)\n            return\n\n        start = chunk_index * chunk_size\n        end = min(start + chunk_size, len(payload_bytes))\n        chunk_data = view[start:end]\n\n        message = create_chunked_binary_message(\n            frame_id, chunk_index, total_chunks, chunk_data\n        )\n        data_channel.send(message)\n\n        # Every N chunks: yield to event loop and check buffer\n        # we want to reduce context switching and keep the event loop responsive\n        if chunk_index % 10 == 0:\n            await wait_for_buffer_drain(\n                data_channel, buffer_timeout, heartbeat_callback\n            )\n            await asyncio.sleep(0)\n\n\nclass RTCPeerConnectionWithLoop(RTCPeerConnection):\n    def __init__(\n        self,\n        asyncio_loop: asyncio.AbstractEventLoop,\n        *args,\n        **kwargs,\n    ):\n        super().__init__(*args, **kwargs)\n        self._loop = asyncio_loop\n\n\nclass VideoFrameProcessor:\n    \"\"\"Base class for processing video frames through workflow.\n\n    Can be used independently for data-only processing (no video track output)\n    or as a base for VideoTransformTrackWithLoop when video output is needed.\n    \"\"\"\n\n    def __init__(\n        self,\n        asyncio_loop: asyncio.AbstractEventLoop,\n        workflow_configuration: WorkflowConfiguration,\n        api_key: str,\n        model_manager: Optional[ModelManager] = None,\n        data_output: Optional[List[str]] = None,\n        stream_output: Optional[str] = None,\n        has_video_track: bool = True,\n        declared_fps: float = 30,\n        termination_date: Optional[datetime.datetime] = None,\n        terminate_event: Optional[asyncio.Event] = None,\n        heartbeat_callback: Optional[Callable[[], None]] = None,\n        realtime_processing: bool = True,\n        is_preview: bool = False,\n    ):\n        self._loop = asyncio_loop\n        self._termination_date = termination_date\n        self._terminate_event = terminate_event\n        self.track: Optional[MediaStreamTrack] = None\n        self._track_active: bool = False\n        self._av_logging_set: bool = False\n        self._received_frames = 0\n        self._declared_fps = declared_fps\n        self._stop_processing = False\n        self.heartbeat_callback = heartbeat_callback\n\n        self.has_video_track = has_video_track\n        self.stream_output = stream_output\n        self.data_channel: Optional[RTCDataChannel] = None\n\n        # Video file upload support\n        self.video_upload_handler: Optional[VideoFileUploadHandler] = None\n        self._track_ready_event: asyncio.Event = asyncio.Event()\n        self.realtime_processing = realtime_processing\n        self._rotation_code: Optional[int] = None\n\n        # Optional receiver-paced flow control (enabled only after first ACK is received)\n        self._ack_last: int = 0\n        # If ack=1 and window=4, server may produce/send up to frame 5.\n        # Configurable via WEBRTC_DATACHANNEL_ACK_WINDOW env var.\n        self._ack_window: int = WEBRTC_DATA_CHANNEL_ACK_WINDOW\n        self._ack_event: asyncio.Event = asyncio.Event()\n\n        if data_output is None:\n            self.data_output = None\n            self._data_mode = DataOutputMode.NONE\n        elif isinstance(data_output, list):\n            self.data_output = [f for f in data_output if f]\n            if self.data_output == [\"*\"]:\n                self._data_mode = DataOutputMode.ALL\n            elif len(self.data_output) == 0:\n                self._data_mode = DataOutputMode.NONE\n            else:\n                self._data_mode = DataOutputMode.SPECIFIC\n        else:\n            raise WebRTCConfigurationError(\n                f\"data_output must be list or None, got {type(data_output).__name__}\"\n            )\n\n        self._validate_output_fields(workflow_configuration)\n\n        self._inference_pipeline = InferencePipeline.init_with_workflow(\n            video_reference=VideoFrameProducer,\n            workflow_specification=workflow_configuration.workflow_specification,\n            workspace_name=workflow_configuration.workspace_name,\n            workflow_id=workflow_configuration.workflow_id,\n            api_key=api_key,\n            image_input_name=workflow_configuration.image_input_name,\n            workflows_parameters=workflow_configuration.workflows_parameters,\n            workflows_thread_pool_workers=workflow_configuration.workflows_thread_pool_workers,\n            cancel_thread_pool_tasks_on_exit=workflow_configuration.cancel_thread_pool_tasks_on_exit,\n            video_metadata_input_name=workflow_configuration.video_metadata_input_name,\n            model_manager=model_manager,\n            _is_preview=is_preview,\n        )\n\n    def set_track(self, track: MediaStreamTrack, rotation_code: Optional[int] = None):\n        if not self.track:\n            self.track = track\n            self._rotation_code = rotation_code\n            self._track_ready_event.set()\n\n    async def close(self):\n        self._track_active = False\n        self._stop_processing = True\n        # Clean up video upload handler if present\n        if self.video_upload_handler is not None:\n            await self.video_upload_handler.cleanup()\n\n    def record_ack(self, ack: int) -> None:\n        \"\"\"Record cumulative ACK from the client.\n\n        ACK semantics: client has fully handled all frames <= ack.\n        Backwards compatible: pacing is disabled until we receive the first ACK.\n        \"\"\"\n        try:\n            ack_int = int(ack)\n        except (TypeError, ValueError):\n            logger.warning(\"Invalid ACK value: %s\", ack)\n            return\n        if ack_int < 0:\n            logger.warning(\"Invalid ACK value: %s\", ack)\n            return\n        if ack_int > self._ack_last:\n            if ack_int % 100 == 1:\n                logger.info(\"ACK received: %s\", ack_int)\n            self._ack_last = ack_int\n            self._ack_event.set()\n\n    async def _wait_for_ack_window(self, next_frame_id: int) -> None:\n        \"\"\"Block frame production when too far ahead of client ACKs.\n\n        Allows up to (_ack_window) frames in flight beyond the last ACK.\n        Only active for non-realtime processing (video file uploads).\n\n        Has a maximum wait time of 30 seconds to prevent infinite blocking\n        if the client stops sending ACKs.\n        \"\"\"\n        if self.realtime_processing:\n            return\n        if self._ack_last == 0:\n            return\n\n        wait_counter = 0\n        max_wait_iterations = 150  # this is...  150 * 0.2s, 30 seconds max wait\n        while not self._stop_processing and next_frame_id > (\n            self._ack_last + self._ack_window\n        ):\n            if self._check_termination():\n                return\n            if self.heartbeat_callback:\n                self.heartbeat_callback()\n\n            # Wait briefly for an ACK; timeout keeps heartbeats flowing.\n            self._ack_event.clear()\n            try:\n                await asyncio.wait_for(self._ack_event.wait(), timeout=0.2)\n            except asyncio.TimeoutError:\n                wait_counter += 1\n                if wait_counter >= max_wait_iterations:\n                    logger.warning(\n                        \"ACK wait timeout exceeded (30s). Disabling ACK pacing. \"\n                        \"(next_frame_id=%s, ack_last=%s)\",\n                        next_frame_id,\n                        self._ack_last,\n                    )\n\n                    self._ack_last = 0\n                    return\n\n    def _check_termination(self):\n        \"\"\"Check if we should terminate based on timeout\"\"\"\n        if (\n            self._termination_date\n            and self._termination_date < datetime.datetime.now()\n            or self._terminate_event\n            and self._terminate_event.is_set()\n        ):\n            logger.info(\"Timeout reached, terminating inference pipeline\")\n            self._terminate_event.set()\n            return True\n        return False\n\n    @staticmethod\n    def serialize_outputs_sync(\n        fields_to_send: List[str],\n        workflow_output: Dict[str, Any],\n        data_output_mode: DataOutputMode,\n    ) -> Tuple[Dict[str, Any], List[str]]:\n        \"\"\"Serialize workflow outputs in a thread to avoid blocking the event loop.\n\n        Uses low JPEG quality (quality=10) for image compression to reduce\n        frame size from ~1MB to ~50KB for efficient WebRTC transmission.\n        \"\"\"\n        serialized = {}\n        serialization_errors = []\n\n        for field_name in fields_to_send:\n            if field_name not in workflow_output:\n                serialization_errors.append(\n                    f\"Requested output '{field_name}' not found in workflow outputs\"\n                )\n                continue\n\n            output_data = workflow_output[field_name]\n\n            if data_output_mode == DataOutputMode.ALL and isinstance(\n                output_data, WorkflowImageData\n            ):\n                continue\n\n            try:\n                serialized_value = serialize_for_webrtc(output_data)\n                serialized[field_name] = serialized_value\n            except Exception as e:\n                serialization_errors.append(f\"{field_name}: {e}\")\n                serialized[field_name] = {\"__serialization_error__\": str(e)}\n\n        return serialized, serialization_errors\n\n    async def _send_data_output(\n        self,\n        workflow_output: Dict[str, Any],\n        frame_timestamp: datetime.datetime,\n        frame: VideoFrame,\n        errors: List[str],\n    ):\n        if not self.data_channel or self.data_channel.readyState != \"open\":\n            return\n\n        video_metadata = WebRTCVideoMetadata(\n            frame_id=self._received_frames,\n            received_at=frame_timestamp.isoformat(),\n            pts=frame.pts,\n            time_base=frame.time_base,\n            declared_fps=self._declared_fps,\n        )\n\n        webrtc_output = WebRTCOutput(\n            serialized_output_data=None,\n            video_metadata=video_metadata,\n            errors=errors.copy(),\n        )\n\n        if self._data_mode == DataOutputMode.NONE:\n            # Even empty responses use binary protocol\n            json_bytes = await asyncio.to_thread(\n                lambda: json.dumps(webrtc_output.model_dump()).encode(\"utf-8\")\n            )\n            await send_chunked_data(\n                self.data_channel,\n                self._received_frames,\n                json_bytes,\n                heartbeat_callback=self.heartbeat_callback,\n            )\n            return\n\n        if self._data_mode == DataOutputMode.ALL:\n            fields_to_send = list(workflow_output.keys())\n        else:\n            fields_to_send = self.data_output\n\n        # Offload CPU-intensive serialization (especially image base64 encoding) to thread\n        serialized_outputs, serialization_errors = await asyncio.to_thread(\n            VideoFrameProcessor.serialize_outputs_sync,\n            fields_to_send,\n            workflow_output,\n            self._data_mode,\n        )\n        webrtc_output.errors.extend(serialization_errors)\n\n        # Set serialized outputs\n        if serialized_outputs:\n            webrtc_output.serialized_output_data = serialized_outputs\n\n        # Send using binary chunked protocol\n        json_bytes = await asyncio.to_thread(\n            lambda: json.dumps(webrtc_output.model_dump(mode=\"json\")).encode(\"utf-8\")\n        )\n        await send_chunked_data(\n            self.data_channel,\n            self._received_frames,\n            json_bytes,\n            heartbeat_callback=self.heartbeat_callback,\n        )\n\n    async def _send_processing_complete(self):\n        \"\"\"Send final message indicating processing is complete.\"\"\"\n        if not self.data_channel or self.data_channel.readyState != \"open\":\n            return\n\n        completion_output = WebRTCOutput(\n            processing_complete=True,\n            video_metadata=WebRTCVideoMetadata(\n                frame_id=self._received_frames,\n                received_at=datetime.datetime.now().isoformat(),\n            ),\n        )\n        json_bytes = json.dumps(completion_output.model_dump()).encode(\"utf-8\")\n        await send_chunked_data(\n            self.data_channel, self._received_frames + 1, json_bytes\n        )\n        logger.info(\n            \"Sent processing_complete signal after %s frames\", self._received_frames\n        )\n\n    async def process_frames_data_only(self):\n        \"\"\"Process frames for data extraction only, without video track output.\n\n        This is used when stream_output=[] and no video track is needed.\n        \"\"\"\n        # Silencing swscaler warnings in multi-threading environment\n        if not self._av_logging_set:\n            av_logging.set_libav_level(av_logging.ERROR)\n            self._av_logging_set = True\n\n        logger.info(\"Starting data-only frame processing\")\n\n        try:\n            while not self._stop_processing:\n                await self._wait_for_ack_window(next_frame_id=self._received_frames + 1)\n                if self._check_termination():\n                    break\n                if self.heartbeat_callback:\n                    self.heartbeat_callback()\n\n                if not self.track or self.track.readyState == \"ended\":\n                    break\n\n                # Drain queue if using PlayerStreamTrack (RTSP)\n                if (\n                    isinstance(self.track, PlayerStreamTrack)\n                    and self.realtime_processing\n                ):\n                    while self.track._queue.qsize() > 30:\n                        self.track._queue.get_nowait()\n\n                frame = await self.track.recv()\n                self._received_frames += 1\n\n                frame_timestamp = datetime.datetime.now()\n\n                workflow_output, _, errors = await self._process_frame_async(\n                    frame=frame,\n                    frame_id=self._received_frames,\n                    render_output=False,\n                    include_errors_on_frame=False,\n                )\n\n                await self._send_data_output(\n                    workflow_output, frame_timestamp, frame, errors\n                )\n\n        except asyncio.CancelledError as exc:\n            logger.info(\"Data-only processing cancelled: %s\", exc)\n        except MediaStreamError as exc:\n            logger.info(\"Stream ended in data-only processing: %s\", exc)\n        except Exception as exc:\n            logger.error(\"Error in data-only processing: %s\", exc)\n        finally:\n            # Send completion signal to client\n            await self._send_processing_complete()\n\n    @staticmethod\n    def _ensure_workflow_specification(\n        workflow_configuration: WorkflowConfiguration, api_key: str\n    ) -> None:\n        has_specification = workflow_configuration.workflow_specification is not None\n        has_workspace_and_workflow_id = (\n            workflow_configuration.workspace_name is not None\n            and workflow_configuration.workflow_id is not None\n        )\n\n        if not has_specification and not has_workspace_and_workflow_id:\n            raise WebRTCConfigurationError(\n                \"Either 'workflow_specification' or both 'workspace_name' and 'workflow_id' must be provided\"\n            )\n\n        if not has_specification and has_workspace_and_workflow_id:\n            try:\n                workflow_configuration.workflow_specification = (\n                    get_workflow_specification(\n                        api_key=api_key,\n                        workspace_id=workflow_configuration.workspace_name,\n                        workflow_id=workflow_configuration.workflow_id,\n                    )\n                )\n                workflow_configuration.workspace_name = None\n                workflow_configuration.workflow_id = None\n            except Exception as e:\n                raise WebRTCConfigurationError(\n                    f\"Failed to fetch workflow specification from API: {str(e)}\"\n                )\n\n    def _validate_output_fields(\n        self, workflow_configuration: WorkflowConfiguration\n    ) -> None:\n        if workflow_configuration.workflow_specification is None:\n            return\n\n        workflow_outputs = workflow_configuration.workflow_specification.get(\n            \"outputs\", []\n        )\n        available_output_names = [o.get(\"name\") for o in workflow_outputs]\n\n        if self._data_mode == DataOutputMode.SPECIFIC:\n            invalid_fields = [\n                field\n                for field in self.data_output\n                if field not in available_output_names\n            ]\n            if invalid_fields:\n                raise WebRTCConfigurationError(\n                    f\"Invalid data_output fields: {invalid_fields}. \"\n                    f\"Available workflow outputs: {available_output_names}\"\n                )\n\n        if self.stream_output and self.stream_output not in available_output_names:\n            raise WebRTCConfigurationError(\n                f\"Invalid stream_output field: '{self.stream_output}'. \"\n                f\"Available workflow outputs: {available_output_names}\"\n            )\n\n    async def _process_frame_async(\n        self,\n        frame: VideoFrame,\n        frame_id: int,\n        stream_output: Optional[str] = None,\n        render_output: bool = True,\n        include_errors_on_frame: bool = True,\n    ) -> Tuple[Dict[str, Any], Optional[VideoFrame], List[str]]:\n        \"\"\"Async wrapper for process_frame using executor.\"\"\"\n\n        if self._rotation_code is not None:\n            frame = rotate_video_frame(frame, self._rotation_code)\n\n        loop = asyncio.get_running_loop()\n        return await loop.run_in_executor(\n            None,\n            process_frame,\n            frame,\n            frame_id,\n            self._inference_pipeline,\n            stream_output,\n            render_output,\n            include_errors_on_frame,\n        )\n\n\nclass VideoTransformTrackWithLoop(VideoStreamTrack, VideoFrameProcessor):\n    \"\"\"Video track that processes frames through workflow and sends video back.\n\n    Inherits from both VideoStreamTrack (for WebRTC video track functionality)\n    and VideoFrameProcessor (for workflow processing logic).\n    \"\"\"\n\n    def __init__(\n        self,\n        asyncio_loop: asyncio.AbstractEventLoop,\n        workflow_configuration: WorkflowConfiguration,\n        api_key: str,\n        model_manager: Optional[ModelManager] = None,\n        data_output: Optional[List[str]] = None,\n        stream_output: Optional[str] = None,\n        has_video_track: bool = True,\n        declared_fps: float = 30,\n        termination_date: Optional[datetime.datetime] = None,\n        terminate_event: Optional[asyncio.Event] = None,\n        heartbeat_callback: Optional[Callable[[], None]] = None,\n        realtime_processing: bool = True,\n        is_preview: bool = False,\n        *args,\n        **kwargs,\n    ):\n        VideoStreamTrack.__init__(self, *args, **kwargs)\n        VideoFrameProcessor.__init__(\n            self,\n            asyncio_loop=asyncio_loop,\n            workflow_configuration=workflow_configuration,\n            api_key=api_key,\n            data_output=data_output,\n            stream_output=stream_output,\n            has_video_track=has_video_track,\n            declared_fps=declared_fps,\n            termination_date=termination_date,\n            terminate_event=terminate_event,\n            model_manager=model_manager,\n            heartbeat_callback=heartbeat_callback,\n            realtime_processing=realtime_processing,\n            is_preview=is_preview,\n        )\n\n    async def _auto_detect_stream_output(\n        self, frame: VideoFrame, frame_id: int\n    ) -> None:\n        workflow_output_for_detect, _, _ = await self._process_frame_async(\n            frame=frame,\n            frame_id=frame_id,\n            render_output=False,\n            include_errors_on_frame=False,\n        )\n        detected_output = detect_image_output(workflow_output_for_detect)\n        if detected_output:\n            self.stream_output = detected_output\n            logger.info(f\"Auto-detected stream_output: {detected_output}\")\n        else:\n            logger.warning(\"No image output detected, will use fallback\")\n            self.stream_output = \"\"\n\n    async def recv(self):\n        # Silencing swscaler warnings in multi-threading environment\n        if not self._av_logging_set:\n            av_logging.set_libav_level(av_logging.ERROR)\n            self._av_logging_set = True\n\n        if self.heartbeat_callback:\n            self.heartbeat_callback()\n\n        # Check if we should terminate\n        if self._check_termination():\n            raise MediaStreamError(\"Processing terminated due to timeout\")\n\n        # Wait for track to be ready (video file upload case)\n        if self.track is None:\n            logger.info(\"Waiting for track to be ready...\")\n            await self._track_ready_event.wait()\n            if self.track is None:\n                raise MediaStreamError(\"Track not available after wait\")\n\n        # Optional ACK pacing: block producing the next frame if we're too far ahead.\n        await self._wait_for_ack_window(next_frame_id=self._received_frames + 1)\n\n        # Drain queue if using PlayerStreamTrack (RTSP/video file)\n        if isinstance(self.track, PlayerStreamTrack) and self.realtime_processing:\n            while self.track._queue.qsize() > 30:\n                self.track._queue.get_nowait()\n\n        frame: VideoFrame = await self.track.recv()\n        self._received_frames += 1\n        frame_timestamp = datetime.datetime.now()\n\n        if self.stream_output is None and self._received_frames == 1:\n            await self._auto_detect_stream_output(frame, self._received_frames)\n\n        workflow_output, new_frame, errors = await self._process_frame_async(\n            frame=frame,\n            frame_id=self._received_frames,\n            stream_output=self.stream_output,\n            render_output=True,\n            include_errors_on_frame=True,\n        )\n\n        new_frame.pts = frame.pts\n        new_frame.time_base = frame.time_base\n\n        await self._send_data_output(workflow_output, frame_timestamp, frame, errors)\n\n        return new_frame\n\n\nasync def _wait_ice_complete(peer_connection: RTCPeerConnectionWithLoop, timeout=2.0):\n    if peer_connection.iceGatheringState == \"complete\":\n        logger.info(\"ICE gathering state already complete\")\n        return\n    fut = asyncio.get_running_loop().create_future()\n\n    @peer_connection.on(\"icegatheringstatechange\")\n    def _():\n        logger.info(\n            \"ICE gathering state changed to %s\", peer_connection.iceGatheringState\n        )\n        if not fut.done() and peer_connection.iceGatheringState == \"complete\":\n            fut.set_result(True)\n\n    try:\n        logger.info(\"Waiting for ICE gathering to complete...\")\n        await asyncio.wait_for(fut, timeout)\n        logger.info(\"ICE gathering completed\")\n    except asyncio.TimeoutError:\n        logger.info(\"ICE gathering did not complete in %s seconds\", timeout)\n        pass\n\n\nasync def init_rtc_peer_connection_with_loop(\n    webrtc_request: WebRTCWorkerRequest,\n    send_answer: Callable[[WebRTCWorkerResult], None],\n    asyncio_loop: Optional[asyncio.AbstractEventLoop] = None,\n    model_manager: Optional[ModelManager] = None,\n    shutdown_reserve: int = WEBRTC_MODAL_SHUTDOWN_RESERVE,\n    heartbeat_callback: Optional[Callable[[], None]] = None,\n) -> RTCPeerConnectionWithLoop:\n    logger.info(\"Initializing RTC peer connection with loop\")\n    # ice._mdns is instantiated on the module level, it has a lock that is bound to the event loop\n    # avoid RuntimeError: asyncio.locks.Lock is bound to a different event loop\n    if hasattr(ice, \"_mdns\"):\n        if hasattr(ice._mdns, \"lock\"):\n            logger.info(\"Removing lock from aioice.ice._mdns\")\n            delattr(ice._mdns, \"lock\")\n    else:\n        logger.warning(\n            \"aioice.ice implementation was changed, _mdns attribute is not available\"\n        )\n\n    termination_date = None\n    terminate_event = asyncio.Event()\n\n    if webrtc_request.processing_timeout is not None:\n        try:\n            time_limit_seconds = int(webrtc_request.processing_timeout)\n            datetime_now = webrtc_request.processing_session_started\n            if datetime_now is None:\n                datetime_now = datetime.datetime.now()\n            termination_date = datetime_now + datetime.timedelta(\n                seconds=time_limit_seconds - shutdown_reserve\n            )\n            logger.info(\n                \"Setting termination date to %s (%s seconds from %s)\",\n                termination_date.isoformat(),\n                time_limit_seconds,\n                datetime_now.isoformat(),\n            )\n        except (TypeError, ValueError):\n            pass\n    if webrtc_request.stream_output is None:\n        stream_mode = StreamOutputMode.AUTO_DETECT\n        stream_field = None\n    elif len(webrtc_request.stream_output) == 0:\n        stream_mode = StreamOutputMode.NO_VIDEO\n        stream_field = None\n    else:\n        filtered = [s for s in webrtc_request.stream_output if s]\n        if filtered:\n            stream_mode = StreamOutputMode.SPECIFIC_FIELD\n            stream_field = filtered[0]\n        else:\n            stream_mode = StreamOutputMode.NO_VIDEO\n            stream_field = None\n\n    if webrtc_request.data_output is None or len(webrtc_request.data_output) == 0:\n        data_fields = None\n    elif webrtc_request.data_output == [\"*\"]:\n        data_fields = [\"*\"]\n    else:\n        data_fields = webrtc_request.data_output\n\n    try:\n        should_send_video = stream_mode != StreamOutputMode.NO_VIDEO\n\n        if should_send_video:\n            video_processor = VideoTransformTrackWithLoop(\n                asyncio_loop=asyncio_loop,\n                workflow_configuration=webrtc_request.workflow_configuration,\n                model_manager=model_manager,\n                api_key=webrtc_request.api_key,\n                data_output=data_fields,\n                stream_output=stream_field,\n                has_video_track=True,\n                declared_fps=webrtc_request.declared_fps,\n                termination_date=termination_date,\n                terminate_event=terminate_event,\n                heartbeat_callback=heartbeat_callback,\n                realtime_processing=webrtc_request.webrtc_realtime_processing,\n                is_preview=webrtc_request.is_preview,\n            )\n        else:\n            # No video track - use base VideoFrameProcessor\n            video_processor = VideoFrameProcessor(\n                asyncio_loop=asyncio_loop,\n                workflow_configuration=webrtc_request.workflow_configuration,\n                model_manager=model_manager,\n                api_key=webrtc_request.api_key,\n                data_output=data_fields,\n                stream_output=None,\n                has_video_track=False,\n                declared_fps=webrtc_request.declared_fps,\n                termination_date=termination_date,\n                terminate_event=terminate_event,\n                heartbeat_callback=heartbeat_callback,\n                realtime_processing=webrtc_request.webrtc_realtime_processing,\n                is_preview=webrtc_request.is_preview,\n            )\n    except (\n        ValidationError,\n        MissingApiKeyError,\n        KeyError,\n        NotImplementedError,\n    ) as error:\n        # heartbeat to indicate caller error\n        heartbeat_callback()\n        send_answer(\n            WebRTCWorkerResult(\n                exception_type=error.__class__.__name__,\n                error_message=\"Could not decode InferencePipeline initialisation command payload.\",\n            )\n        )\n        return\n    except WebRTCConfigurationError as error:\n        # heartbeat to indicate caller error\n        heartbeat_callback()\n        send_answer(\n            WebRTCWorkerResult(\n                exception_type=error.__class__.__name__,\n                error_message=str(error),\n            )\n        )\n        return\n    except RoboflowAPINotAuthorizedError:\n        # heartbeat to indicate caller error\n        heartbeat_callback()\n        send_answer(\n            WebRTCWorkerResult(\n                exception_type=RoboflowAPINotAuthorizedError.__name__,\n                error_message=\"Invalid API key used or API key is missing. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key\",\n            )\n        )\n        return\n    except RoboflowAPINotNotFoundError:\n        # heartbeat to indicate caller error\n        heartbeat_callback()\n        send_answer(\n            WebRTCWorkerResult(\n                exception_type=RoboflowAPINotNotFoundError.__name__,\n                error_message=\"Requested Roboflow resources (models / workflows etc.) not available or wrong API key used.\",\n            )\n        )\n        return\n    except WorkflowSyntaxError as error:\n        # heartbeat to indicate caller error\n        heartbeat_callback()\n        send_answer(\n            WebRTCWorkerResult(\n                exception_type=WorkflowSyntaxError.__name__,\n                error_message=str(error),\n                error_context=str(error.context),\n                inner_error=str(error.inner_error),\n            )\n        )\n        return\n    except WorkflowError as error:\n        # heartbeat to indicate caller error\n        heartbeat_callback()\n        send_answer(\n            WebRTCWorkerResult(\n                exception_type=WorkflowError.__name__,\n                error_message=str(error),\n            )\n        )\n        return\n    except Exception as error:\n        send_answer(\n            WebRTCWorkerResult(\n                exception_type=error.__class__.__name__,\n                error_message=str(error),\n            )\n        )\n        return\n\n    if webrtc_request.webrtc_config is not None:\n        ice_servers = []\n        for ice_server in webrtc_request.webrtc_config.iceServers:\n            ice_servers.append(\n                RTCIceServer(\n                    urls=ice_server.urls,\n                    username=ice_server.username,\n                    credential=ice_server.credential,\n                )\n            )\n        # Always add public stun servers (if specified)\n        if WEBRTC_MODAL_PUBLIC_STUN_SERVERS:\n            for stun_server in WEBRTC_MODAL_PUBLIC_STUN_SERVERS.split(\",\"):\n                try:\n                    ice_servers.append(RTCIceServer(urls=stun_server.strip()))\n                except Exception as e:\n                    logger.warning(\n                        \"Failed to add public stun server '%s': %s\", stun_server, e\n                    )\n    else:\n        ice_servers = None\n    peer_connection = RTCPeerConnectionWithLoop(\n        configuration=RTCConfiguration(iceServers=ice_servers) if ice_servers else None,\n        asyncio_loop=asyncio_loop,\n    )\n\n    relay = MediaRelay()\n\n    # Add video track early for SDP negotiation when stream_output is requested\n    # The track source will be set later by the appropriate handler (RTSP, on_track, video_upload)\n    if should_send_video:\n        logger.info(\"Adding video track early for SDP negotiation\")\n        peer_connection.addTrack(video_processor)\n\n    player: Optional[MediaPlayer] = None\n    if webrtc_request.rtsp_url:\n        if webrtc_request.rtsp_url == WEBRTC_MODAL_RTSP_PLACEHOLDER:\n            webrtc_request.rtsp_url = WEBRTC_MODAL_RTSP_PLACEHOLDER_URL\n        logger.info(\"Processing RTSP URL: %s\", webrtc_request.rtsp_url)\n        player = MediaPlayer(\n            webrtc_request.rtsp_url,\n            format=\"rtsp\",\n            options={\n                \"rtsp_transport\": \"tcp\",\n                \"rtsp_flags\": \"prefer_tcp\",\n                \"stimeout\": \"2000000\",  # 2s socket timeout\n            },\n        )\n        video_processor.set_track(track=player.video)\n\n        # For DATA_ONLY mode, start data-only processing task\n        if not should_send_video:\n            logger.info(\"Starting data-only processing for RTSP stream\")\n            asyncio.create_task(video_processor.process_frames_data_only())\n\n    elif webrtc_request.mjpeg_url:\n        logger.info(\"Processing MJPEG URL: %s\", webrtc_request.mjpeg_url)\n        player = MediaPlayer(webrtc_request.mjpeg_url)\n        video_processor.set_track(track=player.video)\n\n        if not should_send_video:\n            logger.info(\"Starting data-only processing for MJPEG stream\")\n            asyncio.create_task(video_processor.process_frames_data_only())\n\n    @peer_connection.on(\"track\")\n    def on_track(track: RemoteStreamTrack):\n        logger.info(\"Track received from client\")\n        relayed_track = relay.subscribe(\n            track,\n            buffered=False if webrtc_request.webrtc_realtime_processing else True,\n        )\n        video_processor.set_track(track=relayed_track)\n\n        # For DATA_ONLY mode, start data-only processing task\n        if not should_send_video:\n            logger.info(\"Starting data-only processing (no video track)\")\n            asyncio.create_task(video_processor.process_frames_data_only())\n\n    @peer_connection.on(\"connectionstatechange\")\n    async def on_connectionstatechange():\n        logger.info(\"on_connectionstatechange: %s\", peer_connection.connectionState)\n        if peer_connection.connectionState in {\"failed\", \"closed\"}:\n            if video_processor.track:\n                logger.info(\"Stopping video processor track\")\n                video_processor.track.stop()\n            await video_processor.close()\n            logger.info(\"Stopping WebRTC peer\")\n            await peer_connection.close()\n            terminate_event.set()\n\n    def process_video_upload_message(\n        message: bytes, video_processor: VideoTransformTrackWithLoop\n    ):\n        chunk_index, total_chunks, data = parse_video_file_chunk(message)\n        video_processor.video_upload_handler.handle_chunk(\n            chunk_index, total_chunks, data\n        )\n\n        video_path = video_processor.video_upload_handler.try_start_processing()\n        return video_path\n\n    @peer_connection.on(\"datachannel\")\n    def on_datachannel(channel: RTCDataChannel):\n        logger.info(\"Data channel '%s' received\", channel.label)\n        # Handle video file upload channel\n        if channel.label == \"video_upload\":\n            logger.info(\"Video upload channel established\")\n\n            video_processor.video_upload_handler = VideoFileUploadHandler()\n\n            @channel.on(\"message\")\n            async def on_upload_message(message):\n                # Keep watchdog alive during upload and keepalive pings\n                if video_processor.heartbeat_callback:\n                    video_processor.heartbeat_callback()\n\n                # Ignore keepalive pings (1-byte messages)\n                if len(message) <= 1:\n                    channel.send(message)\n                    return\n                loop = asyncio.get_running_loop()\n                video_path = await loop.run_in_executor(\n                    None, process_video_upload_message, message, video_processor\n                )\n                if video_path:\n                    logger.info(\n                        \"Video upload complete, processing: realtime=%s, path=%s\",\n                        webrtc_request.webrtc_realtime_processing,\n                        video_path,\n                    )\n\n                    rotation = get_video_rotation(video_path)\n                    rotation_code = get_cv2_rotation_code(rotation)\n                    if rotation_code is not None:\n                        logger.info(\"Video has %d\u00b0 rotation, will correct\", rotation)\n\n                    if webrtc_request.webrtc_realtime_processing:\n                        # Throttled playback - use MediaPlayer\n                        player = MediaPlayer(video_path, loop=False)\n                        player._throttle_playback = True\n                        video_processor.set_track(\n                            track=player.video, rotation_code=rotation_code\n                        )\n                    else:\n                        # Fast processing - use ThreadedVideoTrack\n                        track = ThreadedVideoTrack(video_path)\n                        video_processor.set_track(\n                            track=track, rotation_code=rotation_code\n                        )\n\n                    if not should_send_video:\n                        logger.info(\"Starting data-only processing for video file\")\n                        asyncio.create_task(video_processor.process_frames_data_only())\n\n            return\n\n        # Handle inference control channel (bidirectional communication)\n        @channel.on(\"message\")\n        def on_message(message):\n            try:\n                message_data = WebRTCData(**json.loads(message))\n            except json.JSONDecodeError:\n                logger.error(\"Failed to decode webrtc data payload: %s\", message)\n                return\n            # Optional ACK-based flow control (enabled only after first ACK is received)\n            if message_data.ack is not None:\n                video_processor.record_ack(message_data.ack)\n\n            # Handle stream_output changes\n            if message_data.stream_output is not None:\n                if not video_processor.has_video_track:\n                    logger.warning(\n                        \"Cannot change stream_output: video track was not initialized. \"\n                        \"stream_output must be set at initialization to enable video.\"\n                    )\n                else:\n                    if len(message_data.stream_output) == 0:\n                        video_processor.stream_output = None\n                    else:\n                        filtered = [s for s in message_data.stream_output if s]\n                        video_processor.stream_output = (\n                            filtered[0] if filtered else None\n                        )\n\n            # Handle data_output changes (always allowed)\n            if message_data.data_output is not None:\n                video_processor.data_output = message_data.data_output\n                if (\n                    message_data.data_output is None\n                    or len(message_data.data_output) == 0\n                ):\n                    video_processor._data_mode = DataOutputMode.NONE\n                elif message_data.data_output == [\"*\"]:\n                    video_processor._data_mode = DataOutputMode.ALL\n                else:\n                    video_processor._data_mode = DataOutputMode.SPECIFIC\n\n        video_processor.data_channel = channel\n\n    await peer_connection.setRemoteDescription(\n        RTCSessionDescription(\n            sdp=webrtc_request.webrtc_offer.sdp, type=webrtc_request.webrtc_offer.type\n        )\n    )\n    answer = await peer_connection.createAnswer()\n    await peer_connection.setLocalDescription(answer)\n\n    await _wait_ice_complete(peer_connection, timeout=2.0)\n\n    logger.info(\n        \"Initialized RTC peer connection with loop (status: %s), sending answer\",\n        peer_connection.connectionState,\n    )\n\n    send_answer(\n        WebRTCWorkerResult(\n            answer={\n                \"type\": peer_connection.localDescription.type,\n                \"sdp\": peer_connection.localDescription.sdp,\n            },\n        )\n    )\n\n    logger.info(\"Answer sent, waiting for termination event\")\n    await terminate_event.wait()\n    logger.info(\"Termination event received, closing WebRTC connection\")\n    if player:\n        logger.info(\"Stopping player\")\n        player.video.stop()\n    if peer_connection.connectionState != \"closed\":\n        logger.info(\"Closing WebRTC connection\")\n        await peer_connection.close()\n    if video_processor.track:\n        logger.info(\"Stopping video processor track\")\n        video_processor.track.stop()\n    await video_processor.close()\n    await usage_collector.async_push_usage_payloads()\n    logger.info(\"WebRTC peer connection closed\")\n",
    "patch": null
  },
  {
    "trace_id": "da57dc38-860a-4f59-a834-0b7ccf7d6003",
    "function_name": "YOLO26InstanceSegmentation.predict",
    "file_path": "inference/models/yolo26/yolo26_instance_segmentation.py",
    "speedup_x": 0.26,
    "review_quality": "high",
    "pre_optimization_commit": "HEAD",
    "resolution_method": "db_code_only",
    "source": "db_events",
    "original_function_code": "    def predict(self, img_in: np.ndarray, **kwargs) -> Tuple[np.ndarray, np.ndarray]:\n        \"\"\"Performs inference on the given image using the ONNX session.\n\n        Args:\n            img_in (np.ndarray): Input image as a NumPy array.\n\n        Returns:\n            Tuple[np.ndarray, np.ndarray]: Predictions and mask prototypes.\n        \"\"\"\n        with self._session_lock:\n            predictions, protos = run_session_via_iobinding(\n                self.onnx_session, self.input_name, img_in\n            )\n\n        # YOLO26 end-to-end format: (batch, num_det, 38)\n        # [x1, y1, x2, y2, conf, class_idx, mask_coeffs...]\n        boxes = predictions[:, :, :4]\n        confs = predictions[:, :, 4:5]\n        class_indices = predictions[:, :, 5:6]\n        mask_coeffs = predictions[:, :, 6:]\n\n        # Reformat to match expected format: [boxes, conf, class_idx, mask_coeffs]\n        predictions = np.concatenate([boxes, confs, class_indices, mask_coeffs], axis=2)\n\n        return predictions, protos",
    "optimized_function_code": "import numpy as np\nfrom inference.core.utils.onnx import run_session_via_iobinding\nfrom inference.models.yolov11.yolov11_instance_segmentation import YOLOv11InstanceSegmentation\nfrom typing import Tuple\n\n\nclass YOLO26InstanceSegmentation(YOLOv11InstanceSegmentation):\n\n    def predict(self, img_in: np.ndarray, **kwargs) -> Tuple[np.ndarray, np.ndarray]:\n        \"\"\"Performs inference on the given image using the ONNX session.\n\n        Args:\n            img_in (np.ndarray): Input image as a NumPy array.\n\n        Returns:\n            Tuple[np.ndarray, np.ndarray]: Predictions and mask prototypes.\n        \"\"\"\n        with self._session_lock:\n            predictions, protos = run_session_via_iobinding(\n                self.onnx_session, self.input_name, img_in\n            )\n\n        return predictions, protos",
    "optimized_raw_markdown": "```python:inference/core/utils/onnx.py\nimport torch\nimport numpy as np\nimport onnxruntime as ort\nfrom typing import List, Union\n\nImageMetaType = Union[np.ndarray, \"torch.Tensor\"]\n\n\ndef run_session_via_iobinding(\n    session: ort.InferenceSession, input_name: str, input_data: ImageMetaType\n) -> List[np.ndarray]:\n    if isinstance(input_data, (np.ndarray, list)):\n        # skip the iobinding and just run the session\n        # we likely won't get any gains by pointing to the input data directly\n        predictions = session.run(None, {input_name: input_data})\n    elif \"CUDAExecutionProvider\" not in session.get_providers():\n        # no point in doing iobinding as the input must live on CPU anyway\n        input_data = (\n            input_data.cpu().numpy()\n        )  # since we must be a tensor but ONNX needs a numpy array\n        predictions = session.run(None, {input_name: input_data})\n    else:\n        # we live on GPU and we can use CUDA ONNX, so point to the input data directly\n        binding = session.io_binding()\n\n        predictions = []\n        dtype = None\n        for output in session.get_outputs():\n            # assemble numpy-based output buffers for the ONNX runtime to write to\n            if dtype is None:\n                dtype = np.float16 if \"16\" in output.type else np.float32\n            prediction = np.empty(output.shape, dtype=dtype)\n            binding.bind_output(\n                name=output.name,\n                device_type=\"cpu\",\n                device_id=0,\n                element_type=dtype,\n                shape=output.shape,\n                buffer_ptr=prediction.ctypes.data,\n            )\n            predictions.append(prediction)\n\n        input_data = input_data.contiguous()\n        binding.bind_input(\n            name=input_name,\n            device_type=input_data.device.type,\n            device_id=(\n                input_data.device.index if input_data.device.index is not None else 0\n            ),\n            element_type=dtype,\n            shape=input_data.shape,\n            buffer_ptr=input_data.data_ptr(),\n        )\n\n        binding.synchronize_inputs()\n\n        session.run_with_iobinding(binding)\n\n        # convert the output buffers to float32 as we may run mixed precision inference in the future\n        predictions = [prediction.astype(np.float32) for prediction in predictions]\n\n    return predictions\n```\n```python:inference/models/yolo26/yolo26_instance_segmentation.py\nimport numpy as np\nfrom inference.core.utils.onnx import run_session_via_iobinding\nfrom inference.models.yolov11.yolov11_instance_segmentation import YOLOv11InstanceSegmentation\nfrom typing import Tuple\n\n\nclass YOLO26InstanceSegmentation(YOLOv11InstanceSegmentation):\n\n    def predict(self, img_in: np.ndarray, **kwargs) -> Tuple[np.ndarray, np.ndarray]:\n        \"\"\"Performs inference on the given image using the ONNX session.\n\n        Args:\n            img_in (np.ndarray): Input image as a NumPy array.\n\n        Returns:\n            Tuple[np.ndarray, np.ndarray]: Predictions and mask prototypes.\n        \"\"\"\n        with self._session_lock:\n            predictions, protos = run_session_via_iobinding(\n                self.onnx_session, self.input_name, img_in\n            )\n\n        return predictions, protos\n```",
    "optimized_function_only": "    def predict(self, img_in: np.ndarray, **kwargs) -> Tuple[np.ndarray, np.ndarray]:\n        \"\"\"Performs inference on the given image using the ONNX session.\n\n        Args:\n            img_in (np.ndarray): Input image as a NumPy array.\n\n        Returns:\n            Tuple[np.ndarray, np.ndarray]: Predictions and mask prototypes.\n        \"\"\"\n        with self._session_lock:\n            predictions, protos = run_session_via_iobinding(\n                self.onnx_session, self.input_name, img_in\n            )\n\n        return predictions, protos",
    "original_file_content": "import numpy as np\nfrom inference.core.utils.onnx import run_session_via_iobinding\nfrom inference.models.yolov11.yolov11_instance_segmentation import YOLOv11InstanceSegmentation\nfrom typing import Tuple\n\nclass YOLO26InstanceSegmentation(YOLOv11InstanceSegmentation):\n\n    def predict(self, img_in: np.ndarray, **kwargs) -> Tuple[np.ndarray, np.ndarray]:\n        \"\"\"Performs inference on the given image using the ONNX session.\n\n        Args:\n            img_in (np.ndarray): Input image as a NumPy array.\n\n        Returns:\n            Tuple[np.ndarray, np.ndarray]: Predictions and mask prototypes.\n        \"\"\"\n        with self._session_lock:\n            predictions, protos = run_session_via_iobinding(\n                self.onnx_session, self.input_name, img_in\n            )\n\n        # YOLO26 end-to-end format: (batch, num_det, 38)\n        # [x1, y1, x2, y2, conf, class_idx, mask_coeffs...]\n        boxes = predictions[:, :, :4]\n        confs = predictions[:, :, 4:5]\n        class_indices = predictions[:, :, 5:6]\n        mask_coeffs = predictions[:, :, 6:]\n\n        # Reformat to match expected format: [boxes, conf, class_idx, mask_coeffs]\n        predictions = np.concatenate([boxes, confs, class_indices, mask_coeffs], axis=2)\n\n        return predictions, protos",
    "patch": null
  },
  {
    "trace_id": "e8d0f5d4-85ac-4dd4-ac4d-04e0196764b2",
    "function_name": "InferenceModelsObjectDetectionAdapter.postprocess",
    "file_path": "inference/core/models/inference_models_adapters.py",
    "speedup_x": 0.23,
    "review_quality": "high",
    "pre_optimization_commit": "459f2b015b4df2c21d99608520607c01d3460822",
    "resolution_method": "db_code_match",
    "source": "db_events",
    "original_function_code": "    def postprocess(\n        self,\n        predictions: List[Detections],\n        preprocess_return_metadata: PreprocessingMetadata,\n        **kwargs,\n    ) -> List[ObjectDetectionInferenceResponse]:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        detections_list = self._model.post_process(\n            predictions, preprocess_return_metadata, **mapped_kwargs\n        )\n\n        responses: List[ObjectDetectionInferenceResponse] = []\n        for preproc_metadata, det in zip(preprocess_return_metadata, detections_list):\n            H = preproc_metadata.original_size.height\n            W = preproc_metadata.original_size.width\n\n            xyxy = det.xyxy.detach().cpu().numpy()\n            confs = det.confidence.detach().cpu().numpy()\n            class_ids = det.class_id.detach().cpu().numpy()\n\n            predictions: List[ObjectDetectionPrediction] = []\n\n            for (x1, y1, x2, y2), conf, class_id in zip(xyxy, confs, class_ids):\n                cx = (float(x1) + float(x2)) / 2.0\n                cy = (float(y1) + float(y2)) / 2.0\n                w = float(x2) - float(x1)\n                h = float(y2) - float(y1)\n                class_id_int = int(class_id)\n                class_name = (\n                    self.class_names[class_id_int]\n                    if 0 <= class_id_int < len(self.class_names)\n                    else str(class_id_int)\n                )\n                if (\n                    kwargs.get(\"class_filter\")\n                    and class_name not in kwargs[\"class_filter\"]\n                ):\n                    continue\n                predictions.append(\n                    ObjectDetectionPrediction(\n                        x=cx,\n                        y=cy,\n                        width=w,\n                        height=h,\n                        confidence=float(conf),\n                        **{\"class\": class_name},\n                        class_id=class_id_int,\n                    )\n                )\n\n            responses.append(\n                ObjectDetectionInferenceResponse(\n                    predictions=predictions,\n                    image=InferenceResponseImage(width=W, height=H),\n                )\n            )\n        return responses\n",
    "optimized_function_code": "from typing import List\n\nfrom inference.core.entities.responses.inference import (\n    InferenceResponseImage, ObjectDetectionInferenceResponse,\n    ObjectDetectionPrediction)\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES, API_KEY)\nfrom inference.core.models.base import Model\nfrom inference.core.models.inference_models_adapters import \\\n    get_extra_weights_provider_headers\nfrom inference.models.aliases import resolve_roboflow_model_alias\nfrom inference_models import AutoModel, Detections, ObjectDetectionModel\nfrom inference_models.models.base.types import PreprocessingMetadata\n\n\nclass InferenceModelsObjectDetectionAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n        model_id = resolve_roboflow_model_alias(model_id=model_id)\n\n        self.task_type = \"object-detection\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers()\n\n        self._model: ObjectDetectionModel = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            extra_weights_provider_headers=extra_weights_provider_headers,\n            **kwargs,\n        )\n        self.class_names = list(self._model.class_names)\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        return kwargs\n\n    def postprocess(\n        self,\n        predictions: List[Detections],\n        preprocess_return_metadata: PreprocessingMetadata,\n        **kwargs,\n    ) -> List[ObjectDetectionInferenceResponse]:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        detections_list = self._model.post_process(\n            predictions, preprocess_return_metadata, **mapped_kwargs\n        )\n\n        responses: List[ObjectDetectionInferenceResponse] = []\n\n        # Prepare class filter set once for faster membership checks\n        _class_filter = kwargs.get(\"class_filter\")\n        if _class_filter:\n            try:\n                class_filter_set = set(_class_filter)\n            except TypeError:\n                # If the provided filter is not iterable as expected, fall back to using it directly\n                class_filter_set = _class_filter\n        else:\n            class_filter_set = None\n\n        for preproc_metadata, det in zip(preprocess_return_metadata, detections_list):\n            H = preproc_metadata.original_size.height\n            W = preproc_metadata.original_size.width\n\n            # Use tolist() to get Python-native floats/ints which avoids repeated float()/int() conversions\n            xyxy = det.xyxy.detach().cpu().tolist()\n            confs = det.confidence.detach().cpu().tolist()\n            class_ids = det.class_id.detach().cpu().tolist()\n\n\n            predictions: List[ObjectDetectionPrediction] = []\n\n            for (x1, y1, x2, y2), conf, class_id in zip(xyxy, confs, class_ids):\n                cx = (x1 + x2) / 2.0\n                cy = (y1 + y2) / 2.0\n                w = x2 - x1\n                h = y2 - y1\n                class_id_int = int(class_id)\n                class_name = (\n                    self.class_names[class_id_int]\n                    if 0 <= class_id_int < len(self.class_names)\n                    else str(class_id_int)\n                )\n                if class_filter_set and class_name not in class_filter_set:\n                    continue\n                predictions.append(\n                    ObjectDetectionPrediction(\n                        x=cx,\n                        y=cy,\n                        width=w,\n                        height=h,\n                        confidence=float(conf),\n                        **{\"class\": class_name},\n                        class_id=class_id_int,\n                    )\n                )\n\n            responses.append(\n                ObjectDetectionInferenceResponse(\n                    predictions=predictions,\n                    image=InferenceResponseImage(width=W, height=H),\n                )\n            )\n        return responses",
    "optimized_raw_markdown": "```python:inference/core/models/inference_models_adapters.py\nfrom typing import List\n\nfrom inference.core.entities.responses.inference import (\n    InferenceResponseImage, ObjectDetectionInferenceResponse,\n    ObjectDetectionPrediction)\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES, API_KEY)\nfrom inference.core.models.base import Model\nfrom inference.core.models.inference_models_adapters import \\\n    get_extra_weights_provider_headers\nfrom inference.models.aliases import resolve_roboflow_model_alias\nfrom inference_models import AutoModel, Detections, ObjectDetectionModel\nfrom inference_models.models.base.types import PreprocessingMetadata\n\n\nclass InferenceModelsObjectDetectionAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n        model_id = resolve_roboflow_model_alias(model_id=model_id)\n\n        self.task_type = \"object-detection\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers()\n\n        self._model: ObjectDetectionModel = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            extra_weights_provider_headers=extra_weights_provider_headers,\n            **kwargs,\n        )\n        self.class_names = list(self._model.class_names)\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        return kwargs\n\n    def postprocess(\n        self,\n        predictions: List[Detections],\n        preprocess_return_metadata: PreprocessingMetadata,\n        **kwargs,\n    ) -> List[ObjectDetectionInferenceResponse]:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        detections_list = self._model.post_process(\n            predictions, preprocess_return_metadata, **mapped_kwargs\n        )\n\n        responses: List[ObjectDetectionInferenceResponse] = []\n\n        # Prepare class filter set once for faster membership checks\n        _class_filter = kwargs.get(\"class_filter\")\n        if _class_filter:\n            try:\n                class_filter_set = set(_class_filter)\n            except TypeError:\n                # If the provided filter is not iterable as expected, fall back to using it directly\n                class_filter_set = _class_filter\n        else:\n            class_filter_set = None\n\n        for preproc_metadata, det in zip(preprocess_return_metadata, detections_list):\n            H = preproc_metadata.original_size.height\n            W = preproc_metadata.original_size.width\n\n            # Use tolist() to get Python-native floats/ints which avoids repeated float()/int() conversions\n            xyxy = det.xyxy.detach().cpu().tolist()\n            confs = det.confidence.detach().cpu().tolist()\n            class_ids = det.class_id.detach().cpu().tolist()\n\n\n            predictions: List[ObjectDetectionPrediction] = []\n\n            for (x1, y1, x2, y2), conf, class_id in zip(xyxy, confs, class_ids):\n                cx = (x1 + x2) / 2.0\n                cy = (y1 + y2) / 2.0\n                w = x2 - x1\n                h = y2 - y1\n                class_id_int = int(class_id)\n                class_name = (\n                    self.class_names[class_id_int]\n                    if 0 <= class_id_int < len(self.class_names)\n                    else str(class_id_int)\n                )\n                if class_filter_set and class_name not in class_filter_set:\n                    continue\n                predictions.append(\n                    ObjectDetectionPrediction(\n                        x=cx,\n                        y=cy,\n                        width=w,\n                        height=h,\n                        confidence=float(conf),\n                        **{\"class\": class_name},\n                        class_id=class_id_int,\n                    )\n                )\n\n            responses.append(\n                ObjectDetectionInferenceResponse(\n                    predictions=predictions,\n                    image=InferenceResponseImage(width=W, height=H),\n                )\n            )\n        return responses\n```",
    "optimized_function_only": "    def postprocess(\n        self,\n        predictions: List[Detections],\n        preprocess_return_metadata: PreprocessingMetadata,\n        **kwargs,\n    ) -> List[ObjectDetectionInferenceResponse]:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        detections_list = self._model.post_process(\n            predictions, preprocess_return_metadata, **mapped_kwargs\n        )\n\n        responses: List[ObjectDetectionInferenceResponse] = []\n\n        # Prepare class filter set once for faster membership checks\n        _class_filter = kwargs.get(\"class_filter\")\n        if _class_filter:\n            try:\n                class_filter_set = set(_class_filter)\n            except TypeError:\n                # If the provided filter is not iterable as expected, fall back to using it directly\n                class_filter_set = _class_filter\n        else:\n            class_filter_set = None\n\n        for preproc_metadata, det in zip(preprocess_return_metadata, detections_list):\n            H = preproc_metadata.original_size.height\n            W = preproc_metadata.original_size.width\n\n            # Use tolist() to get Python-native floats/ints which avoids repeated float()/int() conversions\n            xyxy = det.xyxy.detach().cpu().tolist()\n            confs = det.confidence.detach().cpu().tolist()\n            class_ids = det.class_id.detach().cpu().tolist()\n\n\n            predictions: List[ObjectDetectionPrediction] = []\n\n            for (x1, y1, x2, y2), conf, class_id in zip(xyxy, confs, class_ids):\n                cx = (x1 + x2) / 2.0\n                cy = (y1 + y2) / 2.0\n                w = x2 - x1\n                h = y2 - y1\n                class_id_int = int(class_id)\n                class_name = (\n                    self.class_names[class_id_int]\n                    if 0 <= class_id_int < len(self.class_names)\n                    else str(class_id_int)\n                )\n                if class_filter_set and class_name not in class_filter_set:\n                    continue\n                predictions.append(\n                    ObjectDetectionPrediction(\n                        x=cx,\n                        y=cy,\n                        width=w,\n                        height=h,\n                        confidence=float(conf),\n                        **{\"class\": class_name},\n                        class_id=class_id_int,\n                    )\n                )\n\n            responses.append(\n                ObjectDetectionInferenceResponse(\n                    predictions=predictions,\n                    image=InferenceResponseImage(width=W, height=H),\n                )\n            )\n        return responses",
    "original_file_content": "import base64\nimport io\nfrom io import BytesIO\nfrom time import perf_counter\nfrom typing import Any, List, Optional, Tuple, Union\n\nimport numpy as np\nimport torch\nfrom PIL import Image, ImageDraw, ImageFont\n\nfrom inference.core.entities.requests import (\n    ClassificationInferenceRequest,\n    InferenceRequest,\n)\nfrom inference.core.entities.responses.inference import (\n    ClassificationInferenceResponse,\n    InferenceResponse,\n    InferenceResponseImage,\n    InstanceSegmentationInferenceResponse,\n    InstanceSegmentationPrediction,\n    Keypoint,\n    KeypointsDetectionInferenceResponse,\n    KeypointsPrediction,\n    MultiLabelClassificationInferenceResponse,\n    ObjectDetectionInferenceResponse,\n    ObjectDetectionPrediction,\n    Point,\n    SemanticSegmentationInferenceResponse,\n    SemanticSegmentationPrediction,\n)\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n    API_KEY,\n    DISABLED_INFERENCE_MODELS_BACKENDS,\n    RFDETR_ONNX_MAX_RESOLUTION,\n    VALID_INFERENCE_MODELS_BACKENDS,\n)\nfrom inference.core.models.base import Model\nfrom inference.core.roboflow_api import get_extra_weights_provider_headers\nfrom inference.core.utils.image_utils import load_image_bgr, load_image_rgb\nfrom inference.core.utils.postprocess import masks2poly\nfrom inference.core.utils.visualisation import draw_detection_predictions\nfrom inference.models.aliases import resolve_roboflow_model_alias\nfrom inference_models import (\n    AutoModel,\n    ClassificationModel,\n    ClassificationPrediction,\n    Detections,\n    InstanceDetections,\n    InstanceSegmentationModel,\n    KeyPoints,\n    KeyPointsDetectionModel,\n    MultiLabelClassificationModel,\n    MultiLabelClassificationPrediction,\n    ObjectDetectionModel,\n    PreProcessingOverrides,\n    SemanticSegmentationModel,\n)\nfrom inference_models.models.base.semantic_segmentation import (\n    SemanticSegmentationResult,\n)\nfrom inference_models.models.base.types import PreprocessingMetadata\n\ndef _resolve_cached_model_path(model_id: str) -> str:\n    \"\"\"If the model is already in the inference-models local cache, return the\n    package directory path so ``AutoModel.from_pretrained`` can load directly\n    from disk without calling the Roboflow API.  Returns the original\n    *model_id* unchanged when no local cache hit is found.\n    \"\"\"\n    try:\n        from inference.core.cache.air_gapped import (\n            _get_inference_models_home,\n            _slugify_model_id,\n        )\n        from inference.core.env import MODEL_CACHE_DIR\n\n        slug = _slugify_model_id(model_id)\n        bases = [MODEL_CACHE_DIR]\n        inference_home = _get_inference_models_home()\n        if inference_home is not None and inference_home != MODEL_CACHE_DIR:\n            bases.append(inference_home)\n\n        for base in bases:\n            import os\n\n            slug_dir = os.path.join(base, \"models-cache\", slug)\n            if not os.path.isdir(slug_dir):\n                continue\n            for package_id in os.listdir(slug_dir):\n                package_dir = os.path.join(slug_dir, package_id)\n                if os.path.isfile(os.path.join(package_dir, \"model_config.json\")):\n                    return package_dir\n    except Exception:\n        pass\n    return model_id\n\n\nDEFAULT_COLOR_PALETTE = [\n    \"#A351FB\",\n    \"#FF4040\",\n    \"#FFA1A0\",\n    \"#FF7633\",\n    \"#FFB633\",\n    \"#D1D435\",\n    \"#4CFB12\",\n    \"#94CF1A\",\n    \"#40DE8A\",\n    \"#1B9640\",\n    \"#00D6C1\",\n    \"#2E9CAA\",\n    \"#00C4FF\",\n    \"#364797\",\n    \"#6675FF\",\n    \"#0019EF\",\n    \"#863AFF\",\n    \"#530087\",\n    \"#CD3AFF\",\n    \"#FF97CA\",\n    \"#FF39C9\",\n]\n\n\nclass InferenceModelsObjectDetectionAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n        model_id = resolve_roboflow_model_alias(model_id=model_id)\n\n        self.task_type = \"object-detection\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n        backend = list(\n            VALID_INFERENCE_MODELS_BACKENDS.difference(\n                DISABLED_INFERENCE_MODELS_BACKENDS\n            )\n        )\n        self._model: ObjectDetectionModel = AutoModel.from_pretrained(\n            model_id_or_path=_resolve_cached_model_path(model_id),\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            backend=backend,\n            rf_detr_max_input_resolution=RFDETR_ONNX_MAX_RESOLUTION,\n            **kwargs,\n        )\n        self.class_names = list(self._model.class_names)\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        pre_processing_overrides = PreProcessingOverrides(\n            disable_contrast_enhancement=kwargs.get(\"disable_preproc_contrast\", False),\n            disable_grayscale=kwargs.get(\"disable_preproc_grayscale\", False),\n            disable_static_crop=kwargs.get(\"disable_preproc_static_crop\", False),\n        )\n        kwargs[\"pre_processing_overrides\"] = pre_processing_overrides\n        return kwargs\n\n    def preprocess(self, image: Any, **kwargs):\n        is_batch = isinstance(image, list)\n        images = image if is_batch else [image]\n        np_images: List[np.ndarray] = [\n            load_image_bgr(\n                v,\n                disable_preproc_auto_orient=kwargs.get(\n                    \"disable_preproc_auto_orient\", False\n                ),\n            )\n            for v in images\n        ]\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.pre_process(np_images, **mapped_kwargs)\n\n    def predict(self, img_in, **kwargs):\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.forward(img_in, **mapped_kwargs)\n\n    def postprocess(\n        self,\n        predictions: List[Detections],\n        preprocess_return_metadata: PreprocessingMetadata,\n        **kwargs,\n    ) -> List[ObjectDetectionInferenceResponse]:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        detections_list = self._model.post_process(\n            predictions, preprocess_return_metadata, **mapped_kwargs\n        )\n\n        responses: List[ObjectDetectionInferenceResponse] = []\n        for preproc_metadata, det in zip(preprocess_return_metadata, detections_list):\n            H = preproc_metadata.original_size.height\n            W = preproc_metadata.original_size.width\n\n            xyxy = det.xyxy.detach().cpu().numpy()\n            confs = det.confidence.detach().cpu().numpy()\n            class_ids = det.class_id.detach().cpu().numpy()\n\n            predictions: List[ObjectDetectionPrediction] = []\n\n            for (x1, y1, x2, y2), conf, class_id in zip(xyxy, confs, class_ids):\n                cx = (float(x1) + float(x2)) / 2.0\n                cy = (float(y1) + float(y2)) / 2.0\n                w = float(x2) - float(x1)\n                h = float(y2) - float(y1)\n                class_id_int = int(class_id)\n                class_name = (\n                    self.class_names[class_id_int]\n                    if 0 <= class_id_int < len(self.class_names)\n                    else str(class_id_int)\n                )\n                if (\n                    kwargs.get(\"class_filter\")\n                    and class_name not in kwargs[\"class_filter\"]\n                ):\n                    continue\n                predictions.append(\n                    ObjectDetectionPrediction(\n                        x=cx,\n                        y=cy,\n                        width=w,\n                        height=h,\n                        confidence=float(conf),\n                        **{\"class\": class_name},\n                        class_id=class_id_int,\n                    )\n                )\n\n            responses.append(\n                ObjectDetectionInferenceResponse(\n                    predictions=predictions,\n                    image=InferenceResponseImage(width=W, height=H),\n                )\n            )\n        return responses\n\n    def clear_cache(self, delete_from_disk: bool = True) -> None:\n        \"\"\"Clears any cache if necessary. TODO: Implement this to delete the cache from the experimental model.\n\n        Args:\n            delete_from_disk (bool, optional): Whether to delete cached files from disk. Defaults to True.\n        \"\"\"\n        pass\n\n    def draw_predictions(\n        self,\n        inference_request: InferenceRequest,\n        inference_response: InferenceResponse,\n    ) -> bytes:\n        \"\"\"Draw predictions from an inference response onto the original image provided by an inference request\n\n        Args:\n            inference_request (ObjectDetectionInferenceRequest): The inference request containing the image on which to draw predictions\n            inference_response (ObjectDetectionInferenceResponse): The inference response containing predictions to be drawn\n\n        Returns:\n            str: A base64 encoded image string\n        \"\"\"\n        class_id_2_color = {\n            i: DEFAULT_COLOR_PALETTE[i % len(DEFAULT_COLOR_PALETTE)]\n            for i, class_name in enumerate(self._model.class_names)\n        }\n        return draw_detection_predictions(\n            inference_request=inference_request,\n            inference_response=inference_response,\n            colors=class_id_2_color,\n        )\n\n\nclass InferenceModelsInstanceSegmentationAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n        model_id = resolve_roboflow_model_alias(model_id=model_id)\n\n        self.task_type = \"instance-segmentation\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n        backend = list(\n            VALID_INFERENCE_MODELS_BACKENDS.difference(\n                DISABLED_INFERENCE_MODELS_BACKENDS\n            )\n        )\n        self._model: InstanceSegmentationModel = AutoModel.from_pretrained(\n            model_id_or_path=_resolve_cached_model_path(model_id),\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            backend=backend,\n            rf_detr_max_input_resolution=RFDETR_ONNX_MAX_RESOLUTION,\n            **kwargs,\n        )\n        self.class_names = list(self._model.class_names)\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        pre_processing_overrides = PreProcessingOverrides(\n            disable_contrast_enhancement=kwargs.get(\"disable_preproc_contrast\", False),\n            disable_grayscale=kwargs.get(\"disable_preproc_grayscale\", False),\n            disable_static_crop=kwargs.get(\"disable_preproc_static_crop\", False),\n        )\n        kwargs[\"pre_processing_overrides\"] = pre_processing_overrides\n        return kwargs\n\n    def preprocess(self, image: Any, **kwargs):\n        is_batch = isinstance(image, list)\n        images = image if is_batch else [image]\n        np_images: List[np.ndarray] = [\n            load_image_bgr(\n                v,\n                disable_preproc_auto_orient=kwargs.get(\n                    \"disable_preproc_auto_orient\", False\n                ),\n            )\n            for v in images\n        ]\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.pre_process(np_images, **mapped_kwargs)\n\n    def predict(self, img_in, **kwargs):\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.forward(img_in, **mapped_kwargs)\n\n    def postprocess(\n        self,\n        predictions: List[InstanceDetections],\n        preprocess_return_metadata: PreprocessingMetadata,\n        **kwargs,\n    ) -> List[InstanceSegmentationInferenceResponse]:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        detections_list = self._model.post_process(\n            predictions, preprocess_return_metadata, **mapped_kwargs\n        )\n\n        responses: List[InstanceSegmentationInferenceResponse] = []\n        for preproc_metadata, det in zip(preprocess_return_metadata, detections_list):\n            H = preproc_metadata.original_size.height\n            W = preproc_metadata.original_size.width\n\n            xyxy = det.xyxy.detach().cpu().numpy()\n            confs = det.confidence.detach().cpu().numpy()\n            masks = det.mask.detach().cpu().numpy()\n            polys = masks2poly(masks)\n            class_ids = det.class_id.detach().cpu().numpy()\n\n            predictions: List[InstanceSegmentationPrediction] = []\n\n            for (x1, y1, x2, y2), mask_as_poly, conf, class_id in zip(\n                xyxy, polys, confs, class_ids\n            ):\n                cx = (float(x1) + float(x2)) / 2.0\n                cy = (float(y1) + float(y2)) / 2.0\n                w = float(x2) - float(x1)\n                h = float(y2) - float(y1)\n                class_id_int = int(class_id)\n                class_name = (\n                    self.class_names[class_id_int]\n                    if 0 <= class_id_int < len(self.class_names)\n                    else str(class_id_int)\n                )\n                if (\n                    kwargs.get(\"class_filter\")\n                    and class_name not in kwargs[\"class_filter\"]\n                ):\n                    continue\n                predictions.append(\n                    InstanceSegmentationPrediction(\n                        x=cx,\n                        y=cy,\n                        width=w,\n                        height=h,\n                        confidence=float(conf),\n                        points=[\n                            Point(x=point[0], y=point[1]) for point in mask_as_poly\n                        ],\n                        **{\"class\": class_name},\n                        class_id=class_id_int,\n                    )\n                )\n\n            responses.append(\n                InstanceSegmentationInferenceResponse(\n                    predictions=predictions,\n                    image=InferenceResponseImage(width=W, height=H),\n                )\n            )\n        return responses\n\n    def clear_cache(self, delete_from_disk: bool = True) -> None:\n        \"\"\"Clears any cache if necessary. TODO: Implement this to delete the cache from the experimental model.\n\n        Args:\n            delete_from_disk (bool, optional): Whether to delete cached files from disk. Defaults to True.\n        \"\"\"\n        pass\n\n    def draw_predictions(\n        self,\n        inference_request: InferenceRequest,\n        inference_response: InferenceResponse,\n    ) -> bytes:\n        \"\"\"Draw predictions from an inference response onto the original image provided by an inference request\n\n        Args:\n            inference_request (ObjectDetectionInferenceRequest): The inference request containing the image on which to draw predictions\n            inference_response (ObjectDetectionInferenceResponse): The inference response containing predictions to be drawn\n\n        Returns:\n            str: A base64 encoded image string\n        \"\"\"\n        class_id_2_color = {\n            i: DEFAULT_COLOR_PALETTE[i % len(DEFAULT_COLOR_PALETTE)]\n            for i, class_name in enumerate(self._model.class_names)\n        }\n        return draw_detection_predictions(\n            inference_request=inference_request,\n            inference_response=inference_response,\n            colors=class_id_2_color,\n        )\n\n\nclass InferenceModelsKeyPointsDetectionAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n        model_id = resolve_roboflow_model_alias(model_id=model_id)\n\n        self.task_type = \"keypoint-detection\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n        backend = list(\n            VALID_INFERENCE_MODELS_BACKENDS.difference(\n                DISABLED_INFERENCE_MODELS_BACKENDS\n            )\n        )\n        self._model: KeyPointsDetectionModel = AutoModel.from_pretrained(\n            model_id_or_path=_resolve_cached_model_path(model_id),\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            backend=backend,\n            **kwargs,\n        )\n        self.class_names = list(self._model.class_names)\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        if \"request\" in kwargs:\n            keypoint_confidence_threshold = kwargs[\"request\"].keypoint_confidence\n            kwargs[\"key_points_threshold\"] = keypoint_confidence_threshold\n        pre_processing_overrides = PreProcessingOverrides(\n            disable_contrast_enhancement=kwargs.get(\"disable_preproc_contrast\", False),\n            disable_grayscale=kwargs.get(\"disable_preproc_grayscale\", False),\n            disable_static_crop=kwargs.get(\"disable_preproc_static_crop\", False),\n        )\n        kwargs[\"pre_processing_overrides\"] = pre_processing_overrides\n        return kwargs\n\n    def preprocess(self, image: Any, **kwargs):\n        is_batch = isinstance(image, list)\n        images = image if is_batch else [image]\n        np_images: List[np.ndarray] = [\n            load_image_bgr(\n                v,\n                disable_preproc_auto_orient=kwargs.get(\n                    \"disable_preproc_auto_orient\", False\n                ),\n            )\n            for v in images\n        ]\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.pre_process(np_images, **mapped_kwargs)\n\n    def predict(self, img_in, **kwargs):\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.forward(img_in, **mapped_kwargs)\n\n    def postprocess(\n        self,\n        predictions: Tuple[List[KeyPoints], Optional[List[Detections]]],\n        preprocess_return_metadata: PreprocessingMetadata,\n        **kwargs,\n    ) -> List[KeypointsDetectionInferenceResponse]:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        keypoints_list, detections_list = self._model.post_process(\n            predictions, preprocess_return_metadata, **mapped_kwargs\n        )\n        if detections_list is None:\n            raise RuntimeError(\n                \"Keypoints detection model does not provide instances detection - this is not supported for \"\n                \"models from `inference-models` package which are adapted to work with `inference`.\"\n            )\n        key_points_classes = self._model.key_points_classes\n        responses: List[KeypointsDetectionInferenceResponse] = []\n        for preproc_metadata, keypoints, det in zip(\n            preprocess_return_metadata, keypoints_list, detections_list\n        ):\n\n            H = preproc_metadata.original_size.height\n            W = preproc_metadata.original_size.width\n\n            xyxy = det.xyxy.detach().cpu().numpy()\n            confs = det.confidence.detach().cpu().numpy()\n            class_ids = det.class_id.detach().cpu().numpy()\n            keypoints_xy = keypoints.xy.detach().cpu().tolist()\n            keypoints_class_id = keypoints.class_id.detach().cpu().tolist()\n            keypoints_confidence = keypoints.confidence.detach().cpu().tolist()\n            predictions: List[KeypointsPrediction] = []\n\n            for (\n                (x1, y1, x2, y2),\n                conf,\n                class_id,\n                instance_keypoints_xy,\n                instance_keypoints_class_id,\n                instance_keypoints_confidence,\n            ) in zip(\n                xyxy,\n                confs,\n                class_ids,\n                keypoints_xy,\n                keypoints_class_id,\n                keypoints_confidence,\n            ):\n                cx = (float(x1) + float(x2)) / 2.0\n                cy = (float(y1) + float(y2)) / 2.0\n                w = float(x2) - float(x1)\n                h = float(y2) - float(y1)\n                class_id_int = int(class_id)\n                class_name = (\n                    self.class_names[class_id_int]\n                    if 0 <= class_id_int < len(self.class_names)\n                    else str(class_id_int)\n                )\n                if (\n                    kwargs.get(\"class_filter\")\n                    and class_name not in kwargs[\"class_filter\"]\n                ):\n                    continue\n                predictions.append(\n                    KeypointsPrediction(\n                        x=cx,\n                        y=cy,\n                        width=w,\n                        height=h,\n                        confidence=float(conf),\n                        **{\"class\": class_name},\n                        class_id=class_id_int,\n                        keypoints=model_keypoints_to_response(\n                            instance_keypoints_xy=instance_keypoints_xy,\n                            instance_keypoints_confidence=instance_keypoints_confidence,\n                            instance_keypoints_class_id=instance_keypoints_class_id,\n                            key_points_classes=key_points_classes,\n                        ),\n                    )\n                )\n\n            responses.append(\n                KeypointsDetectionInferenceResponse(\n                    predictions=predictions,\n                    image=InferenceResponseImage(width=W, height=H),\n                )\n            )\n\n        return responses\n\n    def clear_cache(self, delete_from_disk: bool = True) -> None:\n        \"\"\"Clears any cache if necessary. TODO: Implement this to delete the cache from the experimental model.\n\n        Args:\n            delete_from_disk (bool, optional): Whether to delete cached files from disk. Defaults to True.\n        \"\"\"\n        pass\n\n    def draw_predictions(\n        self,\n        inference_request: InferenceRequest,\n        inference_response: InferenceResponse,\n    ) -> bytes:\n        \"\"\"Draw predictions from an inference response onto the original image provided by an inference request\n\n        Args:\n            inference_request (ObjectDetectionInferenceRequest): The inference request containing the image on which to draw predictions\n            inference_response (ObjectDetectionInferenceResponse): The inference response containing predictions to be drawn\n\n        Returns:\n            str: A base64 encoded image string\n        \"\"\"\n        class_id_2_color = {\n            i: DEFAULT_COLOR_PALETTE[i % len(DEFAULT_COLOR_PALETTE)]\n            for i, class_name in enumerate(self._model.class_names)\n        }\n        return draw_detection_predictions(\n            inference_request=inference_request,\n            inference_response=inference_response,\n            colors=class_id_2_color,\n        )\n\n\ndef model_keypoints_to_response(\n    instance_keypoints_xy: List[\n        List[Union[float, int]]\n    ],  # (num_key_points_foc_class_of_object, 2)\n    instance_keypoints_confidence: List[float],  # (instance_key_points, )\n    instance_keypoints_class_id: int,\n    key_points_classes: List[List[str]],\n) -> List[Keypoint]:\n    keypoint_classes = key_points_classes[instance_keypoints_class_id]\n    results = []\n    for keypoint_class_id, ((x, y), confidence, keypoint_class_name) in enumerate(\n        zip(instance_keypoints_xy, instance_keypoints_confidence, keypoint_classes)\n    ):\n        if confidence <= 0.0:\n            continue\n        keypoint = Keypoint(\n            x=x,\n            y=y,\n            confidence=confidence,\n            class_id=keypoint_class_id,\n            **{\"class\": keypoint_class_name},\n        )\n        results.append(keypoint)\n    return results\n\n\nclass InferenceModelsClassificationAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n        model_id = resolve_roboflow_model_alias(model_id=model_id)\n\n        self.task_type = \"classification\"\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n        backend = list(\n            VALID_INFERENCE_MODELS_BACKENDS.difference(\n                DISABLED_INFERENCE_MODELS_BACKENDS\n            )\n        )\n        self._model: Union[ClassificationModel, MultiLabelClassificationModel] = (\n            AutoModel.from_pretrained(\n                model_id_or_path=_resolve_cached_model_path(model_id),\n                api_key=self.api_key,\n                allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n                allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n                weights_provider_extra_headers=extra_weights_provider_headers,\n                backend=backend,\n                **kwargs,\n            )\n        )\n        self.class_names = list(self._model.class_names)\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        pre_processing_overrides = PreProcessingOverrides(\n            disable_contrast_enhancement=kwargs.get(\"disable_preproc_contrast\", False),\n            disable_grayscale=kwargs.get(\"disable_preproc_grayscale\", False),\n            disable_static_crop=kwargs.get(\"disable_preproc_static_crop\", False),\n        )\n        kwargs[\"pre_processing_overrides\"] = pre_processing_overrides\n        return kwargs\n\n    def preprocess(self, image: Any, **kwargs):\n        is_batch = isinstance(image, list)\n        images = image if is_batch else [image]\n        np_images: List[np.ndarray] = [\n            load_image_bgr(\n                v,\n                disable_preproc_auto_orient=kwargs.get(\n                    \"disable_preproc_auto_orient\", False\n                ),\n            )\n            for v in images\n        ]\n        images_shapes = [i.shape[:2] for i in np_images]\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.pre_process(np_images, **mapped_kwargs), images_shapes\n\n    def predict(self, img_in, **kwargs):\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.forward(img_in, **mapped_kwargs)\n\n    def postprocess(\n        self,\n        predictions: Tuple[List[KeyPoints], Optional[List[Detections]]],\n        returned_metadata: List[Tuple[int, int]],\n        **kwargs,\n    ) -> Union[\n        List[MultiLabelClassificationInferenceResponse],\n        List[ClassificationInferenceResponse],\n    ]:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        post_processed_predictions = self._model.post_process(\n            predictions, **mapped_kwargs\n        )\n        if isinstance(post_processed_predictions, list):\n            # multi-label classification\n            return prepare_multi_label_classification_response(\n                post_processed_predictions,\n                image_sizes=returned_metadata,\n                class_names=self.class_names,\n                confidence_threshold=kwargs.get(\"confidence\", 0.5),\n            )\n        else:\n            # single-label classification\n            return prepare_classification_response(\n                post_processed_predictions,\n                image_sizes=returned_metadata,\n                class_names=self.class_names,\n                confidence_threshold=kwargs.get(\"confidence\", 0.5),\n            )\n\n    def clear_cache(self, delete_from_disk: bool = True) -> None:\n        \"\"\"Clears any cache if necessary. TODO: Implement this to delete the cache from the experimental model.\n\n        Args:\n            delete_from_disk (bool, optional): Whether to delete cached files from disk. Defaults to True.\n        \"\"\"\n        pass\n\n    def infer_from_request(\n        self,\n        request: ClassificationInferenceRequest,\n    ) -> Union[List[InferenceResponse], InferenceResponse]:\n        \"\"\"\n        Handle an inference request to produce an appropriate response.\n\n        Args:\n            request (ClassificationInferenceRequest): The request object encapsulating the image(s) and relevant parameters.\n\n        Returns:\n            Union[List[InferenceResponse], InferenceResponse]: The response object(s) containing the predictions, visualization, and other pertinent details. If a list of images was provided, a list of responses is returned. Otherwise, a single response is returned.\n\n        Notes:\n            - Starts a timer at the beginning to calculate inference time.\n            - Processes the image(s) through the `infer` method.\n            - Generates the appropriate response object(s) using `make_response`.\n            - Calculates and sets the time taken for inference.\n            - If visualization is requested, the predictions are drawn on the image.\n        \"\"\"\n        t1 = perf_counter()\n        responses = self.infer(**request.dict(), return_image_dims=True)\n        for response in responses:\n            response.time = perf_counter() - t1\n            response.inference_id = getattr(request, \"id\", None)\n\n        if request.visualize_predictions:\n            for response in responses:\n                response.visualization = draw_predictions(\n                    request, response, self.class_names\n                )\n\n        if not isinstance(request.image, list):\n            responses = responses[0]\n\n        return responses\n\n\ndef prepare_multi_label_classification_response(\n    post_processed_predictions: List[MultiLabelClassificationPrediction],\n    image_sizes: List[Tuple[int, int]],\n    class_names: List[str],\n    confidence_threshold: float,\n) -> List[MultiLabelClassificationInferenceResponse]:\n    results = []\n    for prediction, image_size in zip(post_processed_predictions, image_sizes):\n        image_predictions_dict = dict()\n        predicted_classes = []\n        for class_id, confidence in enumerate(prediction.confidence.cpu().tolist()):\n            cls_name = class_names[class_id]\n            image_predictions_dict[cls_name] = {\n                \"confidence\": confidence,\n                \"class_id\": class_id,\n            }\n            if confidence > confidence_threshold:\n                predicted_classes.append(cls_name)\n        results.append(\n            MultiLabelClassificationInferenceResponse(\n                predictions=image_predictions_dict,\n                predicted_classes=predicted_classes,\n                image=InferenceResponseImage(width=image_size[1], height=image_size[0]),\n                # essentially pushing a dummy values as I have no intention breaking the new API for the sake of delivering value that has no practical use\n            )\n        )\n    return results\n\n\ndef prepare_classification_response(\n    post_processed_predictions: ClassificationPrediction,\n    image_sizes: List[Tuple[int, int]],\n    class_names: List[str],\n    confidence_threshold: float,\n) -> List[ClassificationInferenceResponse]:\n    responses = []\n    for classes_confidence, image_size in zip(\n        post_processed_predictions.confidence.cpu().tolist(), image_sizes\n    ):\n        individual_classes_predictions = []\n        for i, cls_name in enumerate(class_names):\n            class_score = float(classes_confidence[i])\n            if class_score < confidence_threshold:\n                continue\n            class_prediction = {\n                \"class_id\": i,\n                \"class\": cls_name,\n                \"confidence\": round(class_score, 4),\n            }\n            individual_classes_predictions.append(class_prediction)\n        individual_classes_predictions = sorted(\n            individual_classes_predictions, key=lambda x: x[\"confidence\"], reverse=True\n        )\n        response = ClassificationInferenceResponse(\n            image=InferenceResponseImage(width=image_size[1], height=image_size[0]),\n            # essentially pushing a dummy values as I have no intention breaking the new API for the sake of delivering value that has no practical use\n            predictions=individual_classes_predictions,\n            top=(\n                individual_classes_predictions[0][\"class\"]\n                if individual_classes_predictions\n                else \"\"\n            ),\n            confidence=(\n                individual_classes_predictions[0][\"confidence\"]\n                if individual_classes_predictions\n                else 0.0\n            ),\n        )\n        responses.append(response)\n    return responses\n\n\ndef draw_predictions(inference_request, inference_response, class_names: List[str]):\n    \"\"\"Draw prediction visuals on an image.\n\n    This method overlays the predictions on the input image, including drawing rectangles and text to visualize the predicted classes.\n\n    Args:\n        inference_request: The request object containing the image and parameters.\n        inference_response: The response object containing the predictions and other details.\n        class_names: List of class names corresponding to the model's classes.\n\n    Returns:\n        bytes: The bytes of the visualized image in JPEG format.\n    \"\"\"\n    image = load_image_rgb(inference_request.image)\n    image = Image.fromarray(image)\n    draw = ImageDraw.Draw(image)\n    font = ImageFont.load_default()\n    class_id_2_color = {\n        i: DEFAULT_COLOR_PALETTE[i % len(DEFAULT_COLOR_PALETTE)]\n        for i, class_name in enumerate(class_names)\n    }\n    if isinstance(inference_response.predictions, list):\n        prediction = inference_response.predictions[0]\n        color = class_id_2_color.get(prediction.class_id, \"#4892EA\")\n        draw.rectangle(\n            [0, 0, image.size[1], image.size[0]],\n            outline=color,\n            width=inference_request.visualization_stroke_width,\n        )\n        text = f\"{prediction.class_id} - {prediction.class_name} {prediction.confidence:.2f}\"\n        text_size = font.getbbox(text)\n\n        # set button size + 10px margins\n        button_size = (text_size[2] + 20, text_size[3] + 20)\n        button_img = Image.new(\"RGBA\", button_size, color)\n        # put text on button with 10px margins\n        button_draw = ImageDraw.Draw(button_img)\n        button_draw.text((10, 10), text, font=font, fill=(255, 255, 255, 255))\n\n        # put button on source image in position (0, 0)\n        image.paste(button_img, (0, 0))\n    else:\n        if len(inference_response.predictions) > 0:\n            box_color = \"#4892EA\"\n            draw.rectangle(\n                [0, 0, image.size[1], image.size[0]],\n                outline=box_color,\n                width=inference_request.visualization_stroke_width,\n            )\n        row = 0\n        predictions = [\n            (cls_name, pred)\n            for cls_name, pred in inference_response.predictions.items()\n        ]\n        predictions = sorted(predictions, key=lambda x: x[1].confidence, reverse=True)\n        for i, (cls_name, pred) in enumerate(predictions):\n            color = class_id_2_color.get(cls_name, \"#4892EA\")\n            text = f\"{cls_name} {pred.confidence:.2f}\"\n            text_size = font.getbbox(text)\n\n            # set button size + 10px margins\n            button_size = (text_size[2] + 20, text_size[3] + 20)\n            button_img = Image.new(\"RGBA\", button_size, color)\n            # put text on button with 10px margins\n            button_draw = ImageDraw.Draw(button_img)\n            button_draw.text((10, 10), text, font=font, fill=(255, 255, 255, 255))\n\n            # put button on source image in position (0, 0)\n            image.paste(button_img, (0, row))\n            row += button_size[1]\n\n    buffered = BytesIO()\n    image = image.convert(\"RGB\")\n    image.save(buffered, format=\"JPEG\")\n    return buffered.getvalue()\n\n\nclass InferenceModelsSemanticSegmentationAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n        model_id = resolve_roboflow_model_alias(model_id=model_id)\n\n        self.task_type = \"semantic-segmentation\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n        backend = list(\n            VALID_INFERENCE_MODELS_BACKENDS.difference(\n                DISABLED_INFERENCE_MODELS_BACKENDS\n            )\n        )\n        self._model: SemanticSegmentationModel = AutoModel.from_pretrained(\n            model_id_or_path=_resolve_cached_model_path(model_id),\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            backend=backend,\n            **kwargs,\n        )\n        self.class_names = list(self._model.class_names)\n\n    @property\n    def class_map(self):\n        # match segment.roboflow.com\n        return {str(k): v for k, v in enumerate(self.class_names)}\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        pre_processing_overrides = PreProcessingOverrides(\n            disable_contrast_enhancement=kwargs.get(\"disable_preproc_contrast\", False),\n            disable_grayscale=kwargs.get(\"disable_preproc_grayscale\", False),\n            disable_static_crop=kwargs.get(\"disable_preproc_static_crop\", False),\n        )\n        kwargs[\"pre_processing_overrides\"] = pre_processing_overrides\n        return kwargs\n\n    def preprocess(self, image: Any, **kwargs):\n        is_batch = isinstance(image, list)\n        images = image if is_batch else [image]\n        np_images: List[np.ndarray] = [\n            load_image_bgr(\n                v,\n                disable_preproc_auto_orient=kwargs.get(\n                    \"disable_preproc_auto_orient\", False\n                ),\n            )\n            for v in images\n        ]\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.pre_process(np_images, **mapped_kwargs)\n\n    def predict(self, img_in, **kwargs):\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.forward(img_in, **mapped_kwargs)\n\n    def postprocess(\n        self,\n        predictions: torch.Tensor,\n        preprocess_return_metadata: PreprocessingMetadata,\n        **kwargs,\n    ) -> List[SemanticSegmentationInferenceResponse]:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        segmentation_results = self._model.post_process(\n            predictions, preprocess_return_metadata, **mapped_kwargs\n        )\n\n        responses: List[SemanticSegmentationInferenceResponse] = []\n        for preproc_metadata, segmentation in zip(\n            preprocess_return_metadata, segmentation_results\n        ):\n            height = preproc_metadata.original_size.height\n            width = preproc_metadata.original_size.width\n            response_image = InferenceResponseImage(width=width, height=height)\n            # WARNING! This way of conversion is hazardous - first of all, if background class is not in class names,\n            # for certain pre-processing, we end up with -1 values which will be wrapped to 255 - second of all,\n            # we can support only 256 classes - those constraints should be fine until inference 2.0\n            response_predictions = SemanticSegmentationPrediction(\n                segmentation_mask=self.img_to_b64_str(\n                    segmentation.segmentation_map.to(torch.uint8)\n                ),\n                confidence_mask=self.img_to_b64_str(\n                    (segmentation.confidence * 255).to(torch.uint8)\n                ),\n                class_map=self.class_map,\n                image=dict(response_image),\n            )\n            response = SemanticSegmentationInferenceResponse(\n                predictions=response_predictions,\n                image=response_image,\n            )\n            responses.append(response)\n        return responses\n\n    def clear_cache(self, delete_from_disk: bool = True) -> None:\n        \"\"\"Clears any cache if necessary. TODO: Implement this to delete the cache from the experimental model.\n\n        Args:\n            delete_from_disk (bool, optional): Whether to delete cached files from disk. Defaults to True.\n        \"\"\"\n        pass\n\n    def img_to_b64_str(self, img: torch.Tensor) -> str:\n        if img.dtype != torch.uint8:\n            raise ValueError(\n                f\"img_to_b64_str requires uint8 tensor but got dtype {img.dtype}\"\n            )\n\n        img = Image.fromarray(img.cpu().numpy())\n        buffered = io.BytesIO()\n        img.save(buffered, format=\"PNG\")\n\n        img_str = base64.b64encode(buffered.getvalue())\n        img_str = img_str.decode(\"ascii\")\n\n        return img_str\n\n    def draw_predictions(\n        self,\n        inference_request: InferenceRequest,\n        inference_response: InferenceResponse,\n    ) -> bytes:\n        raise NotImplementedError(\n            \"draw_predictions(...) is not implemented for semantic segmentation models - responses contain \"\n            \"visualization already.\"\n        )\n",
    "patch": null
  },
  {
    "trace_id": "008c8c5d-317f-4a48-8d15-114823387469",
    "function_name": "serialise_sv_detections",
    "file_path": "inference/core/workflows/core_steps/common/serializers.py",
    "speedup_x": 0.19,
    "review_quality": "high",
    "pre_optimization_commit": "0252251cb80688cc86e37b908dbdde62e01f22c6",
    "resolution_method": "db_code_match",
    "source": "db_events",
    "original_function_code": "def serialise_sv_detections(detections: sv.Detections) -> dict:\n    serialized_detections = []\n    image_dimensions = None\n    for xyxy, mask, confidence, class_id, tracker_id, data in detections:\n        detection_dict = {}\n        image_dimensions = data.get(IMAGE_DIMENSIONS_KEY)\n        if isinstance(xyxy, np.ndarray):\n            xyxy = xyxy.astype(float).tolist()\n        x1, y1, x2, y2 = xyxy\n        detection_dict[WIDTH_KEY] = abs(x2 - x1)\n        detection_dict[HEIGHT_KEY] = abs(y2 - y1)\n        detection_dict[X_KEY] = x1 + detection_dict[WIDTH_KEY] / 2\n        detection_dict[Y_KEY] = y1 + detection_dict[HEIGHT_KEY] / 2\n\n        detection_dict[CONFIDENCE_KEY] = float(confidence)\n        detection_dict[CLASS_ID_KEY] = int(class_id)\n        if mask is not None:\n            if (\n                POLYGON_KEY_IN_SV_DETECTIONS in data\n                and data[POLYGON_KEY_IN_SV_DETECTIONS] is not None\n                and len(data[POLYGON_KEY_IN_SV_DETECTIONS]) > 2\n            ):\n                polygon = data[POLYGON_KEY_IN_SV_DETECTIONS]\n            else:\n                polygon = mask_to_polygon(mask=mask)\n            if polygon is None:\n                # ignoring the whole instance\n                continue\n            detection_dict[POLYGON_KEY] = []\n            for x, y in polygon:\n                detection_dict[POLYGON_KEY].append(\n                    {\n                        X_KEY: float(x),\n                        Y_KEY: float(y),\n                    }\n                )\n        if tracker_id is not None:\n            detection_dict[TRACKER_ID_KEY] = int(tracker_id)\n        detection_dict[CLASS_NAME_KEY] = str(data[\"class_name\"])\n        detection_dict[DETECTION_ID_KEY] = str(data[DETECTION_ID_KEY])\n        if PATH_DEVIATION_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[PATH_DEVIATION_KEY_IN_INFERENCE_RESPONSE] = data[\n                PATH_DEVIATION_KEY_IN_SV_DETECTIONS\n            ]\n        if TIME_IN_ZONE_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[TIME_IN_ZONE_KEY_IN_INFERENCE_RESPONSE] = data[\n                TIME_IN_ZONE_KEY_IN_SV_DETECTIONS\n            ]\n        if POLYGON_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[POLYGON_KEY_IN_INFERENCE_RESPONSE] = (\n                data[POLYGON_KEY_IN_SV_DETECTIONS]\n                .astype(float)\n                .round()\n                .astype(int)\n                .tolist()\n            )\n        if (\n            BOUNDING_RECT_ANGLE_KEY_IN_SV_DETECTIONS in data\n            and BOUNDING_RECT_RECT_KEY_IN_SV_DETECTIONS in data\n            and BOUNDING_RECT_HEIGHT_KEY_IN_SV_DETECTIONS in data\n            and BOUNDING_RECT_WIDTH_KEY_IN_SV_DETECTIONS in data\n        ):\n            detection_dict[BOUNDING_RECT_ANGLE_KEY_IN_INFERENCE_RESPONSE] = data[\n                BOUNDING_RECT_ANGLE_KEY_IN_SV_DETECTIONS\n            ]\n            detection_dict[BOUNDING_RECT_RECT_KEY_IN_INFERENCE_RESPONSE] = data[\n                BOUNDING_RECT_RECT_KEY_IN_SV_DETECTIONS\n            ]\n            detection_dict[BOUNDING_RECT_HEIGHT_KEY_IN_INFERENCE_RESPONSE] = data[\n                BOUNDING_RECT_HEIGHT_KEY_IN_SV_DETECTIONS\n            ]\n            detection_dict[BOUNDING_RECT_WIDTH_KEY_IN_INFERENCE_RESPONSE] = data[\n                BOUNDING_RECT_WIDTH_KEY_IN_SV_DETECTIONS\n            ]\n\n        if PARENT_ID_KEY in data:\n            detection_dict[PARENT_ID_KEY] = str(data[PARENT_ID_KEY])\n\n        # Add parent origin metadata if detection is based on a crop/slice\n        if (\n            PARENT_ID_KEY in data\n            and ROOT_PARENT_ID_KEY in data\n            and str(data[PARENT_ID_KEY]) != str(data[ROOT_PARENT_ID_KEY])\n        ):\n            _attach_parent_metadata_to_detection_dict(\n                detection_dict=detection_dict,\n                data=data,\n                coordinates_key=PARENT_COORDINATES_KEY,\n                dimensions_key=PARENT_DIMENSIONS_KEY,\n                origin_key=PARENT_ORIGIN_KEY,\n            )\n\n            detection_dict[ROOT_PARENT_ID_KEY] = str(data[ROOT_PARENT_ID_KEY])\n\n            _attach_parent_metadata_to_detection_dict(\n                detection_dict=detection_dict,\n                data=data,\n                coordinates_key=ROOT_PARENT_COORDINATES_KEY,\n                dimensions_key=ROOT_PARENT_DIMENSIONS_KEY,\n                origin_key=ROOT_PARENT_ORIGIN_KEY,\n            )\n\n        if (\n            KEYPOINTS_CLASS_ID_KEY_IN_SV_DETECTIONS in data\n            and KEYPOINTS_CLASS_NAME_KEY_IN_SV_DETECTIONS in data\n            and KEYPOINTS_CONFIDENCE_KEY_IN_SV_DETECTIONS in data\n            and KEYPOINTS_XY_KEY_IN_SV_DETECTIONS in data\n        ):\n            kp_class_id = data[KEYPOINTS_CLASS_ID_KEY_IN_SV_DETECTIONS]\n            kp_class_name = data[KEYPOINTS_CLASS_NAME_KEY_IN_SV_DETECTIONS]\n            kp_confidence = data[KEYPOINTS_CONFIDENCE_KEY_IN_SV_DETECTIONS]\n            kp_xy = data[KEYPOINTS_XY_KEY_IN_SV_DETECTIONS]\n            detection_dict[KEYPOINTS_KEY_IN_INFERENCE_RESPONSE] = []\n            for (\n                keypoint_class_id,\n                keypoint_class_name,\n                keypoint_confidence,\n                (x, y),\n            ) in zip(kp_class_id, kp_class_name, kp_confidence, kp_xy):\n                detection_dict[KEYPOINTS_KEY_IN_INFERENCE_RESPONSE].append(\n                    {\n                        \"class_id\": int(keypoint_class_id),\n                        \"class\": str(keypoint_class_name),\n                        \"confidence\": float(keypoint_confidence),\n                        \"x\": float(x),\n                        \"y\": float(y),\n                    }\n                )\n        if DETECTED_CODE_KEY in data:\n            detection_dict[DETECTED_CODE_KEY] = data[DETECTED_CODE_KEY]\n        if VELOCITY_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[VELOCITY_KEY_IN_INFERENCE_RESPONSE] = data[\n                VELOCITY_KEY_IN_SV_DETECTIONS\n            ].tolist()\n        if SPEED_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[SPEED_KEY_IN_INFERENCE_RESPONSE] = data[\n                SPEED_KEY_IN_SV_DETECTIONS\n            ].astype(float)\n        if SMOOTHED_VELOCITY_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[SMOOTHED_VELOCITY_KEY_IN_INFERENCE_RESPONSE] = data[\n                SMOOTHED_VELOCITY_KEY_IN_SV_DETECTIONS\n            ].tolist()\n        if SMOOTHED_SPEED_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[SMOOTHED_SPEED_KEY_IN_INFERENCE_RESPONSE] = data[\n                SMOOTHED_SPEED_KEY_IN_SV_DETECTIONS\n            ].astype(float)\n        if AREA_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[AREA_KEY_IN_INFERENCE_RESPONSE] = float(\n                data[AREA_KEY_IN_SV_DETECTIONS]\n            )\n        if AREA_CONVERTED_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[AREA_CONVERTED_KEY_IN_INFERENCE_RESPONSE] = float(\n                data[AREA_CONVERTED_KEY_IN_SV_DETECTIONS]\n            )\n        serialized_detections.append(detection_dict)\n    image_metadata = {\n        \"width\": None,\n        \"height\": None,\n    }  # TODO: this breaks the contract of\n    # standard inference, but to fix that problem, we would need sv.Detections to provide\n    # detection-level metadata.\n    if image_dimensions is not None:\n        image_metadata = {\n            \"width\": image_dimensions[1].item(),\n            \"height\": image_dimensions[0].item(),\n        }\n    return {\"image\": image_metadata, \"predictions\": serialized_detections}\n",
    "optimized_function_code": "from typing import Dict, Optional, Union\n\nimport cv2\nimport numpy as np\nimport supervision as sv\nfrom inference.core import logger\nfrom inference.core.workflows.execution_engine.constants import (\n    AREA_CONVERTED_KEY_IN_INFERENCE_RESPONSE,\n    AREA_CONVERTED_KEY_IN_SV_DETECTIONS, AREA_KEY_IN_INFERENCE_RESPONSE,\n    AREA_KEY_IN_SV_DETECTIONS, BOUNDING_RECT_ANGLE_KEY_IN_INFERENCE_RESPONSE,\n    BOUNDING_RECT_ANGLE_KEY_IN_SV_DETECTIONS,\n    BOUNDING_RECT_HEIGHT_KEY_IN_INFERENCE_RESPONSE,\n    BOUNDING_RECT_HEIGHT_KEY_IN_SV_DETECTIONS,\n    BOUNDING_RECT_RECT_KEY_IN_INFERENCE_RESPONSE,\n    BOUNDING_RECT_RECT_KEY_IN_SV_DETECTIONS,\n    BOUNDING_RECT_WIDTH_KEY_IN_INFERENCE_RESPONSE,\n    BOUNDING_RECT_WIDTH_KEY_IN_SV_DETECTIONS, CLASS_ID_KEY, CLASS_NAME_KEY,\n    CONFIDENCE_KEY, DETECTED_CODE_KEY, DETECTION_ID_KEY, HEIGHT_KEY,\n    IMAGE_DIMENSIONS_KEY, KEYPOINTS_CLASS_ID_KEY_IN_SV_DETECTIONS,\n    KEYPOINTS_CLASS_NAME_KEY_IN_SV_DETECTIONS,\n    KEYPOINTS_CONFIDENCE_KEY_IN_SV_DETECTIONS,\n    KEYPOINTS_KEY_IN_INFERENCE_RESPONSE)\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as _KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as __KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as ___KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as ____KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as _____KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as ______KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as _______KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as ________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as _________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as __________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as ___________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as ____________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as _____________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as ______________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as _______________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as ________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as _________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as __________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as ___________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as ____________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as _____________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as ______________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as _______________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as ________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as _________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as __________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as ___________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as ____________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as _____________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as ______________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as _______________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as ________________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as _________________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as \\\n    __________________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as \\\n    ___________________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as \\\n    ____________________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as \\\n    _____________________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as \\\n    ______________________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as \\\n    _______________________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as \\\n    ________________________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as \\\n    _________________________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as \\\n    __________________________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as \\\n    ___________________________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as \\\n    ____________________________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as \\\n    _____________________________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as \\\n    ______________________________________________KP_XY\nfrom inference.core.workflows.execution_engine.entities.base import \\\n    ParentOrigin\n\nMIN_POLYGON_POINT_COUNT = 3\n\n\ndef serialise_sv_detections(detections: sv.Detections) -> dict:\n    serialized_detections = []\n    image_dimensions = None\n    for xyxy, mask, confidence, class_id, tracker_id, data in detections:\n        detection_dict = {}\n        image_dimensions = data.get(IMAGE_DIMENSIONS_KEY)\n\n        # Avoid creating an intermediate Python list from a numpy array:\n        # cast coordinates directly to float scalars.\n        try:\n            # This will work for sequences (lists/tuples) and numpy arrays via indexing.\n            x1 = float(xyxy[0])\n            y1 = float(xyxy[1])\n            x2 = float(xyxy[2])\n            y2 = float(xyxy[3])\n        except Exception:\n            # Fall back to original behavior if indexing fails (keeps behavior identical).\n            if isinstance(xyxy, np.ndarray):\n                xyxy = xyxy.astype(float).tolist()\n            x1, y1, x2, y2 = xyxy  # type: ignore[assignment]\n\n        detection_dict[WIDTH_KEY] = abs(x2 - x1)\n        detection_dict[HEIGHT_KEY] = abs(y2 - y1)\n        detection_dict[X_KEY] = x1 + detection_dict[WIDTH_KEY] / 2\n        detection_dict[Y_KEY] = y1 + detection_dict[HEIGHT_KEY] / 2\n\n        detection_dict[CONFIDENCE_KEY] = float(confidence)\n        detection_dict[CLASS_ID_KEY] = int(class_id)\n        if mask is not None:\n            poly_in_data = data.get(POLYGON_KEY_IN_SV_DETECTIONS)\n            if (\n                poly_in_data is not None\n                and not isinstance(poly_in_data, type(None))\n                and len(poly_in_data) > 2\n            ):\n                polygon = poly_in_data\n            else:\n                polygon = mask_to_polygon(mask=mask)\n            if polygon is None:\n                # ignoring the whole instance\n                continue\n            # Build polygon list via comprehension to avoid repeated append calls.\n            detection_dict[POLYGON_KEY] = [\n                {X_KEY: float(x), Y_KEY: float(y)} for x, y in polygon\n            ]\n        if tracker_id is not None:\n            detection_dict[TRACKER_ID_KEY] = int(tracker_id)\n        detection_dict[CLASS_NAME_KEY] = str(data[\"class_name\"])\n        detection_dict[DETECTION_ID_KEY] = str(data[DETECTION_ID_KEY])\n        if PATH_DEVIATION_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[PATH_DEVIATION_KEY_IN_INFERENCE_RESPONSE] = data[\n                PATH_DEVIATION_KEY_IN_SV_DETECTIONS\n            ]\n        if TIME_IN_ZONE_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[TIME_IN_ZONE_KEY_IN_INFERENCE_RESPONSE] = data[\n                TIME_IN_ZONE_KEY_IN_SV_DETECTIONS\n            ]\n        if POLYGON_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[POLYGON_KEY_IN_INFERENCE_RESPONSE] = (\n                data[POLYGON_KEY_IN_SV_DETECTIONS]\n                .astype(float)\n                .round()\n                .astype(int)\n                .tolist()\n            )\n        if (\n            BOUNDING_RECT_ANGLE_KEY_IN_SV_DETECTIONS in data\n            and BOUNDING_RECT_RECT_KEY_IN_SV_DETECTIONS in data\n            and BOUNDING_RECT_HEIGHT_KEY_IN_SV_DETECTIONS in data\n            and BOUNDING_RECT_WIDTH_KEY_IN_SV_DETECTIONS in data\n        ):\n            detection_dict[BOUNDING_RECT_ANGLE_KEY_IN_INFERENCE_RESPONSE] = data[\n                BOUNDING_RECT_ANGLE_KEY_IN_SV_DETECTIONS\n            ]\n            detection_dict[BOUNDING_RECT_RECT_KEY_IN_INFERENCE_RESPONSE] = data[\n                BOUNDING_RECT_RECT_KEY_IN_SV_DETECTIONS\n            ]\n            detection_dict[BOUNDING_RECT_HEIGHT_KEY_IN_INFERENCE_RESPONSE] = data[\n                BOUNDING_RECT_HEIGHT_KEY_IN_SV_DETECTIONS\n            ]\n            detection_dict[BOUNDING_RECT_WIDTH_KEY_IN_INFERENCE_RESPONSE] = data[\n                BOUNDING_RECT_WIDTH_KEY_IN_SV_DETECTIONS\n            ]\n\n        if PARENT_ID_KEY in data:\n            detection_dict[PARENT_ID_KEY] = str(data[PARENT_ID_KEY])\n\n        # Add parent origin metadata if detection is based on a crop/slice\n        if (\n            PARENT_ID_KEY in data\n            and ROOT_PARENT_ID_KEY in data\n            and str(data[PARENT_ID_KEY]) != str(data[ROOT_PARENT_ID_KEY])\n        ):\n            _attach_parent_metadata_to_detection_dict(\n                detection_dict=detection_dict,\n                data=data,\n                coordinates_key=PARENT_COORDINATES_KEY,\n                dimensions_key=PARENT_DIMENSIONS_KEY,\n                origin_key=PARENT_ORIGIN_KEY,\n            )\n\n            detection_dict[ROOT_PARENT_ID_KEY] = str(data[ROOT_PARENT_ID_KEY])\n\n            _attach_parent_metadata_to_detection_dict(\n                detection_dict=detection_dict,\n                data=data,\n                coordinates_key=ROOT_PARENT_COORDINATES_KEY,\n                dimensions_key=ROOT_PARENT_DIMENSIONS_KEY,\n                origin_key=ROOT_PARENT_ORIGIN_KEY,\n            )\n\n        if (\n            KEYPOINTS_CLASS_ID_KEY_IN_SV_DETECTIONS in data\n            and KEYPOINTS_CLASS_NAME_KEY_IN_SV_DETECTIONS in data\n            and KEYPOINTS_CONFIDENCE_KEY_IN_SV_DETECTIONS in data\n            and KEYPOINTS_XY_KEY_IN_SV_DETECTIONS in data\n        ):\n            kp_class_id = data[KEYPOINTS_CLASS_ID_KEY_IN_SV_DETECTIONS]\n            kp_class_name = data[KEYPOINTS_CLASS_NAME_KEY_IN_SV_DETECTIONS]\n            kp_confidence = data[KEYPOINTS_CONFIDENCE_KEY_IN_SV_DETECTIONS]\n            kp_xy = data[KEYPOINTS_XY_KEY_IN_SV_DETECTIONS]\n            # build keypoints list via comprehension\n            detection_dict[KEYPOINTS_KEY_IN_INFERENCE_RESPONSE] = [\n                {\n                    \"class_id\": int(keypoint_class_id),\n                    \"class\": str(keypoint_class_name),\n                    \"confidence\": float(keypoint_confidence),\n                    \"x\": float(xy[0]),\n                    \"y\": float(xy[1]),\n                }\n                for keypoint_class_id, keypoint_class_name, keypoint_confidence, xy in zip(\n                    kp_class_id, kp_class_name, kp_confidence, kp_xy\n                )\n            ]\n\n        if DETECTED_CODE_KEY in data:\n            detection_dict[DETECTED_CODE_KEY] = data[DETECTED_CODE_KEY]\n        if VELOCITY_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[VELOCITY_KEY_IN_INFERENCE_RESPONSE] = data[\n                VELOCITY_KEY_IN_SV_DETECTIONS\n            ].tolist()\n        if SPEED_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[SPEED_KEY_IN_INFERENCE_RESPONSE] = data[\n                SPEED_KEY_IN_SV_DETECTIONS\n            ].astype(float)\n        if SMOOTHED_VELOCITY_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[SMOOTHED_VELOCITY_KEY_IN_INFERENCE_RESPONSE] = data[\n                SMOOTHED_VELOCITY_KEY_IN_SV_DETECTIONS\n            ].tolist()\n        if SMOOTHED_SPEED_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[SMOOTHED_SPEED_KEY_IN_INFERENCE_RESPONSE] = data[\n                SMOOTHED_SPEED_KEY_IN_SV_DETECTIONS\n            ].astype(float)\n        if AREA_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[AREA_KEY_IN_INFERENCE_RESPONSE] = float(\n                data[AREA_KEY_IN_SV_DETECTIONS]\n            )\n        if AREA_CONVERTED_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[AREA_CONVERTED_KEY_IN_INFERENCE_RESPONSE] = float(\n                data[AREA_CONVERTED_KEY_IN_SV_DETECTIONS]\n            )\n        serialized_detections.append(detection_dict)\n    image_metadata = {\n        \"width\": None,\n        \"height\": None,\n    }  # TODO: this breaks the contract of\n    # standard inference, but to fix that problem, we would need sv.Detections to provide\n    # detection-level metadata.\n    if image_dimensions is not None:\n        image_metadata = {\n            \"width\": image_dimensions[1].item(),\n            \"height\": image_dimensions[0].item(),\n        }\n    return {\"image\": image_metadata, \"predictions\": serialized_detections}\n\n\ndef _attach_parent_metadata_to_detection_dict(\n    detection_dict: dict,\n    data: Dict[str, Union[np.ndarray, list]],\n    coordinates_key: str,\n    dimensions_key: str,\n    origin_key: str,\n) -> None:\n    if coordinates_key in data and dimensions_key in data:\n        parent_coords = data[coordinates_key]\n        parent_dims = data[dimensions_key]\n        if isinstance(parent_coords, np.ndarray):\n            parent_coords = parent_coords.astype(float).round().astype(int).tolist()\n        if isinstance(parent_dims, np.ndarray):\n            parent_dims = parent_dims.astype(float).round().astype(int).tolist()\n        detection_dict[origin_key] = ParentOrigin(\n            offset_x=parent_coords[0],\n            offset_y=parent_coords[1],\n            width=parent_dims[1],\n            height=parent_dims[0],\n        ).model_dump()\n\n\ndef mask_to_polygon(mask: np.ndarray) -> Optional[np.ndarray]:\n    # masks here should be predicted by instance segmentation\n    # model and in theory can only present SINGLE!!! shape\n    # our response schema for InstanceSegmentationPrediction\n    # (see `inference.core.entities.responses.inference.InstanceSegmentationPrediction`)\n    # FROM THE BEGINNING were allowing to serialise single polygon that belongs to mask,\n    # no hierarchy respected and multiple polygons are not taken into account\n    contours, _ = cv2.findContours(\n        # avoid an extra copy if mask is already uint8\n        mask.astype(np.uint8) if mask.dtype != np.uint8 else mask,\n        cv2.RETR_TREE,\n        cv2.CHAIN_APPROX_SIMPLE,\n    )\n    if len(contours) == 0:\n        # nothing found - instance should be rejected\n        return None\n    if len(contours) > 1:\n        logger.warning(\n            f\"Detected instance segmentation that has {len(contours)} in the mask, which by convention \"\n            \"should not happen. We are taking the first polygon to avoid exceptions, but if you see this \"\n            \"warning - it may indicate that some model producing instance segmentation result works under \"\n            \"different assumptions that models historically added into inference and that should be a signal \"\n            \"to figure out more generic representation for instance seg predictions.\"\n        )\n    contour = np.squeeze(contours[0], axis=1)\n    contour_padding = max(MIN_POLYGON_POINT_COUNT - contour.shape[0], 0)\n    if contour_padding > 0:\n        padding = np.repeat(\n            np.expand_dims(contour[-1], axis=0), repeats=contour_padding, axis=0\n        )\n        return np.append(contour, padding, axis=0)\n    return contour",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/common/serializers.py\nfrom typing import Dict, Optional, Union\n\nimport cv2\nimport numpy as np\nimport supervision as sv\nfrom inference.core import logger\nfrom inference.core.workflows.execution_engine.constants import (\n    AREA_CONVERTED_KEY_IN_INFERENCE_RESPONSE,\n    AREA_CONVERTED_KEY_IN_SV_DETECTIONS, AREA_KEY_IN_INFERENCE_RESPONSE,\n    AREA_KEY_IN_SV_DETECTIONS, BOUNDING_RECT_ANGLE_KEY_IN_INFERENCE_RESPONSE,\n    BOUNDING_RECT_ANGLE_KEY_IN_SV_DETECTIONS,\n    BOUNDING_RECT_HEIGHT_KEY_IN_INFERENCE_RESPONSE,\n    BOUNDING_RECT_HEIGHT_KEY_IN_SV_DETECTIONS,\n    BOUNDING_RECT_RECT_KEY_IN_INFERENCE_RESPONSE,\n    BOUNDING_RECT_RECT_KEY_IN_SV_DETECTIONS,\n    BOUNDING_RECT_WIDTH_KEY_IN_INFERENCE_RESPONSE,\n    BOUNDING_RECT_WIDTH_KEY_IN_SV_DETECTIONS, CLASS_ID_KEY, CLASS_NAME_KEY,\n    CONFIDENCE_KEY, DETECTED_CODE_KEY, DETECTION_ID_KEY, HEIGHT_KEY,\n    IMAGE_DIMENSIONS_KEY, KEYPOINTS_CLASS_ID_KEY_IN_SV_DETECTIONS,\n    KEYPOINTS_CLASS_NAME_KEY_IN_SV_DETECTIONS,\n    KEYPOINTS_CONFIDENCE_KEY_IN_SV_DETECTIONS,\n    KEYPOINTS_KEY_IN_INFERENCE_RESPONSE)\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as _KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as __KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as ___KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as ____KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as _____KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as ______KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as _______KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as ________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as _________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as __________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as ___________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as ____________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as _____________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as ______________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as _______________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as ________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as _________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as __________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as ___________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as ____________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as _____________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as ______________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as _______________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as ________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as _________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as __________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as ___________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as ____________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as _____________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as ______________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as _______________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as ________________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as _________________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as \\\n    __________________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as \\\n    ___________________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as \\\n    ____________________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as \\\n    _____________________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as \\\n    ______________________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as \\\n    _______________________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as \\\n    ________________________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as \\\n    _________________________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as \\\n    __________________________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as \\\n    ___________________________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as \\\n    ____________________________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as \\\n    _____________________________________________KP_XY\nfrom inference.core.workflows.execution_engine.constants import \\\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS as \\\n    ______________________________________________KP_XY\nfrom inference.core.workflows.execution_engine.entities.base import \\\n    ParentOrigin\n\nMIN_POLYGON_POINT_COUNT = 3\n\n\ndef serialise_sv_detections(detections: sv.Detections) -> dict:\n    serialized_detections = []\n    image_dimensions = None\n    for xyxy, mask, confidence, class_id, tracker_id, data in detections:\n        detection_dict = {}\n        image_dimensions = data.get(IMAGE_DIMENSIONS_KEY)\n\n        # Avoid creating an intermediate Python list from a numpy array:\n        # cast coordinates directly to float scalars.\n        try:\n            # This will work for sequences (lists/tuples) and numpy arrays via indexing.\n            x1 = float(xyxy[0])\n            y1 = float(xyxy[1])\n            x2 = float(xyxy[2])\n            y2 = float(xyxy[3])\n        except Exception:\n            # Fall back to original behavior if indexing fails (keeps behavior identical).\n            if isinstance(xyxy, np.ndarray):\n                xyxy = xyxy.astype(float).tolist()\n            x1, y1, x2, y2 = xyxy  # type: ignore[assignment]\n\n        detection_dict[WIDTH_KEY] = abs(x2 - x1)\n        detection_dict[HEIGHT_KEY] = abs(y2 - y1)\n        detection_dict[X_KEY] = x1 + detection_dict[WIDTH_KEY] / 2\n        detection_dict[Y_KEY] = y1 + detection_dict[HEIGHT_KEY] / 2\n\n        detection_dict[CONFIDENCE_KEY] = float(confidence)\n        detection_dict[CLASS_ID_KEY] = int(class_id)\n        if mask is not None:\n            poly_in_data = data.get(POLYGON_KEY_IN_SV_DETECTIONS)\n            if (\n                poly_in_data is not None\n                and not isinstance(poly_in_data, type(None))\n                and len(poly_in_data) > 2\n            ):\n                polygon = poly_in_data\n            else:\n                polygon = mask_to_polygon(mask=mask)\n            if polygon is None:\n                # ignoring the whole instance\n                continue\n            # Build polygon list via comprehension to avoid repeated append calls.\n            detection_dict[POLYGON_KEY] = [\n                {X_KEY: float(x), Y_KEY: float(y)} for x, y in polygon\n            ]\n        if tracker_id is not None:\n            detection_dict[TRACKER_ID_KEY] = int(tracker_id)\n        detection_dict[CLASS_NAME_KEY] = str(data[\"class_name\"])\n        detection_dict[DETECTION_ID_KEY] = str(data[DETECTION_ID_KEY])\n        if PATH_DEVIATION_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[PATH_DEVIATION_KEY_IN_INFERENCE_RESPONSE] = data[\n                PATH_DEVIATION_KEY_IN_SV_DETECTIONS\n            ]\n        if TIME_IN_ZONE_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[TIME_IN_ZONE_KEY_IN_INFERENCE_RESPONSE] = data[\n                TIME_IN_ZONE_KEY_IN_SV_DETECTIONS\n            ]\n        if POLYGON_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[POLYGON_KEY_IN_INFERENCE_RESPONSE] = (\n                data[POLYGON_KEY_IN_SV_DETECTIONS]\n                .astype(float)\n                .round()\n                .astype(int)\n                .tolist()\n            )\n        if (\n            BOUNDING_RECT_ANGLE_KEY_IN_SV_DETECTIONS in data\n            and BOUNDING_RECT_RECT_KEY_IN_SV_DETECTIONS in data\n            and BOUNDING_RECT_HEIGHT_KEY_IN_SV_DETECTIONS in data\n            and BOUNDING_RECT_WIDTH_KEY_IN_SV_DETECTIONS in data\n        ):\n            detection_dict[BOUNDING_RECT_ANGLE_KEY_IN_INFERENCE_RESPONSE] = data[\n                BOUNDING_RECT_ANGLE_KEY_IN_SV_DETECTIONS\n            ]\n            detection_dict[BOUNDING_RECT_RECT_KEY_IN_INFERENCE_RESPONSE] = data[\n                BOUNDING_RECT_RECT_KEY_IN_SV_DETECTIONS\n            ]\n            detection_dict[BOUNDING_RECT_HEIGHT_KEY_IN_INFERENCE_RESPONSE] = data[\n                BOUNDING_RECT_HEIGHT_KEY_IN_SV_DETECTIONS\n            ]\n            detection_dict[BOUNDING_RECT_WIDTH_KEY_IN_INFERENCE_RESPONSE] = data[\n                BOUNDING_RECT_WIDTH_KEY_IN_SV_DETECTIONS\n            ]\n\n        if PARENT_ID_KEY in data:\n            detection_dict[PARENT_ID_KEY] = str(data[PARENT_ID_KEY])\n\n        # Add parent origin metadata if detection is based on a crop/slice\n        if (\n            PARENT_ID_KEY in data\n            and ROOT_PARENT_ID_KEY in data\n            and str(data[PARENT_ID_KEY]) != str(data[ROOT_PARENT_ID_KEY])\n        ):\n            _attach_parent_metadata_to_detection_dict(\n                detection_dict=detection_dict,\n                data=data,\n                coordinates_key=PARENT_COORDINATES_KEY,\n                dimensions_key=PARENT_DIMENSIONS_KEY,\n                origin_key=PARENT_ORIGIN_KEY,\n            )\n\n            detection_dict[ROOT_PARENT_ID_KEY] = str(data[ROOT_PARENT_ID_KEY])\n\n            _attach_parent_metadata_to_detection_dict(\n                detection_dict=detection_dict,\n                data=data,\n                coordinates_key=ROOT_PARENT_COORDINATES_KEY,\n                dimensions_key=ROOT_PARENT_DIMENSIONS_KEY,\n                origin_key=ROOT_PARENT_ORIGIN_KEY,\n            )\n\n        if (\n            KEYPOINTS_CLASS_ID_KEY_IN_SV_DETECTIONS in data\n            and KEYPOINTS_CLASS_NAME_KEY_IN_SV_DETECTIONS in data\n            and KEYPOINTS_CONFIDENCE_KEY_IN_SV_DETECTIONS in data\n            and KEYPOINTS_XY_KEY_IN_SV_DETECTIONS in data\n        ):\n            kp_class_id = data[KEYPOINTS_CLASS_ID_KEY_IN_SV_DETECTIONS]\n            kp_class_name = data[KEYPOINTS_CLASS_NAME_KEY_IN_SV_DETECTIONS]\n            kp_confidence = data[KEYPOINTS_CONFIDENCE_KEY_IN_SV_DETECTIONS]\n            kp_xy = data[KEYPOINTS_XY_KEY_IN_SV_DETECTIONS]\n            # build keypoints list via comprehension\n            detection_dict[KEYPOINTS_KEY_IN_INFERENCE_RESPONSE] = [\n                {\n                    \"class_id\": int(keypoint_class_id),\n                    \"class\": str(keypoint_class_name),\n                    \"confidence\": float(keypoint_confidence),\n                    \"x\": float(xy[0]),\n                    \"y\": float(xy[1]),\n                }\n                for keypoint_class_id, keypoint_class_name, keypoint_confidence, xy in zip(\n                    kp_class_id, kp_class_name, kp_confidence, kp_xy\n                )\n            ]\n\n        if DETECTED_CODE_KEY in data:\n            detection_dict[DETECTED_CODE_KEY] = data[DETECTED_CODE_KEY]\n        if VELOCITY_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[VELOCITY_KEY_IN_INFERENCE_RESPONSE] = data[\n                VELOCITY_KEY_IN_SV_DETECTIONS\n            ].tolist()\n        if SPEED_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[SPEED_KEY_IN_INFERENCE_RESPONSE] = data[\n                SPEED_KEY_IN_SV_DETECTIONS\n            ].astype(float)\n        if SMOOTHED_VELOCITY_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[SMOOTHED_VELOCITY_KEY_IN_INFERENCE_RESPONSE] = data[\n                SMOOTHED_VELOCITY_KEY_IN_SV_DETECTIONS\n            ].tolist()\n        if SMOOTHED_SPEED_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[SMOOTHED_SPEED_KEY_IN_INFERENCE_RESPONSE] = data[\n                SMOOTHED_SPEED_KEY_IN_SV_DETECTIONS\n            ].astype(float)\n        if AREA_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[AREA_KEY_IN_INFERENCE_RESPONSE] = float(\n                data[AREA_KEY_IN_SV_DETECTIONS]\n            )\n        if AREA_CONVERTED_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[AREA_CONVERTED_KEY_IN_INFERENCE_RESPONSE] = float(\n                data[AREA_CONVERTED_KEY_IN_SV_DETECTIONS]\n            )\n        serialized_detections.append(detection_dict)\n    image_metadata = {\n        \"width\": None,\n        \"height\": None,\n    }  # TODO: this breaks the contract of\n    # standard inference, but to fix that problem, we would need sv.Detections to provide\n    # detection-level metadata.\n    if image_dimensions is not None:\n        image_metadata = {\n            \"width\": image_dimensions[1].item(),\n            \"height\": image_dimensions[0].item(),\n        }\n    return {\"image\": image_metadata, \"predictions\": serialized_detections}\n\n\ndef _attach_parent_metadata_to_detection_dict(\n    detection_dict: dict,\n    data: Dict[str, Union[np.ndarray, list]],\n    coordinates_key: str,\n    dimensions_key: str,\n    origin_key: str,\n) -> None:\n    if coordinates_key in data and dimensions_key in data:\n        parent_coords = data[coordinates_key]\n        parent_dims = data[dimensions_key]\n        if isinstance(parent_coords, np.ndarray):\n            parent_coords = parent_coords.astype(float).round().astype(int).tolist()\n        if isinstance(parent_dims, np.ndarray):\n            parent_dims = parent_dims.astype(float).round().astype(int).tolist()\n        detection_dict[origin_key] = ParentOrigin(\n            offset_x=parent_coords[0],\n            offset_y=parent_coords[1],\n            width=parent_dims[1],\n            height=parent_dims[0],\n        ).model_dump()\n\n\ndef mask_to_polygon(mask: np.ndarray) -> Optional[np.ndarray]:\n    # masks here should be predicted by instance segmentation\n    # model and in theory can only present SINGLE!!! shape\n    # our response schema for InstanceSegmentationPrediction\n    # (see `inference.core.entities.responses.inference.InstanceSegmentationPrediction`)\n    # FROM THE BEGINNING were allowing to serialise single polygon that belongs to mask,\n    # no hierarchy respected and multiple polygons are not taken into account\n    contours, _ = cv2.findContours(\n        # avoid an extra copy if mask is already uint8\n        mask.astype(np.uint8) if mask.dtype != np.uint8 else mask,\n        cv2.RETR_TREE,\n        cv2.CHAIN_APPROX_SIMPLE,\n    )\n    if len(contours) == 0:\n        # nothing found - instance should be rejected\n        return None\n    if len(contours) > 1:\n        logger.warning(\n            f\"Detected instance segmentation that has {len(contours)} in the mask, which by convention \"\n            \"should not happen. We are taking the first polygon to avoid exceptions, but if you see this \"\n            \"warning - it may indicate that some model producing instance segmentation result works under \"\n            \"different assumptions that models historically added into inference and that should be a signal \"\n            \"to figure out more generic representation for instance seg predictions.\"\n        )\n    contour = np.squeeze(contours[0], axis=1)\n    contour_padding = max(MIN_POLYGON_POINT_COUNT - contour.shape[0], 0)\n    if contour_padding > 0:\n        padding = np.repeat(\n            np.expand_dims(contour[-1], axis=0), repeats=contour_padding, axis=0\n        )\n        return np.append(contour, padding, axis=0)\n    return contour\n```",
    "optimized_function_only": "def serialise_sv_detections(detections: sv.Detections) -> dict:\n    serialized_detections = []\n    image_dimensions = None\n    for xyxy, mask, confidence, class_id, tracker_id, data in detections:\n        detection_dict = {}\n        image_dimensions = data.get(IMAGE_DIMENSIONS_KEY)\n\n        # Avoid creating an intermediate Python list from a numpy array:\n        # cast coordinates directly to float scalars.\n        try:\n            # This will work for sequences (lists/tuples) and numpy arrays via indexing.\n            x1 = float(xyxy[0])\n            y1 = float(xyxy[1])\n            x2 = float(xyxy[2])\n            y2 = float(xyxy[3])\n        except Exception:\n            # Fall back to original behavior if indexing fails (keeps behavior identical).\n            if isinstance(xyxy, np.ndarray):\n                xyxy = xyxy.astype(float).tolist()\n            x1, y1, x2, y2 = xyxy  # type: ignore[assignment]\n\n        detection_dict[WIDTH_KEY] = abs(x2 - x1)\n        detection_dict[HEIGHT_KEY] = abs(y2 - y1)\n        detection_dict[X_KEY] = x1 + detection_dict[WIDTH_KEY] / 2\n        detection_dict[Y_KEY] = y1 + detection_dict[HEIGHT_KEY] / 2\n\n        detection_dict[CONFIDENCE_KEY] = float(confidence)\n        detection_dict[CLASS_ID_KEY] = int(class_id)\n        if mask is not None:\n            poly_in_data = data.get(POLYGON_KEY_IN_SV_DETECTIONS)\n            if (\n                poly_in_data is not None\n                and not isinstance(poly_in_data, type(None))\n                and len(poly_in_data) > 2\n            ):\n                polygon = poly_in_data\n            else:\n                polygon = mask_to_polygon(mask=mask)\n            if polygon is None:\n                # ignoring the whole instance\n                continue\n            # Build polygon list via comprehension to avoid repeated append calls.\n            detection_dict[POLYGON_KEY] = [\n                {X_KEY: float(x), Y_KEY: float(y)} for x, y in polygon\n            ]\n        if tracker_id is not None:\n            detection_dict[TRACKER_ID_KEY] = int(tracker_id)\n        detection_dict[CLASS_NAME_KEY] = str(data[\"class_name\"])\n        detection_dict[DETECTION_ID_KEY] = str(data[DETECTION_ID_KEY])\n        if PATH_DEVIATION_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[PATH_DEVIATION_KEY_IN_INFERENCE_RESPONSE] = data[\n                PATH_DEVIATION_KEY_IN_SV_DETECTIONS\n            ]\n        if TIME_IN_ZONE_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[TIME_IN_ZONE_KEY_IN_INFERENCE_RESPONSE] = data[\n                TIME_IN_ZONE_KEY_IN_SV_DETECTIONS\n            ]\n        if POLYGON_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[POLYGON_KEY_IN_INFERENCE_RESPONSE] = (\n                data[POLYGON_KEY_IN_SV_DETECTIONS]\n                .astype(float)\n                .round()\n                .astype(int)\n                .tolist()\n            )\n        if (\n            BOUNDING_RECT_ANGLE_KEY_IN_SV_DETECTIONS in data\n            and BOUNDING_RECT_RECT_KEY_IN_SV_DETECTIONS in data\n            and BOUNDING_RECT_HEIGHT_KEY_IN_SV_DETECTIONS in data\n            and BOUNDING_RECT_WIDTH_KEY_IN_SV_DETECTIONS in data\n        ):\n            detection_dict[BOUNDING_RECT_ANGLE_KEY_IN_INFERENCE_RESPONSE] = data[\n                BOUNDING_RECT_ANGLE_KEY_IN_SV_DETECTIONS\n            ]\n            detection_dict[BOUNDING_RECT_RECT_KEY_IN_INFERENCE_RESPONSE] = data[\n                BOUNDING_RECT_RECT_KEY_IN_SV_DETECTIONS\n            ]\n            detection_dict[BOUNDING_RECT_HEIGHT_KEY_IN_INFERENCE_RESPONSE] = data[\n                BOUNDING_RECT_HEIGHT_KEY_IN_SV_DETECTIONS\n            ]\n            detection_dict[BOUNDING_RECT_WIDTH_KEY_IN_INFERENCE_RESPONSE] = data[\n                BOUNDING_RECT_WIDTH_KEY_IN_SV_DETECTIONS\n            ]\n\n        if PARENT_ID_KEY in data:\n            detection_dict[PARENT_ID_KEY] = str(data[PARENT_ID_KEY])\n\n        # Add parent origin metadata if detection is based on a crop/slice\n        if (\n            PARENT_ID_KEY in data\n            and ROOT_PARENT_ID_KEY in data\n            and str(data[PARENT_ID_KEY]) != str(data[ROOT_PARENT_ID_KEY])\n        ):\n            _attach_parent_metadata_to_detection_dict(\n                detection_dict=detection_dict,\n                data=data,\n                coordinates_key=PARENT_COORDINATES_KEY,\n                dimensions_key=PARENT_DIMENSIONS_KEY,\n                origin_key=PARENT_ORIGIN_KEY,\n            )\n\n            detection_dict[ROOT_PARENT_ID_KEY] = str(data[ROOT_PARENT_ID_KEY])\n\n            _attach_parent_metadata_to_detection_dict(\n                detection_dict=detection_dict,\n                data=data,\n                coordinates_key=ROOT_PARENT_COORDINATES_KEY,\n                dimensions_key=ROOT_PARENT_DIMENSIONS_KEY,\n                origin_key=ROOT_PARENT_ORIGIN_KEY,\n            )\n\n        if (\n            KEYPOINTS_CLASS_ID_KEY_IN_SV_DETECTIONS in data\n            and KEYPOINTS_CLASS_NAME_KEY_IN_SV_DETECTIONS in data\n            and KEYPOINTS_CONFIDENCE_KEY_IN_SV_DETECTIONS in data\n            and KEYPOINTS_XY_KEY_IN_SV_DETECTIONS in data\n        ):\n            kp_class_id = data[KEYPOINTS_CLASS_ID_KEY_IN_SV_DETECTIONS]\n            kp_class_name = data[KEYPOINTS_CLASS_NAME_KEY_IN_SV_DETECTIONS]\n            kp_confidence = data[KEYPOINTS_CONFIDENCE_KEY_IN_SV_DETECTIONS]\n            kp_xy = data[KEYPOINTS_XY_KEY_IN_SV_DETECTIONS]\n            # build keypoints list via comprehension\n            detection_dict[KEYPOINTS_KEY_IN_INFERENCE_RESPONSE] = [\n                {\n                    \"class_id\": int(keypoint_class_id),\n                    \"class\": str(keypoint_class_name),\n                    \"confidence\": float(keypoint_confidence),\n                    \"x\": float(xy[0]),\n                    \"y\": float(xy[1]),\n                }\n                for keypoint_class_id, keypoint_class_name, keypoint_confidence, xy in zip(\n                    kp_class_id, kp_class_name, kp_confidence, kp_xy\n                )\n            ]\n\n        if DETECTED_CODE_KEY in data:\n            detection_dict[DETECTED_CODE_KEY] = data[DETECTED_CODE_KEY]\n        if VELOCITY_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[VELOCITY_KEY_IN_INFERENCE_RESPONSE] = data[\n                VELOCITY_KEY_IN_SV_DETECTIONS\n            ].tolist()\n        if SPEED_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[SPEED_KEY_IN_INFERENCE_RESPONSE] = data[\n                SPEED_KEY_IN_SV_DETECTIONS\n            ].astype(float)\n        if SMOOTHED_VELOCITY_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[SMOOTHED_VELOCITY_KEY_IN_INFERENCE_RESPONSE] = data[\n                SMOOTHED_VELOCITY_KEY_IN_SV_DETECTIONS\n            ].tolist()\n        if SMOOTHED_SPEED_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[SMOOTHED_SPEED_KEY_IN_INFERENCE_RESPONSE] = data[\n                SMOOTHED_SPEED_KEY_IN_SV_DETECTIONS\n            ].astype(float)\n        if AREA_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[AREA_KEY_IN_INFERENCE_RESPONSE] = float(\n                data[AREA_KEY_IN_SV_DETECTIONS]\n            )\n        if AREA_CONVERTED_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[AREA_CONVERTED_KEY_IN_INFERENCE_RESPONSE] = float(\n                data[AREA_CONVERTED_KEY_IN_SV_DETECTIONS]\n            )\n        serialized_detections.append(detection_dict)\n    image_metadata = {\n        \"width\": None,\n        \"height\": None,\n    }  # TODO: this breaks the contract of\n    # standard inference, but to fix that problem, we would need sv.Detections to provide\n    # detection-level metadata.\n    if image_dimensions is not None:\n        image_metadata = {\n            \"width\": image_dimensions[1].item(),\n            \"height\": image_dimensions[0].item(),\n        }\n    return {\"image\": image_metadata, \"predictions\": serialized_detections}\n",
    "original_file_content": "from datetime import datetime\nfrom typing import Any, Dict, List, Optional, Union\n\nimport cv2\nimport numpy as np\nimport supervision as sv\n\nfrom inference.core import logger\nfrom inference.core.workflows.execution_engine.constants import (\n    AREA_CONVERTED_KEY_IN_INFERENCE_RESPONSE,\n    AREA_CONVERTED_KEY_IN_SV_DETECTIONS,\n    AREA_KEY_IN_INFERENCE_RESPONSE,\n    AREA_KEY_IN_SV_DETECTIONS,\n    BOUNDING_RECT_ANGLE_KEY_IN_INFERENCE_RESPONSE,\n    BOUNDING_RECT_ANGLE_KEY_IN_SV_DETECTIONS,\n    BOUNDING_RECT_HEIGHT_KEY_IN_INFERENCE_RESPONSE,\n    BOUNDING_RECT_HEIGHT_KEY_IN_SV_DETECTIONS,\n    BOUNDING_RECT_RECT_KEY_IN_INFERENCE_RESPONSE,\n    BOUNDING_RECT_RECT_KEY_IN_SV_DETECTIONS,\n    BOUNDING_RECT_WIDTH_KEY_IN_INFERENCE_RESPONSE,\n    BOUNDING_RECT_WIDTH_KEY_IN_SV_DETECTIONS,\n    CLASS_ID_KEY,\n    CLASS_NAME_KEY,\n    CONFIDENCE_KEY,\n    DETECTED_CODE_KEY,\n    DETECTION_ID_KEY,\n    HEIGHT_KEY,\n    IMAGE_DIMENSIONS_KEY,\n    KEYPOINTS_CLASS_ID_KEY_IN_SV_DETECTIONS,\n    KEYPOINTS_CLASS_NAME_KEY_IN_SV_DETECTIONS,\n    KEYPOINTS_CONFIDENCE_KEY_IN_SV_DETECTIONS,\n    KEYPOINTS_KEY_IN_INFERENCE_RESPONSE,\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS,\n    PARENT_COORDINATES_KEY,\n    PARENT_DIMENSIONS_KEY,\n    PARENT_ID_KEY,\n    PARENT_ORIGIN_KEY,\n    PATH_DEVIATION_KEY_IN_INFERENCE_RESPONSE,\n    PATH_DEVIATION_KEY_IN_SV_DETECTIONS,\n    POLYGON_KEY,\n    POLYGON_KEY_IN_INFERENCE_RESPONSE,\n    POLYGON_KEY_IN_SV_DETECTIONS,\n    RLE_MASK_KEY_IN_INFERENCE_RESPONSE,\n    RLE_MASK_KEY_IN_SV_DETECTIONS,\n    ROOT_PARENT_COORDINATES_KEY,\n    ROOT_PARENT_DIMENSIONS_KEY,\n    ROOT_PARENT_ID_KEY,\n    ROOT_PARENT_ORIGIN_KEY,\n    SMOOTHED_SPEED_KEY_IN_INFERENCE_RESPONSE,\n    SMOOTHED_SPEED_KEY_IN_SV_DETECTIONS,\n    SMOOTHED_VELOCITY_KEY_IN_INFERENCE_RESPONSE,\n    SMOOTHED_VELOCITY_KEY_IN_SV_DETECTIONS,\n    SPEED_KEY_IN_INFERENCE_RESPONSE,\n    SPEED_KEY_IN_SV_DETECTIONS,\n    TIME_IN_ZONE_KEY_IN_INFERENCE_RESPONSE,\n    TIME_IN_ZONE_KEY_IN_SV_DETECTIONS,\n    TRACKER_ID_KEY,\n    VELOCITY_KEY_IN_INFERENCE_RESPONSE,\n    VELOCITY_KEY_IN_SV_DETECTIONS,\n    WIDTH_KEY,\n    X_KEY,\n    Y_KEY,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    ParentOrigin,\n    VideoMetadata,\n    WorkflowImageData,\n)\n\nMIN_SECRET_LENGTH_TO_REVEAL_PREFIX = 8\nMIN_POLYGON_POINT_COUNT = 3\n\n\ndef serialise_sv_detections(detections: sv.Detections) -> dict:\n    serialized_detections = []\n    image_dimensions = None\n    for xyxy, mask, confidence, class_id, tracker_id, data in detections:\n        detection_dict = {}\n        image_dimensions = data.get(IMAGE_DIMENSIONS_KEY)\n        if isinstance(xyxy, np.ndarray):\n            xyxy = xyxy.astype(float).tolist()\n        x1, y1, x2, y2 = xyxy\n        detection_dict[WIDTH_KEY] = abs(x2 - x1)\n        detection_dict[HEIGHT_KEY] = abs(y2 - y1)\n        detection_dict[X_KEY] = x1 + detection_dict[WIDTH_KEY] / 2\n        detection_dict[Y_KEY] = y1 + detection_dict[HEIGHT_KEY] / 2\n\n        detection_dict[CONFIDENCE_KEY] = float(confidence)\n        detection_dict[CLASS_ID_KEY] = int(class_id)\n        if mask is not None:\n            if (\n                POLYGON_KEY_IN_SV_DETECTIONS in data\n                and data[POLYGON_KEY_IN_SV_DETECTIONS] is not None\n                and len(data[POLYGON_KEY_IN_SV_DETECTIONS]) > 2\n            ):\n                polygon = data[POLYGON_KEY_IN_SV_DETECTIONS]\n            else:\n                polygon = mask_to_polygon(mask=mask)\n            if polygon is None:\n                # ignoring the whole instance\n                continue\n            detection_dict[POLYGON_KEY] = []\n            for x, y in polygon:\n                detection_dict[POLYGON_KEY].append(\n                    {\n                        X_KEY: float(x),\n                        Y_KEY: float(y),\n                    }\n                )\n        if tracker_id is not None:\n            detection_dict[TRACKER_ID_KEY] = int(tracker_id)\n        detection_dict[CLASS_NAME_KEY] = str(data[\"class_name\"])\n        detection_dict[DETECTION_ID_KEY] = str(data[DETECTION_ID_KEY])\n        if PATH_DEVIATION_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[PATH_DEVIATION_KEY_IN_INFERENCE_RESPONSE] = data[\n                PATH_DEVIATION_KEY_IN_SV_DETECTIONS\n            ]\n        if TIME_IN_ZONE_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[TIME_IN_ZONE_KEY_IN_INFERENCE_RESPONSE] = data[\n                TIME_IN_ZONE_KEY_IN_SV_DETECTIONS\n            ]\n        if POLYGON_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[POLYGON_KEY_IN_INFERENCE_RESPONSE] = (\n                data[POLYGON_KEY_IN_SV_DETECTIONS]\n                .astype(float)\n                .round()\n                .astype(int)\n                .tolist()\n            )\n        if (\n            BOUNDING_RECT_ANGLE_KEY_IN_SV_DETECTIONS in data\n            and BOUNDING_RECT_RECT_KEY_IN_SV_DETECTIONS in data\n            and BOUNDING_RECT_HEIGHT_KEY_IN_SV_DETECTIONS in data\n            and BOUNDING_RECT_WIDTH_KEY_IN_SV_DETECTIONS in data\n        ):\n            detection_dict[BOUNDING_RECT_ANGLE_KEY_IN_INFERENCE_RESPONSE] = data[\n                BOUNDING_RECT_ANGLE_KEY_IN_SV_DETECTIONS\n            ]\n            detection_dict[BOUNDING_RECT_RECT_KEY_IN_INFERENCE_RESPONSE] = data[\n                BOUNDING_RECT_RECT_KEY_IN_SV_DETECTIONS\n            ]\n            detection_dict[BOUNDING_RECT_HEIGHT_KEY_IN_INFERENCE_RESPONSE] = data[\n                BOUNDING_RECT_HEIGHT_KEY_IN_SV_DETECTIONS\n            ]\n            detection_dict[BOUNDING_RECT_WIDTH_KEY_IN_INFERENCE_RESPONSE] = data[\n                BOUNDING_RECT_WIDTH_KEY_IN_SV_DETECTIONS\n            ]\n\n        if PARENT_ID_KEY in data:\n            detection_dict[PARENT_ID_KEY] = str(data[PARENT_ID_KEY])\n\n        # Add parent origin metadata if detection is based on a crop/slice\n        if (\n            PARENT_ID_KEY in data\n            and ROOT_PARENT_ID_KEY in data\n            and str(data[PARENT_ID_KEY]) != str(data[ROOT_PARENT_ID_KEY])\n        ):\n            _attach_parent_metadata_to_detection_dict(\n                detection_dict=detection_dict,\n                data=data,\n                coordinates_key=PARENT_COORDINATES_KEY,\n                dimensions_key=PARENT_DIMENSIONS_KEY,\n                origin_key=PARENT_ORIGIN_KEY,\n            )\n\n            detection_dict[ROOT_PARENT_ID_KEY] = str(data[ROOT_PARENT_ID_KEY])\n\n            _attach_parent_metadata_to_detection_dict(\n                detection_dict=detection_dict,\n                data=data,\n                coordinates_key=ROOT_PARENT_COORDINATES_KEY,\n                dimensions_key=ROOT_PARENT_DIMENSIONS_KEY,\n                origin_key=ROOT_PARENT_ORIGIN_KEY,\n            )\n\n        if (\n            KEYPOINTS_CLASS_ID_KEY_IN_SV_DETECTIONS in data\n            and KEYPOINTS_CLASS_NAME_KEY_IN_SV_DETECTIONS in data\n            and KEYPOINTS_CONFIDENCE_KEY_IN_SV_DETECTIONS in data\n            and KEYPOINTS_XY_KEY_IN_SV_DETECTIONS in data\n        ):\n            kp_class_id = data[KEYPOINTS_CLASS_ID_KEY_IN_SV_DETECTIONS]\n            kp_class_name = data[KEYPOINTS_CLASS_NAME_KEY_IN_SV_DETECTIONS]\n            kp_confidence = data[KEYPOINTS_CONFIDENCE_KEY_IN_SV_DETECTIONS]\n            kp_xy = data[KEYPOINTS_XY_KEY_IN_SV_DETECTIONS]\n            detection_dict[KEYPOINTS_KEY_IN_INFERENCE_RESPONSE] = []\n            for (\n                keypoint_class_id,\n                keypoint_class_name,\n                keypoint_confidence,\n                (x, y),\n            ) in zip(kp_class_id, kp_class_name, kp_confidence, kp_xy):\n                detection_dict[KEYPOINTS_KEY_IN_INFERENCE_RESPONSE].append(\n                    {\n                        \"class_id\": int(keypoint_class_id),\n                        \"class\": str(keypoint_class_name),\n                        \"confidence\": float(keypoint_confidence),\n                        \"x\": float(x),\n                        \"y\": float(y),\n                    }\n                )\n        if DETECTED_CODE_KEY in data:\n            detection_dict[DETECTED_CODE_KEY] = data[DETECTED_CODE_KEY]\n        if VELOCITY_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[VELOCITY_KEY_IN_INFERENCE_RESPONSE] = data[\n                VELOCITY_KEY_IN_SV_DETECTIONS\n            ].tolist()\n        if SPEED_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[SPEED_KEY_IN_INFERENCE_RESPONSE] = data[\n                SPEED_KEY_IN_SV_DETECTIONS\n            ].astype(float)\n        if SMOOTHED_VELOCITY_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[SMOOTHED_VELOCITY_KEY_IN_INFERENCE_RESPONSE] = data[\n                SMOOTHED_VELOCITY_KEY_IN_SV_DETECTIONS\n            ].tolist()\n        if SMOOTHED_SPEED_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[SMOOTHED_SPEED_KEY_IN_INFERENCE_RESPONSE] = data[\n                SMOOTHED_SPEED_KEY_IN_SV_DETECTIONS\n            ].astype(float)\n        if AREA_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[AREA_KEY_IN_INFERENCE_RESPONSE] = float(\n                data[AREA_KEY_IN_SV_DETECTIONS]\n            )\n        if AREA_CONVERTED_KEY_IN_SV_DETECTIONS in data:\n            detection_dict[AREA_CONVERTED_KEY_IN_INFERENCE_RESPONSE] = float(\n                data[AREA_CONVERTED_KEY_IN_SV_DETECTIONS]\n            )\n        serialized_detections.append(detection_dict)\n    image_metadata = {\n        \"width\": None,\n        \"height\": None,\n    }  # TODO: this breaks the contract of\n    # standard inference, but to fix that problem, we would need sv.Detections to provide\n    # detection-level metadata.\n    if image_dimensions is not None:\n        image_metadata = {\n            \"width\": image_dimensions[1].item(),\n            \"height\": image_dimensions[0].item(),\n        }\n    return {\"image\": image_metadata, \"predictions\": serialized_detections}\n\n\ndef _attach_parent_metadata_to_detection_dict(\n    detection_dict: dict,\n    data: Dict[str, Union[np.ndarray, list]],\n    coordinates_key: str,\n    dimensions_key: str,\n    origin_key: str,\n) -> None:\n    if coordinates_key in data and dimensions_key in data:\n        parent_coords = data[coordinates_key]\n        parent_dims = data[dimensions_key]\n        if isinstance(parent_coords, np.ndarray):\n            parent_coords = parent_coords.astype(float).round().astype(int).tolist()\n        if isinstance(parent_dims, np.ndarray):\n            parent_dims = parent_dims.astype(float).round().astype(int).tolist()\n        detection_dict[origin_key] = ParentOrigin(\n            offset_x=parent_coords[0],\n            offset_y=parent_coords[1],\n            width=parent_dims[1],\n            height=parent_dims[0],\n        ).model_dump()\n\n\ndef mask_to_polygon(mask: np.ndarray) -> Optional[np.ndarray]:\n    # masks here should be predicted by instance segmentation\n    # model and in theory can only present SINGLE!!! shape\n    # our response schema for InstanceSegmentationPrediction\n    # (see `inference.core.entities.responses.inference.InstanceSegmentationPrediction`)\n    # FROM THE BEGINNING were allowing to serialise single polygon that belongs to mask,\n    # no hierarchy respected and multiple polygons are not taken into account\n    contours, _ = cv2.findContours(\n        mask.astype(np.uint8), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE\n    )\n    if len(contours) == 0:\n        # nothing found - instance should be rejected\n        return None\n    if len(contours) > 1:\n        logger.warning(\n            f\"Detected instance segmentation that has {len(contours)} in the mask, which by convention \"\n            \"should not happen. We are taking the first polygon to avoid exceptions, but if you see this \"\n            \"warning - it may indicate that some model producing instance segmentation result works under \"\n            \"different assumptions that models historically added into inference and that should be a signal \"\n            \"to figure out more generic representation for instance seg predictions.\"\n        )\n    contour = np.squeeze(contours[0], axis=1)\n    contour_padding = max(MIN_POLYGON_POINT_COUNT - contour.shape[0], 0)\n    if contour_padding > 0:\n        padding = np.repeat(\n            np.expand_dims(contour[-1], axis=0), repeats=contour_padding, axis=0\n        )\n        return np.append(contour, padding, axis=0)\n    return contour\n\n\ndef serialise_image(image: WorkflowImageData) -> Dict[str, Any]:\n    result = {\n        \"type\": \"base64\",\n        \"value\": image.base64_image,\n        \"video_metadata\": image.video_metadata.dict() if image.video_metadata else None,\n    }\n\n    parent_metadata = image.parent_metadata\n    root_metadata = image.workflow_root_ancestor_metadata\n\n    # Add parent origin metadata if image is a crop/slice\n    if parent_metadata.parent_id != root_metadata.parent_id:\n        result[PARENT_ID_KEY] = parent_metadata.parent_id\n        result[PARENT_ORIGIN_KEY] = ParentOrigin.from_origin_coordinates_system(\n            parent_metadata.origin_coordinates\n        ).model_dump()\n\n        result[ROOT_PARENT_ID_KEY] = root_metadata.parent_id\n        result[ROOT_PARENT_ORIGIN_KEY] = ParentOrigin.from_origin_coordinates_system(\n            root_metadata.origin_coordinates\n        ).model_dump()\n\n    return result\n\n\ndef serialize_video_metadata_kind(video_metadata: VideoMetadata) -> dict:\n    return video_metadata.dict()\n\n\ndef serialize_wildcard_kind(value: Any) -> Any:\n    if isinstance(value, WorkflowImageData):\n        value = serialise_image(image=value)\n    elif isinstance(value, dict):\n        value = serialize_dict(elements=value)\n    elif isinstance(value, list):\n        value = serialize_list(elements=value)\n    elif isinstance(value, sv.Detections):\n        value = serialise_sv_detections(detections=value)\n    elif isinstance(value, datetime):\n        value = serialize_timestamp(timestamp=value)\n    elif isinstance(value, np.ndarray):\n        value = serialize_numpy_array(value=value)\n    return value\n\n\ndef serialize_list(elements: List[Any]) -> List[Any]:\n    result = []\n    for element in elements:\n        element = serialize_wildcard_kind(value=element)\n        result.append(element)\n    return result\n\n\ndef serialize_dict(elements: Dict[str, Any]) -> Dict[str, Any]:\n    serialized_result = {}\n    for key, value in elements.items():\n        value = serialize_wildcard_kind(value=value)\n        serialized_result[key] = value\n    return serialized_result\n\n\ndef serialize_secret(secret: str) -> str:\n    if len(secret) < MIN_SECRET_LENGTH_TO_REVEAL_PREFIX:\n        return \"*\" * MIN_SECRET_LENGTH_TO_REVEAL_PREFIX\n    prefix = secret[:2]\n    infix = \"*\" * MIN_SECRET_LENGTH_TO_REVEAL_PREFIX\n    suffix = secret[-2:]\n    return f\"{prefix}{infix}{suffix}\"\n\n\ndef serialize_timestamp(timestamp: datetime) -> str:\n    return timestamp.isoformat()\n\n\ndef serialise_rle_sv_detections(detections: sv.Detections) -> dict:\n    rle_masks = detections.data.get(RLE_MASK_KEY_IN_SV_DETECTIONS)\n    if rle_masks is None:\n        raise ValueError(\n            \"No RLE masks found in detections.data['rle_mask']. \"\n            \"This serializer requires RLE masks to be present.\"\n        )\n\n    result = serialise_sv_detections(detections=detections)\n\n    for idx, detection_dict in enumerate(result[\"predictions\"]):\n        detection_dict.pop(POLYGON_KEY, None)\n\n        if idx < len(rle_masks):\n            rle = rle_masks[idx]\n            if isinstance(rle.get(\"counts\"), bytes):\n                rle = {\"size\": rle[\"size\"], \"counts\": rle[\"counts\"].decode(\"utf-8\")}\n            detection_dict[RLE_MASK_KEY_IN_INFERENCE_RESPONSE] = rle\n\n    return result\n\n\ndef serialize_numpy_array(value: np.ndarray) -> list:\n    return value.tolist()\n",
    "patch": null
  },
  {
    "trace_id": "a8b29434-aa7f-44be-bf34-904ce73ce6b6",
    "function_name": "CustomCollector._fetch_stream_metrics",
    "file_path": "inference/core/managers/prometheus.py",
    "speedup_x": 0.19,
    "review_quality": "high",
    "pre_optimization_commit": "HEAD",
    "resolution_method": "db_code_only",
    "source": "db_events",
    "original_function_code": "    async def _fetch_stream_metrics(self) -> Dict[str, dict]:\n        pipelines_response = await self.stream_manager_client.list_pipelines()\n        pipeline_ids = pipelines_response.pipelines\n        metrics = {}\n        for pipeline_id in pipeline_ids:\n            status_response = await self.stream_manager_client.get_status(pipeline_id)\n            report = status_response.report\n            latency_reports = report.get(\"latency_reports\", [])\n            sources_metadata = report.get(\"sources_metadata\", [])\n            camera_fps = self._average_source_fps(sources_metadata)\n            metrics[pipeline_id] = {\n                \"inference_throughput\": report.get(\"inference_throughput\", 0.0),\n                \"camera_fps\": camera_fps,\n                \"frame_decoding_latency\": self._average_latency_field(\n                    latency_reports, \"frame_decoding_latency\"\n                ),\n                \"inference_latency\": self._average_latency_field(\n                    latency_reports, \"inference_latency\"\n                ),\n                \"e2e_latency\": self._average_latency_field(\n                    latency_reports, \"e2e_latency\"\n                ),\n            }\n        return metrics\n",
    "optimized_function_code": "from typing import Dict, List\n\nfrom prometheus_client.registry import Collector\n\n\nclass CustomCollector(Collector):\n    def __init__(self, model_manager, time_window: int = 10):\n        super(CustomCollector, self).__init__()\n        self.model_manager = model_manager\n        self.time_window = time_window\n        self.stream_manager_client = None\n\n    async def _fetch_stream_metrics(self) -> Dict[str, dict]:\n        pipelines_response = await self.stream_manager_client.list_pipelines()\n        pipeline_ids = pipelines_response.pipelines\n        metrics = {}\n        for pipeline_id in pipeline_ids:\n            status_response = await self.stream_manager_client.get_status(pipeline_id)\n            report = status_response.report\n            latency_reports = report.get(\"latency_reports\", [])\n            sources_metadata = report.get(\"sources_metadata\", [])\n            camera_fps = self._average_source_fps(sources_metadata)\n            metrics[pipeline_id] = {\n                \"inference_throughput\": report.get(\"inference_throughput\", 0.0),\n                \"camera_fps\": camera_fps,\n                \"frame_decoding_latency\": self._average_latency_field(\n                    latency_reports, \"frame_decoding_latency\"\n                ),\n                \"inference_latency\": self._average_latency_field(\n                    latency_reports, \"inference_latency\"\n                ),\n                \"e2e_latency\": self._average_latency_field(\n                    latency_reports, \"e2e_latency\"\n                ),\n            }\n        return metrics\n\n    @staticmethod\n    def _average_latency_field(latency_reports: List[dict], field: str) -> float:\n        total = 0.0\n        count = 0\n        for r in latency_reports:\n            value = r.get(field)\n            if value is not None:\n                total += value\n                count += 1\n        if count == 0:\n            return 0.0\n        return total / count\n\n\n    @staticmethod\n    def _average_source_fps(sources_metadata: List[dict]) -> float:\n        total = 0.0\n        count = 0\n        for src in sources_metadata:\n            props = src.get(\"source_properties\")\n            if props:\n                fps = props.get(\"fps\")\n                if fps is not None and fps > 0:\n                    total += fps\n                    count += 1\n        if count == 0:\n            return 0.0\n        return total / count",
    "optimized_raw_markdown": "```python:inference/core/managers/prometheus.py\nfrom typing import Dict, List\n\nfrom prometheus_client.registry import Collector\n\n\nclass CustomCollector(Collector):\n    def __init__(self, model_manager, time_window: int = 10):\n        super(CustomCollector, self).__init__()\n        self.model_manager = model_manager\n        self.time_window = time_window\n        self.stream_manager_client = None\n\n    async def _fetch_stream_metrics(self) -> Dict[str, dict]:\n        pipelines_response = await self.stream_manager_client.list_pipelines()\n        pipeline_ids = pipelines_response.pipelines\n        metrics = {}\n        for pipeline_id in pipeline_ids:\n            status_response = await self.stream_manager_client.get_status(pipeline_id)\n            report = status_response.report\n            latency_reports = report.get(\"latency_reports\", [])\n            sources_metadata = report.get(\"sources_metadata\", [])\n            camera_fps = self._average_source_fps(sources_metadata)\n            metrics[pipeline_id] = {\n                \"inference_throughput\": report.get(\"inference_throughput\", 0.0),\n                \"camera_fps\": camera_fps,\n                \"frame_decoding_latency\": self._average_latency_field(\n                    latency_reports, \"frame_decoding_latency\"\n                ),\n                \"inference_latency\": self._average_latency_field(\n                    latency_reports, \"inference_latency\"\n                ),\n                \"e2e_latency\": self._average_latency_field(\n                    latency_reports, \"e2e_latency\"\n                ),\n            }\n        return metrics\n\n    @staticmethod\n    def _average_latency_field(latency_reports: List[dict], field: str) -> float:\n        total = 0.0\n        count = 0\n        for r in latency_reports:\n            value = r.get(field)\n            if value is not None:\n                total += value\n                count += 1\n        if count == 0:\n            return 0.0\n        return total / count\n\n\n    @staticmethod\n    def _average_source_fps(sources_metadata: List[dict]) -> float:\n        total = 0.0\n        count = 0\n        for src in sources_metadata:\n            props = src.get(\"source_properties\")\n            if props:\n                fps = props.get(\"fps\")\n                if fps is not None and fps > 0:\n                    total += fps\n                    count += 1\n        if count == 0:\n            return 0.0\n        return total / count\n```",
    "optimized_function_only": "    async def _fetch_stream_metrics(self) -> Dict[str, dict]:\n        pipelines_response = await self.stream_manager_client.list_pipelines()\n        pipeline_ids = pipelines_response.pipelines\n        metrics = {}\n        for pipeline_id in pipeline_ids:\n            status_response = await self.stream_manager_client.get_status(pipeline_id)\n            report = status_response.report\n            latency_reports = report.get(\"latency_reports\", [])\n            sources_metadata = report.get(\"sources_metadata\", [])\n            camera_fps = self._average_source_fps(sources_metadata)\n            metrics[pipeline_id] = {\n                \"inference_throughput\": report.get(\"inference_throughput\", 0.0),\n                \"camera_fps\": camera_fps,\n                \"frame_decoding_latency\": self._average_latency_field(\n                    latency_reports, \"frame_decoding_latency\"\n                ),\n                \"inference_latency\": self._average_latency_field(\n                    latency_reports, \"inference_latency\"\n                ),\n                \"e2e_latency\": self._average_latency_field(\n                    latency_reports, \"e2e_latency\"\n                ),\n            }\n        return metrics\n",
    "original_file_content": "from prometheus_client.registry import Collector\nfrom typing import Dict, List\n\nclass CustomCollector(Collector):\n    def __init__(self, model_manager, time_window: int = 10):\n        super(CustomCollector, self).__init__()\n        self.model_manager = model_manager\n        self.time_window = time_window\n        self.stream_manager_client = None\n\n    async def _fetch_stream_metrics(self) -> Dict[str, dict]:\n        pipelines_response = await self.stream_manager_client.list_pipelines()\n        pipeline_ids = pipelines_response.pipelines\n        metrics = {}\n        for pipeline_id in pipeline_ids:\n            status_response = await self.stream_manager_client.get_status(pipeline_id)\n            report = status_response.report\n            latency_reports = report.get(\"latency_reports\", [])\n            sources_metadata = report.get(\"sources_metadata\", [])\n            camera_fps = self._average_source_fps(sources_metadata)\n            metrics[pipeline_id] = {\n                \"inference_throughput\": report.get(\"inference_throughput\", 0.0),\n                \"camera_fps\": camera_fps,\n                \"frame_decoding_latency\": self._average_latency_field(\n                    latency_reports, \"frame_decoding_latency\"\n                ),\n                \"inference_latency\": self._average_latency_field(\n                    latency_reports, \"inference_latency\"\n                ),\n                \"e2e_latency\": self._average_latency_field(\n                    latency_reports, \"e2e_latency\"\n                ),\n            }\n        return metrics\n\n    @staticmethod\n    def _average_latency_field(latency_reports: List[dict], field: str) -> float:\n        values = [r[field] for r in latency_reports if r.get(field) is not None]\n        if not values:\n            return 0.0\n        return sum(values) / len(values)\n\n    @staticmethod\n    def _average_source_fps(sources_metadata: List[dict]) -> float:\n        values = []\n        for src in sources_metadata:\n            props = src.get(\"source_properties\") or {}\n            fps = props.get(\"fps\")\n            if fps is not None and fps > 0:\n                values.append(fps)\n        if not values:\n            return 0.0\n        return sum(values) / len(values)",
    "patch": null
  },
  {
    "trace_id": "4f02367b-64d8-46f0-9750-29947e699ef1",
    "function_name": "Batch.remove_by_indices",
    "file_path": "inference/core/workflows/execution_engine/entities/base.py",
    "speedup_x": 0.2643246529003779,
    "review_quality": "high",
    "pre_optimization_commit": "90243bdc6278ef7d17b6db09dc1eb5b0d155b4be",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def remove_by_indices(self, indices_to_remove: Set[tuple]) -> \"Batch\":\n        filtered_content = [\n            (\n                element\n                if not isinstance(element, Batch)\n                else element.remove_by_indices(indices_to_remove=indices_to_remove)\n            )\n            for index, element in zip(self._indices, self._content)\n            if index not in indices_to_remove\n        ]\n        filtered_indices = [\n            index for index in self._indices if index not in indices_to_remove\n        ]\n\n        return Batch(content=filtered_content, indices=filtered_indices)\n",
    "optimized_function_code": "from __future__ import annotations\n\nfrom typing import Generic, List, Optional, Set, Tuple, TypeVar\n\nB = TypeVar(\"B\")\n\n\nclass Batch(Generic[B]):\n\n    def __init__(self, content: List[B], indices: Optional[List[Tuple[int, ...]]]):\n        self._content = content\n        self._indices = indices\n\n    def remove_by_indices(self, indices_to_remove: Set[tuple]) -> \"Batch\":\n        filtered_content: List[B] = []\n        filtered_indices: List[Tuple[int, ...]] = []\n\n        for index, element in zip(self._indices, self._content):\n            if index in indices_to_remove:\n                continue\n            if isinstance(element, Batch):\n                filtered_content.append(\n                    element.remove_by_indices(indices_to_remove=indices_to_remove)\n                )\n            else:\n                filtered_content.append(element)\n            filtered_indices.append(index)\n\n        return Batch(content=filtered_content, indices=filtered_indices)",
    "optimized_raw_markdown": "```python:inference/core/workflows/execution_engine/entities/base.py\nfrom __future__ import annotations\n\nfrom typing import Generic, List, Optional, Set, Tuple, TypeVar\n\nB = TypeVar(\"B\")\n\n\nclass Batch(Generic[B]):\n\n    def __init__(self, content: List[B], indices: Optional[List[Tuple[int, ...]]]):\n        self._content = content\n        self._indices = indices\n\n    def remove_by_indices(self, indices_to_remove: Set[tuple]) -> \"Batch\":\n        filtered_content: List[B] = []\n        filtered_indices: List[Tuple[int, ...]] = []\n\n        for index, element in zip(self._indices, self._content):\n            if index in indices_to_remove:\n                continue\n            if isinstance(element, Batch):\n                filtered_content.append(\n                    element.remove_by_indices(indices_to_remove=indices_to_remove)\n                )\n            else:\n                filtered_content.append(element)\n            filtered_indices.append(index)\n\n        return Batch(content=filtered_content, indices=filtered_indices)\n```",
    "optimized_function_only": "    def remove_by_indices(self, indices_to_remove: Set[tuple]) -> \"Batch\":\n        filtered_content: List[B] = []\n        filtered_indices: List[Tuple[int, ...]] = []\n\n        for index, element in zip(self._indices, self._content):\n            if index in indices_to_remove:\n                continue\n            if isinstance(element, Batch):\n                filtered_content.append(\n                    element.remove_by_indices(indices_to_remove=indices_to_remove)\n                )\n            else:\n                filtered_content.append(element)\n            filtered_indices.append(index)\n\n        return Batch(content=filtered_content, indices=filtered_indices)",
    "original_file_content": "import base64\nfrom copy import copy\nfrom dataclasses import dataclass, replace\nfrom datetime import datetime\nfrom enum import Enum\nfrom typing import (\n    Any,\n    Dict,\n    Generic,\n    Iterator,\n    List,\n    Optional,\n    Set,\n    Tuple,\n    TypeVar,\n    Union,\n)\n\nimport cv2\nimport numpy as np\nfrom pydantic import BaseModel, Field\nfrom typing_extensions import Annotated, Literal\n\nfrom inference.core.utils.image_utils import (\n    attempt_loading_image_from_string,\n    encode_image_to_jpeg_bytes,\n    load_image_from_url,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    IMAGE_KIND,\n    VIDEO_METADATA_KIND,\n    WILDCARD_KIND,\n    Kind,\n)\n\n\nclass OutputDefinition(BaseModel):\n    name: str\n    kind: List[Kind] = Field(default_factory=lambda: [WILDCARD_KIND])\n\n\nclass CoordinatesSystem(Enum):\n    OWN = \"own\"\n    PARENT = \"parent\"\n\n\nclass JsonField(BaseModel):\n    type: Literal[\"JsonField\"]\n    name: str\n    selector: str\n    coordinates_system: CoordinatesSystem = Field(default=CoordinatesSystem.PARENT)\n\n    def get_type(self) -> str:\n        return self.type\n\n\nclass WorkflowInput(BaseModel):\n    type: str\n    name: str\n    kind: List[Union[str, Kind]]\n    dimensionality: int\n\n    @classmethod\n    def is_batch_oriented(cls) -> bool:\n        return False\n\n\nclass WorkflowImage(WorkflowInput):\n    type: Literal[\"WorkflowImage\", \"InferenceImage\"]\n    name: str\n    kind: List[Union[str, Kind]] = Field(default=[IMAGE_KIND])\n    dimensionality: int = Field(default=1, ge=1, le=1)\n\n    @classmethod\n    def is_batch_oriented(cls) -> bool:\n        return True\n\n\nclass WorkflowVideoMetadata(WorkflowInput):\n    type: Literal[\"WorkflowVideoMetadata\"]\n    name: str\n    kind: List[Union[str, Kind]] = Field(default=[VIDEO_METADATA_KIND])\n    dimensionality: int = Field(default=1, ge=1, le=1)\n\n    @classmethod\n    def is_batch_oriented(cls) -> bool:\n        return True\n\n\nclass WorkflowBatchInput(WorkflowInput):\n    type: Literal[\"WorkflowBatchInput\"]\n    name: str\n    kind: List[Union[str, Kind]] = Field(default_factory=lambda: [WILDCARD_KIND])\n    dimensionality: int = Field(default=1)\n\n    @classmethod\n    def is_batch_oriented(cls) -> bool:\n        return True\n\n\nclass WorkflowParameter(WorkflowInput):\n    type: Literal[\"WorkflowParameter\", \"InferenceParameter\"]\n    name: str\n    kind: List[Union[str, Kind]] = Field(default_factory=lambda: [WILDCARD_KIND])\n    default_value: Optional[Union[float, int, str, bool, list, set, dict]] = Field(\n        default=None\n    )\n    dimensionality: int = Field(default=0, ge=0, le=0)\n\n\nInputType = Annotated[\n    Union[WorkflowImage, WorkflowVideoMetadata, WorkflowParameter, WorkflowBatchInput],\n    Field(discriminator=\"type\"),\n]\n\nB = TypeVar(\"B\")\n\n\nclass Batch(Generic[B]):\n\n    @classmethod\n    def init(\n        cls,\n        content: List[B],\n        indices: List[Tuple[int, ...]],\n    ) -> \"Batch\":\n        if len(content) != len(indices):\n            raise ValueError(\n                \"Attempted to initialise Batch object providing batch indices of size differing \"\n                \"from size of the data.\"\n            )\n\n        return cls(content=content, indices=indices)\n\n    def __init__(self, content: List[B], indices: Optional[List[Tuple[int, ...]]]):\n        self._content = content\n        self._indices = indices\n\n    @property\n    def indices(self) -> List[Tuple[int, ...]]:\n        return copy(self._indices)\n\n    def __getitem__(\n        self,\n        index: int,\n    ) -> B:\n        return self._content[index]\n\n    def __len__(self):\n        return len(self._content)\n\n    def __iter__(self) -> Iterator[B]:\n        yield from self._content\n\n    def remove_by_indices(self, indices_to_remove: Set[tuple]) -> \"Batch\":\n        filtered_content = [\n            (\n                element\n                if not isinstance(element, Batch)\n                else element.remove_by_indices(indices_to_remove=indices_to_remove)\n            )\n            for index, element in zip(self._indices, self._content)\n            if index not in indices_to_remove\n        ]\n        filtered_indices = [\n            index for index in self._indices if index not in indices_to_remove\n        ]\n\n        return Batch(content=filtered_content, indices=filtered_indices)\n\n    def iter_with_indices(self) -> Iterator[Tuple[Tuple[int, ...], B]]:\n        return zip(self._indices, self._content)\n\n    def broadcast(self, n: int) -> \"Batch\":\n        if n <= 0:\n            raise ValueError(\n                f\"Broadcast to size {n} requested which is an invalid operation.\"\n            )\n\n        num_content = len(self._content)\n\n        if num_content == n:\n            return self\n\n        if num_content == 1:\n            return Batch(content=self._content * n, indices=self._indices * n)\n\n        raise ValueError(f\"Could not broadcast batch of size {num_content} to size {n}\")\n\n\nclass VideoMetadata(BaseModel):\n    video_identifier: str = Field(\n        description=\"Identifier string for video. To be treated as opaque.\"\n    )\n    frame_number: int\n    frame_timestamp: datetime = Field(\n        description=\"The timestamp of video frame. When processing video it is suggested that \"\n        \"blocks rely on `fps` and `frame_number`, as real-world time-elapse will not \"\n        \"match time-elapse in video file\",\n    )\n    fps: Optional[float] = Field(\n        description=\"Field represents FPS value (if possible to be retrieved)\",\n        default=None,\n    )\n    measured_fps: Optional[float] = Field(\n        description=\"Field represents measured FPS of live stream\",\n        default=None,\n    )\n    comes_from_video_file: Optional[bool] = Field(\n        description=\"Field is a flag telling if frame comes from video file or stream - \"\n        \"if not possible to be determined - pass None\",\n        default=None,\n    )\n\n\nclass ParentOrigin(BaseModel):\n    offset_x: int = Field(\n        description=\"Offset from the left of the parent image in pixels\"\n    )\n    offset_y: int = Field(\n        description=\"Offset from the top of the parent image in pixels\"\n    )\n    width: int = Field(\n        description=\"Width of the parent image in pixels\",\n        gt=0,\n    )\n    height: int = Field(\n        description=\"Height of the parent image in pixels\",\n        gt=0,\n    )\n\n    @classmethod\n    def from_origin_coordinates_system(\n        cls, origin_coordinates_system: \"OriginCoordinatesSystem\"\n    ) -> \"ParentOrigin\":\n        return cls(\n            offset_x=origin_coordinates_system.left_top_x,\n            offset_y=origin_coordinates_system.left_top_y,\n            width=origin_coordinates_system.origin_width,\n            height=origin_coordinates_system.origin_height,\n        )\n\n    def to_origin_coordinates_system(self) -> \"OriginCoordinatesSystem\":\n        return OriginCoordinatesSystem(\n            left_top_x=self.offset_x,\n            left_top_y=self.offset_y,\n            origin_width=self.width,\n            origin_height=self.height,\n        )\n\n\n@dataclass(frozen=True)\nclass OriginCoordinatesSystem:\n    left_top_x: int\n    left_top_y: int\n    origin_width: int\n    origin_height: int\n\n\n@dataclass(frozen=True)\nclass ImageParentMetadata:\n    parent_id: str\n    origin_coordinates: Optional[OriginCoordinatesSystem] = None\n\n\nclass WorkflowImageData:\n\n    def __init__(\n        self,\n        parent_metadata: ImageParentMetadata,\n        workflow_root_ancestor_metadata: Optional[ImageParentMetadata] = None,\n        image_reference: Optional[str] = None,\n        base64_image: Optional[str] = None,\n        numpy_image: Optional[np.ndarray] = None,\n        video_metadata: Optional[VideoMetadata] = None,\n    ):\n        if not base64_image and numpy_image is None and not image_reference:\n            raise ValueError(\"Could not initialise empty `WorkflowImageData`.\")\n        self._parent_metadata = parent_metadata\n        self._workflow_root_ancestor_metadata = (\n            workflow_root_ancestor_metadata\n            if workflow_root_ancestor_metadata\n            else self._parent_metadata\n        )\n        self._image_reference = image_reference\n        self._base64_image = base64_image\n        self._numpy_image = numpy_image\n        self._video_metadata = video_metadata\n\n    @classmethod\n    def copy_and_replace(\n        cls, origin_image_data: \"WorkflowImageData\", **kwargs\n    ) -> \"WorkflowImageData\":\n        \"\"\"\n        Creates new instance of `WorkflowImageData` with updated property.\n\n        Properties are passed by kwargs, supported properties are:\n        * parent_metadata\n        * workflow_root_ancestor_metadata\n        * image_reference\n        * base64_image\n        * numpy_image\n        * video_metadata\n\n        When more than one from [\"numpy_image\", \"base64_image\", \"image_reference\"] args are\n        given, they MUST be compliant.\n        \"\"\"\n        parent_metadata = origin_image_data._parent_metadata\n        workflow_root_ancestor_metadata = (\n            origin_image_data._workflow_root_ancestor_metadata\n        )\n        image_reference = origin_image_data._image_reference\n        base64_image = origin_image_data._base64_image\n        numpy_image = origin_image_data._numpy_image\n        video_metadata = origin_image_data._video_metadata\n        if any(k in kwargs for k in [\"numpy_image\", \"base64_image\", \"image_reference\"]):\n            numpy_image = kwargs.get(\"numpy_image\")\n            base64_image = kwargs.get(\"base64_image\")\n            image_reference = kwargs.get(\"image_reference\")\n        if \"parent_metadata\" in kwargs:\n            if workflow_root_ancestor_metadata is parent_metadata:\n                workflow_root_ancestor_metadata = kwargs[\"parent_metadata\"]\n            parent_metadata = kwargs[\"parent_metadata\"]\n        if \"workflow_root_ancestor_metadata\" in kwargs:\n            if parent_metadata is workflow_root_ancestor_metadata:\n                parent_metadata = kwargs[\"workflow_root_ancestor_metadata\"]\n            workflow_root_ancestor_metadata = kwargs[\"workflow_root_ancestor_metadata\"]\n        if \"video_metadata\" in kwargs:\n            video_metadata = kwargs[\"video_metadata\"]\n        return cls(\n            parent_metadata=parent_metadata,\n            workflow_root_ancestor_metadata=workflow_root_ancestor_metadata,\n            image_reference=image_reference,\n            base64_image=base64_image,\n            numpy_image=numpy_image,\n            video_metadata=video_metadata,\n        )\n\n    @classmethod\n    def create_crop(\n        cls,\n        origin_image_data: \"WorkflowImageData\",\n        crop_identifier: str,\n        cropped_image: np.ndarray,\n        offset_x: int,\n        offset_y: int,\n        preserve_video_metadata: bool = False,\n    ) -> \"WorkflowImageData\":\n        \"\"\"\n        Creates new instance of `WorkflowImageData` being a crop of original image,\n        making adjustment to all metadata.\n        \"\"\"\n        parent_metadata = ImageParentMetadata(\n            parent_id=crop_identifier,\n            origin_coordinates=OriginCoordinatesSystem(\n                left_top_x=offset_x,\n                left_top_y=offset_y,\n                origin_width=origin_image_data.numpy_image.shape[1],\n                origin_height=origin_image_data.numpy_image.shape[0],\n            ),\n        )\n        workflow_root_ancestor_coordinates = replace(\n            origin_image_data.workflow_root_ancestor_metadata.origin_coordinates,\n            left_top_x=origin_image_data.workflow_root_ancestor_metadata.origin_coordinates.left_top_x\n            + offset_x,\n            left_top_y=origin_image_data.workflow_root_ancestor_metadata.origin_coordinates.left_top_y\n            + offset_y,\n        )\n        workflow_root_ancestor_metadata = ImageParentMetadata(\n            parent_id=origin_image_data.workflow_root_ancestor_metadata.parent_id,\n            origin_coordinates=workflow_root_ancestor_coordinates,\n        )\n        video_metadata = None\n        if preserve_video_metadata and origin_image_data._video_metadata is not None:\n            video_metadata = copy(origin_image_data._video_metadata)\n            video_metadata.video_identifier = (\n                f\"{video_metadata.video_identifier} | crop: {crop_identifier}\"\n            )\n        return WorkflowImageData(\n            parent_metadata=parent_metadata,\n            workflow_root_ancestor_metadata=workflow_root_ancestor_metadata,\n            numpy_image=cropped_image,\n            video_metadata=video_metadata,\n        )\n\n    @property\n    def parent_metadata(self) -> ImageParentMetadata:\n        if self._parent_metadata.origin_coordinates is None:\n            numpy_image = self.numpy_image\n            origin_coordinates = OriginCoordinatesSystem(\n                left_top_y=0,\n                left_top_x=0,\n                origin_width=numpy_image.shape[1],\n                origin_height=numpy_image.shape[0],\n            )\n            self._parent_metadata = replace(\n                self._parent_metadata, origin_coordinates=origin_coordinates\n            )\n        return self._parent_metadata\n\n    @property\n    def workflow_root_ancestor_metadata(self) -> ImageParentMetadata:\n        if self._workflow_root_ancestor_metadata.origin_coordinates is None:\n            numpy_image = self.numpy_image\n            origin_coordinates = OriginCoordinatesSystem(\n                left_top_y=0,\n                left_top_x=0,\n                origin_width=numpy_image.shape[1],\n                origin_height=numpy_image.shape[0],\n            )\n            self._workflow_root_ancestor_metadata = replace(\n                self._workflow_root_ancestor_metadata,\n                origin_coordinates=origin_coordinates,\n            )\n        return self._workflow_root_ancestor_metadata\n\n    @property\n    def numpy_image(self) -> np.ndarray:\n        if self._numpy_image is not None:\n            return self._numpy_image\n        if self._base64_image:\n            self._numpy_image = attempt_loading_image_from_string(self._base64_image)[0]\n            return self._numpy_image\n        if self._image_reference.startswith(\n            \"http://\"\n        ) or self._image_reference.startswith(\"https://\"):\n            self._numpy_image = load_image_from_url(value=self._image_reference)\n        else:\n            self._numpy_image = cv2.imread(self._image_reference)\n        return self._numpy_image\n\n    @property\n    def base64_image(self) -> str:\n        if self._base64_image is not None:\n            return self._base64_image\n        numpy_image = self.numpy_image\n        self._base64_image = base64.b64encode(\n            encode_image_to_jpeg_bytes(numpy_image, jpeg_quality=95)\n        ).decode(\"ascii\")\n        return self._base64_image\n\n    @property\n    def video_metadata(self) -> VideoMetadata:\n        if self._video_metadata is not None:\n            return self._video_metadata\n        return VideoMetadata(\n            video_identifier=self.parent_metadata.parent_id,\n            frame_number=0,\n            frame_timestamp=datetime.now(),\n            fps=30,\n            comes_from_video_file=None,\n        )\n\n    def to_inference_format(self, numpy_preferred: bool = False) -> Dict[str, Any]:\n        if numpy_preferred:\n            return {\"type\": \"numpy_object\", \"value\": self.numpy_image}\n        if self._image_reference:\n            if self._image_reference.startswith(\n                \"http://\"\n            ) or self._image_reference.startswith(\"https://\"):\n                return {\"type\": \"url\", \"value\": self._image_reference}\n            return {\"type\": \"file\", \"value\": self._image_reference}\n        if self._base64_image:\n            return {\"type\": \"base64\", \"value\": self.base64_image}\n        return {\"type\": \"numpy_object\", \"value\": self.numpy_image}\n",
    "patch": null
  },
  {
    "trace_id": "3c94634e-3cb0-4cc0-aa69-36b43ae856f9",
    "function_name": "draw_background_with_alpha",
    "file_path": "inference/core/workflows/core_steps/visualizations/text_display/utils.py",
    "speedup_x": 0.18,
    "review_quality": "high",
    "pre_optimization_commit": "82a08ad7e97efa30ce3224d142070ce0ecacd716",
    "resolution_method": "db_code_match",
    "source": "db_events",
    "original_function_code": "def draw_background_with_alpha(\n    img: np.ndarray,\n    pt1: Tuple[int, int],\n    pt2: Tuple[int, int],\n    color: Tuple[int, int, int],\n    alpha: float,\n    border_radius: int,\n) -> None:\n    \"\"\"Draw a filled rectangle with alpha blending using overlay compositing.\n\n    Uses proper overlay-based alpha blending for smooth antialiased edges,\n    especially important for rounded rectangles.\n\n    Process:\n    1. Extract the affected region\n    2. Create overlay and draw shape on it\n    3. Alpha-blend overlay with original region\n    4. Write blended result back\n    \"\"\"\n    x1, y1 = pt1\n    x2, y2 = pt2\n\n    # Clamp to image bounds\n    img_h, img_w = img.shape[:2]\n    x1_clamped = max(0, x1)\n    y1_clamped = max(0, y1)\n    x2_clamped = min(img_w, x2)\n    y2_clamped = min(img_h, y2)\n\n    if x2_clamped <= x1_clamped or y2_clamped <= y1_clamped:\n        return\n\n    # Extract the region of interest\n    roi = img[y1_clamped:y2_clamped, x1_clamped:x2_clamped]\n\n    # Create overlay for just this region\n    overlay = roi.copy()\n\n    roi_w = x2_clamped - x1_clamped\n    roi_h = y2_clamped - y1_clamped\n\n    # Draw the shape onto the overlay (coordinates relative\n    # to ROI and OpenCV uses inclusive coordinates,\n    # so max index is size - 1\n    if border_radius > 0:\n        draw_rounded_rectangle(\n            overlay,\n            (0, 0),\n            (roi_w - 1, roi_h - 1),\n            color,\n            border_radius,\n        )\n    else:\n        cv2.rectangle(\n            overlay,\n            (0, 0),\n            (roi_w - 1, roi_h - 1),\n            color,\n            -1,\n        )\n\n    # Alpha blend: result = overlay * alpha + original * (1 - alpha)\n    blended = cv2.addWeighted(overlay, alpha, roi, 1 - alpha, 0)\n\n    # Write blended result back to image\n    img[y1_clamped:y2_clamped, x1_clamped:x2_clamped] = blended\n",
    "optimized_function_code": "from __future__ import annotations\n\nfrom typing import Tuple\n\nimport cv2\nimport numpy as np\n\n\ndef draw_rounded_rectangle(\n    img: np.ndarray,\n    pt1: Tuple[int, int],\n    pt2: Tuple[int, int],\n    color: Tuple[int, int, int],\n    radius: int,\n) -> None:\n    \"\"\"Draw a filled rounded rectangle on an image.\"\"\"\n    x1, y1 = pt1\n    x2, y2 = pt2\n\n    # Early return for invalid coordinates\n    if x2 <= x1 or y2 <= y1:\n        return\n\n    max_radius = min((x2 - x1) // 2, (y2 - y1) // 2)\n    radius = min(radius, max_radius)\n\n    if radius <= 0:\n        cv2.rectangle(img, pt1, pt2, color, -1)\n        return\n\n    cv2.rectangle(img, (x1 + radius, y1), (x2 - radius, y2), color, -1)\n    cv2.rectangle(img, (x1, y1 + radius), (x2, y2 - radius), color, -1)\n\n    cv2.ellipse(img, (x1 + radius, y1 + radius), (radius, radius), 180, 0, 90, color, -1)\n    cv2.ellipse(img, (x2 - radius, y1 + radius), (radius, radius), 270, 0, 90, color, -1)\n    cv2.ellipse(img, (x1 + radius, y2 - radius), (radius, radius), 90, 0, 90, color, -1)\n    cv2.ellipse(img, (x2 - radius, y2 - radius), (radius, radius), 0, 0, 90, color, -1)\n\n\ndef draw_background_with_alpha(\n    img: np.ndarray,\n    pt1: Tuple[int, int],\n    pt2: Tuple[int, int],\n    color: Tuple[int, int, int],\n    alpha: float,\n    border_radius: int,\n) -> None:\n    \"\"\"Draw a filled rectangle with alpha blending using overlay compositing.\n\n    Uses proper overlay-based alpha blending for smooth antialiased edges,\n    especially important for rounded rectangles.\n\n    Process:\n    1. Extract the affected region\n    2. Create overlay and draw shape on it\n    3. Alpha-blend overlay with original region\n    4. Write blended result back\n    \"\"\"\n    x1, y1 = pt1\n    x2, y2 = pt2\n\n    # Clamp to image bounds\n    img_h, img_w = img.shape[:2]\n    x1_clamped = max(0, x1)\n    y1_clamped = max(0, y1)\n    x2_clamped = min(img_w, x2)\n    y2_clamped = min(img_h, y2)\n\n    if x2_clamped <= x1_clamped or y2_clamped <= y1_clamped:\n        return\n\n    # Extract the region of interest\n    roi = img[y1_clamped:y2_clamped, x1_clamped:x2_clamped]\n\n    roi_w = x2_clamped - x1_clamped\n    roi_h = y2_clamped - y1_clamped\n\n    # Draw the shape onto the overlay (coordinates relative\n    # to ROI and OpenCV uses inclusive coordinates,\n    # so max index is size - 1\n\n    # Allocate overlay directly (avoid unnecessary .copy())\n    overlay = np.empty_like(roi)\n    overlay[:] = roi  # initialize overlay with roi content\n\n    # Draw the shape onto the overlay (coordinates relative to ROI)\n    if border_radius > 0:\n        draw_rounded_rectangle(\n            overlay,\n            (0, 0),\n            (roi_w - 1, roi_h - 1),\n            color,\n            border_radius,\n        )\n    else:\n        cv2.rectangle(\n            overlay,\n            (0, 0),\n            (roi_w - 1, roi_h - 1),\n            color,\n            -1,\n        )\n\n    # Alpha blend: result = overlay * alpha + original * (1 - alpha)\n    cv2.addWeighted(overlay, alpha, roi, 1 - alpha, 0, dst=roi)  # write directly to roi (in-place)",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/visualizations/text_display/utils.py\nfrom __future__ import annotations\n\nfrom typing import Tuple\n\nimport cv2\nimport numpy as np\n\n\ndef draw_rounded_rectangle(\n    img: np.ndarray,\n    pt1: Tuple[int, int],\n    pt2: Tuple[int, int],\n    color: Tuple[int, int, int],\n    radius: int,\n) -> None:\n    \"\"\"Draw a filled rounded rectangle on an image.\"\"\"\n    x1, y1 = pt1\n    x2, y2 = pt2\n\n    # Early return for invalid coordinates\n    if x2 <= x1 or y2 <= y1:\n        return\n\n    max_radius = min((x2 - x1) // 2, (y2 - y1) // 2)\n    radius = min(radius, max_radius)\n\n    if radius <= 0:\n        cv2.rectangle(img, pt1, pt2, color, -1)\n        return\n\n    cv2.rectangle(img, (x1 + radius, y1), (x2 - radius, y2), color, -1)\n    cv2.rectangle(img, (x1, y1 + radius), (x2, y2 - radius), color, -1)\n\n    cv2.ellipse(img, (x1 + radius, y1 + radius), (radius, radius), 180, 0, 90, color, -1)\n    cv2.ellipse(img, (x2 - radius, y1 + radius), (radius, radius), 270, 0, 90, color, -1)\n    cv2.ellipse(img, (x1 + radius, y2 - radius), (radius, radius), 90, 0, 90, color, -1)\n    cv2.ellipse(img, (x2 - radius, y2 - radius), (radius, radius), 0, 0, 90, color, -1)\n\n\ndef draw_background_with_alpha(\n    img: np.ndarray,\n    pt1: Tuple[int, int],\n    pt2: Tuple[int, int],\n    color: Tuple[int, int, int],\n    alpha: float,\n    border_radius: int,\n) -> None:\n    \"\"\"Draw a filled rectangle with alpha blending using overlay compositing.\n\n    Uses proper overlay-based alpha blending for smooth antialiased edges,\n    especially important for rounded rectangles.\n\n    Process:\n    1. Extract the affected region\n    2. Create overlay and draw shape on it\n    3. Alpha-blend overlay with original region\n    4. Write blended result back\n    \"\"\"\n    x1, y1 = pt1\n    x2, y2 = pt2\n\n    # Clamp to image bounds\n    img_h, img_w = img.shape[:2]\n    x1_clamped = max(0, x1)\n    y1_clamped = max(0, y1)\n    x2_clamped = min(img_w, x2)\n    y2_clamped = min(img_h, y2)\n\n    if x2_clamped <= x1_clamped or y2_clamped <= y1_clamped:\n        return\n\n    # Extract the region of interest\n    roi = img[y1_clamped:y2_clamped, x1_clamped:x2_clamped]\n\n    roi_w = x2_clamped - x1_clamped\n    roi_h = y2_clamped - y1_clamped\n\n    # Draw the shape onto the overlay (coordinates relative\n    # to ROI and OpenCV uses inclusive coordinates,\n    # so max index is size - 1\n\n    # Allocate overlay directly (avoid unnecessary .copy())\n    overlay = np.empty_like(roi)\n    overlay[:] = roi  # initialize overlay with roi content\n\n    # Draw the shape onto the overlay (coordinates relative to ROI)\n    if border_radius > 0:\n        draw_rounded_rectangle(\n            overlay,\n            (0, 0),\n            (roi_w - 1, roi_h - 1),\n            color,\n            border_radius,\n        )\n    else:\n        cv2.rectangle(\n            overlay,\n            (0, 0),\n            (roi_w - 1, roi_h - 1),\n            color,\n            -1,\n        )\n\n    # Alpha blend: result = overlay * alpha + original * (1 - alpha)\n    cv2.addWeighted(overlay, alpha, roi, 1 - alpha, 0, dst=roi)  # write directly to roi (in-place)\n```",
    "optimized_function_only": "def draw_background_with_alpha(\n    img: np.ndarray,\n    pt1: Tuple[int, int],\n    pt2: Tuple[int, int],\n    color: Tuple[int, int, int],\n    alpha: float,\n    border_radius: int,\n) -> None:\n    \"\"\"Draw a filled rectangle with alpha blending using overlay compositing.\n\n    Uses proper overlay-based alpha blending for smooth antialiased edges,\n    especially important for rounded rectangles.\n\n    Process:\n    1. Extract the affected region\n    2. Create overlay and draw shape on it\n    3. Alpha-blend overlay with original region\n    4. Write blended result back\n    \"\"\"\n    x1, y1 = pt1\n    x2, y2 = pt2\n\n    # Clamp to image bounds\n    img_h, img_w = img.shape[:2]\n    x1_clamped = max(0, x1)\n    y1_clamped = max(0, y1)\n    x2_clamped = min(img_w, x2)\n    y2_clamped = min(img_h, y2)\n\n    if x2_clamped <= x1_clamped or y2_clamped <= y1_clamped:\n        return\n\n    # Extract the region of interest\n    roi = img[y1_clamped:y2_clamped, x1_clamped:x2_clamped]\n\n    roi_w = x2_clamped - x1_clamped\n    roi_h = y2_clamped - y1_clamped\n\n    # Draw the shape onto the overlay (coordinates relative\n    # to ROI and OpenCV uses inclusive coordinates,\n    # so max index is size - 1\n\n    # Allocate overlay directly (avoid unnecessary .copy())\n    overlay = np.empty_like(roi)\n    overlay[:] = roi  # initialize overlay with roi content\n\n    # Draw the shape onto the overlay (coordinates relative to ROI)\n    if border_radius > 0:\n        draw_rounded_rectangle(\n            overlay,\n            (0, 0),\n            (roi_w - 1, roi_h - 1),\n            color,\n            border_radius,\n        )\n    else:\n        cv2.rectangle(\n            overlay,\n            (0, 0),\n            (roi_w - 1, roi_h - 1),\n            color,\n            -1,\n        )\n\n    # Alpha blend: result = overlay * alpha + original * (1 - alpha)\n    cv2.addWeighted(overlay, alpha, roi, 1 - alpha, 0, dst=roi)  # write directly to roi (in-place)",
    "original_file_content": "from __future__ import annotations\n\nfrom dataclasses import dataclass\nfrom typing import Dict, Final, List, Optional, Tuple\n\nimport cv2\nimport numpy as np\n\nANCHORS: Final[Dict[str, Tuple[float, float]]] = {\n    \"top_left\": (0.0, 0.0),\n    \"top_center\": (0.5, 0.0),\n    \"top_right\": (1.0, 0.0),\n    \"center_left\": (0.0, 0.5),\n    \"center\": (0.5, 0.5),\n    \"center_right\": (1.0, 0.5),\n    \"bottom_left\": (0.0, 1.0),\n    \"bottom_center\": (0.5, 1.0),\n    \"bottom_right\": (1.0, 1.0),\n}\n\n\ndef calculate_relative_position(\n    anchor: str,\n    offset_x: int,\n    offset_y: int,\n    box_width: int,\n    box_height: int,\n    img_width: int,\n    img_height: int,\n) -> Tuple[int, int]:\n    \"\"\"Calculate the top-left corner position for a box positioned relative to an image anchor.\n\n    Args:\n        anchor: Anchor point name (e.g., \"top_left\", \"center\", \"bottom_right\")\n        offset_x: Horizontal offset from anchor point (positive = right)\n        offset_y: Vertical offset from anchor point (positive = down)\n        box_width: Width of the box to position\n        box_height: Height of the box to position\n        img_width: Width of the image\n        img_height: Height of the image\n\n    Returns:\n        Tuple of (x, y) coordinates for the top-left corner of the box\n\n    Raises:\n        ValueError: If anchor is not recognized\n    \"\"\"\n    key = anchor.lower()\n    try:\n        ax, ay = ANCHORS[key]\n    except KeyError as e:\n        raise ValueError(\n            f\"Unknown anchor: {anchor!r}. Must be one of {sorted(ANCHORS.keys())}\"\n        ) from e\n\n    anchor_x = int(round(ax * img_width))\n    anchor_y = int(round(ay * img_height))\n\n    box_x = anchor_x - int(round(ax * box_width)) + offset_x\n    box_y = anchor_y - int(round(ay * box_height)) + offset_y\n\n    return box_x, box_y\n\n\n@dataclass(frozen=True)\nclass TextLayout:\n    lines: List[str]\n    line_widths: List[int]\n    max_width: int\n    ref_height: int\n    line_advance: int\n    line_spacing: int\n    box_x: int\n    box_y: int\n    box_w: int\n    box_h: int\n\n\ndef clamp_box(\n    box_x: int, box_y: int, box_w: int, box_h: int, img_w: int, img_h: int\n) -> Tuple[int, int]:\n    \"\"\"Clamp box position to image bounds.\"\"\"\n    box_x = 0 if box_w > img_w else max(0, min(box_x, img_w - box_w))\n    box_y = 0 if box_h > img_h else max(0, min(box_y, img_h - box_h))\n    return box_x, box_y\n\n\ndef align_offset(text_align: str, max_width: int, line_width: int) -> int:\n    \"\"\"Calculate horizontal offset for text alignment.\"\"\"\n    if text_align == \"center\":\n        return (max_width - line_width) // 2\n    elif text_align == \"right\":\n        return max_width - line_width\n    else:  # left\n        return 0\n\n\ndef compute_layout(\n    *,\n    formatted_text: str,\n    font,\n    font_scale: float,\n    font_thickness: int,\n    padding: int,\n    position_mode: str,\n    position_x: int,\n    position_y: int,\n    anchor: str,\n    offset_x: int,\n    offset_y: int,\n    img_w: int,\n    img_h: int,\n) -> TextLayout:\n    \"\"\"Compute text layout including dimensions and position.\"\"\"\n    lines = formatted_text.split(\"\\n\") if formatted_text else [\"\"]\n    (_, ref_h), ref_base = cv2.getTextSize(\"Ag\", font, font_scale, font_thickness)\n    line_advance = ref_h + ref_base\n    line_spacing = max(1, int(round(0.25 * line_advance)))\n\n    line_widths = [\n        (\n            cv2.getTextSize(line, font, font_scale, font_thickness)[0][0]\n            if line.strip()\n            else 0\n        )\n        for line in lines\n    ]\n    max_width = max(line_widths, default=0)\n\n    num_lines = len(lines)\n    total_h = num_lines * line_advance + max(0, num_lines - 1) * line_spacing\n\n    box_w = max_width + 2 * padding\n    box_h = total_h + 2 * padding\n\n    if position_mode == \"absolute\":\n        box_x, box_y = position_x, position_y\n    else:\n        box_x, box_y = calculate_relative_position(\n            anchor=anchor,\n            offset_x=offset_x,\n            offset_y=offset_y,\n            box_width=box_w,\n            box_height=box_h,\n            img_width=img_w,\n            img_height=img_h,\n        )\n\n    box_x, box_y = clamp_box(box_x, box_y, box_w, box_h, img_w, img_h)\n\n    return TextLayout(\n        lines=lines,\n        line_widths=line_widths,\n        max_width=max_width,\n        ref_height=ref_h,\n        line_advance=line_advance,\n        line_spacing=line_spacing,\n        box_x=box_x,\n        box_y=box_y,\n        box_w=box_w,\n        box_h=box_h,\n    )\n\n\ndef draw_text_lines(\n    img: np.ndarray,\n    *,\n    layout: TextLayout,\n    padding: int,\n    text_align: str,\n    font,\n    font_scale: float,\n    font_thickness: int,\n    color_bgr: Tuple[int, int, int],\n) -> None:\n    \"\"\"Draw text lines on the image.\"\"\"\n    img_h, img_w = img.shape[:2]\n    current_y = layout.box_y + padding\n    base_x = layout.box_x + padding\n\n    for i, line in enumerate(layout.lines):\n        if line.strip():\n            w = layout.line_widths[i]\n            text_x = base_x + align_offset(text_align, layout.max_width, w)\n            text_y = current_y + layout.ref_height\n\n            if text_y > 0 and current_y < img_h and text_x < img_w:\n                cv2.putText(\n                    img,\n                    line,\n                    (text_x, text_y),\n                    font,\n                    font_scale,\n                    color_bgr,\n                    font_thickness,\n                    cv2.LINE_AA,\n                )\n\n        current_y += layout.line_advance\n        if i < len(layout.lines) - 1:\n            current_y += layout.line_spacing\n\n\ndef draw_rounded_rectangle(\n    img: np.ndarray,\n    pt1: Tuple[int, int],\n    pt2: Tuple[int, int],\n    color: Tuple[int, int, int],\n    radius: int,\n) -> None:\n    \"\"\"Draw a filled rounded rectangle on an image.\"\"\"\n    x1, y1 = pt1\n    x2, y2 = pt2\n\n    # Early return for invalid coordinates\n    if x2 <= x1 or y2 <= y1:\n        return\n\n    max_radius = min((x2 - x1) // 2, (y2 - y1) // 2)\n    radius = min(radius, max_radius)\n\n    if radius <= 0:\n        cv2.rectangle(img, pt1, pt2, color, -1)\n        return\n\n    cv2.rectangle(img, (x1 + radius, y1), (x2 - radius, y2), color, -1)\n    cv2.rectangle(img, (x1, y1 + radius), (x2, y2 - radius), color, -1)\n\n    cv2.ellipse(\n        img, (x1 + radius, y1 + radius), (radius, radius), 180, 0, 90, color, -1\n    )\n    cv2.ellipse(\n        img, (x2 - radius, y1 + radius), (radius, radius), 270, 0, 90, color, -1\n    )\n    cv2.ellipse(img, (x1 + radius, y2 - radius), (radius, radius), 90, 0, 90, color, -1)\n    cv2.ellipse(img, (x2 - radius, y2 - radius), (radius, radius), 0, 0, 90, color, -1)\n\n\ndef draw_background_with_alpha(\n    img: np.ndarray,\n    pt1: Tuple[int, int],\n    pt2: Tuple[int, int],\n    color: Tuple[int, int, int],\n    alpha: float,\n    border_radius: int,\n) -> None:\n    \"\"\"Draw a filled rectangle with alpha blending using overlay compositing.\n\n    Uses proper overlay-based alpha blending for smooth antialiased edges,\n    especially important for rounded rectangles.\n\n    Process:\n    1. Extract the affected region\n    2. Create overlay and draw shape on it\n    3. Alpha-blend overlay with original region\n    4. Write blended result back\n    \"\"\"\n    x1, y1 = pt1\n    x2, y2 = pt2\n\n    # Clamp to image bounds\n    img_h, img_w = img.shape[:2]\n    x1_clamped = max(0, x1)\n    y1_clamped = max(0, y1)\n    x2_clamped = min(img_w, x2)\n    y2_clamped = min(img_h, y2)\n\n    if x2_clamped <= x1_clamped or y2_clamped <= y1_clamped:\n        return\n\n    # Extract the region of interest\n    roi = img[y1_clamped:y2_clamped, x1_clamped:x2_clamped]\n\n    # Create overlay for just this region\n    overlay = roi.copy()\n\n    roi_w = x2_clamped - x1_clamped\n    roi_h = y2_clamped - y1_clamped\n\n    # Draw the shape onto the overlay (coordinates relative\n    # to ROI and OpenCV uses inclusive coordinates,\n    # so max index is size - 1\n    if border_radius > 0:\n        draw_rounded_rectangle(\n            overlay,\n            (0, 0),\n            (roi_w - 1, roi_h - 1),\n            color,\n            border_radius,\n        )\n    else:\n        cv2.rectangle(\n            overlay,\n            (0, 0),\n            (roi_w - 1, roi_h - 1),\n            color,\n            -1,\n        )\n\n    # Alpha blend: result = overlay * alpha + original * (1 - alpha)\n    blended = cv2.addWeighted(overlay, alpha, roi, 1 - alpha, 0)\n\n    # Write blended result back to image\n    img[y1_clamped:y2_clamped, x1_clamped:x2_clamped] = blended\n\n\ndef draw_background(\n    img: np.ndarray,\n    x1: int,\n    y1: int,\n    x2: int,\n    y2: int,\n    bg_color_bgr: Optional[Tuple[int, int, int]],\n    background_opacity: float,\n    border_radius: int,\n) -> None:\n    \"\"\"Draw background rectangle with optional transparency and rounded corners.\"\"\"\n    if bg_color_bgr is None or x2 <= x1 or y2 <= y1:\n        return\n\n    if background_opacity > 0.0:\n        if background_opacity < 1.0:\n            # Alpha blending required\n            draw_background_with_alpha(\n                img,\n                (x1, y1),\n                (x2, y2),\n                bg_color_bgr,\n                background_opacity,\n                border_radius,\n            )\n        else:\n            # Fully opaque - use direct drawing\n            # OpenCV uses inclusive coordinates, so subtract 1 from exclusive end coords\n            if border_radius > 0:\n                draw_rounded_rectangle(\n                    img,\n                    (x1, y1),\n                    (x2 - 1, y2 - 1),\n                    bg_color_bgr,\n                    border_radius,\n                )\n            else:\n                cv2.rectangle(\n                    img,\n                    (x1, y1),\n                    (x2 - 1, y2 - 1),\n                    bg_color_bgr,\n                    -1,\n                )\n",
    "patch": null
  },
  {
    "trace_id": "54ebd6d8-ca87-4901-ae05-719f007536b1",
    "function_name": "get_masks_intersection_for_dimensions",
    "file_path": "inference/core/workflows/execution_engine/v1/executor/execution_data_manager/step_input_assembler.py",
    "speedup_x": 0.22828228810493909,
    "review_quality": "high",
    "pre_optimization_commit": "90243bdc6278ef7d17b6db09dc1eb5b0d155b4be",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def get_masks_intersection_for_dimensions(\n    batch_masks: List[Set[DynamicBatchIndex]],\n    dimensions: Set[int],\n) -> Dict[int, Optional[Set[DynamicBatchIndex]]]:\n    \"\"\"Intersect masks at each dimension and filter to valid prefix chains.\"\"\"\n    if not batch_masks:\n        return {dim: None for dim in dimensions}\n\n    sorted_dims = sorted(dimensions)\n\n    if len(sorted_dims) <= 1:\n        result = intersect_masks_per_dimension(batch_masks, dimensions)\n        return {dim: result[dim] for dim in sorted_dims}\n\n    per_dim = intersect_masks_per_dimension(batch_masks, dimensions)\n    return filter_to_valid_prefix_chains(per_dim, dimensions)\n",
    "optimized_function_code": "from typing import Dict, List, Optional, Set\n\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.dynamic_batches_manager import \\\n    DynamicBatchIndex\n\n\ndef intersect_masks_per_dimension(\n    batch_masks: List[Set[DynamicBatchIndex]],\n    dimensions: Set[int],\n) -> Dict[int, Set[DynamicBatchIndex]]:\n    \"\"\"Intersect masks at each dimensionality level.\n\n    For each dimension d, returns the set of indices (with length d) that appear\n    in every mask that has at least one index at that dimension. Masks with no\n    indices at d are ignored for that dimension. Used for intra-dimensional\n    intersection.\n    \"\"\"\n    sorted_dims = sorted(dimensions)\n    result: Dict[int, Set[DynamicBatchIndex]] = {}\n    for dim in sorted_dims:\n        acc: Optional[Set[DynamicBatchIndex]] = None\n        # Iterate masks once per dimension, but avoid creating intermediate lists\n        for mask in batch_masks:\n            # Build the set of indices in this mask that have length == dim\n            s = {idx for idx in mask if len(idx) == dim}\n            if not s:\n                # Masks with no indices at d are ignored\n                continue\n            if acc is None:\n                # First non-empty set becomes the accumulator (copy to avoid mutating inputs)\n                acc = set(s)\n            else:\n                # Intersect in place to avoid extra temporaries\n                acc &= s\n                if not acc:\n                    # Early break: intersection is empty, further intersections cannot add elements\n                    break\n        result[dim] = acc if acc is not None else set()\n    return result\n\n\ndef filter_to_valid_prefix_chains(\n    per_dim_sets: Dict[int, Set[DynamicBatchIndex]],\n    dimensions: Set[int],\n) -> Dict[int, Set[DynamicBatchIndex]]:\n    \"\"\"Keep only indices that form a complete parent-child chain across dimensions.\n\n    Given per-dimension sets (e.g. from intersect_masks_per_dimension), retains\n    only indices that have a full lineage from the smallest to the largest\n    dimension. Used for inter-level intersection.\n    \"\"\"\n    sorted_dims = sorted(dimensions)\n    by_dim: Dict[int, Set[DynamicBatchIndex]] = {\n        dim: per_dim_sets.get(dim, set()) for dim in sorted_dims\n    }\n\n    if len(sorted_dims) <= 1:\n        return dict(by_dim)\n\n    prev_dim = {sorted_dims[i]: sorted_dims[i - 1] for i in range(1, len(sorted_dims))}\n\n    # Bottom-up: mark indices that have at least one descendant\n    has_child: Set[DynamicBatchIndex] = set()\n    last_dim = sorted_dims[-1]\n    # Iterate from largest to smallest dimension\n    for dim in reversed(sorted_dims):\n        # Localize for speed\n        elems = by_dim[dim]\n        if not elems:\n            continue\n        if dim == last_dim:\n            # Any index at the last level contributes its parent\n            for idx in elems:\n                parent = idx[:-1]\n                if parent:\n                    has_child.add(parent)\n\n    # Top-down: keep indices only if full prefix chain exists\n        else:\n            # Only indices that either are in has_child (i.e., have descendant) should propagate parents\n            for idx in elems:\n                if idx in has_child:\n                    parent = idx[:-1]\n                    if parent:\n                        has_child.add(parent)\n\n    # Top-down: keep indices only if full prefix chain exists\n    valid: Dict[int, Set[DynamicBatchIndex]] = {dim: set() for dim in sorted_dims}\n    first_dim = sorted_dims[0]\n    last_dim = sorted_dims[-1]\n    for dim in sorted_dims:\n        elems = by_dim[dim]\n        if not elems:\n            continue\n        if dim == first_dim:\n            # Root-level indices are valid only if they have at least one descendant\n            for idx in elems:\n                if idx in has_child:\n                    valid[dim].add(idx)\n        else:\n            parent_set = valid[prev_dim[dim]]\n            if not parent_set:\n                # No valid parents at this level, skip early\n                continue\n            if dim == last_dim:\n                # For last dimension, any child of a valid parent is valid\n                for idx in elems:\n                    parent = idx[:-1]\n                    if parent in parent_set:\n                        valid[dim].add(idx)\n            else:\n                # For intermediate dims, require both a valid parent and that this index has a descendant\n                for idx in elems:\n                    parent = idx[:-1]\n                    if parent in parent_set and idx in has_child:\n                        valid[dim].add(idx)\n\n\n    return valid\n\n\ndef get_masks_intersection_for_dimensions(\n    batch_masks: List[Set[DynamicBatchIndex]],\n    dimensions: Set[int],\n) -> Dict[int, Optional[Set[DynamicBatchIndex]]]:\n    \"\"\"Intersect masks at each dimension and filter to valid prefix chains.\"\"\"\n    if not batch_masks:\n        return {dim: None for dim in dimensions}\n\n    sorted_dims = sorted(dimensions)\n\n    if len(sorted_dims) <= 1:\n        result = intersect_masks_per_dimension(batch_masks, dimensions)\n        return {dim: result[dim] for dim in sorted_dims}\n\n    per_dim = intersect_masks_per_dimension(batch_masks, dimensions)\n    return filter_to_valid_prefix_chains(per_dim, dimensions)",
    "optimized_raw_markdown": "```python:inference/core/workflows/execution_engine/v1/executor/execution_data_manager/step_input_assembler.py\nfrom typing import Dict, List, Optional, Set\n\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.dynamic_batches_manager import \\\n    DynamicBatchIndex\n\n\ndef intersect_masks_per_dimension(\n    batch_masks: List[Set[DynamicBatchIndex]],\n    dimensions: Set[int],\n) -> Dict[int, Set[DynamicBatchIndex]]:\n    \"\"\"Intersect masks at each dimensionality level.\n\n    For each dimension d, returns the set of indices (with length d) that appear\n    in every mask that has at least one index at that dimension. Masks with no\n    indices at d are ignored for that dimension. Used for intra-dimensional\n    intersection.\n    \"\"\"\n    sorted_dims = sorted(dimensions)\n    result: Dict[int, Set[DynamicBatchIndex]] = {}\n    for dim in sorted_dims:\n        acc: Optional[Set[DynamicBatchIndex]] = None\n        # Iterate masks once per dimension, but avoid creating intermediate lists\n        for mask in batch_masks:\n            # Build the set of indices in this mask that have length == dim\n            s = {idx for idx in mask if len(idx) == dim}\n            if not s:\n                # Masks with no indices at d are ignored\n                continue\n            if acc is None:\n                # First non-empty set becomes the accumulator (copy to avoid mutating inputs)\n                acc = set(s)\n            else:\n                # Intersect in place to avoid extra temporaries\n                acc &= s\n                if not acc:\n                    # Early break: intersection is empty, further intersections cannot add elements\n                    break\n        result[dim] = acc if acc is not None else set()\n    return result\n\n\ndef filter_to_valid_prefix_chains(\n    per_dim_sets: Dict[int, Set[DynamicBatchIndex]],\n    dimensions: Set[int],\n) -> Dict[int, Set[DynamicBatchIndex]]:\n    \"\"\"Keep only indices that form a complete parent-child chain across dimensions.\n\n    Given per-dimension sets (e.g. from intersect_masks_per_dimension), retains\n    only indices that have a full lineage from the smallest to the largest\n    dimension. Used for inter-level intersection.\n    \"\"\"\n    sorted_dims = sorted(dimensions)\n    by_dim: Dict[int, Set[DynamicBatchIndex]] = {\n        dim: per_dim_sets.get(dim, set()) for dim in sorted_dims\n    }\n\n    if len(sorted_dims) <= 1:\n        return dict(by_dim)\n\n    prev_dim = {sorted_dims[i]: sorted_dims[i - 1] for i in range(1, len(sorted_dims))}\n\n    # Bottom-up: mark indices that have at least one descendant\n    has_child: Set[DynamicBatchIndex] = set()\n    last_dim = sorted_dims[-1]\n    # Iterate from largest to smallest dimension\n    for dim in reversed(sorted_dims):\n        # Localize for speed\n        elems = by_dim[dim]\n        if not elems:\n            continue\n        if dim == last_dim:\n            # Any index at the last level contributes its parent\n            for idx in elems:\n                parent = idx[:-1]\n                if parent:\n                    has_child.add(parent)\n\n    # Top-down: keep indices only if full prefix chain exists\n        else:\n            # Only indices that either are in has_child (i.e., have descendant) should propagate parents\n            for idx in elems:\n                if idx in has_child:\n                    parent = idx[:-1]\n                    if parent:\n                        has_child.add(parent)\n\n    # Top-down: keep indices only if full prefix chain exists\n    valid: Dict[int, Set[DynamicBatchIndex]] = {dim: set() for dim in sorted_dims}\n    first_dim = sorted_dims[0]\n    last_dim = sorted_dims[-1]\n    for dim in sorted_dims:\n        elems = by_dim[dim]\n        if not elems:\n            continue\n        if dim == first_dim:\n            # Root-level indices are valid only if they have at least one descendant\n            for idx in elems:\n                if idx in has_child:\n                    valid[dim].add(idx)\n        else:\n            parent_set = valid[prev_dim[dim]]\n            if not parent_set:\n                # No valid parents at this level, skip early\n                continue\n            if dim == last_dim:\n                # For last dimension, any child of a valid parent is valid\n                for idx in elems:\n                    parent = idx[:-1]\n                    if parent in parent_set:\n                        valid[dim].add(idx)\n            else:\n                # For intermediate dims, require both a valid parent and that this index has a descendant\n                for idx in elems:\n                    parent = idx[:-1]\n                    if parent in parent_set and idx in has_child:\n                        valid[dim].add(idx)\n\n\n    return valid\n\n\ndef get_masks_intersection_for_dimensions(\n    batch_masks: List[Set[DynamicBatchIndex]],\n    dimensions: Set[int],\n) -> Dict[int, Optional[Set[DynamicBatchIndex]]]:\n    \"\"\"Intersect masks at each dimension and filter to valid prefix chains.\"\"\"\n    if not batch_masks:\n        return {dim: None for dim in dimensions}\n\n    sorted_dims = sorted(dimensions)\n\n    if len(sorted_dims) <= 1:\n        result = intersect_masks_per_dimension(batch_masks, dimensions)\n        return {dim: result[dim] for dim in sorted_dims}\n\n    per_dim = intersect_masks_per_dimension(batch_masks, dimensions)\n    return filter_to_valid_prefix_chains(per_dim, dimensions)\n```",
    "optimized_function_only": "def get_masks_intersection_for_dimensions(\n    batch_masks: List[Set[DynamicBatchIndex]],\n    dimensions: Set[int],\n) -> Dict[int, Optional[Set[DynamicBatchIndex]]]:\n    \"\"\"Intersect masks at each dimension and filter to valid prefix chains.\"\"\"\n    if not batch_masks:\n        return {dim: None for dim in dimensions}\n\n    sorted_dims = sorted(dimensions)\n\n    if len(sorted_dims) <= 1:\n        result = intersect_masks_per_dimension(batch_masks, dimensions)\n        return {dim: result[dim] for dim in sorted_dims}\n\n    per_dim = intersect_masks_per_dimension(batch_masks, dimensions)\n    return filter_to_valid_prefix_chains(per_dim, dimensions)",
    "original_file_content": "from dataclasses import dataclass\nfrom typing import Any, Dict, Generator, List, Optional, Set, Tuple, TypeVar, Union\n\nfrom inference.core.workflows.errors import AssumptionError, ExecutionEngineRuntimeError\nfrom inference.core.workflows.execution_engine.entities.base import Batch\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import (\n    AutoBatchCastingConfig,\n    CompoundStepInputDefinition,\n    DynamicStepInputDefinition,\n    StaticStepInputDefinition,\n    StepInputDefinition,\n    StepNode,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import (\n    get_last_chunk_of_selector,\n)\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.branching_manager import (\n    BranchingManager,\n)\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.dynamic_batches_manager import (\n    DynamicBatchesManager,\n    DynamicBatchIndex,\n)\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.execution_cache import (\n    ExecutionCache,\n)\n\nT = TypeVar(\"T\")\n\n\n@dataclass(frozen=True)\nclass BatchModeSIMDStepInput:\n    indices: List[DynamicBatchIndex]\n    parameters: Dict[str, Any]\n\n\n@dataclass(frozen=True)\nclass NonBatchModeSIMDStepInput:\n    index: DynamicBatchIndex\n    parameters: Dict[str, Any]\n\n\ndef construct_non_simd_step_input(\n    step_node: StepNode,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    branching_manager: BranchingManager,\n) -> Optional[Dict[str, Any]]:\n    if step_node.batch_oriented_parameters:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Attempted to get non-SIMD input for SIMD step: {step_node.name}.\"\n            f\"This is most likely a bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    masks = set()\n    for execution_branch in step_node.execution_branches_impacting_inputs:\n        if not branching_manager.is_execution_branch_registered(\n            execution_branch=execution_branch\n        ):\n            masks.add(False)\n            continue\n        if branching_manager.is_execution_branch_batch_oriented(\n            execution_branch=execution_branch\n        ):\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"For step: {step_node.name}, detected batch-oriented condition statements \"\n                f\"impacting non-SIMD step, which should be prevented by Workflows Compiler. \"\n                f\"This is most likely a bug. Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n        else:\n            mask = branching_manager.get_mask(execution_branch=execution_branch)\n            masks.add(mask)\n    if False in masks:\n        return None\n    result = {}\n    detected_empty_step_output_selector = False\n    for parameter_name, parameter_spec in step_node.input_data.items():\n        if parameter_spec.is_compound_input():\n            result[parameter_name], contains_empty_step_output_selector = (\n                construct_non_simd_step_compound_input(\n                    step_node=step_node,\n                    parameter_spec=parameter_spec,\n                    runtime_parameters=runtime_parameters,\n                    execution_cache=execution_cache,\n                )\n            )\n        else:\n            result[parameter_name], contains_empty_step_output_selector = (\n                construct_non_simd_step_non_compound_input(\n                    step_node=step_node,\n                    parameter_spec=parameter_spec,\n                    runtime_parameters=runtime_parameters,\n                    execution_cache=execution_cache,\n                )\n            )\n        detected_empty_step_output_selector = (\n            detected_empty_step_output_selector or contains_empty_step_output_selector\n        )\n    if (\n        detected_empty_step_output_selector\n        and not step_node.step_manifest.accepts_empty_values()\n    ):\n        return None\n    return result\n\n\ndef construct_non_simd_step_compound_input(\n    step_node: StepNode,\n    parameter_spec: CompoundStepInputDefinition,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> Tuple[Any, bool]:\n    if parameter_spec.represents_list_of_inputs():\n        return construct_non_simd_step_compound_list_input(\n            step_node=step_node,\n            parameter_spec=parameter_spec,\n            runtime_parameters=runtime_parameters,\n            execution_cache=execution_cache,\n        )\n    return construct_non_simd_step_compound_dict_input(\n        step_node=step_node,\n        parameter_spec=parameter_spec,\n        runtime_parameters=runtime_parameters,\n        execution_cache=execution_cache,\n    )\n\n\ndef construct_non_simd_step_compound_list_input(\n    step_node: StepNode,\n    parameter_spec: CompoundStepInputDefinition,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> Tuple[List[Any], bool]:\n    result = []\n    contains_empty_step_output_selector = False\n    for nested_definition in parameter_spec.iterate_through_definitions():\n        nested_value, value_contains_empty_selector = (\n            construct_non_simd_step_non_compound_input(\n                step_node=step_node,\n                parameter_spec=nested_definition,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n            )\n        )\n        result.append(nested_value)\n        contains_empty_step_output_selector = (\n            contains_empty_step_output_selector or value_contains_empty_selector\n        )\n    return result, contains_empty_step_output_selector\n\n\ndef construct_non_simd_step_compound_dict_input(\n    step_node: StepNode,\n    parameter_spec: CompoundStepInputDefinition,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> Tuple[Dict[str, Any], bool]:\n    result = {}\n    contains_empty_step_output_selector = False\n    for nested_definition in parameter_spec.iterate_through_definitions():\n        (\n            result[nested_definition.parameter_specification.nested_element_key],\n            value_contains_empty_selector,\n        ) = construct_non_simd_step_non_compound_input(\n            step_node=step_node,\n            parameter_spec=nested_definition,\n            runtime_parameters=runtime_parameters,\n            execution_cache=execution_cache,\n        )\n        contains_empty_step_output_selector = (\n            contains_empty_step_output_selector or value_contains_empty_selector\n        )\n    return result, contains_empty_step_output_selector\n\n\ndef construct_non_simd_step_non_compound_input(\n    step_node: StepNode,\n    parameter_spec: StepInputDefinition,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> Tuple[Any, bool]:\n    if parameter_spec.is_compound_input():\n        raise AssumptionError(\n            public_message=f\"Workflows Execution Error encountered unexpected state probably related to the fact \"\n            f\"that Workflows Compiler allowed for multi-level nesting of inputs selectors which \"\n            f\"is not supported. This is most likely the bug. Contact Roboflow team \"\n            f\"through github issues (https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if parameter_spec.is_batch_oriented():\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Encountered batch-oriented input for non-SIMD step: {step_node.name}.\"\n            f\"This is most likely a bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if parameter_spec.points_to_input():\n        parameter_spec: DynamicStepInputDefinition = parameter_spec  # type: ignore\n        input_name = get_last_chunk_of_selector(selector=parameter_spec.selector)\n        return runtime_parameters[input_name], False\n    if parameter_spec.points_to_step_output():\n        parameter_spec: DynamicStepInputDefinition = parameter_spec  # type: ignore\n        step_output = execution_cache.get_non_batch_output(\n            selector=parameter_spec.selector\n        )\n        return step_output, step_output is None\n    parameter_spec: StaticStepInputDefinition = parameter_spec  # type: ignore\n    return parameter_spec.value, False\n\n\ndef iterate_over_simd_step_input(\n    step_node: StepNode,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    dynamic_batches_manager: DynamicBatchesManager,\n    branching_manager: BranchingManager,\n) -> Generator[NonBatchModeSIMDStepInput, None, None]:\n    simd_step_input = construct_simd_step_input(\n        step_node=step_node,\n        runtime_parameters=runtime_parameters,\n        execution_cache=execution_cache,\n        dynamic_batches_manager=dynamic_batches_manager,\n        branching_manager=branching_manager,\n    )\n    parameters_generator = unfold_parameters(\n        parameters=simd_step_input.parameters,\n        indices=simd_step_input.indices,\n    )\n    for index, single_parameters_set in zip(\n        simd_step_input.indices, parameters_generator\n    ):\n        yield NonBatchModeSIMDStepInput(\n            index=index,\n            parameters=single_parameters_set,\n        )\n\n\ndef construct_simd_step_input(\n    step_node: StepNode,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    dynamic_batches_manager: DynamicBatchesManager,\n    branching_manager: BranchingManager,\n) -> BatchModeSIMDStepInput:\n    masks, scalars_discarded = construct_mask_for_all_inputs_dimensionalities(\n        step_node=step_node,\n        branching_manager=branching_manager,\n    )\n    return prepare_parameters(\n        step_node=step_node,\n        dynamic_batches_manager=dynamic_batches_manager,\n        masks=masks,\n        scalars_discarded=scalars_discarded,\n        runtime_parameters=runtime_parameters,\n        execution_cache=execution_cache,\n    )\n\n\ndef construct_mask_for_all_inputs_dimensionalities(\n    step_node: StepNode,\n    branching_manager: BranchingManager,\n) -> Tuple[Any, bool]:\n    inputs_dimensionalities = collect_inputs_dimensionalities(step_node=step_node)\n    all_dimensionalities = {dim for dim in inputs_dimensionalities.values() if dim > 0}\n    if step_node.control_flow_lineage_support:\n        for dim_level in step_node.control_flow_lineage_dims:\n            all_dimensionalities.add(dim_level)\n    batch_masks, non_batch_masks = [], set()\n    for execution_branch in step_node.execution_branches_impacting_inputs:\n        if not branching_manager.is_execution_branch_registered(\n            execution_branch=execution_branch\n        ):\n            non_batch_masks.add(False)\n            continue\n        if branching_manager.is_execution_branch_batch_oriented(\n            execution_branch=execution_branch\n        ):\n            mask = branching_manager.get_mask(execution_branch=execution_branch)\n            batch_masks.append(mask)\n        else:\n            mask = branching_manager.get_mask(execution_branch=execution_branch)\n            non_batch_masks.add(mask)\n    scalar_mask_contains_false = False in non_batch_masks\n    if scalar_mask_contains_false:\n        return {\n            dimension: set() for dimension in all_dimensionalities\n        }, scalar_mask_contains_false\n    return (\n        get_masks_intersection_for_dimensions(\n            batch_masks=batch_masks,\n            dimensions=all_dimensionalities,\n        ),\n        scalar_mask_contains_false,\n    )\n\n\ndef collect_inputs_dimensionalities(\n    step_node: StepNode,\n) -> Dict[str, int]:\n    result = {}\n    for parameter_name, parameter_specs in step_node.input_data.items():\n        if parameter_specs.is_compound_input():\n            dimensionalities = [\n                nested_definition.get_dimensionality()\n                for nested_definition in parameter_specs.iterate_through_definitions()\n            ]\n            # to help for empty values\n            dimensionalities.append(0)\n            result[parameter_name] = max(dimensionalities)\n        else:\n            result[parameter_name] = parameter_specs.get_dimensionality()\n    return result\n\n\ndef intersect_masks_per_dimension(\n    batch_masks: List[Set[DynamicBatchIndex]],\n    dimensions: Set[int],\n) -> Dict[int, Set[DynamicBatchIndex]]:\n    \"\"\"Intersect masks at each dimensionality level.\n\n    For each dimension d, returns the set of indices (with length d) that appear\n    in every mask that has at least one index at that dimension. Masks with no\n    indices at d are ignored for that dimension. Used for intra-dimensional\n    intersection.\n    \"\"\"\n    sorted_dims = sorted(dimensions)\n    result: Dict[int, Set[DynamicBatchIndex]] = {}\n    for dim in sorted_dims:\n        sets_at_dim = [{idx for idx in mask if len(idx) == dim} for mask in batch_masks]\n        non_empty = [s for s in sets_at_dim if s]\n        result[dim] = set.intersection(*non_empty) if non_empty else set()\n    return result\n\n\ndef filter_to_valid_prefix_chains(\n    per_dim_sets: Dict[int, Set[DynamicBatchIndex]],\n    dimensions: Set[int],\n) -> Dict[int, Set[DynamicBatchIndex]]:\n    \"\"\"Keep only indices that form a complete parent-child chain across dimensions.\n\n    Given per-dimension sets (e.g. from intersect_masks_per_dimension), retains\n    only indices that have a full lineage from the smallest to the largest\n    dimension. Used for inter-level intersection.\n    \"\"\"\n    sorted_dims = sorted(dimensions)\n    by_dim: Dict[int, Set[DynamicBatchIndex]] = {\n        dim: per_dim_sets.get(dim, set()) for dim in sorted_dims\n    }\n\n    if len(sorted_dims) <= 1:\n        return dict(by_dim)\n\n    prev_dim = {sorted_dims[i]: sorted_dims[i - 1] for i in range(1, len(sorted_dims))}\n\n    # Bottom-up: mark indices that have at least one descendant\n    has_child: Set[DynamicBatchIndex] = set()\n    for dim in reversed(sorted_dims):\n        for idx in by_dim[dim]:\n            if dim == sorted_dims[-1] or idx in has_child:\n                parent = idx[:-1]\n                if parent:\n                    has_child.add(parent)\n\n    # Top-down: keep indices only if full prefix chain exists\n    valid: Dict[int, Set[DynamicBatchIndex]] = {dim: set() for dim in sorted_dims}\n    for dim in sorted_dims:\n        for idx in by_dim[dim]:\n            parent = idx[:-1]\n            if dim == sorted_dims[0]:\n                if idx in has_child:\n                    valid[dim].add(idx)\n            elif parent in valid[prev_dim[dim]]:\n                if dim == sorted_dims[-1] or idx in has_child:\n                    valid[dim].add(idx)\n\n    return valid\n\n\ndef get_masks_intersection_for_dimensions(\n    batch_masks: List[Set[DynamicBatchIndex]],\n    dimensions: Set[int],\n) -> Dict[int, Optional[Set[DynamicBatchIndex]]]:\n    \"\"\"Intersect masks at each dimension and filter to valid prefix chains.\"\"\"\n    if not batch_masks:\n        return {dim: None for dim in dimensions}\n\n    sorted_dims = sorted(dimensions)\n\n    if len(sorted_dims) <= 1:\n        result = intersect_masks_per_dimension(batch_masks, dimensions)\n        return {dim: result[dim] for dim in sorted_dims}\n\n    per_dim = intersect_masks_per_dimension(batch_masks, dimensions)\n    return filter_to_valid_prefix_chains(per_dim, dimensions)\n\n\nclass GuardForIndicesWrapping:\n\n    def __init__(self):\n        self._registered_wrapping: Optional[List[DynamicBatchIndex]] = None\n\n    def register_wrapping(\n        self, indices_before_wrapping: List[DynamicBatchIndex]\n    ) -> None:\n        if self._registered_wrapping is None:\n            self._registered_wrapping = indices_before_wrapping\n        elif self._registered_wrapping != indices_before_wrapping:\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Detected a situation when step requires dimensionality wrapping, but\"\n                f\"different inputs register different elements indices to wrap which is illegal \"\n                f\"and should be detected earlier by Workflows compiler. This is most likely a bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n\n\ndef prepare_parameters(\n    step_node: StepNode,\n    dynamic_batches_manager: DynamicBatchesManager,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> BatchModeSIMDStepInput:\n    step_requests_batch_input = step_node.step_manifest.accepts_batch_input()\n    result = {}\n    indices_for_parameter = {}\n    guard_of_indices_wrapping = GuardForIndicesWrapping()\n    compound_inputs = set()\n    contains_empty_scalar_step_output_selector = False\n    for parameter_name, parameter_specs in step_node.input_data.items():\n        if parameter_specs.is_compound_input():\n            (\n                result[parameter_name],\n                indices_for_parameter[parameter_name],\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_compound_parameter_value(\n                parameter=parameter_specs,\n                step_execution_dimensionality=step_node.step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=step_node.auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n            compound_inputs.add(parameter_name)\n        else:\n            (\n                result[parameter_name],\n                indices_for_parameter[parameter_name],\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=parameter_specs,\n                step_execution_dimensionality=step_node.step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=step_node.auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n        contains_empty_scalar_step_output_selector = (\n            contains_empty_scalar_step_output_selector\n            or value_contains_empty_scalar_step_output_selector\n        )\n    batch_parameters_indices = [\n        i for i in indices_for_parameter.values() if i is not None\n    ]\n    ensure_compound_input_indices_match(indices=batch_parameters_indices)\n    if not batch_parameters_indices:\n        if not step_node.control_flow_lineage_support:\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"For step: {step_node.name} which is assessed by Workflows Compiler as \"\n                f\"SIMD step Execution Engine cannot detect neither batch inputs nor control flow inputs. \"\n                f\"This is most likely a bug. Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n        indices = dynamic_batches_manager.get_indices_for_data_lineage(\n            lineage=step_node.control_flow_lineage_support,\n        )\n        mask_dimension = len(step_node.control_flow_lineage_support)\n        mask_for_dimension = masks.get(mask_dimension)\n        if mask_for_dimension is not None:\n            indices = [idx for idx in indices if idx in mask_for_dimension]\n    else:\n        indices = batch_parameters_indices[0]\n    if not step_node.step_manifest.accepts_empty_values():\n        if contains_empty_scalar_step_output_selector:\n            return BatchModeSIMDStepInput(\n                indices=[],\n                parameters={},\n            )\n        empty_indices = get_empty_batch_elements_indices(value=result)\n        if empty_indices:\n            indices = [e for e in indices if e not in empty_indices]\n            result = remove_indices(value=result, indices=empty_indices)\n    return BatchModeSIMDStepInput(\n        indices=indices,\n        parameters=result,\n    )\n\n\ndef get_compound_parameter_value(\n    parameter: CompoundStepInputDefinition,\n    step_execution_dimensionality: int,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n    dynamic_batches_manager: DynamicBatchesManager,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n    auto_batch_casting_lineage_supports: Dict[str, AutoBatchCastingConfig],\n    step_requests_batch_input: bool,\n) -> Tuple[Union[list, Dict[str, Any]], Optional[List[DynamicBatchIndex]], bool]:\n    contains_empty_scalar_step_output_selector = False\n    batch_indices = []\n    if parameter.represents_list_of_inputs():\n        result = []\n        for nested_element in parameter.iterate_through_definitions():\n            (\n                non_compound_parameter_value,\n                non_compound_indices,\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=nested_element,\n                step_execution_dimensionality=step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n            result.append(non_compound_parameter_value)\n            contains_empty_scalar_step_output_selector = (\n                contains_empty_scalar_step_output_selector\n                or value_contains_empty_scalar_step_output_selector\n            )\n            if non_compound_indices is not None:\n                batch_indices.append(non_compound_indices)\n    else:\n        result = {}\n        for nested_element in parameter.iterate_through_definitions():\n            (\n                non_compound_parameter_value,\n                non_compound_indices,\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=nested_element,\n                step_execution_dimensionality=step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n            result[nested_element.parameter_specification.nested_element_key] = (\n                non_compound_parameter_value\n            )\n            contains_empty_scalar_step_output_selector = (\n                contains_empty_scalar_step_output_selector\n                or value_contains_empty_scalar_step_output_selector\n            )\n            if non_compound_indices is not None:\n                batch_indices.append(non_compound_indices)\n    ensure_compound_input_indices_match(indices=batch_indices)\n    result_indices = None\n    if len(batch_indices) > 0:\n        result_indices = batch_indices[0]\n    return result, result_indices, contains_empty_scalar_step_output_selector\n\n\ndef get_non_compound_parameter_value(\n    parameter: StepInputDefinition,\n    step_execution_dimensionality: int,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n    dynamic_batches_manager: DynamicBatchesManager,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n    auto_batch_casting_lineage_supports: Dict[str, AutoBatchCastingConfig],\n    step_requests_batch_input: bool,\n) -> Tuple[Any, Optional[List[DynamicBatchIndex]], bool]:\n    if not parameter.is_batch_oriented():\n        requested_as_batch = (\n            parameter.parameter_specification.parameter_name\n            in auto_batch_casting_lineage_supports\n        )\n        if parameter.points_to_input():\n            input_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n            parameter_name = get_last_chunk_of_selector(\n                selector=input_parameter.selector\n            )\n            if not requested_as_batch:\n                return runtime_parameters[parameter_name], None, False\n            else:\n                return apply_auto_batch_casting(\n                    parameter_name=parameter_name,\n                    value=runtime_parameters[parameter_name],\n                    auto_batch_casting_config=auto_batch_casting_lineage_supports[\n                        parameter.parameter_specification.parameter_name\n                    ],\n                    contains_empty_scalar_step_output_selector=False,\n                    dynamic_batches_manager=dynamic_batches_manager,\n                    step_execution_dimensionality=step_execution_dimensionality,\n                    guard_of_indices_wrapping=guard_of_indices_wrapping,\n                    step_requests_batch_input=step_requests_batch_input,\n                    masks=masks,\n                    scalars_discarded=False,\n                )\n        elif parameter.points_to_step_output():\n            input_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n            value = execution_cache.get_non_batch_output(\n                selector=input_parameter.selector\n            )\n            if not requested_as_batch:\n                return value, None, value is None\n            else:\n                return apply_auto_batch_casting(\n                    parameter_name=parameter.parameter_specification.parameter_name,\n                    value=value,\n                    auto_batch_casting_config=auto_batch_casting_lineage_supports[\n                        parameter.parameter_specification.parameter_name\n                    ],\n                    contains_empty_scalar_step_output_selector=value is None,\n                    dynamic_batches_manager=dynamic_batches_manager,\n                    step_execution_dimensionality=step_execution_dimensionality,\n                    guard_of_indices_wrapping=guard_of_indices_wrapping,\n                    step_requests_batch_input=step_requests_batch_input,\n                    masks=masks,\n                    scalars_discarded=scalars_discarded,\n                )\n        else:\n            static_input: StaticStepInputDefinition = parameter  # type: ignore\n            if not requested_as_batch or static_input.value is None:\n                # when we have Optional[Selector()] in manifest - we must retain\n                # ability to inject None into the run(...) parameters - as\n                # if we treat that as actual batch and broadcast Batch[None],\n                # we would behave exactly as condition execution does -\n                # and the logic executing after this, will filter-out empty\n                # elements - so on None, we behave \"the old way\" regardless of the fact that ABC\n                # was requested\n                return static_input.value, None, False\n            else:\n                return apply_auto_batch_casting(\n                    parameter_name=parameter.parameter_specification.parameter_name,\n                    value=static_input.value,\n                    auto_batch_casting_config=auto_batch_casting_lineage_supports[\n                        parameter.parameter_specification.parameter_name\n                    ],\n                    contains_empty_scalar_step_output_selector=False,\n                    dynamic_batches_manager=dynamic_batches_manager,\n                    step_execution_dimensionality=step_execution_dimensionality,\n                    guard_of_indices_wrapping=guard_of_indices_wrapping,\n                    step_requests_batch_input=step_requests_batch_input,\n                    masks=masks,\n                    scalars_discarded=False,\n                )\n    dynamic_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n    parameter_dimensionality = dynamic_parameter.get_dimensionality()\n    lineage_indices = dynamic_batches_manager.get_indices_for_data_lineage(\n        lineage=dynamic_parameter.data_lineage,\n    )\n    mask_for_dimension = masks[parameter_dimensionality]\n    if dynamic_parameter.points_to_input():\n        input_name = get_last_chunk_of_selector(selector=dynamic_parameter.selector)\n        batch_input = _flatten_batch_oriented_inputs(\n            runtime_parameters[input_name],\n            dimensionality=parameter_dimensionality,\n        )\n        if mask_for_dimension is not None:\n            if len(lineage_indices) != len(batch_input):\n                raise ExecutionEngineRuntimeError(\n                    public_message=f\"Detected a situation when input parameter: \"\n                    f\"{input_name}\"\n                    f\"size is mismatched compared to mask requested for that input. \"\n                    f\"Input length: {len(batch_input)}, mask size: {len(lineage_indices)}. \"\n                    f\"This is most likely a bug. \"\n                    f\"Contact Roboflow team through github issues \"\n                    f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                    f\"the problem - including workflow definition you use.\",\n                    context=\"workflow_execution | step_input_assembling\",\n                )\n            batch_input = [\n                input_element if element_index in mask_for_dimension else None\n                for element_index, input_element in zip(lineage_indices, batch_input)\n            ]\n    else:\n        batch_input = execution_cache.get_batch_output(\n            selector=dynamic_parameter.selector,\n            batch_elements_indices=lineage_indices,\n            mask=mask_for_dimension,\n        )\n    if step_execution_dimensionality == parameter_dimensionality:\n        return Batch(batch_input, lineage_indices), lineage_indices, False\n    if step_execution_dimensionality > parameter_dimensionality:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter.parameter_specification.parameter_name}\"\n            f\"has a dimensionality {parameter_dimensionality} larger \"\n            f\"than step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if abs(parameter_dimensionality - step_execution_dimensionality) > 1:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter.parameter_specification.parameter_name}\"\n            f\"has a dimensionality {parameter_dimensionality} differing more than one level \"\n            f\"from step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if step_execution_dimensionality == 0 and not step_requests_batch_input:\n        return Batch(batch_input, lineage_indices), lineage_indices, False\n    upper_lineage = dynamic_parameter.data_lineage[:-1]\n    if len(upper_lineage) == 0:\n        if not step_requests_batch_input:\n            raise AssumptionError(\n                public_message=f\"Parameter: {parameter.parameter_specification.parameter_name} \"\n                f\"requires dimensionality wrapping, but registered lineage support is incompatible \"\n                f\"which should be detected by the compiler. This is most likely a bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n        upper_level_indices = [()]\n    else:\n        upper_level_indices = dynamic_batches_manager.get_indices_for_data_lineage(\n            lineage=dynamic_parameter.data_lineage[:-1],\n        )\n    result = reduce_batch_dimensionality(\n        indices=lineage_indices,\n        upper_level_index=upper_level_indices,\n        data=batch_input,\n        guard_of_indices_wrapping=guard_of_indices_wrapping,\n    )\n    return result, result.indices, False\n\n\ndef apply_auto_batch_casting(\n    parameter_name: str,\n    value: Any,\n    auto_batch_casting_config: AutoBatchCastingConfig,\n    contains_empty_scalar_step_output_selector: bool,\n    dynamic_batches_manager: DynamicBatchesManager,\n    step_execution_dimensionality: int,\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n    step_requests_batch_input: bool,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n) -> Tuple[Any, List[DynamicBatchIndex], bool]:\n    if auto_batch_casting_config.lineage_support is None:\n        indices = [(0,) * auto_batch_casting_config.casted_dimensionality]\n    else:\n        indices = dynamic_batches_manager.get_indices_for_data_lineage(\n            lineage=auto_batch_casting_config.lineage_support,\n        )\n        missing_dimensions = auto_batch_casting_config.casted_dimensionality - len(\n            auto_batch_casting_config.lineage_support\n        )\n        if missing_dimensions > 0:\n            padding = (0,) * missing_dimensions\n            indices = [i + padding for i in indices]\n    if scalars_discarded:\n        batch_content = [None] * len(indices)\n    elif auto_batch_casting_config.lineage_support is None:\n        batch_content = [value] * len(indices)\n    else:\n        support_dimensionality = len(auto_batch_casting_config.lineage_support)\n        mask_for_support_dimensionality = masks[support_dimensionality]\n        if mask_for_support_dimensionality is None:\n            batch_content = [value] * len(indices)\n        else:\n            batch_content = []\n            for index in indices:\n                if index[:support_dimensionality] in mask_for_support_dimensionality:\n                    batch_content.append(value)\n                else:\n                    batch_content.append(None)\n    created_batch = Batch(content=batch_content, indices=indices)\n    if step_execution_dimensionality == auto_batch_casting_config.casted_dimensionality:\n        return (\n            created_batch,\n            indices,\n            contains_empty_scalar_step_output_selector or scalars_discarded,\n        )\n    if step_execution_dimensionality > auto_batch_casting_config.casted_dimensionality:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter_name}\"\n            f\"has auto-batch casted dimensionality {auto_batch_casting_config.casted_dimensionality} larger \"\n            f\"than step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if (\n        abs(\n            auto_batch_casting_config.casted_dimensionality\n            - step_execution_dimensionality\n        )\n        > 1\n    ):\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter_name} has auto batch casted \"\n            f\"dimensionality {auto_batch_casting_config.casted_dimensionality} differing more than one level \"\n            f\"from step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    upper_level_lineage_dimensionality = (\n        auto_batch_casting_config.casted_dimensionality - 1\n    )\n    if upper_level_lineage_dimensionality == 0 and not step_requests_batch_input:\n        # for batch collapse into scalar\n        return (\n            created_batch,\n            indices,\n            contains_empty_scalar_step_output_selector or scalars_discarded,\n        )\n    if auto_batch_casting_config.lineage_support is None:\n        upper_level_indices = [indices[0][:-1]]\n    else:\n        upper_level_lineage = auto_batch_casting_config.lineage_support[\n            :upper_level_lineage_dimensionality\n        ]\n        if (\n            upper_level_lineage_dimensionality < 1\n            or len(upper_level_lineage) < upper_level_lineage_dimensionality\n        ):\n            if not step_requests_batch_input:\n                raise AssumptionError(\n                    public_message=f\"Detected a situation when parameter: {parameter_name} requires dimensionality \"\n                    f\"wrapping, but registered lineage support is incompatible which should be detected \"\n                    f\"by the compiler. This is most likely a bug. \"\n                    f\"Contact Roboflow team through github issues \"\n                    f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                    f\"the problem - including workflow definition you use.\",\n                    context=\"workflow_execution | step_input_assembling\",\n                )\n            upper_level_indices = [()]\n        else:\n            upper_level_indices = dynamic_batches_manager.get_indices_for_data_lineage(\n                lineage=upper_level_lineage,\n            )\n    result = reduce_batch_dimensionality(\n        indices=indices,\n        upper_level_index=upper_level_indices,\n        data=batch_content,\n        guard_of_indices_wrapping=guard_of_indices_wrapping,\n    )\n    return (\n        result,\n        result.indices,\n        contains_empty_scalar_step_output_selector or scalars_discarded,\n    )\n\n\ndef _flatten_batch_oriented_inputs(\n    inputs: list,\n    dimensionality: int,\n) -> List[Any]:\n    if dimensionality == 0 or not isinstance(inputs, list):\n        raise AssumptionError(\n            public_message=f\"Could not prepare batch-oriented input data. This is most likely the bug. Contact \"\n            f\"Roboflow team through github issues (https://github.com/roboflow/inference/issues) \"\n            f\"providing full context of the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if dimensionality == 1:\n        return inputs\n    result = []\n    for element in inputs:\n        result.extend(\n            _flatten_batch_oriented_inputs(\n                inputs=element, dimensionality=dimensionality - 1\n            )\n        )\n    return result\n\n\ndef reduce_batch_dimensionality(\n    indices: List[DynamicBatchIndex],\n    upper_level_index: List[DynamicBatchIndex],\n    data: List[T],\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n) -> Batch[Optional[Batch[T]]]:\n    guard_of_indices_wrapping.register_wrapping(indices_before_wrapping=indices)\n    already_spotted_downgraded_indices = set()\n    wrapped_batch_index, wrapped_batch_content = [], []\n    upper_level_indices_data = {index: None for index in upper_level_index}\n    for index, data in zip(indices, data):\n        downgraded_index = index[:-1]\n        if downgraded_index in already_spotted_downgraded_indices:\n            wrapped_batch_index.append(index)\n            wrapped_batch_content.append(data)\n        else:\n            if wrapped_batch_index:\n                upper_level_indices_data[wrapped_batch_index[-1][:-1]] = Batch(\n                    content=wrapped_batch_content, indices=wrapped_batch_index\n                )\n            already_spotted_downgraded_indices.add(downgraded_index)\n            wrapped_batch_index = [index]\n            wrapped_batch_content = [data]\n    if wrapped_batch_index:\n        upper_level_indices_data[wrapped_batch_index[-1][:-1]] = Batch(\n            content=wrapped_batch_content, indices=wrapped_batch_index\n        )\n    return Batch(\n        content=[upper_level_indices_data[index] for index in upper_level_index],\n        indices=upper_level_index,\n    )\n\n\ndef ensure_compound_input_indices_match(indices: List[List[DynamicBatchIndex]]) -> None:\n    if len(indices) < 2:\n        return None\n    reference_set = set(indices[0])\n    for index in indices[1:]:\n        other_set = set(index)\n        if reference_set != other_set:\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Detected a situation when step input parameters cannot be created \"\n                f\"due to missmatch in batch element indices. This is most likely a bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n\n\ndef get_empty_batch_elements_indices(value: Any) -> Set[DynamicBatchIndex]:\n    result = set()\n    if isinstance(value, dict):\n        for v in value.values():\n            value_result = get_empty_batch_elements_indices(v)\n            result = result.union(value_result)\n    if isinstance(value, list):\n        for v in value:\n            value_result = get_empty_batch_elements_indices(v)\n            result = result.union(value_result)\n    if isinstance(value, Batch):\n        for index, value_element in value.iter_with_indices():\n            if isinstance(value_element, Batch):\n                value_result = get_empty_batch_elements_indices(value=value_element)\n                result = result.union(value_result)\n            elif value_element is None:\n                result.add(index)\n    return result\n\n\ndef remove_indices(value: Any, indices: Set[DynamicBatchIndex]) -> Any:\n    if isinstance(value, dict):\n        return {k: remove_indices(value=v, indices=indices) for k, v in value.items()}\n    if isinstance(value, list):\n        return [remove_indices(value=v, indices=indices) for v in value]\n    if isinstance(value, Batch):\n        return value.remove_by_indices(indices_to_remove=indices)\n    return value\n\n\ndef unfold_parameters(\n    parameters: Dict[str, Any],\n    indices: Optional[\n        List[tuple]\n    ] = None,  # TODO: none here is only for unit tests to pass\n) -> Generator[Dict[str, Any], None, None]:\n    batch_parameters = get_batch_parameters(parameters=parameters)\n    non_batch_parameters = {\n        k: v for k, v in parameters.items() if k not in batch_parameters\n    }\n    if not batch_parameters:\n        if not non_batch_parameters:\n            return None\n        if indices:\n            for _ in indices:\n                yield non_batch_parameters\n        else:\n            yield non_batch_parameters\n        return None\n    for unfolded_batch_parameters in iterate_over_batches(\n        batch_parameters=batch_parameters\n    ):\n        yield {**unfolded_batch_parameters, **non_batch_parameters}\n\n\ndef get_batch_parameters(parameters: Dict[str, Any]) -> Dict[str, Any]:\n    result = {}\n    for name, value in parameters.items():\n        if isinstance(value, Batch):\n            result[name] = value\n        elif isinstance(value, list) and any(isinstance(v, Batch) for v in value):\n            result[name] = value\n        elif isinstance(value, dict) and any(\n            isinstance(v, Batch) for v in value.values()\n        ):\n            result[name] = value\n    return result\n\n\ndef iterate_over_batches(\n    batch_parameters: Dict[str, Any],\n) -> Generator[Dict[str, Any], None, None]:\n    index = 0\n    end = False\n    while not end:\n        result = {}\n        for name, value in batch_parameters.items():\n            if isinstance(value, Batch):\n                if len(value) <= index:\n                    end = True\n                    break\n                result[name] = value[index]\n            elif isinstance(value, list):\n                to_yield = []\n                for element in value:\n                    if isinstance(element, Batch):\n                        if len(element) <= index:\n                            end = True\n                            break\n                        to_yield.append(element[index])\n                    else:\n                        to_yield.append(element)\n                result[name] = to_yield\n            elif isinstance(value, dict):\n                to_yield = {}\n                for key, key_value in value.items():\n                    if not isinstance(key_value, Batch):\n                        to_yield[key] = key_value\n                    else:\n                        if len(key_value) <= index:\n                            end = True\n                            break\n                        else:\n                            to_yield[key] = key_value[index]\n                result[name] = to_yield\n        index += 1\n        if not end:\n            yield result\n",
    "patch": null
  },
  {
    "trace_id": "0a2dae36-998a-41b2-aeda-6d4da43017d6",
    "function_name": "get_workflow_cache_file",
    "file_path": "inference/core/roboflow_api.py",
    "speedup_x": 0.17,
    "review_quality": "high",
    "pre_optimization_commit": "7ebca7153d72dbe3d62dea55854fe932aef1bd3d",
    "resolution_method": "db_code_match",
    "source": "db_events",
    "original_function_code": "def get_workflow_cache_file(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    workflow_version_id: Optional[str] = None,\n) -> str:\n    sanitized_workspace_id = sanitize_path_segment(workspace_id)\n    sanitized_workflow_id = sanitize_path_segment(workflow_id)\n    if SINGLE_TENANT_WORKFLOW_CACHE:\n        version_suffix = (\n            f\"_v{sanitize_path_segment(workflow_version_id)}\"\n            if workflow_version_id\n            else \"\"\n        )\n        filename = f\"{sanitized_workflow_id}{version_suffix}.json\"\n    else:\n        cache_seed = f\"{workspace_id}:{api_key or ''}\"\n        cache_fingerprint = hashlib.sha256(\n            cache_seed.encode(\"utf-8\"), usedforsecurity=False\n        ).hexdigest()\n        filename = f\"{sanitized_workflow_id}_{cache_fingerprint}.json\"\n    prefix = os.path.abspath(os.path.join(MODEL_CACHE_DIR, \"workflow\"))\n    result = os.path.abspath(\n        os.path.join(\n            prefix,\n            sanitized_workspace_id,\n            filename,\n        )\n    )\n    if not result.startswith(prefix):\n        raise ValueError(\n            \"Detected attempt to save workflow definition in insecure location\"\n        )\n    return result\n",
    "optimized_function_code": "import hashlib\nimport os\nfrom inference.core.entities.types import WorkspaceID\nfrom inference.core.env import MODEL_CACHE_DIR, SINGLE_TENANT_WORKFLOW_CACHE\nfrom inference.core.utils.file_system import sanitize_path_segment\nfrom typing import Optional\n\ndef get_workflow_cache_file(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    workflow_version_id: Optional[str] = None,\n) -> str:\n    sanitized_workspace_id = sanitize_path_segment(workspace_id)\n    sanitized_workflow_id = sanitize_path_segment(workflow_id)\n    if SINGLE_TENANT_WORKFLOW_CACHE:\n        version_suffix = (\n            f\"_v{sanitize_path_segment(workflow_version_id)}\"\n            if workflow_version_id\n            else \"\"\n        )\n        filename = f\"{sanitized_workflow_id}{version_suffix}.json\"\n    else:\n        cache_seed = f\"{workspace_id}:{api_key or ''}\"\n        cache_fingerprint = hashlib.sha256(\n            cache_seed.encode(\"utf-8\"), usedforsecurity=False\n        ).hexdigest()\n        filename = f\"{sanitized_workflow_id}_{cache_fingerprint}.json\"\n    prefix = os.path.abspath(os.path.join(MODEL_CACHE_DIR, \"workflow\"))\n    result = os.path.abspath(\n        os.path.join(\n            prefix,\n            sanitized_workspace_id,\n            filename,\n        )\n    )\n    if not result.startswith(prefix):\n        raise ValueError(\n            \"Detected attempt to save workflow definition in insecure location\"\n        )\n    return result",
    "optimized_raw_markdown": "```python:inference/core/utils/file_system.py\nimport re\n\n# Precompile the pattern so we don't recompile it on every call.\n_pattern = re.compile(r\"[^A-Za-z0-9_-]\")\n\ndef sanitize_path_segment(path_segment: str) -> str:\n    # Keep only letters, numbers, underscores and dashes\n    return _pattern.sub(\"_\", path_segment)\n```\n```python:inference/core/roboflow_api.py\nimport hashlib\nimport os\nfrom inference.core.entities.types import WorkspaceID\nfrom inference.core.env import MODEL_CACHE_DIR, SINGLE_TENANT_WORKFLOW_CACHE\nfrom inference.core.utils.file_system import sanitize_path_segment\nfrom typing import Optional\n\ndef get_workflow_cache_file(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    workflow_version_id: Optional[str] = None,\n) -> str:\n    sanitized_workspace_id = sanitize_path_segment(workspace_id)\n    sanitized_workflow_id = sanitize_path_segment(workflow_id)\n    if SINGLE_TENANT_WORKFLOW_CACHE:\n        version_suffix = (\n            f\"_v{sanitize_path_segment(workflow_version_id)}\"\n            if workflow_version_id\n            else \"\"\n        )\n        filename = f\"{sanitized_workflow_id}{version_suffix}.json\"\n    else:\n        cache_seed = f\"{workspace_id}:{api_key or ''}\"\n        cache_fingerprint = hashlib.sha256(\n            cache_seed.encode(\"utf-8\"), usedforsecurity=False\n        ).hexdigest()\n        filename = f\"{sanitized_workflow_id}_{cache_fingerprint}.json\"\n    prefix = os.path.abspath(os.path.join(MODEL_CACHE_DIR, \"workflow\"))\n    result = os.path.abspath(\n        os.path.join(\n            prefix,\n            sanitized_workspace_id,\n            filename,\n        )\n    )\n    if not result.startswith(prefix):\n        raise ValueError(\n            \"Detected attempt to save workflow definition in insecure location\"\n        )\n    return result\n```",
    "optimized_function_only": "def get_workflow_cache_file(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    workflow_version_id: Optional[str] = None,\n) -> str:\n    sanitized_workspace_id = sanitize_path_segment(workspace_id)\n    sanitized_workflow_id = sanitize_path_segment(workflow_id)\n    if SINGLE_TENANT_WORKFLOW_CACHE:\n        version_suffix = (\n            f\"_v{sanitize_path_segment(workflow_version_id)}\"\n            if workflow_version_id\n            else \"\"\n        )\n        filename = f\"{sanitized_workflow_id}{version_suffix}.json\"\n    else:\n        cache_seed = f\"{workspace_id}:{api_key or ''}\"\n        cache_fingerprint = hashlib.sha256(\n            cache_seed.encode(\"utf-8\"), usedforsecurity=False\n        ).hexdigest()\n        filename = f\"{sanitized_workflow_id}_{cache_fingerprint}.json\"\n    prefix = os.path.abspath(os.path.join(MODEL_CACHE_DIR, \"workflow\"))\n    result = os.path.abspath(\n        os.path.join(\n            prefix,\n            sanitized_workspace_id,\n            filename,\n        )\n    )\n    if not result.startswith(prefix):\n        raise ValueError(\n            \"Detected attempt to save workflow definition in insecure location\"\n        )\n    return result",
    "original_file_content": "import asyncio\nimport base64\nimport binascii\nimport hashlib\nimport json\nimport os\nimport re\nimport time\nimport urllib.parse\nfrom enum import Enum\nfrom hashlib import sha256\nfrom json import JSONDecodeError\nfrom pathlib import Path\nfrom typing import Any, Callable, Dict, List, Optional, Tuple, Type, Union\n\nimport aiohttp\nimport backoff\nimport requests\nfrom cachetools.func import ttl_cache\nfrom requests import Response, Timeout\nfrom requests_toolbelt import MultipartEncoder\n\nfrom inference.core import logger\nfrom inference.core.cache import cache\nfrom inference.core.cache.base import BaseCache\nfrom inference.core.cache.model_artifacts import get_cache_dir, initialise_cache\nfrom inference.core.entities.types import (\n    DatasetID,\n    ModelID,\n    ModelType,\n    TaskType,\n    VersionID,\n    WorkspaceID,\n)\nfrom inference.core.env import (\n    API_BASE_URL,\n    ENFORCE_CREDITS_VERIFICATION,\n    GCP_SERVERLESS,\n    INTERNAL_WEIGHTS_URL_SUFFIX,\n    MD5_VERIFICATION_ENABLED,\n    MODEL_CACHE_DIR,\n    MODELS_CACHE_AUTH_CACHE_MAX_SIZE,\n    MODELS_CACHE_AUTH_CACHE_TTL,\n    MODELS_CACHE_AUTH_ENABLED,\n    RETRY_CONNECTION_ERRORS_TO_ROBOFLOW_API,\n    ROBOFLOW_API_EXTRA_HEADERS,\n    ROBOFLOW_API_REQUEST_TIMEOUT,\n    ROBOFLOW_API_VERIFY_SSL,\n    ROBOFLOW_SERVICE_SECRET,\n    SINGLE_TENANT_WORKFLOW_CACHE,\n    TRANSIENT_ROBOFLOW_API_ERRORS,\n    TRANSIENT_ROBOFLOW_API_ERRORS_RETRIES,\n    TRANSIENT_ROBOFLOW_API_ERRORS_RETRY_INTERVAL,\n    USE_FILE_CACHE_FOR_WORKFLOWS_DEFINITIONS,\n    WORKFLOWS_DEFINITION_CACHE_EXPIRY,\n)\nfrom inference.core.exceptions import (\n    MalformedRoboflowAPIResponseError,\n    MalformedWorkflowResponseError,\n    MissingDefaultModelError,\n    PaymentRequiredError,\n    RetryRequestError,\n    RoboflowAPIConnectionError,\n    RoboflowAPIForbiddenError,\n    RoboflowAPIIAlreadyAnnotatedError,\n    RoboflowAPIIAnnotationRejectionError,\n    RoboflowAPIImageUploadRejectionError,\n    RoboflowAPINotAuthorizedError,\n    RoboflowAPINotNotFoundError,\n    RoboflowAPITimeoutError,\n    RoboflowAPIUnsuccessfulRequestError,\n    RoboflowAPIUsagePausedError,\n    WorkspaceLoadError,\n)\nfrom inference.core.telemetry import record_api_call, record_error, start_span\nfrom inference.core.utils.file_system import sanitize_path_segment\nfrom inference.core.utils.requests import (\n    api_key_safe_raise_for_status,\n    api_key_safe_raise_for_status_aiohttp,\n)\nfrom inference.core.utils.url_utils import wrap_url\nfrom inference.core.version import __version__\n\nLOCAL_API_KEY = \"local\"\n\nENFORCE_CREDITS_VERIFICATION_HEADER = \"x-enforce-credits-verification\"\nENFORCE_INTERNAL_ARTIFACTS_URLS_HEADER = \"x-enforce-internal-artefacts-urls\"\n\nMODEL_TYPE_DEFAULTS = {\n    \"object-detection\": \"yolov5v2s\",\n    \"instance-segmentation\": \"yolact\",\n    \"classification\": \"vit\",\n    \"keypoint-detection\": \"yolov8n\",\n}\nPROJECT_TASK_TYPE_KEY = \"project_task_type\"\nMODEL_TYPE_KEY = \"model_type\"\n\nNOT_FOUND_ERROR_MESSAGE = (\n    \"Could not find requested Roboflow resource. Check that the provided dataset and \"\n    \"version are correct, and check that the provided Roboflow API key has the correct permissions.\"\n)\n\nROBOFLOW_INFERENCE_VERSION_HEADER = \"X-Roboflow-Inference-Version\"\nALLOW_CHUNKED_RESPONSE_HEADER = \"X-Allow-Chunked\"\n\n\ndef raise_from_lambda(\n    inner_error: Exception, exception_type: Type[Exception], message: str\n) -> None:\n    raise exception_type(message) from inner_error\n\n\nDEFAULT_ERROR_HANDLERS = {\n    401: lambda e: raise_from_lambda(\n        e,\n        RoboflowAPINotAuthorizedError,\n        \"Unauthorized access to roboflow API - check API key. Visit \"\n        \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve one.\",\n    ),\n    402: lambda e: raise_from_lambda(\n        e,\n        PaymentRequiredError,\n        \"Not enough credits to perform this request. Verify your workspace billing page.\",\n    ),\n    403: lambda e: raise_from_lambda(\n        e,\n        RoboflowAPIForbiddenError,\n        \"Unauthorized access to roboflow API - check API key regarding correctness and required scopes. Visit \"\n        \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve one.\",\n    ),\n    404: lambda e: raise_from_lambda(\n        e, RoboflowAPINotNotFoundError, NOT_FOUND_ERROR_MESSAGE\n    ),\n    423: lambda e: raise_from_lambda(\n        e,\n        RoboflowAPIUsagePausedError,\n        \"Roboflow API usage is paused. Please contact your workspace administrator to re-enable api keys.\",\n    ),\n}\n\n\ndef wrap_roboflow_api_errors(\n    http_errors_handlers: Optional[\n        Dict[int, Callable[[Union[requests.exceptions.HTTPError]], None]]\n    ] = None,\n) -> callable:\n    def decorator(function: callable) -> callable:\n        def wrapper(*args, **kwargs) -> Any:\n            t_start = time.perf_counter()\n            with start_span(\n                \"roboflow_api.call\",\n                {\"roboflow_api.function\": function.__name__},\n            ):\n                try:\n                    try:\n                        return function(*args, **kwargs)\n                    except RetryRequestError as error:\n                        raise error.inner_error\n                except Timeout as error:\n                    record_error(error)\n                    raise RoboflowAPITimeoutError(\n                        \"Timeout when attempting to connect to Roboflow API.\"\n                    ) from error\n                except (\n                    requests.exceptions.ConnectionError,\n                    ConnectionError,\n                ) as error:\n                    record_error(error)\n                    raise RoboflowAPIConnectionError(\n                        \"Could not connect to Roboflow API.\"\n                    ) from error\n                except requests.exceptions.HTTPError as error:\n                    record_error(error)\n                    user_handler_override = (\n                        http_errors_handlers if http_errors_handlers is not None else {}\n                    )\n                    status_code = error.response.status_code\n                    default_handler = DEFAULT_ERROR_HANDLERS.get(status_code)\n                    error_handler = user_handler_override.get(\n                        status_code, default_handler\n                    )\n                    if error_handler is not None:\n                        error_handler(error)\n                    raise RoboflowAPIUnsuccessfulRequestError(\n                        f\"Unsuccessful request to Roboflow API with response code: {status_code}\"\n                    ) from error\n                except requests.exceptions.InvalidJSONError as error:\n                    record_error(error)\n                    raise MalformedRoboflowAPIResponseError(\n                        \"Could not decode JSON response from Roboflow API.\"\n                    ) from error\n                finally:\n                    record_api_call(function.__name__, time.perf_counter() - t_start)\n\n        return wrapper\n\n    return decorator\n\n\ndef wrap_roboflow_api_errors_async(\n    http_errors_handlers: Optional[\n        Dict[int, Callable[[Union[aiohttp.ClientError]], None]]\n    ] = None,\n) -> callable:\n    def decorator(function: callable) -> callable:\n        async def wrapper(*args, **kwargs) -> Any:\n            t_start = time.perf_counter()\n            with start_span(\n                \"roboflow_api.call\",\n                {\"roboflow_api.function\": function.__name__},\n            ):\n                try:\n                    try:\n                        return await function(*args, **kwargs)\n                    except RetryRequestError as error:\n                        raise error.inner_error\n                except asyncio.TimeoutError as error:\n                    record_error(error)\n                    raise RoboflowAPITimeoutError(\n                        \"Timeout when attempting to connect to Roboflow API.\"\n                    ) from error\n                except (aiohttp.ClientConnectionError, ConnectionError) as error:\n                    record_error(error)\n                    raise RoboflowAPIConnectionError(\n                        \"Could not connect to Roboflow API.\"\n                    ) from error\n                except (aiohttp.ContentTypeError, JSONDecodeError) as error:\n                    record_error(error)\n                    raise MalformedRoboflowAPIResponseError(\n                        \"Could not decode JSON response from Roboflow API.\"\n                    ) from error\n                except aiohttp.ClientResponseError as error:\n                    record_error(error)\n                    user_handler_override = (\n                        http_errors_handlers if http_errors_handlers is not None else {}\n                    )\n                    status_code = error.status\n                    default_handler = DEFAULT_ERROR_HANDLERS.get(status_code)\n                    error_handler = user_handler_override.get(\n                        status_code, default_handler\n                    )\n                    if error_handler is not None:\n                        error_handler(error)\n                    raise RoboflowAPIUnsuccessfulRequestError(\n                        f\"Unsuccessful request to Roboflow API with response code: {status_code}\"\n                    ) from error\n                # remaining aiohttp.ClientError seems to qualify to simply pass-through raise\n                finally:\n                    record_api_call(function.__name__, time.perf_counter() - t_start)\n\n        return wrapper\n\n    return decorator\n\n\n@ttl_cache(ttl=MODELS_CACHE_AUTH_CACHE_TTL, maxsize=MODELS_CACHE_AUTH_CACHE_MAX_SIZE)\n@wrap_roboflow_api_errors()\ndef get_roboflow_workspace(api_key: str) -> WorkspaceID:\n    if not api_key:\n        raise WorkspaceLoadError(\"Empty workspace encountered, check your API key.\")\n\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/\",\n        params=[(\"api_key\", api_key), (\"nocache\", \"true\")],\n    )\n    api_key_info = _get_from_url(url=api_url)\n    workspace_id = api_key_info.get(\"workspace\")\n    if workspace_id is None:\n        raise WorkspaceLoadError(\"Empty workspace encountered, check your API key.\")\n    return workspace_id\n\n\n@wrap_roboflow_api_errors_async()\n@backoff.on_exception(\n    backoff.constant,\n    exception=RetryRequestError,\n    max_tries=TRANSIENT_ROBOFLOW_API_ERRORS_RETRIES,\n    interval=TRANSIENT_ROBOFLOW_API_ERRORS_RETRY_INTERVAL,\n)\nasync def get_roboflow_workspace_async(api_key: str) -> WorkspaceID:\n    try:\n        headers = build_roboflow_api_headers()\n        async with aiohttp.ClientSession() as session:\n            async with session.get(\n                f\"{API_BASE_URL}/\",\n                params={\"api_key\": api_key, \"nocache\": \"true\"},\n                headers=headers,\n                timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n            ) as response:\n                try:\n                    api_key_safe_raise_for_status_aiohttp(response=response)\n                except Exception as error:\n                    if response.status in TRANSIENT_ROBOFLOW_API_ERRORS:\n                        raise RetryRequestError(\n                            message=str(error), inner_error=error\n                        ) from error\n                    raise error\n                response_payload = await response.json()\n                workspace_id = response_payload.get(\"workspace\")\n                if workspace_id is None:\n                    raise WorkspaceLoadError(\n                        \"Empty workspace encountered, check your API key.\"\n                    )\n                return workspace_id\n    except (aiohttp.ClientConnectionError, ConnectionError) as error:\n        if RETRY_CONNECTION_ERRORS_TO_ROBOFLOW_API:\n            raise RetryRequestError(\n                message=\"Connectivity error\", inner_error=error\n            ) from error\n        raise error\n\n\n@wrap_roboflow_api_errors()\ndef add_custom_metadata(\n    api_key: str,\n    workspace_id: WorkspaceID,\n    inference_ids: List[str],\n    field_name: str,\n    field_value: str,\n):\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/inference-stats/metadata\",\n        params=[(\"api_key\", api_key), (\"nocache\", \"true\")],\n    )\n    response = requests.post(\n        url=api_url,\n        json={\n            \"data\": [\n                {\n                    \"inference_ids\": inference_ids,\n                    \"field_name\": field_name,\n                    \"field_value\": field_value,\n                }\n            ]\n        },\n        headers=build_roboflow_api_headers(),\n        timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n        verify=ROBOFLOW_API_VERIFY_SSL,\n    )\n    api_key_safe_raise_for_status(response=response)\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_dataset_type(\n    api_key: str, workspace_id: WorkspaceID, dataset_id: DatasetID\n) -> TaskType:\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/{dataset_id}\",\n        params=[(\"api_key\", api_key), (\"nocache\", \"true\")],\n    )\n    dataset_info = _get_from_url(url=api_url)\n    project_task_type = dataset_info.get(\"project\", {})\n    if \"type\" not in project_task_type:\n        logger.warning(\n            f\"Project task type not defined for workspace={workspace_id} and dataset={dataset_id}, defaulting \"\n            f\"to object-detection.\"\n        )\n    return project_task_type.get(\"type\", \"object-detection\")\n\n\n@wrap_roboflow_api_errors(\n    http_errors_handlers={\n        500: lambda e: raise_from_lambda(\n            e, RoboflowAPINotNotFoundError, NOT_FOUND_ERROR_MESSAGE\n        )\n        # this is temporary solution, empirically checked that backend API responds HTTP 500 on incorrect version.\n        # TO BE FIXED at backend, otherwise this error handling may overshadow existing backend problems.\n    }\n)\ndef get_roboflow_model_type(\n    api_key: str,\n    workspace_id: WorkspaceID,\n    dataset_id: DatasetID,\n    version_id: VersionID,\n    project_task_type: ModelType,\n) -> ModelType:\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/{dataset_id}/{version_id}\",\n        params=[(\"api_key\", api_key), (\"nocache\", \"true\")],\n    )\n    version_info = _get_from_url(url=api_url)\n    model_type = version_info[\"version\"]\n    if \"modelType\" not in model_type:\n        if project_task_type not in MODEL_TYPE_DEFAULTS:\n            raise MissingDefaultModelError(\n                f\"Could not set default model for {project_task_type}\"\n            )\n        logger.warning(\n            f\"Model type not defined - using default for {project_task_type} task.\"\n        )\n    return model_type.get(\"modelType\", MODEL_TYPE_DEFAULTS[project_task_type])\n\n\nclass ModelEndpointType(Enum):\n    ORT = \"ort\"\n    CORE_MODEL = \"core_model\"\n    OWLV2 = \"owlv2\"\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_model_data(\n    api_key: str,\n    model_id: str,\n    endpoint_type: ModelEndpointType,\n    device_id: str,\n    countinference: Optional[bool] = None,\n    service_secret: Optional[str] = None,\n) -> dict:\n    api_data_cache_key = f\"roboflow_api_data:{endpoint_type.value}:{model_id}\"\n    api_data = None\n    if not MODELS_CACHE_AUTH_ENABLED:\n        api_data = cache.get(api_data_cache_key)\n    if api_data is not None:\n        logger.debug(f\"Loaded model data from cache with key: {api_data_cache_key}.\")\n        return api_data\n    else:\n        params = [\n            (\"nocache\", \"true\"),\n            (\"device\", device_id),\n            (\"dynamic\", \"true\"),\n        ]\n        if api_key is not None and api_key != LOCAL_API_KEY:\n            params.append((\"api_key\", api_key))\n\n        if (\n            INTERNAL_WEIGHTS_URL_SUFFIX == \"serverless\"\n            and countinference is False\n            and service_secret == ROBOFLOW_SERVICE_SECRET\n        ):\n            params.append((\"countinference\", str(countinference).lower()))\n            params.append((\"service_secret\", service_secret))\n\n        api_base_url = urllib.parse.urljoin(API_BASE_URL, INTERNAL_WEIGHTS_URL_SUFFIX)\n        api_url = _add_params_to_url(\n            url=f\"{api_base_url}/{endpoint_type.value}/{model_id}\",\n            params=params,\n        )\n        api_data = _get_from_url(url=api_url)\n        cache.set(\n            api_data_cache_key,\n            api_data,\n            expire=10,\n        )\n        logger.debug(\n            f\"Loaded model data from Roboflow API and saved to cache with key: {api_data_cache_key}.\"\n        )\n        return api_data\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_instant_model_data(\n    api_key: str,\n    model_id: ModelID,\n    cache_prefix: str = \"roboflow_api_data\",\n    countinference: Optional[bool] = None,\n    service_secret: Optional[str] = None,\n) -> dict:\n    api_data_cache_key = f\"{cache_prefix}:{model_id}\"\n    api_data = None\n    if not MODELS_CACHE_AUTH_ENABLED:\n        api_data = cache.get(api_data_cache_key)\n    if api_data is not None:\n        logger.debug(f\"Loaded model data from cache with key: {api_data_cache_key}.\")\n        return api_data\n    else:\n        params = [\n            (\"model\", model_id),\n        ]\n        if api_key is not None and api_key != LOCAL_API_KEY:\n            params.append((\"api_key\", api_key))\n\n        if (\n            INTERNAL_WEIGHTS_URL_SUFFIX == \"serverless\"\n            and countinference is False\n            and service_secret == ROBOFLOW_SERVICE_SECRET\n        ):\n            params.append((\"countinference\", str(countinference).lower()))\n            params.append((\"service_secret\", service_secret))\n\n        api_base_url = urllib.parse.urljoin(API_BASE_URL, INTERNAL_WEIGHTS_URL_SUFFIX)\n        api_url = _add_params_to_url(\n            url=f\"{api_base_url}/getWeights\",\n            params=params,\n        )\n        api_data = _get_from_url(url=api_url)\n        cache.set(\n            api_data_cache_key,\n            api_data,\n            expire=10,\n        )\n        logger.debug(\n            f\"Loaded model data from Roboflow API and saved to cache with key: {api_data_cache_key}.\"\n        )\n        return api_data\n\n\n@wrap_roboflow_api_errors()\ndef get_model_metadata_from_inference_models_registry(\n    api_key: str,\n    model_id: ModelID,\n    cache_prefix: str = \"roboflow_api_data:inference_models_registry\",\n    countinference: Optional[bool] = None,\n    service_secret: Optional[str] = None,\n) -> dict:\n    # Watch out - this function should only be used to substitute get_roboflow_instant_model_data()\n    # and only in terms of getting model type and task type\n    # this is only stub to make sure auth works as it should for models which are not\n    # associated to project via version (for which old auth and metadata retrieval method work).\n    api_data_cache_key = f\"{cache_prefix}:{model_id}\"\n    api_data = None\n    if not MODELS_CACHE_AUTH_ENABLED:\n        api_data = cache.get(api_data_cache_key)\n    if api_data is not None:\n        logger.debug(f\"Loaded model data from cache with key: {api_data_cache_key}.\")\n        return api_data\n    query = [(\"modelId\", model_id)]\n    headers = {\"Authorization\": f\"Bearer {api_key}\"}\n    if GCP_SERVERLESS:\n        headers[ENFORCE_INTERNAL_ARTIFACTS_URLS_HEADER] = \"true\"\n    if ENFORCE_CREDITS_VERIFICATION:\n        skip = (\n            countinference is False\n            and service_secret is not None\n            and service_secret == ROBOFLOW_SERVICE_SECRET\n        )\n        if not skip:\n            headers[ENFORCE_CREDITS_VERIFICATION_HEADER] = \"true\"\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/models/v1/external/weights\",\n        params=query,\n    )\n    raw_api_data = _get_from_url(url=api_url, headers=headers)\n    api_data = {\n        \"modelType\": raw_api_data[\"modelMetadata\"][\"modelArchitecture\"],\n        \"taskType\": raw_api_data[\"modelMetadata\"][\"taskType\"],\n    }\n    cache.set(\n        api_data_cache_key,\n        api_data,\n        expire=10,\n    )\n    logger.debug(\n        f\"Loaded model data from Roboflow API (inference-models registry) \"\n        f\"and saved to cache with key: {api_data_cache_key}.\"\n    )\n    return api_data\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_base_lora(\n    api_key: str, repo: str, revision: str, device_id: str\n) -> dict:\n    full_path = f\"{repo.strip('/')}/{revision.strip('/')}\"\n    api_data_cache_key = f\"roboflow_api_data:lora-bases:{full_path}\"\n    api_data = None\n    if not MODELS_CACHE_AUTH_ENABLED:\n        api_data = cache.get(api_data_cache_key)\n    if api_data is not None:\n        logger.debug(f\"Loaded model data from cache with key: {api_data_cache_key}.\")\n        return api_data\n    else:\n        params = [\n            (\"nocache\", \"true\"),\n            (\"device\", device_id),\n            (\"repoAndRevision\", full_path),\n        ]\n        if api_key is not None and api_key != LOCAL_API_KEY:\n            params.append((\"api_key\", api_key))\n        api_url = _add_params_to_url(\n            url=f\"{API_BASE_URL}/lora_bases\",\n            params=params,\n        )\n        api_data = _get_from_url(url=api_url)\n        cache.set(\n            api_data_cache_key,\n            api_data,\n            expire=10,\n        )\n        logger.debug(\n            f\"Loaded lora base model data from Roboflow API and saved to cache with key: {api_data_cache_key}.\"\n        )\n        return api_data\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_active_learning_configuration(\n    api_key: str,\n    workspace_id: WorkspaceID,\n    dataset_id: DatasetID,\n) -> dict:\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/{dataset_id}/active_learning\",\n        params=[(\"api_key\", api_key)],\n    )\n    return _get_from_url(url=api_url)\n\n\n@wrap_roboflow_api_errors()\ndef register_image_at_roboflow(\n    api_key: str,\n    dataset_id: DatasetID,\n    local_image_id: str,\n    image_bytes: bytes,\n    batch_name: str,\n    tags: Optional[List[str]] = None,\n    inference_id: Optional[str] = None,\n    metadata: Optional[Dict[str, Any]] = None,\n) -> dict:\n    url = f\"{API_BASE_URL}/dataset/{dataset_id}/upload\"\n    params = [\n        (\"api_key\", api_key),\n        (\"batch\", batch_name),\n    ]\n    if inference_id is not None:\n        params.append((\"inference_id\", inference_id))\n    tags = tags if tags is not None else []\n    for tag in tags:\n        params.append((\"tag\", tag))\n    wrapped_url = wrap_url(_add_params_to_url(url=url, params=params))\n    fields = {\n        \"name\": f\"{local_image_id}.jpg\",\n        \"file\": (\"imageToUpload\", image_bytes, \"image/jpeg\"),\n    }\n    if metadata is not None:\n        fields[\"metadata\"] = json.dumps(metadata)\n    m = MultipartEncoder(fields=fields)\n    headers = build_roboflow_api_headers(\n        explicit_headers={\"Content-Type\": m.content_type},\n    )\n    response = requests.post(\n        url=wrapped_url,\n        data=m,\n        headers=headers,\n        timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n        verify=ROBOFLOW_API_VERIFY_SSL,\n    )\n    api_key_safe_raise_for_status(response=response)\n    parsed_response = response.json()\n    if not parsed_response.get(\"duplicate\") and not parsed_response.get(\"success\"):\n        raise RoboflowAPIImageUploadRejectionError(\n            f\"Server rejected image: {parsed_response}\"\n        )\n    return parsed_response\n\n\n@wrap_roboflow_api_errors(\n    http_errors_handlers={\n        409: lambda e: raise_from_lambda(\n            e,\n            RoboflowAPIIAlreadyAnnotatedError,\n            \"Given datapoint already has annotation.\",\n        )\n    }\n)\ndef annotate_image_at_roboflow(\n    api_key: str,\n    dataset_id: DatasetID,\n    local_image_id: str,\n    roboflow_image_id: str,\n    annotation_content: str,\n    annotation_file_type: str,\n    is_prediction: bool = True,\n) -> dict:\n    url = f\"{API_BASE_URL}/dataset/{dataset_id}/annotate/{roboflow_image_id}\"\n    params = [\n        (\"api_key\", api_key),\n        (\"name\", f\"{local_image_id}.{annotation_file_type}\"),\n        (\"prediction\", str(is_prediction).lower()),\n    ]\n    wrapped_url = wrap_url(_add_params_to_url(url=url, params=params))\n    headers = build_roboflow_api_headers(\n        explicit_headers={\"Content-Type\": \"text/plain\"},\n    )\n    response = requests.post(\n        wrapped_url,\n        data=annotation_content,\n        headers=headers,\n        timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n        verify=ROBOFLOW_API_VERIFY_SSL,\n    )\n    api_key_safe_raise_for_status(response=response)\n    parsed_response = response.json()\n    if \"error\" in parsed_response or not parsed_response.get(\"success\"):\n        raise RoboflowAPIIAnnotationRejectionError(\n            f\"Failed to save annotation for {roboflow_image_id}. API response: {parsed_response}\"\n        )\n    return parsed_response\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_labeling_batches(\n    api_key: str, workspace_id: WorkspaceID, dataset_id: str\n) -> dict:\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/{dataset_id}/batches\",\n        params=[(\"api_key\", api_key)],\n    )\n    return _get_from_url(url=api_url)\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_labeling_jobs(\n    api_key: str, workspace_id: WorkspaceID, dataset_id: str\n) -> dict:\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/{dataset_id}/jobs\",\n        params=[(\"api_key\", api_key)],\n    )\n    return _get_from_url(url=api_url)\n\n\ndef get_workflow_cache_file(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    workflow_version_id: Optional[str] = None,\n) -> str:\n    sanitized_workspace_id = sanitize_path_segment(workspace_id)\n    sanitized_workflow_id = sanitize_path_segment(workflow_id)\n    if SINGLE_TENANT_WORKFLOW_CACHE:\n        version_suffix = (\n            f\"_v{sanitize_path_segment(workflow_version_id)}\"\n            if workflow_version_id\n            else \"\"\n        )\n        filename = f\"{sanitized_workflow_id}{version_suffix}.json\"\n    else:\n        cache_seed = f\"{workspace_id}:{api_key or ''}\"\n        cache_fingerprint = hashlib.sha256(\n            cache_seed.encode(\"utf-8\"), usedforsecurity=False\n        ).hexdigest()\n        filename = f\"{sanitized_workflow_id}_{cache_fingerprint}.json\"\n    prefix = os.path.abspath(os.path.join(MODEL_CACHE_DIR, \"workflow\"))\n    result = os.path.abspath(\n        os.path.join(\n            prefix,\n            sanitized_workspace_id,\n            filename,\n        )\n    )\n    if not result.startswith(prefix):\n        raise ValueError(\n            \"Detected attempt to save workflow definition in insecure location\"\n        )\n    return result\n\n\ndef cache_workflow_response(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    response: dict,\n    workflow_version_id: Optional[str] = None,\n):\n    workflow_cache_file = get_workflow_cache_file(\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        api_key=api_key,\n        workflow_version_id=workflow_version_id,\n    )\n    workflow_cache_dir = os.path.dirname(workflow_cache_file)\n    if not os.path.exists(workflow_cache_dir):\n        os.makedirs(workflow_cache_dir, exist_ok=True)\n    with open(workflow_cache_file, \"w\") as f:\n        json.dump(response, f)\n\n\ndef delete_cached_workflow_response_if_exists(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    workflow_version_id: Optional[str] = None,\n) -> None:\n    workflow_cache_file = get_workflow_cache_file(\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        api_key=api_key,\n        workflow_version_id=workflow_version_id,\n    )\n    if os.path.exists(workflow_cache_file):\n        os.remove(workflow_cache_file)\n\n\ndef load_cached_workflow_response(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    workflow_version_id: Optional[str] = None,\n) -> Optional[dict]:\n    workflow_cache_file = get_workflow_cache_file(\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        api_key=api_key,\n        workflow_version_id=workflow_version_id,\n    )\n    if not os.path.exists(workflow_cache_file):\n        return None\n    try:\n        with open(workflow_cache_file, \"r\") as f:\n            return json.load(f)\n    except Exception:\n        delete_cached_workflow_response_if_exists(\n            workspace_id=workspace_id,\n            workflow_id=workflow_id,\n            api_key=api_key,\n            workflow_version_id=workflow_version_id,\n        )\n\n\n@wrap_roboflow_api_errors()\ndef get_workflow_specification(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    use_cache: bool = True,\n    ephemeral_cache: Optional[BaseCache] = None,\n    workflow_version_id: Optional[str] = None,\n) -> dict:\n    ephemeral_cache = ephemeral_cache or cache\n    if use_cache:\n        cached_entry = _retrieve_workflow_specification_from_ephemeral_cache(\n            api_key=api_key,\n            workspace_id=workspace_id,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n            ephemeral_cache=ephemeral_cache,\n        )\n        if cached_entry:\n            return cached_entry\n\n    if workspace_id == \"local\":\n        if not re.match(r\"^[\\w\\-]+$\", workflow_id):\n            raise ValueError(\"Invalid workflow id\")\n\n        workflow_hash = sha256(workflow_id.encode()).hexdigest()\n        local_file_path = (\n            Path(MODEL_CACHE_DIR) / \"workflow\" / \"local\" / f\"{workflow_hash}.json\"\n        )\n        if not local_file_path.exists():\n            raise FileNotFoundError(f\"Local workflow file not found: {local_file_path}\")\n\n        with local_file_path.open(\"r\", encoding=\"utf-8\") as f:\n            local_config = json.load(f)\n\n        # Mimic the same shape as the cloud response:\n        response = {\"workflow\": local_config}\n    else:\n        params = []\n        if api_key is not None and api_key != LOCAL_API_KEY:\n            params.append((\"api_key\", api_key))\n        if workflow_version_id is not None:\n            params.append((\"workflow_version\", workflow_version_id))\n        api_url = _add_params_to_url(\n            url=f\"{API_BASE_URL}/{workspace_id}/workflows/{workflow_id}\",\n            params=params,\n        )\n        try:\n            response = _get_from_url(url=api_url)\n            if USE_FILE_CACHE_FOR_WORKFLOWS_DEFINITIONS:\n                cache_workflow_response(\n                    workspace_id=workspace_id,\n                    workflow_id=workflow_id,\n                    api_key=api_key,\n                    response=response,\n                    workflow_version_id=workflow_version_id,\n                )\n        except (\n            requests.exceptions.ConnectionError,\n            ConnectionError,\n            requests.exceptions.Timeout,\n        ) as error:\n            if not USE_FILE_CACHE_FOR_WORKFLOWS_DEFINITIONS:\n                raise error\n            response = load_cached_workflow_response(\n                workspace_id=workspace_id,\n                workflow_id=workflow_id,\n                api_key=api_key,\n                workflow_version_id=workflow_version_id,\n            )\n            if response is None:\n                raise error\n\n    if \"workflow\" not in response or \"config\" not in response[\"workflow\"]:\n        raise MalformedWorkflowResponseError(\n            \"Could not find workflow specification in API response\"\n        )\n    try:\n        workflow_config = json.loads(response[\"workflow\"][\"config\"])\n        specification = workflow_config[\"specification\"]\n        if isinstance(specification, dict):\n            specification[\"id\"] = response[\"workflow\"].get(\"id\")\n        if use_cache:\n            _cache_workflow_specification_in_ephemeral_cache(\n                api_key=api_key,\n                workspace_id=workspace_id,\n                workflow_id=workflow_id,\n                workflow_version_id=workflow_version_id,\n                specification=specification,\n                ephemeral_cache=ephemeral_cache,\n            )\n        return specification\n    except KeyError as error:\n        raise MalformedWorkflowResponseError(\n            \"Workflow specification not found in Roboflow API response\"\n        ) from error\n    except (ValueError, TypeError) as error:\n        raise MalformedWorkflowResponseError(\n            \"Could not decode workflow specification in Roboflow API response\"\n        ) from error\n\n\ndef _retrieve_workflow_specification_from_ephemeral_cache(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    ephemeral_cache: BaseCache,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[dict]:\n    cache_key = _prepare_workflow_response_cache_key(\n        api_key=api_key,\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        workflow_version_id=workflow_version_id,\n    )\n    return ephemeral_cache.get(key=cache_key)\n\n\ndef _cache_workflow_specification_in_ephemeral_cache(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    specification: dict,\n    ephemeral_cache: BaseCache,\n    workflow_version_id: Optional[str] = None,\n) -> None:\n    cache_key = _prepare_workflow_response_cache_key(\n        api_key=api_key,\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        workflow_version_id=workflow_version_id,\n    )\n    ephemeral_cache.set(\n        key=cache_key,\n        value=specification,\n        expire=WORKFLOWS_DEFINITION_CACHE_EXPIRY,\n    )\n\n\ndef _prepare_workflow_response_cache_key(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> str:\n    workflow_version_suffix = (\n        f\":workflow_version={workflow_version_id}\" if workflow_version_id else \"\"\n    )\n    if SINGLE_TENANT_WORKFLOW_CACHE:\n        return (\n            f\"workflow_definition:{workspace_id}:{workflow_id}{workflow_version_suffix}\"\n        )\n    cache_seed = f\"{workspace_id}:{api_key or ''}\"\n    cache_fingerprint = hashlib.sha256(\n        cache_seed.encode(\"utf-8\"), usedforsecurity=False\n    ).hexdigest()\n    return f\"workflow_definition:{workspace_id}:{workflow_id}{workflow_version_suffix}:{cache_fingerprint}\"\n\n\n@wrap_roboflow_api_errors()\ndef get_from_url(\n    url: str,\n    json_response: bool = True,\n) -> Union[Response, dict]:\n    return _get_from_url(\n        url=url,\n        json_response=json_response,\n    )\n\n\n@backoff.on_exception(\n    backoff.constant,\n    exception=RetryRequestError,\n    max_tries=TRANSIENT_ROBOFLOW_API_ERRORS_RETRIES,\n    interval=TRANSIENT_ROBOFLOW_API_ERRORS_RETRY_INTERVAL,\n)\ndef _get_from_url(\n    url: str,\n    json_response: bool = True,\n    headers: Optional[dict] = None,\n) -> Union[Response, dict]:\n    full_url = wrap_url(url)\n    try:\n        response = requests.get(\n            full_url,\n            headers=build_roboflow_api_headers(explicit_headers=headers),\n            timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n            verify=ROBOFLOW_API_VERIFY_SSL,\n        )\n\n    except (ConnectionError, Timeout, requests.exceptions.ConnectionError) as error:\n        if RETRY_CONNECTION_ERRORS_TO_ROBOFLOW_API:\n            raise RetryRequestError(\n                message=\"Connectivity error\", inner_error=error\n            ) from error\n        raise error\n    try:\n        api_key_safe_raise_for_status(response=response)\n    except Exception as error:\n        if response.status_code in TRANSIENT_ROBOFLOW_API_ERRORS:\n            raise RetryRequestError(message=str(error), inner_error=error) from error\n        raise error\n\n    if MD5_VERIFICATION_ENABLED:\n        x_goog_hash = response.headers.get(\"x-goog-hash\")\n        if x_goog_hash is None:\n            logger.warning(\n                f\"MD5 verification enabled but response missing x-goog-hash header. \"\n                f\"Request url: {_url_for_safe_logging(full_url)}\"\n            )\n        else:\n            md5_part = None\n            for part in x_goog_hash.split(\",\"):\n                if part.strip().startswith(\"md5=\"):\n                    md5_part = part.strip()[4:]\n                    break\n            if md5_part is not None:\n                try:\n                    md5_from_header = base64.b64decode(md5_part)\n                except binascii.Error as decode_error:\n                    raise RoboflowAPIUnsuccessfulRequestError(\n                        \"Invalid MD5 value in x-goog-hash header: not valid base64\"\n                    ) from decode_error\n                if md5_from_header != hashlib.md5(response.content).digest():\n                    raise RoboflowAPIUnsuccessfulRequestError(\n                        \"MD5 hash does not match MD5 received from x-goog-hash header\"\n                    )\n            else:\n                logger.warning(\n                    f\"MD5 verification enabled but x-goog-hash header has no md5= part. \"\n                    f\"Request url: {_url_for_safe_logging(full_url)}\"\n                )\n\n    if json_response:\n        return response.json()\n    return response\n\n\ndef _test_range_request(url: str, timeout: int = 10) -> bool:\n    \"\"\"Test if server actually honors range requests by making a real range GET request.\n\n    Note: We can't rely on Accept-Ranges header alone because some servers/CDNs\n    advertise range support but return 200 (full file) instead of 206 (partial).\n    \"\"\"\n    try:\n        headers = {\"Range\": \"bytes=0-0\"}\n        response = requests.get(url, headers=headers, stream=True, timeout=timeout)\n        response.close()\n        if response.status_code == 206:\n            return True\n\n        return False\n    except Exception as e:\n        logger.warning(\n            f\"Failed to test range request support: {e}. Falling back to single-threaded download.\"\n        )\n        return False\n\n\ndef stream_url_to_cache(\n    url: str,\n    filename: str,\n    model_id: str,\n) -> None:\n    from inference_models.utils.download import download_files_to_directory\n\n    with start_span(\n        \"roboflow_api.download_artifact\",\n        {\"http.url\": _url_for_safe_logging(url), \"model.id\": model_id},\n    ):\n        initialise_cache(model_id=model_id)\n        cache_dir = get_cache_dir(model_id=model_id)\n        md5_hash = None\n\n        max_threads = 8 if _test_range_request(url) else 1\n\n        try:\n            download_files_to_directory(\n                target_dir=cache_dir,\n                files_specs=[(filename, wrap_url(url), md5_hash)],\n                verbose=True,\n                download_files_without_hash=True,\n                verify_hash_while_download=False,\n                max_threads_per_download=max_threads,\n            )\n        except Exception as e:\n            raise RoboflowAPIUnsuccessfulRequestError(\n                f\"Failed to download {filename}: {str(e)}\"\n            ) from e\n\n\ndef _url_for_safe_logging(url: str) -> str:\n    \"\"\"Return a URL safe to log by stripping the query string (and params/fragment).\n\n    Expects the full URL as used for the request (e.g. already wrapped).\n    Use this when logging request URLs so that sensitive query parameters\n    (e.g. api_key, tokens) are never written to logs.\n    \"\"\"\n    parsed = urllib.parse.urlparse(url)\n    return urllib.parse.urlunparse(\n        (parsed.scheme, parsed.netloc, parsed.path, \"\", \"\", \"\")\n    )\n\n\ndef _add_params_to_url(url: str, params: List[Tuple[str, str]]) -> str:\n    if len(params) == 0:\n        return url\n    params_chunks = [\n        f\"{name}={urllib.parse.quote_plus(value)}\" for name, value in params\n    ]\n    parameters_string = \"&\".join(params_chunks)\n    return f\"{url}?{parameters_string}\"\n\n\n@wrap_roboflow_api_errors()\ndef send_inference_results_to_model_monitoring(\n    api_key: str,\n    workspace_id: WorkspaceID,\n    inference_data: dict,\n):\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/inference-stats\",\n        params=[(\"api_key\", api_key)],\n    )\n    response = requests.post(\n        url=api_url,\n        json=inference_data,\n        headers=build_roboflow_api_headers(),\n        timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n        verify=ROBOFLOW_API_VERIFY_SSL,\n    )\n    api_key_safe_raise_for_status(response=response)\n\n\ndef get_extra_weights_provider_headers(\n    countinference: Optional[bool] = None,\n    service_secret: Optional[str] = None,\n) -> Optional[Dict[str, str]]:\n    headers = {}\n    if GCP_SERVERLESS:\n        headers[ENFORCE_INTERNAL_ARTIFACTS_URLS_HEADER] = \"true\"\n    if ENFORCE_CREDITS_VERIFICATION:\n        skip = (\n            countinference is False\n            and service_secret is not None\n            and service_secret == ROBOFLOW_SERVICE_SECRET\n        )\n        if not skip:\n            headers[ENFORCE_CREDITS_VERIFICATION_HEADER] = \"true\"\n    return build_roboflow_api_headers(explicit_headers=headers)\n\n\ndef build_roboflow_api_headers(\n    explicit_headers: Optional[Dict[str, Union[str, List[str]]]] = None,\n) -> Dict[str, Union[str, List[str]]]:\n    if explicit_headers is None:\n        explicit_headers = {}\n    explicit_headers = {\n        **explicit_headers,\n        ROBOFLOW_INFERENCE_VERSION_HEADER: __version__,\n        ALLOW_CHUNKED_RESPONSE_HEADER: \"true\",\n    }\n    if not ROBOFLOW_API_EXTRA_HEADERS:\n        return explicit_headers\n    try:\n        extra_headers: dict = json.loads(ROBOFLOW_API_EXTRA_HEADERS)\n        if explicit_headers:\n            extra_headers.update(explicit_headers)\n        return extra_headers\n    except ValueError:\n        logger.warning(\"Could not decode ROBOFLOW_API_EXTRA_HEADERS\")\n        return explicit_headers\n\n\ndef post_to_roboflow_api(\n    endpoint: str,\n    api_key: Optional[str],\n    payload: Optional[dict] = None,\n    params: Optional[List[Tuple[str, str]]] = None,\n    http_errors_handlers: Optional[\n        Dict[int, Callable[[Union[requests.exceptions.HTTPError]], None]]\n    ] = None,\n) -> dict:\n    \"\"\"Generic function to make a POST request to the Roboflow API.\n\n    Args:\n        endpoint: API endpoint path\n        api_key: Roboflow API key\n        payload: JSON payload\n        params: Additional URL parameters\n        http_errors_handlers: Optional custom HTTP error handlers by status code\n    \"\"\"\n\n    @wrap_roboflow_api_errors(http_errors_handlers=http_errors_handlers)\n    def _make_request():\n        url_params = []\n        if api_key and api_key != LOCAL_API_KEY:\n            url_params.append((\"api_key\", api_key))\n        if params:\n            url_params.extend(params)\n\n        full_url = _add_params_to_url(\n            url=f\"{API_BASE_URL}/{endpoint.strip('/')}\", params=url_params\n        )\n        wrapped_url = wrap_url(full_url)\n\n        headers = build_roboflow_api_headers()\n\n        response = requests.post(\n            url=wrapped_url,\n            json=payload,\n            headers=headers,\n            timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n            verify=ROBOFLOW_API_VERIFY_SSL,\n        )\n        api_key_safe_raise_for_status(response=response)\n        return response.json()\n\n    return _make_request()\n",
    "patch": null
  },
  {
    "trace_id": "321633ed-4cbf-4276-b446-71c559c306fe",
    "function_name": "register_datapoint",
    "file_path": "inference/core/workflows/core_steps/sinks/roboflow/dataset_upload/v1.py",
    "speedup_x": 0.16,
    "review_quality": "high",
    "pre_optimization_commit": "c20359386c628a08bde69f5f3f780cedd782c50c",
    "resolution_method": "db_code_match",
    "source": "db_events",
    "original_function_code": "def register_datapoint(\n    target_project: str,\n    encoded_image: bytes,\n    local_image_id: str,\n    prediction: Optional[Union[sv.Detections, dict]],\n    api_key: str,\n    batch_name: str,\n    tags: List[str],\n    metadata: Optional[Dict[str, Any]] = None,\n) -> str:\n    inference_id = None\n    if isinstance(prediction, dict):\n        inference_id = prediction.get(INFERENCE_ID_KEY)\n    if isinstance(prediction, sv.Detections) and len(prediction) > 0:\n        # TODO: Lack of inference ID for empty prediction -\n        #  dependent on https://github.com/roboflow/inference/issues/567\n        inference_id_array = prediction.data.get(INFERENCE_ID_KEY)\n        if inference_id_array is not None:\n            inference_id_list = inference_id_array.tolist()\n            inference_id = inference_id_list[0]\n    roboflow_image_id = safe_register_image_at_roboflow(\n        target_project=target_project,\n        encoded_image=encoded_image,\n        local_image_id=local_image_id,\n        api_key=api_key,\n        batch_name=batch_name,\n        tags=tags,\n        inference_id=inference_id,\n        metadata=metadata,\n    )\n    if roboflow_image_id is None:\n        return DUPLICATED_STATUS\n    if is_prediction_registration_forbidden(prediction=prediction):\n        return \"Successfully registered image\"\n    encoded_prediction, prediction_format = encode_prediction(prediction=prediction)\n    _ = annotate_image_at_roboflow(\n        api_key=api_key,\n        dataset_id=target_project,\n        local_image_id=local_image_id,\n        roboflow_image_id=roboflow_image_id,\n        annotation_content=encoded_prediction,\n        annotation_file_type=prediction_format,\n        is_prediction=True,\n    )\n    return \"Successfully registered image and annotation\"\n",
    "optimized_function_code": "import json\nfrom typing import Any, Dict, List, Optional, Tuple, Union\n\nimport supervision as sv\nfrom inference.core.roboflow_api import (annotate_image_at_roboflow,\n                                         register_image_at_roboflow)\nfrom inference.core.workflows.core_steps.common.serializers import \\\n    serialise_sv_detections\nfrom inference.core.workflows.execution_engine.constants import \\\n    INFERENCE_ID_KEY\n\nDUPLICATED_STATUS = \"Duplicated image\"\n\n\ndef register_datapoint(\n    target_project: str,\n    encoded_image: bytes,\n    local_image_id: str,\n    prediction: Optional[Union[sv.Detections, dict]],\n    api_key: str,\n    batch_name: str,\n    tags: List[str],\n    metadata: Optional[Dict[str, Any]] = None,\n) -> str:\n    inference_id = None\n    if isinstance(prediction, dict):\n        inference_id = prediction.get(INFERENCE_ID_KEY)\n    if isinstance(prediction, sv.Detections) and len(prediction) > 0:\n        # TODO: Lack of inference ID for empty prediction -\n        #  dependent on https://github.com/roboflow/inference/issues/567\n        inference_id_array = prediction.data.get(INFERENCE_ID_KEY)\n        if inference_id_array is not None:\n            inference_id_list = inference_id_array.tolist()\n            inference_id = inference_id_list[0]\n    roboflow_image_id = safe_register_image_at_roboflow(\n        target_project=target_project,\n        encoded_image=encoded_image,\n        local_image_id=local_image_id,\n        api_key=api_key,\n        batch_name=batch_name,\n        tags=tags,\n        inference_id=inference_id,\n        metadata=metadata,\n    )\n    if roboflow_image_id is None:\n        return DUPLICATED_STATUS\n    if is_prediction_registration_forbidden(prediction=prediction):\n        return \"Successfully registered image\"\n    encoded_prediction, prediction_format = encode_prediction(prediction=prediction)\n    _ = annotate_image_at_roboflow(\n        api_key=api_key,\n        dataset_id=target_project,\n        local_image_id=local_image_id,\n        roboflow_image_id=roboflow_image_id,\n        annotation_content=encoded_prediction,\n        annotation_file_type=prediction_format,\n        is_prediction=True,\n    )\n    return \"Successfully registered image and annotation\"\n\n\ndef safe_register_image_at_roboflow(\n    target_project: str,\n    encoded_image: bytes,\n    local_image_id: str,\n    api_key: str,\n    batch_name: str,\n    tags: List[str],\n    inference_id: Optional[str],\n    metadata: Optional[Dict[str, Any]] = None,\n) -> Optional[str]:\n    registration_response = register_image_at_roboflow(\n        api_key=api_key,\n        dataset_id=target_project,\n        local_image_id=local_image_id,\n        image_bytes=encoded_image,\n        batch_name=batch_name,\n        tags=tags,\n        inference_id=inference_id,\n        metadata=metadata,\n    )\n    image_duplicated = registration_response.get(\"duplicate\", False)\n    if image_duplicated:\n        return None\n    return registration_response[\"id\"]\n\n\ndef is_prediction_registration_forbidden(\n    prediction: Optional[Union[sv.Detections, dict]],\n) -> bool:\n    if prediction is None:\n        return True\n    \n    # Check dict type first as it's more common based on profiling\n    if isinstance(prediction, dict):\n        return \"top\" not in prediction and \"predicted_classes\" not in prediction\n    \n    # sv.Detections case\n    return len(prediction) == 0\n\n\n\n\ndef encode_prediction(\n    prediction: Union[sv.Detections, dict],\n) -> Tuple[str, str]:\n    if isinstance(prediction, dict):\n        if \"predicted_classes\" in prediction:\n            return \",\".join(prediction[\"predicted_classes\"]), \"txt\"\n        return prediction[\"top\"], \"txt\"\n    detections_in_inference_format = serialise_sv_detections(detections=prediction)\n    return json.dumps(detections_in_inference_format), \"json\"",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/sinks/roboflow/dataset_upload/v1.py\nimport json\nfrom typing import Any, Dict, List, Optional, Tuple, Union\n\nimport supervision as sv\nfrom inference.core.roboflow_api import (annotate_image_at_roboflow,\n                                         register_image_at_roboflow)\nfrom inference.core.workflows.core_steps.common.serializers import \\\n    serialise_sv_detections\nfrom inference.core.workflows.execution_engine.constants import \\\n    INFERENCE_ID_KEY\n\nDUPLICATED_STATUS = \"Duplicated image\"\n\n\ndef register_datapoint(\n    target_project: str,\n    encoded_image: bytes,\n    local_image_id: str,\n    prediction: Optional[Union[sv.Detections, dict]],\n    api_key: str,\n    batch_name: str,\n    tags: List[str],\n    metadata: Optional[Dict[str, Any]] = None,\n) -> str:\n    inference_id = None\n    if isinstance(prediction, dict):\n        inference_id = prediction.get(INFERENCE_ID_KEY)\n    if isinstance(prediction, sv.Detections) and len(prediction) > 0:\n        # TODO: Lack of inference ID for empty prediction -\n        #  dependent on https://github.com/roboflow/inference/issues/567\n        inference_id_array = prediction.data.get(INFERENCE_ID_KEY)\n        if inference_id_array is not None:\n            inference_id_list = inference_id_array.tolist()\n            inference_id = inference_id_list[0]\n    roboflow_image_id = safe_register_image_at_roboflow(\n        target_project=target_project,\n        encoded_image=encoded_image,\n        local_image_id=local_image_id,\n        api_key=api_key,\n        batch_name=batch_name,\n        tags=tags,\n        inference_id=inference_id,\n        metadata=metadata,\n    )\n    if roboflow_image_id is None:\n        return DUPLICATED_STATUS\n    if is_prediction_registration_forbidden(prediction=prediction):\n        return \"Successfully registered image\"\n    encoded_prediction, prediction_format = encode_prediction(prediction=prediction)\n    _ = annotate_image_at_roboflow(\n        api_key=api_key,\n        dataset_id=target_project,\n        local_image_id=local_image_id,\n        roboflow_image_id=roboflow_image_id,\n        annotation_content=encoded_prediction,\n        annotation_file_type=prediction_format,\n        is_prediction=True,\n    )\n    return \"Successfully registered image and annotation\"\n\n\ndef safe_register_image_at_roboflow(\n    target_project: str,\n    encoded_image: bytes,\n    local_image_id: str,\n    api_key: str,\n    batch_name: str,\n    tags: List[str],\n    inference_id: Optional[str],\n    metadata: Optional[Dict[str, Any]] = None,\n) -> Optional[str]:\n    registration_response = register_image_at_roboflow(\n        api_key=api_key,\n        dataset_id=target_project,\n        local_image_id=local_image_id,\n        image_bytes=encoded_image,\n        batch_name=batch_name,\n        tags=tags,\n        inference_id=inference_id,\n        metadata=metadata,\n    )\n    image_duplicated = registration_response.get(\"duplicate\", False)\n    if image_duplicated:\n        return None\n    return registration_response[\"id\"]\n\n\ndef is_prediction_registration_forbidden(\n    prediction: Optional[Union[sv.Detections, dict]],\n) -> bool:\n    if prediction is None:\n        return True\n    \n    # Check dict type first as it's more common based on profiling\n    if isinstance(prediction, dict):\n        return \"top\" not in prediction and \"predicted_classes\" not in prediction\n    \n    # sv.Detections case\n    return len(prediction) == 0\n\n\n\n\ndef encode_prediction(\n    prediction: Union[sv.Detections, dict],\n) -> Tuple[str, str]:\n    if isinstance(prediction, dict):\n        if \"predicted_classes\" in prediction:\n            return \",\".join(prediction[\"predicted_classes\"]), \"txt\"\n        return prediction[\"top\"], \"txt\"\n    detections_in_inference_format = serialise_sv_detections(detections=prediction)\n    return json.dumps(detections_in_inference_format), \"json\"\n```",
    "optimized_function_only": "def register_datapoint(\n    target_project: str,\n    encoded_image: bytes,\n    local_image_id: str,\n    prediction: Optional[Union[sv.Detections, dict]],\n    api_key: str,\n    batch_name: str,\n    tags: List[str],\n    metadata: Optional[Dict[str, Any]] = None,\n) -> str:\n    inference_id = None\n    if isinstance(prediction, dict):\n        inference_id = prediction.get(INFERENCE_ID_KEY)\n    if isinstance(prediction, sv.Detections) and len(prediction) > 0:\n        # TODO: Lack of inference ID for empty prediction -\n        #  dependent on https://github.com/roboflow/inference/issues/567\n        inference_id_array = prediction.data.get(INFERENCE_ID_KEY)\n        if inference_id_array is not None:\n            inference_id_list = inference_id_array.tolist()\n            inference_id = inference_id_list[0]\n    roboflow_image_id = safe_register_image_at_roboflow(\n        target_project=target_project,\n        encoded_image=encoded_image,\n        local_image_id=local_image_id,\n        api_key=api_key,\n        batch_name=batch_name,\n        tags=tags,\n        inference_id=inference_id,\n        metadata=metadata,\n    )\n    if roboflow_image_id is None:\n        return DUPLICATED_STATUS\n    if is_prediction_registration_forbidden(prediction=prediction):\n        return \"Successfully registered image\"\n    encoded_prediction, prediction_format = encode_prediction(prediction=prediction)\n    _ = annotate_image_at_roboflow(\n        api_key=api_key,\n        dataset_id=target_project,\n        local_image_id=local_image_id,\n        roboflow_image_id=roboflow_image_id,\n        annotation_content=encoded_prediction,\n        annotation_file_type=prediction_format,\n        is_prediction=True,\n    )\n    return \"Successfully registered image and annotation\"\n",
    "original_file_content": "\"\"\"\n*****************************************************************\n*                           WARNING!                            *\n*****************************************************************\nThis module contains the utility functions used by\nRoboflowDatasetUploadBlockV2.\n\nWe do not recommend making multiple blocks dependent on the same code,\nbut the change between v1 and v2 was basically the default value of\nsome parameter - hence we decided not to replicate the code.\n\nIf you need to modify this module beware that you may introduce\nchange to RoboflowDatasetUploadBlockV2! If that happens,\nprobably that's the time to disentangle those blocks and copy the\ncode.\n\"\"\"\n\nimport hashlib\nimport json\nimport logging\nfrom collections import OrderedDict\nfrom concurrent.futures import ThreadPoolExecutor\nfrom datetime import datetime, timedelta\nfrom functools import partial\nfrom typing import Any, Dict, List, Literal, Optional, Tuple, Type, Union\nfrom uuid import uuid4\n\nimport supervision as sv\nfrom fastapi import BackgroundTasks\nfrom pydantic import AliasChoices, ConfigDict, Field\n\nfrom inference.core.active_learning.cache_operations import (\n    return_strategy_credit,\n    use_credit_of_matching_strategy,\n)\nfrom inference.core.active_learning.core import prepare_image_to_registration\nfrom inference.core.active_learning.entities import (\n    ImageDimensions,\n    StrategyLimit,\n    StrategyLimitType,\n)\nfrom inference.core.cache.base import BaseCache\nfrom inference.core.roboflow_api import (\n    annotate_image_at_roboflow,\n    get_roboflow_workspace,\n    register_image_at_roboflow,\n)\nfrom inference.core.workflows.core_steps.common.serializers import (\n    serialise_sv_detections,\n)\nfrom inference.core.workflows.core_steps.common.utils import scale_sv_detections\nfrom inference.core.workflows.execution_engine.constants import INFERENCE_ID_KEY\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    BOOLEAN_KIND,\n    CLASSIFICATION_PREDICTION_KIND,\n    IMAGE_KIND,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    KEYPOINT_DETECTION_PREDICTION_KIND,\n    LIST_OF_VALUES_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    ROBOFLOW_PROJECT_KIND,\n    STRING_KIND,\n    ImageInputField,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    AirGappedAvailability,\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nSHORT_DESCRIPTION = \"Save images and predictions to your Roboflow Dataset.\"\n\nLONG_DESCRIPTION = \"\"\"\nUpload images and model predictions to a Roboflow dataset for active learning, model improvement, and data collection, with configurable usage quotas, batch organization, image compression, and optional annotation persistence.\n\n## How This Block Works\n\nThis block uploads workflow images and predictions to your Roboflow dataset for storage, labeling, and model training. The block:\n\n1. Takes images and optional model predictions (object detection, instance segmentation, keypoint detection, or classification) as input\n2. Validates the Roboflow API key is available (required for uploading)\n3. Checks usage quotas (minutely, hourly, daily limits) to ensure uploads stay within configured rate limits for active learning strategies\n4. Prepares images by resizing if they exceed maximum size (maintaining aspect ratio) and compressing to specified quality level\n5. Generates labeling batch names based on the prefix and batch creation frequency (never, daily, weekly, or monthly), organizing uploaded data into batches\n6. Optionally persists model predictions as annotations if `persist_predictions` is enabled, allowing predictions to serve as pre-labels for review and correction\n7. Attaches registration tags to images for organization and filtering in the Roboflow platform\n8. Registers the image (and annotations if enabled) to the specified Roboflow project via the Roboflow API\n9. Executes synchronously or asynchronously based on `fire_and_forget` setting, allowing non-blocking uploads for faster workflow execution\n10. Returns error status and messages indicating upload success or failure\n\nThe block supports active learning workflows by implementing usage quotas that prevent excessive data collection, helping focus on collecting valuable training data within rate limits. Images are organized into labeling batches that can be automatically recreated on a schedule (daily, weekly, monthly), making it easier to manage and review collected data over time. The block can operate in fire-and-forget mode for asynchronous execution, allowing workflows to continue processing without waiting for uploads to complete, or synchronously for debugging and error handling.\n\n## Requirements\n\n**API Key Required**: This block requires a valid Roboflow API key to upload data. The API key must be configured in your environment or workflow configuration. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve an API key.\n\n## Common Use Cases\n\n- **Active Learning Data Collection**: Collect images and predictions from production environments where models struggle or are uncertain (e.g., low-confidence detections, edge cases), enabling iterative model improvement by gathering challenging examples for retraining\n- **Production Data Logging**: Continuously upload production inference data to Roboflow datasets for monitoring, analysis, and future model training, creating a growing dataset from real-world deployments\n- **Pre-Labeled Data Collection**: Upload images with model predictions as pre-labels (when `persist_predictions` is enabled), accelerating annotation workflows by providing initial labels that can be reviewed and corrected rather than starting from scratch\n- **Stratified Data Sampling**: Use rate limiting and quotas to selectively collect data based on specific criteria (e.g., combine with Rate Limiter or Continue If blocks), ensuring diverse and balanced dataset collection without overwhelming storage or annotation resources\n- **Batch-Based Labeling Workflows**: Organize uploaded data into batches with automatic recreation schedules (daily, weekly, monthly), making it easier to manage labeling tasks, track progress, and organize data collection efforts over time\n- **Tagged Data Organization**: Attach metadata tags to uploaded images (e.g., location, camera ID, time period, model version), enabling filtering and organization of collected data in Roboflow for better dataset management and analysis\n\n## Connecting to Other Blocks\n\nThis block receives data from workflow steps and uploads it to Roboflow:\n\n- **After detection or analysis blocks** (e.g., Object Detection Model, Instance Segmentation Model, Classification Model, Keypoint Detection Model) to upload images along with their predictions, enabling active learning by collecting inference data with model outputs for annotation and retraining\n- **After filtering or analytics blocks** (e.g., Detections Filter, Continue If, Overlap Filter) to selectively upload only specific types of data (e.g., low-confidence detections, overlapping objects, specific classes), focusing data collection on valuable edge cases or interesting scenarios\n- **After rate limiter blocks** (e.g., Rate Limiter) to throttle upload frequency and stay within usage quotas, ensuring controlled data collection that respects rate limits and prevents excessive storage usage\n- **Image inputs or preprocessing blocks** to upload raw images or processed images (e.g., crops, transformed images) without predictions, enabling collection of image data for future labeling or analysis\n- **Conditional workflows** using flow control blocks (e.g., Continue If) to upload data only when certain conditions are met (e.g., upload only when detection count exceeds threshold, upload only errors or failures), enabling selective data collection based on workflow state\n- **Batch processing workflows** where multiple images or predictions are generated, allowing bulk upload of workflow outputs to Roboflow datasets for organized data collection and management\n\"\"\"\n\nWORKSPACE_NAME_CACHE_EXPIRE = 900  # 15 min\nTIMESTAMP_FORMAT = \"%Y_%m_%d\"\nDUPLICATED_STATUS = \"Duplicated image\"\nBatchCreationFrequency = Literal[\"never\", \"daily\", \"weekly\", \"monthly\"]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Roboflow Dataset Upload\",\n            \"version\": \"v1\",\n            \"short_description\": SHORT_DESCRIPTION,\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"sink\",\n            \"ui_manifest\": {\n                \"section\": \"data_storage\",\n                \"icon\": \"fal fa-upload\",\n                \"blockPriority\": 0,\n                \"popular\": True,\n                \"requires_rf_key\": True,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/roboflow_dataset_upload@v1\", \"RoboflowDatasetUpload\"]\n    images: Selector(kind=[IMAGE_KIND]) = Field(\n        title=\"Input Image\",\n        description=\"Image(s) to upload to the Roboflow dataset. Can be a single image or batch of images from workflow inputs or processing steps. Images are resized if they exceed max_image_size and compressed before uploading. Supports batch processing.\",\n        examples=[\"$inputs.image\", \"$steps.cropping.crops\"],\n        validation_alias=AliasChoices(\"image\", \"images\"),\n    )\n    predictions: Optional[\n        Selector(\n            kind=[\n                OBJECT_DETECTION_PREDICTION_KIND,\n                INSTANCE_SEGMENTATION_PREDICTION_KIND,\n                KEYPOINT_DETECTION_PREDICTION_KIND,\n                CLASSIFICATION_PREDICTION_KIND,\n            ]\n        )\n    ] = Field(\n        default=None,\n        description=\"Optional model predictions to upload alongside images. Predictions are saved as annotations (pre-labels) in the Roboflow dataset when persist_predictions is enabled, allowing predictions to serve as starting points for annotation review and correction. Supports object detection, instance segmentation, keypoint detection, and classification predictions. If None, only images are uploaded.\",\n        examples=[\"$steps.object_detection_model.predictions\"],\n    )\n    target_project: Union[Selector(kind=[ROBOFLOW_PROJECT_KIND]), str] = Field(\n        description=\"Roboflow project identifier where uploaded images and annotations will be saved. Must be a valid project in your Roboflow workspace. The project name can be specified directly or referenced from workflow inputs.\",\n        examples=[\"my_project\", \"$inputs.target_project\"],\n    )\n    minutely_usage_limit: int = Field(\n        default=10,\n        description=\"Maximum number of image uploads allowed per minute for this quota. Part of the usage quota system that enforces rate limits for active learning data collection. Uploads exceeding this limit are skipped to prevent excessive data collection. Works together with hourly_usage_limit and daily_usage_limit to provide multi-level rate limiting.\",\n        examples=[10, 60],\n    )\n    hourly_usage_limit: int = Field(\n        default=100,\n        description=\"Maximum number of image uploads allowed per hour for this quota. Part of the usage quota system that enforces rate limits for active learning data collection. Uploads exceeding this limit are skipped to prevent excessive data collection. Works together with minutely_usage_limit and daily_usage_limit to provide multi-level rate limiting.\",\n        examples=[10, 60],\n    )\n    daily_usage_limit: int = Field(\n        default=1000,\n        description=\"Maximum number of image uploads allowed per day for this quota. Part of the usage quota system that enforces rate limits for active learning data collection. Uploads exceeding this limit are skipped to prevent excessive data collection. Works together with minutely_usage_limit and hourly_usage_limit to provide multi-level rate limiting.\",\n        examples=[10, 60],\n    )\n    usage_quota_name: str = Field(\n        description=\"Unique identifier for tracking usage quotas (minutely, hourly, daily limits). Used internally to manage rate limiting across multiple upload operations. Each unique quota name maintains separate counters, allowing different upload strategies or data collection workflows to have independent rate limits.\",\n        examples=[\"quota-for-data-sampling-1\"],\n        json_schema_extra={\"hidden\": True},\n    )\n    max_image_size: Tuple[int, int] = Field(\n        default=(512, 512),\n        description=\"Maximum dimensions (width, height) for uploaded images. Images exceeding these dimensions are automatically resized while preserving aspect ratio before uploading. Smaller sizes reduce storage and bandwidth but may lose image quality. Use larger sizes (e.g., (1920, 1080)) for high-resolution data collection, or smaller sizes (e.g., (512, 512)) for efficient storage and faster uploads.\",\n        examples=[(512, 512), (1920, 1080)],\n    )\n    compression_level: int = Field(\n        default=75,\n        gt=0,\n        le=100,\n        description=\"JPEG compression quality level for uploaded images, ranging from 1 (highest compression, smallest file size, lower quality) to 100 (no compression, largest file size, highest quality). Higher values preserve more image quality but increase storage and bandwidth usage. Typical values range from 70-90 for balanced quality and size. Default of 75 provides good quality with reasonable file sizes.\",\n        examples=[75],\n    )\n    registration_tags: Union[\n        List[Union[Selector(kind=[STRING_KIND]), str]],\n        Selector(kind=[LIST_OF_VALUES_KIND]),\n    ] = Field(\n        default_factory=list,\n        description=\"List of tags to attach to uploaded images for organization and filtering in Roboflow. Tags can be static strings (e.g., 'location-florida', 'camera-1') or dynamic values from workflow inputs. Tags help organize collected data, filter images in Roboflow, and add metadata for dataset management. Can be an empty list if no tags are needed.\",\n        examples=[\n            [\"location-florida\", \"factory-name\", \"$inputs.dynamic_tag\"],\n            \"$inputs.tags\",\n        ],\n    )\n    persist_predictions: bool = Field(\n        default=True,\n        description=\"If True, model predictions are saved as annotations (pre-labels) in the Roboflow dataset alongside images. This enables predictions to serve as starting points for annotation, allowing reviewers to correct or approve labels rather than creating them from scratch. If False, only images are uploaded without annotations. Enabling this accelerates annotation workflows by providing initial labels.\",\n        examples=[True, False],\n    )\n    disable_sink: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=False,\n        description=\"If True, the block execution is disabled and no uploads occur. This allows temporarily disabling data collection without removing the block from workflows, useful for testing, debugging, or conditional data collection. When disabled, returns a message indicating the sink was disabled. Default is False (uploads enabled).\",\n        examples=[True, \"$inputs.disable_active_learning\"],\n    )\n    fire_and_forget: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=True,\n        description=\"If True, uploads execute asynchronously (fire-and-forget mode), allowing the workflow to continue immediately without waiting for upload completion. This improves workflow performance but prevents error handling. If False, uploads execute synchronously, blocking workflow execution until completion and allowing proper error handling and status reporting. Use async mode (True) for production workflows where speed is prioritized, and sync mode (False) for debugging or when error handling is critical.\",\n        examples=[True],\n    )\n    labeling_batch_prefix: Union[str, Selector(kind=[STRING_KIND])] = Field(\n        default=\"workflows_data_collector\",\n        description=\"Prefix used to generate labeling batch names for organizing uploaded images in Roboflow. Combined with the batch recreation frequency and timestamps to create batch names like 'workflows_data_collector_2024_01_15'. Batches help organize collected data for labeling, making it easier to manage and review uploaded images in groups. Can be customized to match your organization scheme.\",\n        examples=[\"my_labeling_batch_name\"],\n    )\n    labeling_batches_recreation_frequency: BatchCreationFrequency = Field(\n        default=\"never\",\n        description=\"Frequency at which new labeling batches are automatically created for uploaded images. Options: 'never' (all images go to the same batch), 'daily' (new batch each day), 'weekly' (new batch each week), 'monthly' (new batch each month). Batch timestamps are appended to the labeling_batch_prefix to create unique batch names. Automatically organizing uploads into time-based batches simplifies dataset management and makes it easier to track and review collected data over time.\",\n        examples=[\"never\", \"daily\"],\n    )\n    image_name: Optional[Union[str, Selector(kind=[STRING_KIND])]] = Field(\n        default=None,\n        description=\"Optional custom name for the uploaded image. If provided, this name will be used instead of an auto-generated UUID. This is useful when you want to preserve the original filename or use a meaningful identifier (e.g., serial number, timestamp) for the image in the Roboflow dataset. The name should not include file extension. If not provided, a UUID will be generated automatically.\",\n        examples=[\"serial_12345\", \"camera1_frame_001\", \"$inputs.filename\"],\n    )\n\n    @classmethod\n    def get_air_gapped_availability(cls) -> AirGappedAvailability:\n        return AirGappedAvailability(available=False, reason=\"requires_internet\")\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return [\"images\", \"predictions\", \"image_name\"]\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"error_status\", kind=[BOOLEAN_KIND]),\n            OutputDefinition(name=\"message\", kind=[STRING_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass RoboflowDatasetUploadBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        cache: BaseCache,\n        api_key: Optional[str],\n        background_tasks: Optional[BackgroundTasks],\n        thread_pool_executor: Optional[ThreadPoolExecutor],\n    ):\n        self._cache = cache\n        self._api_key = api_key\n        self._background_tasks = background_tasks\n        self._thread_pool_executor = thread_pool_executor\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"cache\", \"api_key\", \"background_tasks\", \"thread_pool_executor\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        predictions: Optional[Batch[Union[sv.Detections, dict]]],\n        target_project: str,\n        usage_quota_name: str,\n        minutely_usage_limit: int,\n        persist_predictions: bool,\n        hourly_usage_limit: int,\n        daily_usage_limit: int,\n        max_image_size: Tuple[int, int],\n        compression_level: int,\n        registration_tags: List[str],\n        disable_sink: bool,\n        fire_and_forget: bool,\n        labeling_batch_prefix: str,\n        labeling_batches_recreation_frequency: BatchCreationFrequency,\n        image_name: Optional[Batch[Optional[str]]] = None,\n    ) -> BlockResult:\n        if self._api_key is None:\n            raise ValueError(\n                \"RoboflowDataCollector block cannot run without Roboflow API key. \"\n                \"If you do not know how to get API key - visit \"\n                \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to \"\n                \"retrieve one.\"\n            )\n        if disable_sink:\n            return [\n                {\n                    \"error_status\": False,\n                    \"message\": \"Sink was disabled by parameter `disable_sink`\",\n                }\n                for _ in range(len(images))\n            ]\n        result = []\n        predictions = [None] * len(images) if predictions is None else predictions\n        image_names = [None] * len(images) if image_name is None else image_name\n        for image, prediction, img_name in zip(images, predictions, image_names):\n            error_status, message = register_datapoint_at_roboflow(\n                image=image,\n                prediction=prediction,\n                target_project=target_project,\n                usage_quota_name=usage_quota_name,\n                persist_predictions=persist_predictions,\n                minutely_usage_limit=minutely_usage_limit,\n                hourly_usage_limit=hourly_usage_limit,\n                daily_usage_limit=daily_usage_limit,\n                max_image_size=max_image_size,\n                compression_level=compression_level,\n                registration_tags=registration_tags,\n                fire_and_forget=fire_and_forget,\n                labeling_batch_prefix=labeling_batch_prefix,\n                new_labeling_batch_frequency=labeling_batches_recreation_frequency,\n                cache=self._cache,\n                background_tasks=self._background_tasks,\n                thread_pool_executor=self._thread_pool_executor,\n                api_key=self._api_key,\n                image_name=img_name,\n            )\n            result.append({\"error_status\": error_status, \"message\": message})\n        return result\n\n\ndef register_datapoint_at_roboflow(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    usage_quota_name: str,\n    persist_predictions: bool,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    fire_and_forget: bool,\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    background_tasks: Optional[BackgroundTasks],\n    thread_pool_executor: Optional[ThreadPoolExecutor],\n    api_key: str,\n    image_name: Optional[str] = None,\n    metadata: Optional[Dict[str, Any]] = None,\n) -> Tuple[bool, str]:\n    registration_task = partial(\n        execute_registration,\n        image=image,\n        prediction=prediction,\n        target_project=target_project,\n        usage_quota_name=usage_quota_name,\n        persist_predictions=persist_predictions,\n        minutely_usage_limit=minutely_usage_limit,\n        hourly_usage_limit=hourly_usage_limit,\n        daily_usage_limit=daily_usage_limit,\n        max_image_size=max_image_size,\n        compression_level=compression_level,\n        registration_tags=registration_tags,\n        labeling_batch_prefix=labeling_batch_prefix,\n        new_labeling_batch_frequency=new_labeling_batch_frequency,\n        cache=cache,\n        api_key=api_key,\n        image_name=image_name,\n        metadata=metadata,\n    )\n    if fire_and_forget and background_tasks:\n        background_tasks.add_task(registration_task)\n        return False, \"Element registration happens in the background task\"\n    if fire_and_forget and thread_pool_executor:\n        thread_pool_executor.submit(registration_task)\n        return False, \"Element registration happens in the background task\"\n    return registration_task()\n\n\ndef execute_registration(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    persist_predictions: bool,\n    usage_quota_name: str,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    api_key: str,\n    image_name: Optional[str] = None,\n    metadata: Optional[Dict[str, Any]] = None,\n) -> Tuple[bool, str]:\n    matching_strategies_limits = OrderedDict(\n        {\n            usage_quota_name: [\n                StrategyLimit(\n                    limit_type=StrategyLimitType.MINUTELY, value=minutely_usage_limit\n                ),\n                StrategyLimit(\n                    limit_type=StrategyLimitType.HOURLY, value=hourly_usage_limit\n                ),\n                StrategyLimit(\n                    limit_type=StrategyLimitType.DAILY, value=daily_usage_limit\n                ),\n            ]\n        }\n    )\n    workspace_name = get_workspace_name(api_key=api_key, cache=cache)\n    strategy_with_spare_credit = use_credit_of_matching_strategy(\n        cache=cache,\n        workspace=workspace_name,\n        project=target_project,\n        matching_strategies_limits=matching_strategies_limits,\n    )\n    if strategy_with_spare_credit is None:\n        return False, \"Registration skipped due to usage quota exceeded\"\n    credit_to_be_returned = False\n    try:\n        local_image_id = image_name if image_name else str(uuid4())\n        encoded_image, scaling_factor = prepare_image_to_registration(\n            image=image.numpy_image,\n            desired_size=ImageDimensions(\n                width=max_image_size[0], height=max_image_size[1]\n            ),\n            jpeg_compression_level=compression_level,\n        )\n        batch_name = generate_batch_name(\n            labeling_batch_prefix=labeling_batch_prefix,\n            new_labeling_batch_frequency=new_labeling_batch_frequency,\n        )\n        if isinstance(prediction, sv.Detections):\n            prediction = scale_sv_detections(\n                detections=prediction, scale=scaling_factor\n            )\n        status = register_datapoint(\n            target_project=target_project,\n            encoded_image=encoded_image,\n            local_image_id=local_image_id,\n            prediction=prediction if persist_predictions else None,\n            api_key=api_key,\n            batch_name=batch_name,\n            tags=registration_tags,\n            metadata=metadata,\n        )\n        if status == DUPLICATED_STATUS:\n            credit_to_be_returned = True\n        return False, status\n    except Exception as error:\n        credit_to_be_returned = True\n        logging.exception(\"Failed to register datapoint on the Roboflow platform\")\n        return (\n            True,\n            f\"Error while registration. Error type: {type(error)}. Details: {error}\",\n        )\n    finally:\n        if credit_to_be_returned:\n            return_strategy_credit(\n                cache=cache,\n                workspace=workspace_name,\n                project=target_project,\n                strategy_name=strategy_with_spare_credit,\n            )\n\n\ndef get_workspace_name(\n    api_key: str,\n    cache: BaseCache,\n) -> str:\n    api_key_hash = hashlib.md5(api_key.encode(\"utf-8\")).hexdigest()\n    cache_key = f\"workflows:api_key_to_workspace:{api_key_hash}\"\n    cached_workspace_name = cache.get(cache_key)\n    if cached_workspace_name:\n        return cached_workspace_name\n    workspace_name_from_api = get_roboflow_workspace(api_key=api_key)\n    cache.set(\n        key=cache_key, value=workspace_name_from_api, expire=WORKSPACE_NAME_CACHE_EXPIRE\n    )\n    return workspace_name_from_api\n\n\ndef generate_batch_name(\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n) -> str:\n    if new_labeling_batch_frequency == \"never\":\n        return labeling_batch_prefix\n    timestamp_generator = RECREATION_INTERVAL2TIMESTAMP_GENERATOR[\n        new_labeling_batch_frequency\n    ]\n    timestamp = timestamp_generator()\n    return f\"{labeling_batch_prefix}_{timestamp}\"\n\n\ndef generate_today_timestamp() -> str:\n    return datetime.today().strftime(TIMESTAMP_FORMAT)\n\n\ndef generate_start_timestamp_for_this_week() -> str:\n    today = datetime.today()\n    return (today - timedelta(days=today.weekday())).strftime(TIMESTAMP_FORMAT)\n\n\ndef generate_start_timestamp_for_this_month() -> str:\n    return datetime.today().replace(day=1).strftime(TIMESTAMP_FORMAT)\n\n\nRECREATION_INTERVAL2TIMESTAMP_GENERATOR = {\n    \"daily\": generate_today_timestamp,\n    \"weekly\": generate_start_timestamp_for_this_week,\n    \"monthly\": generate_start_timestamp_for_this_month,\n}\n\n\ndef register_datapoint(\n    target_project: str,\n    encoded_image: bytes,\n    local_image_id: str,\n    prediction: Optional[Union[sv.Detections, dict]],\n    api_key: str,\n    batch_name: str,\n    tags: List[str],\n    metadata: Optional[Dict[str, Any]] = None,\n) -> str:\n    inference_id = None\n    if isinstance(prediction, dict):\n        inference_id = prediction.get(INFERENCE_ID_KEY)\n    if isinstance(prediction, sv.Detections) and len(prediction) > 0:\n        # TODO: Lack of inference ID for empty prediction -\n        #  dependent on https://github.com/roboflow/inference/issues/567\n        inference_id_array = prediction.data.get(INFERENCE_ID_KEY)\n        if inference_id_array is not None:\n            inference_id_list = inference_id_array.tolist()\n            inference_id = inference_id_list[0]\n    roboflow_image_id = safe_register_image_at_roboflow(\n        target_project=target_project,\n        encoded_image=encoded_image,\n        local_image_id=local_image_id,\n        api_key=api_key,\n        batch_name=batch_name,\n        tags=tags,\n        inference_id=inference_id,\n        metadata=metadata,\n    )\n    if roboflow_image_id is None:\n        return DUPLICATED_STATUS\n    if is_prediction_registration_forbidden(prediction=prediction):\n        return \"Successfully registered image\"\n    encoded_prediction, prediction_format = encode_prediction(prediction=prediction)\n    _ = annotate_image_at_roboflow(\n        api_key=api_key,\n        dataset_id=target_project,\n        local_image_id=local_image_id,\n        roboflow_image_id=roboflow_image_id,\n        annotation_content=encoded_prediction,\n        annotation_file_type=prediction_format,\n        is_prediction=True,\n    )\n    return \"Successfully registered image and annotation\"\n\n\ndef safe_register_image_at_roboflow(\n    target_project: str,\n    encoded_image: bytes,\n    local_image_id: str,\n    api_key: str,\n    batch_name: str,\n    tags: List[str],\n    inference_id: Optional[str],\n    metadata: Optional[Dict[str, Any]] = None,\n) -> Optional[str]:\n    registration_response = register_image_at_roboflow(\n        api_key=api_key,\n        dataset_id=target_project,\n        local_image_id=local_image_id,\n        image_bytes=encoded_image,\n        batch_name=batch_name,\n        tags=tags,\n        inference_id=inference_id,\n        metadata=metadata,\n    )\n    image_duplicated = registration_response.get(\"duplicate\", False)\n    if image_duplicated:\n        logging.warning(f\"Image duplication detected: {registration_response}.\")\n        return None\n    return registration_response[\"id\"]\n\n\ndef is_prediction_registration_forbidden(\n    prediction: Optional[Union[sv.Detections, dict]],\n) -> bool:\n    if prediction is None:\n        return True\n    if isinstance(prediction, sv.Detections) and len(prediction) == 0:\n        return True\n    if isinstance(prediction, dict) and (\n        \"top\" not in prediction and \"predicted_classes\" not in prediction\n    ):\n        return True\n    return False\n\n\ndef encode_prediction(\n    prediction: Union[sv.Detections, dict],\n) -> Tuple[str, str]:\n    if isinstance(prediction, dict):\n        if \"predicted_classes\" in prediction:\n            return \",\".join(prediction[\"predicted_classes\"]), \"txt\"\n        return prediction[\"top\"], \"txt\"\n    detections_in_inference_format = serialise_sv_detections(detections=prediction)\n    return json.dumps(detections_in_inference_format), \"json\"\n",
    "patch": null
  },
  {
    "trace_id": "9f6c0572-73bd-45ce-b933-b75948932430",
    "function_name": "RFDETRObjectDetection.postprocess",
    "file_path": "inference/models/rfdetr/rfdetr.py",
    "speedup_x": 0.13,
    "review_quality": "high",
    "pre_optimization_commit": "6078c43bae0aa336aef12e324b9a9008a35d2408",
    "resolution_method": "git_parent",
    "source": "db_events",
    "original_function_code": "    def postprocess(\n        self,\n        predictions: Tuple[np.ndarray, ...],\n        preproc_return_metadata: PreprocessReturnMetadata,\n        confidence: float = DEFAULT_CONFIDENCE,\n        max_detections: int = DEFAUlT_MAX_DETECTIONS,\n        **kwargs,\n    ) -> List[ObjectDetectionInferenceResponse]:\n        bboxes, logits = predictions\n        bboxes = bboxes.astype(np.float32)\n        logits = logits.astype(np.float32)\n\n        batch_size, num_queries, num_classes = logits.shape\n        logits_sigmoid = self.sigmoid_stable(logits)\n\n        img_dims = preproc_return_metadata[\"img_dims\"]\n\n        processed_predictions = []\n\n        for batch_idx in range(batch_size):\n            orig_h, orig_w = img_dims[batch_idx]\n\n            logits_flat = logits_sigmoid[batch_idx].reshape(-1)\n\n            sorted_indices = np.argsort(-logits_flat)[:max_detections]\n            topk_scores = logits_flat[sorted_indices]\n\n            conf_mask = topk_scores > confidence\n            sorted_indices = sorted_indices[conf_mask]\n            topk_scores = topk_scores[conf_mask]\n\n            topk_boxes = sorted_indices // num_classes\n            topk_labels = sorted_indices % num_classes\n\n            if self.is_one_indexed:\n                class_filter_mask = topk_labels != self.background_class_index\n\n                topk_labels[topk_labels > self.background_class_index] -= 1\n                topk_scores = topk_scores[class_filter_mask]\n                topk_labels = topk_labels[class_filter_mask]\n                topk_boxes = topk_boxes[class_filter_mask]\n\n            selected_boxes = bboxes[batch_idx, topk_boxes]\n\n            cxcy = selected_boxes[:, :2]\n            wh = selected_boxes[:, 2:]\n            xy_min = cxcy - 0.5 * wh\n            xy_max = cxcy + 0.5 * wh\n            boxes_xyxy = np.concatenate([xy_min, xy_max], axis=1)\n\n            if self.resize_method == \"Stretch to\":\n                scale_fct = np.array([orig_w, orig_h, orig_w, orig_h], dtype=np.float32)\n                boxes_xyxy *= scale_fct\n            else:\n                input_h, input_w = self.img_size_h, self.img_size_w\n\n                scale = min(input_w / orig_w, input_h / orig_h)\n                scaled_w = int(orig_w * scale)\n                scaled_h = int(orig_h * scale)\n\n                pad_x = (input_w - scaled_w) / 2\n                pad_y = (input_h - scaled_h) / 2\n\n                boxes_input = boxes_xyxy * np.array(\n                    [input_w, input_h, input_w, input_h], dtype=np.float32\n                )\n\n                boxes_input[:, 0] -= pad_x\n                boxes_input[:, 1] -= pad_y\n                boxes_input[:, 2] -= pad_x\n                boxes_input[:, 3] -= pad_y\n\n                boxes_xyxy = boxes_input / scale\n\n            np.clip(\n                boxes_xyxy,\n                [0, 0, 0, 0],\n                [orig_w, orig_h, orig_w, orig_h],\n                out=boxes_xyxy,\n            )\n\n            batch_predictions = np.column_stack(\n                (\n                    boxes_xyxy,\n                    topk_scores,\n                    np.zeros((len(topk_scores), 1), dtype=np.float32),\n                    topk_labels,\n                )\n            )\n\n            processed_predictions.append(batch_predictions)\n\n        return self.make_response(processed_predictions, img_dims, **kwargs)\n",
    "optimized_function_code": "import os\nfrom time import perf_counter\nfrom typing import Any, List, Tuple, Union\n\nimport cv2\nimport numpy as np\nimport onnxruntime\n\nfrom inference.core.entities.requests.inference import InferenceRequestImage\nfrom inference.core.env import (\n    DISABLE_PREPROC_AUTO_ORIENT,\n    FIX_BATCH_SIZE,\n    MAX_BATCH_SIZE,\n    REQUIRED_ONNX_PROVIDERS,\n    USE_PYTORCH_FOR_PREPROCESSING,\n)\nfrom inference.core.exceptions import ModelArtefactError, OnnxProviderNotAvailable\nfrom inference.core.logger import logger\nfrom inference.core.models.defaults import DEFAULT_CONFIDENCE, DEFAUlT_MAX_DETECTIONS\nfrom inference.core.models.object_detection_base import (\n    ObjectDetectionBaseOnnxRoboflowInferenceModel,\n    ObjectDetectionInferenceResponse,\n)\nfrom inference.core.models.types import PreprocessReturnMetadata\nfrom inference.core.models.utils.onnx import has_trt\nfrom inference.core.utils.image_utils import load_image\nfrom inference.core.utils.onnx import ImageMetaType, run_session_via_iobinding\nfrom inference.core.utils.preprocess import letterbox_image\nfrom inference.core.entities.responses.inference import ObjectDetectionInferenceResponse\n\nif USE_PYTORCH_FOR_PREPROCESSING:\n    import torch\n\nROBOFLOW_BACKGROUND_CLASS = \"background_class83422\"\n\n\nclass RFDETRObjectDetection(ObjectDetectionBaseOnnxRoboflowInferenceModel):\n    \"\"\"Roboflow ONNX Object detection with the RFDETR model.\n\n    This class is responsible for performing object detection using the RFDETR model\n    with ONNX runtime.\n\n    Attributes:\n        weights_file (str): Path to the ONNX weights file.\n\n    Methods:\n        predict: Performs object detection on the given image using the ONNX session.\n    \"\"\"\n\n    preprocess_means = [0.485, 0.456, 0.406]\n    preprocess_stds = [0.229, 0.224, 0.225]\n\n    @property\n    def weights_file(self) -> str:\n        \"\"\"Gets the weights file for the RFDETR model.\n\n        Returns:\n            str: Path to the ONNX weights file.\n        \"\"\"\n        return \"weights.onnx\"\n\n    def preproc_image(\n        self,\n        image: Union[Any, InferenceRequestImage],\n        disable_preproc_auto_orient: bool = False,\n        disable_preproc_contrast: bool = False,\n        disable_preproc_grayscale: bool = False,\n        disable_preproc_static_crop: bool = False,\n    ) -> Tuple[np.ndarray, Tuple[int, int]]:\n        \"\"\"\n        Preprocesses an inference request image by loading it, then applying any pre-processing specified by the Roboflow platform, then scaling it to the inference input dimensions.\n\n        Args:\n            image (Union[Any, InferenceRequestImage]): An object containing information necessary to load the image for inference.\n            disable_preproc_auto_orient (bool, optional): If true, the auto orient preprocessing step is disabled for this call. Default is False.\n            disable_preproc_contrast (bool, optional): If true, the contrast preprocessing step is disabled for this call. Default is False.\n            disable_preproc_grayscale (bool, optional): If true, the grayscale preprocessing step is disabled for this call. Default is False.\n            disable_preproc_static_crop (bool, optional): If true, the static crop preprocessing step is disabled for this call. Default is False.\n\n        Returns:\n            Tuple[np.ndarray, Tuple[int, int]]: A tuple containing a numpy array of the preprocessed image pixel data and a tuple of the images original size.\n        \"\"\"\n        np_image, is_bgr = load_image(\n            image,\n            disable_preproc_auto_orient=disable_preproc_auto_orient\n            or \"auto-orient\" not in self.preproc.keys()\n            or DISABLE_PREPROC_AUTO_ORIENT,\n        )\n        preprocessed_image, img_dims = self.preprocess_image(\n            np_image,\n            disable_preproc_contrast=disable_preproc_contrast,\n            disable_preproc_grayscale=disable_preproc_grayscale,\n            disable_preproc_static_crop=disable_preproc_static_crop,\n        )\n\n        preprocessed_image = preprocessed_image.astype(np.float32)\n        preprocessed_image /= 255.0\n\n        preprocessed_image[:, :, 0] = (\n            preprocessed_image[:, :, 0] - self.preprocess_means[0]\n        ) / self.preprocess_stds[0]\n        preprocessed_image[:, :, 1] = (\n            preprocessed_image[:, :, 1] - self.preprocess_means[1]\n        ) / self.preprocess_stds[1]\n        preprocessed_image[:, :, 2] = (\n            preprocessed_image[:, :, 2] - self.preprocess_means[2]\n        ) / self.preprocess_stds[2]\n\n        if USE_PYTORCH_FOR_PREPROCESSING:\n            preprocessed_image = torch.from_numpy(\n                np.ascontiguousarray(preprocessed_image)\n            )\n            if torch.cuda.is_available():\n                preprocessed_image = preprocessed_image.cuda()\n            preprocessed_image = (\n                preprocessed_image.permute(2, 0, 1).unsqueeze(0).contiguous().float()\n            )\n\n        if self.resize_method == \"Stretch to\":\n            if isinstance(preprocessed_image, np.ndarray):\n                preprocessed_image = preprocessed_image.astype(np.float32)\n                resized = cv2.resize(\n                    preprocessed_image,\n                    (self.img_size_w, self.img_size_h),\n                )\n            elif USE_PYTORCH_FOR_PREPROCESSING:\n                resized = torch.nn.functional.interpolate(\n                    preprocessed_image,\n                    size=(self.img_size_h, self.img_size_w),\n                    mode=\"bilinear\",\n                )\n            else:\n                raise ValueError(\n                    f\"Received an image of unknown type, {type(preprocessed_image)}; \"\n                    \"This is most likely a bug. Contact Roboflow team through github issues \"\n                    \"(https://github.com/roboflow/inference/issues) providing full context of the problem\"\n                )\n\n        elif self.resize_method == \"Fit (black edges) in\":\n            resized = letterbox_image(\n                preprocessed_image, (self.img_size_w, self.img_size_h)\n            )\n        elif self.resize_method == \"Fit (white edges) in\":\n            resized = letterbox_image(\n                preprocessed_image,\n                (self.img_size_w, self.img_size_h),\n                color=(255, 255, 255),\n            )\n        elif self.resize_method == \"Fit (grey edges) in\":\n            resized = letterbox_image(\n                preprocessed_image,\n                (self.img_size_w, self.img_size_h),\n                color=(114, 114, 114),\n            )\n\n        if is_bgr:\n            if isinstance(resized, np.ndarray):\n                resized = cv2.cvtColor(resized, cv2.COLOR_BGR2RGB)\n            else:\n                resized = resized[:, [2, 1, 0], :, :]\n\n        if isinstance(resized, np.ndarray):\n            img_in = np.transpose(resized, (2, 0, 1))\n            img_in = img_in.astype(np.float32)\n            img_in = np.expand_dims(img_in, axis=0)\n        elif USE_PYTORCH_FOR_PREPROCESSING:\n            img_in = resized.float()\n        else:\n            raise ValueError(\n                f\"Received an image of unknown type, {type(resized)}; \"\n                \"This is most likely a bug. Contact Roboflow team through github issues \"\n                \"(https://github.com/roboflow/inference/issues) providing full context of the problem\"\n            )\n        return img_in, img_dims\n\n    def preprocess(\n        self,\n        image: Any,\n        disable_preproc_auto_orient: bool = False,\n        disable_preproc_contrast: bool = False,\n        disable_preproc_grayscale: bool = False,\n        disable_preproc_static_crop: bool = False,\n        fix_batch_size: bool = False,\n        **kwargs,\n    ) -> Tuple[np.ndarray, PreprocessReturnMetadata]:\n        img_in, img_dims = self.load_image(\n            image,\n            disable_preproc_auto_orient=disable_preproc_auto_orient,\n            disable_preproc_contrast=disable_preproc_contrast,\n            disable_preproc_grayscale=disable_preproc_grayscale,\n            disable_preproc_static_crop=disable_preproc_static_crop,\n        )\n        img_in = img_in.astype(np.float32)\n\n        if self.batching_enabled:\n            batch_padding = 0\n            if FIX_BATCH_SIZE or fix_batch_size:\n                if MAX_BATCH_SIZE == float(\"inf\"):\n                    logger.warning(\n                        \"Requested fix_batch_size but MAX_BATCH_SIZE is not set. Using dynamic batching.\"\n                    )\n                    batch_padding = 0\n                else:\n                    batch_padding = MAX_BATCH_SIZE - img_in.shape[0]\n            if batch_padding < 0:\n                raise ValueError(\n                    f\"Requested fix_batch_size but passed in {img_in.shape[0]} images \"\n                    f\"when the model's batch size is {MAX_BATCH_SIZE}\\n\"\n                    f\"Consider turning off fix_batch_size, changing `MAX_BATCH_SIZE` in\"\n                    f\"your inference server config, or passing at most {MAX_BATCH_SIZE} images at a time\"\n                )\n            else:\n                raise ValueError(\n                    f\"Received an image of unknown type, {type(img_in)}; \"\n                    \"This is most likely a bug. Contact Roboflow team through github issues \"\n                    \"(https://github.com/roboflow/inference/issues) providing full context of the problem\"\n                )\n\n        return img_in, PreprocessReturnMetadata(\n            {\n                \"img_dims\": img_dims,\n                \"disable_preproc_static_crop\": disable_preproc_static_crop,\n            }\n        )\n\n    def predict(self, img_in: ImageMetaType, **kwargs) -> Tuple[np.ndarray]:\n        \"\"\"Performs object detection on the given image using the ONNX session with the RFDETR model.\n\n        Args:\n            img_in (np.ndarray): Input image as a NumPy array.\n\n        Returns:\n            Tuple[np.ndarray]: NumPy array representing the predictions, including boxes, confidence scores, and class IDs.\n        \"\"\"\n        predictions = run_session_via_iobinding(\n            self.onnx_session, self.input_name, img_in\n        )\n        bboxes = predictions[0]\n        logits = predictions[1]\n\n        return (bboxes, logits)\n\n    def sigmoid_stable(self, x):\n        # More efficient, branchless, numerically stable sigmoid computation\n        z = np.exp(-np.abs(x))\n        return np.where(x >= 0, 1 / (1 + z), z / (1 + z))\n\n    def postprocess(\n        self,\n        predictions: Tuple[np.ndarray, ...],\n        preproc_return_metadata: PreprocessReturnMetadata,\n        confidence: float = DEFAULT_CONFIDENCE,\n        max_detections: int = DEFAUlT_MAX_DETECTIONS,\n        **kwargs,\n    ) -> List[ObjectDetectionInferenceResponse]:\n        bboxes, logits = predictions\n        bboxes = bboxes.astype(np.float32)\n        logits = logits.astype(np.float32)\n\n        batch_size, num_queries, num_classes = logits.shape\n        logits_sigmoid = self.sigmoid_stable(logits)\n\n        img_dims = preproc_return_metadata[\"img_dims\"]\n\n        processed_predictions = []\n\n        for batch_idx in range(batch_size):\n            orig_h, orig_w = img_dims[batch_idx]\n\n            logits_flat = logits_sigmoid[batch_idx].reshape(-1)\n\n            # Use argpartition for better performance when max_detections is smaller than logits_flat\n            partition_indices = np.argpartition(-logits_flat, max_detections)[\n                :max_detections\n            ]\n            sorted_indices = partition_indices[\n                np.argsort(-logits_flat[partition_indices])\n            ]\n            topk_scores = logits_flat[sorted_indices]\n\n            conf_mask = topk_scores > confidence\n            sorted_indices = sorted_indices[conf_mask]\n            topk_scores = topk_scores[conf_mask]\n\n            topk_boxes = sorted_indices // num_classes\n            topk_labels = sorted_indices % num_classes\n\n            if self.is_one_indexed:\n                class_filter_mask = topk_labels != self.background_class_index\n\n                topk_labels[topk_labels > self.background_class_index] -= 1\n                topk_scores = topk_scores[class_filter_mask]\n                topk_labels = topk_labels[class_filter_mask]\n                topk_boxes = topk_boxes[class_filter_mask]\n\n            selected_boxes = bboxes[batch_idx, topk_boxes]\n\n            cxcy = selected_boxes[:, :2]\n            wh = selected_boxes[:, 2:]\n            xy_min = cxcy - 0.5 * wh\n            xy_max = cxcy + 0.5 * wh\n            boxes_xyxy = np.concatenate([xy_min, xy_max], axis=1)\n\n            if self.resize_method == \"Stretch to\":\n                scale_fct = np.array([orig_w, orig_h, orig_w, orig_h], dtype=np.float32)\n                boxes_xyxy *= scale_fct\n            else:\n                input_h, input_w = self.img_size_h, self.img_size_w\n\n                scale = min(input_w / orig_w, input_h / orig_h)\n                scaled_w = int(orig_w * scale)\n                scaled_h = int(orig_h * scale)\n\n                pad_x = (input_w - scaled_w) / 2\n                pad_y = (input_h - scaled_h) / 2\n\n                boxes_input = boxes_xyxy * np.array(\n                    [input_w, input_h, input_w, input_h], dtype=np.float32\n                )\n\n                boxes_input[:, 0] -= pad_x\n                boxes_input[:, 1] -= pad_y\n                boxes_input[:, 2] -= pad_x\n                boxes_input[:, 3] -= pad_y\n\n                boxes_xyxy = boxes_input / scale\n\n            np.clip(\n                boxes_xyxy,\n                [0, 0, 0, 0],\n                [orig_w, orig_h, orig_w, orig_h],\n                out=boxes_xyxy,\n            )\n\n            batch_predictions = np.column_stack(\n                (\n                    boxes_xyxy,\n                    topk_scores,\n                    np.zeros((len(topk_scores), 1), dtype=np.float32),\n                    topk_labels,\n                )\n            )\n\n            processed_predictions.append(batch_predictions)\n\n        return self.make_response(processed_predictions, img_dims, **kwargs)\n\n    def initialize_model(self) -> None:\n        \"\"\"Initializes the ONNX model, setting up the inference session and other necessary properties.\"\"\"\n        logger.debug(\"Getting model artefacts\")\n        self.get_model_artifacts()\n        logger.debug(\"Creating inference session\")\n        if self.load_weights or not self.has_model_metadata:\n            t1_session = perf_counter()\n            # We exclude CoreMLExecutionProvider as it is showing worse performance than CPUExecutionProvider\n            providers = [\n                \"CUDAExecutionProvider\",\n                \"CPUExecutionProvider\",\n            ]  # \"OpenVINOExecutionProvider\" dropped until further investigation is done\n\n            if not self.load_weights:\n                providers = [\n                    \"CPUExecutionProvider\"\n                ]  # \"OpenVINOExecutionProvider\" dropped until further investigation is done\n\n            try:\n                session_options = onnxruntime.SessionOptions()\n                session_options.log_severity_level = 3\n                # TensorRT does better graph optimization for its EP than onnx\n                if has_trt(providers):\n                    session_options.graph_optimization_level = (\n                        onnxruntime.GraphOptimizationLevel.ORT_DISABLE_ALL\n                    )\n                self.onnx_session = onnxruntime.InferenceSession(\n                    self.cache_file(self.weights_file),\n                    providers=providers,\n                    sess_options=session_options,\n                )\n            except Exception as e:\n                self.clear_cache()\n                raise ModelArtefactError(\n                    f\"Unable to load ONNX session. Cause: {e}\"\n                ) from e\n            logger.debug(f\"Session created in {perf_counter() - t1_session} seconds\")\n\n            if REQUIRED_ONNX_PROVIDERS:\n                available_providers = onnxruntime.get_available_providers()\n                for provider in REQUIRED_ONNX_PROVIDERS:\n                    if provider not in available_providers:\n                        raise OnnxProviderNotAvailable(\n                            f\"Required ONNX Execution Provider {provider} is not availble. \"\n                            \"Check that you are using the correct docker image on a supported device. \"\n                            \"Export list of available providers as ONNXRUNTIME_EXECUTION_PROVIDERS environmental variable, \"\n                            \"consult documentation for more details.\"\n                        )\n\n            inputs = self.onnx_session.get_inputs()[0]\n            input_shape = inputs.shape\n            self.batch_size = input_shape[0]\n            self.img_size_h = input_shape[2]\n            self.img_size_w = input_shape[3]\n            self.input_name = inputs.name\n            if isinstance(self.img_size_h, str) or isinstance(self.img_size_w, str):\n                if \"resize\" in self.preproc:\n                    self.img_size_h = int(self.preproc[\"resize\"][\"height\"])\n                    self.img_size_w = int(self.preproc[\"resize\"][\"width\"])\n                else:\n                    self.img_size_h = 640\n                    self.img_size_w = 640\n\n            if isinstance(self.batch_size, str):\n                self.batching_enabled = True\n                logger.debug(\n                    f\"Model {self.endpoint} is loaded with dynamic batching enabled\"\n                )\n            else:\n                self.batching_enabled = False\n                logger.debug(\n                    f\"Model {self.endpoint} is loaded with dynamic batching disabled\"\n                )\n\n            model_metadata = {\n                \"batch_size\": self.batch_size,\n                \"img_size_h\": self.img_size_h,\n                \"img_size_w\": self.img_size_w,\n            }\n            logger.debug(f\"Writing model metadata to memcache\")\n            self.write_model_metadata_to_memcache(model_metadata)\n            if not self.load_weights:  # had to load weights to get metadata\n                del self.onnx_session\n        else:\n            if not self.has_model_metadata:\n                raise ValueError(\n                    \"This should be unreachable, should get weights if we don't have model metadata\"\n                )\n            logger.debug(f\"Loading model metadata from memcache\")\n            metadata = self.model_metadata_from_memcache()\n            self.batch_size = metadata[\"batch_size\"]\n            self.img_size_h = metadata[\"img_size_h\"]\n            self.img_size_w = metadata[\"img_size_w\"]\n            if isinstance(self.batch_size, str):\n                self.batching_enabled = True\n                logger.debug(\n                    f\"Model {self.endpoint} is loaded with dynamic batching enabled\"\n                )\n            else:\n                self.batching_enabled = False\n                logger.debug(\n                    f\"Model {self.endpoint} is loaded with dynamic batching disabled\"\n                )\n\n        if ROBOFLOW_BACKGROUND_CLASS in self.class_names:\n            self.is_one_indexed = True\n            self.background_class_index = self.class_names.index(\n                ROBOFLOW_BACKGROUND_CLASS\n            )\n            self.class_names = (\n                self.class_names[: self.background_class_index]\n                + self.class_names[self.background_class_index + 1 :]\n            )\n        else:\n            self.is_one_indexed = False\n        logger.debug(\"Model initialisation finished.\")\n\n    def validate_model_classes(self) -> None:\n        pass\n",
    "optimized_raw_markdown": "",
    "optimized_function_only": "    def postprocess(\n        self,\n        predictions: Tuple[np.ndarray, ...],\n        preproc_return_metadata: PreprocessReturnMetadata,\n        confidence: float = DEFAULT_CONFIDENCE,\n        max_detections: int = DEFAUlT_MAX_DETECTIONS,\n        **kwargs,\n    ) -> List[ObjectDetectionInferenceResponse]:\n        bboxes, logits = predictions\n        bboxes = bboxes.astype(np.float32)\n        logits = logits.astype(np.float32)\n\n        batch_size, num_queries, num_classes = logits.shape\n        logits_sigmoid = self.sigmoid_stable(logits)\n\n        img_dims = preproc_return_metadata[\"img_dims\"]\n\n        processed_predictions = []\n\n        for batch_idx in range(batch_size):\n            orig_h, orig_w = img_dims[batch_idx]\n\n            logits_flat = logits_sigmoid[batch_idx].reshape(-1)\n\n            # Use argpartition for better performance when max_detections is smaller than logits_flat\n            partition_indices = np.argpartition(-logits_flat, max_detections)[\n                :max_detections\n            ]\n            sorted_indices = partition_indices[\n                np.argsort(-logits_flat[partition_indices])\n            ]\n            topk_scores = logits_flat[sorted_indices]\n\n            conf_mask = topk_scores > confidence\n            sorted_indices = sorted_indices[conf_mask]\n            topk_scores = topk_scores[conf_mask]\n\n            topk_boxes = sorted_indices // num_classes\n            topk_labels = sorted_indices % num_classes\n\n            if self.is_one_indexed:\n                class_filter_mask = topk_labels != self.background_class_index\n\n                topk_labels[topk_labels > self.background_class_index] -= 1\n                topk_scores = topk_scores[class_filter_mask]\n                topk_labels = topk_labels[class_filter_mask]\n                topk_boxes = topk_boxes[class_filter_mask]\n\n            selected_boxes = bboxes[batch_idx, topk_boxes]\n\n            cxcy = selected_boxes[:, :2]\n            wh = selected_boxes[:, 2:]\n            xy_min = cxcy - 0.5 * wh\n            xy_max = cxcy + 0.5 * wh\n            boxes_xyxy = np.concatenate([xy_min, xy_max], axis=1)\n\n            if self.resize_method == \"Stretch to\":\n                scale_fct = np.array([orig_w, orig_h, orig_w, orig_h], dtype=np.float32)\n                boxes_xyxy *= scale_fct\n            else:\n                input_h, input_w = self.img_size_h, self.img_size_w\n\n                scale = min(input_w / orig_w, input_h / orig_h)\n                scaled_w = int(orig_w * scale)\n                scaled_h = int(orig_h * scale)\n\n                pad_x = (input_w - scaled_w) / 2\n                pad_y = (input_h - scaled_h) / 2\n\n                boxes_input = boxes_xyxy * np.array(\n                    [input_w, input_h, input_w, input_h], dtype=np.float32\n                )\n\n                boxes_input[:, 0] -= pad_x\n                boxes_input[:, 1] -= pad_y\n                boxes_input[:, 2] -= pad_x\n                boxes_input[:, 3] -= pad_y\n\n                boxes_xyxy = boxes_input / scale\n\n            np.clip(\n                boxes_xyxy,\n                [0, 0, 0, 0],\n                [orig_w, orig_h, orig_w, orig_h],\n                out=boxes_xyxy,\n            )\n\n            batch_predictions = np.column_stack(\n                (\n                    boxes_xyxy,\n                    topk_scores,\n                    np.zeros((len(topk_scores), 1), dtype=np.float32),\n                    topk_labels,\n                )\n            )\n\n            processed_predictions.append(batch_predictions)\n\n        return self.make_response(processed_predictions, img_dims, **kwargs)\n",
    "original_file_content": "import os\nfrom time import perf_counter\nfrom typing import Any, List, Tuple, Union\n\nimport cv2\nimport numpy as np\nimport onnxruntime\n\nfrom inference.core.entities.requests.inference import InferenceRequestImage\nfrom inference.core.env import (\n    DISABLE_PREPROC_AUTO_ORIENT,\n    FIX_BATCH_SIZE,\n    MAX_BATCH_SIZE,\n    REQUIRED_ONNX_PROVIDERS,\n    USE_PYTORCH_FOR_PREPROCESSING,\n)\nfrom inference.core.exceptions import ModelArtefactError, OnnxProviderNotAvailable\nfrom inference.core.logger import logger\nfrom inference.core.models.defaults import DEFAULT_CONFIDENCE, DEFAUlT_MAX_DETECTIONS\nfrom inference.core.models.object_detection_base import (\n    ObjectDetectionBaseOnnxRoboflowInferenceModel,\n    ObjectDetectionInferenceResponse,\n)\nfrom inference.core.models.types import PreprocessReturnMetadata\nfrom inference.core.models.utils.onnx import has_trt\nfrom inference.core.utils.image_utils import load_image\nfrom inference.core.utils.onnx import ImageMetaType, run_session_via_iobinding\nfrom inference.core.utils.preprocess import letterbox_image\n\nif USE_PYTORCH_FOR_PREPROCESSING:\n    import torch\n\nROBOFLOW_BACKGROUND_CLASS = \"background_class83422\"\n\n\nclass RFDETRObjectDetection(ObjectDetectionBaseOnnxRoboflowInferenceModel):\n    \"\"\"Roboflow ONNX Object detection with the RFDETR model.\n\n    This class is responsible for performing object detection using the RFDETR model\n    with ONNX runtime.\n\n    Attributes:\n        weights_file (str): Path to the ONNX weights file.\n\n    Methods:\n        predict: Performs object detection on the given image using the ONNX session.\n    \"\"\"\n\n    preprocess_means = [0.485, 0.456, 0.406]\n    preprocess_stds = [0.229, 0.224, 0.225]\n\n    @property\n    def weights_file(self) -> str:\n        \"\"\"Gets the weights file for the RFDETR model.\n\n        Returns:\n            str: Path to the ONNX weights file.\n        \"\"\"\n        return \"weights.onnx\"\n\n    def preproc_image(\n        self,\n        image: Union[Any, InferenceRequestImage],\n        disable_preproc_auto_orient: bool = False,\n        disable_preproc_contrast: bool = False,\n        disable_preproc_grayscale: bool = False,\n        disable_preproc_static_crop: bool = False,\n    ) -> Tuple[np.ndarray, Tuple[int, int]]:\n        \"\"\"\n        Preprocesses an inference request image by loading it, then applying any pre-processing specified by the Roboflow platform, then scaling it to the inference input dimensions.\n\n        Args:\n            image (Union[Any, InferenceRequestImage]): An object containing information necessary to load the image for inference.\n            disable_preproc_auto_orient (bool, optional): If true, the auto orient preprocessing step is disabled for this call. Default is False.\n            disable_preproc_contrast (bool, optional): If true, the contrast preprocessing step is disabled for this call. Default is False.\n            disable_preproc_grayscale (bool, optional): If true, the grayscale preprocessing step is disabled for this call. Default is False.\n            disable_preproc_static_crop (bool, optional): If true, the static crop preprocessing step is disabled for this call. Default is False.\n\n        Returns:\n            Tuple[np.ndarray, Tuple[int, int]]: A tuple containing a numpy array of the preprocessed image pixel data and a tuple of the images original size.\n        \"\"\"\n        np_image, is_bgr = load_image(\n            image,\n            disable_preproc_auto_orient=disable_preproc_auto_orient\n            or \"auto-orient\" not in self.preproc.keys()\n            or DISABLE_PREPROC_AUTO_ORIENT,\n        )\n        preprocessed_image, img_dims = self.preprocess_image(\n            np_image,\n            disable_preproc_contrast=disable_preproc_contrast,\n            disable_preproc_grayscale=disable_preproc_grayscale,\n            disable_preproc_static_crop=disable_preproc_static_crop,\n        )\n\n        preprocessed_image = preprocessed_image.astype(np.float32)\n        preprocessed_image /= 255.0\n\n        preprocessed_image[:, :, 0] = (\n            preprocessed_image[:, :, 0] - self.preprocess_means[0]\n        ) / self.preprocess_stds[0]\n        preprocessed_image[:, :, 1] = (\n            preprocessed_image[:, :, 1] - self.preprocess_means[1]\n        ) / self.preprocess_stds[1]\n        preprocessed_image[:, :, 2] = (\n            preprocessed_image[:, :, 2] - self.preprocess_means[2]\n        ) / self.preprocess_stds[2]\n\n        if USE_PYTORCH_FOR_PREPROCESSING:\n            preprocessed_image = torch.from_numpy(\n                np.ascontiguousarray(preprocessed_image)\n            )\n            if torch.cuda.is_available():\n                preprocessed_image = preprocessed_image.cuda()\n            preprocessed_image = (\n                preprocessed_image.permute(2, 0, 1).unsqueeze(0).contiguous().float()\n            )\n\n        if self.resize_method == \"Stretch to\":\n            if isinstance(preprocessed_image, np.ndarray):\n                preprocessed_image = preprocessed_image.astype(np.float32)\n                resized = cv2.resize(\n                    preprocessed_image,\n                    (self.img_size_w, self.img_size_h),\n                )\n            elif USE_PYTORCH_FOR_PREPROCESSING:\n                resized = torch.nn.functional.interpolate(\n                    preprocessed_image,\n                    size=(self.img_size_h, self.img_size_w),\n                    mode=\"bilinear\",\n                )\n            else:\n                raise ValueError(\n                    f\"Received an image of unknown type, {type(preprocessed_image)}; \"\n                    \"This is most likely a bug. Contact Roboflow team through github issues \"\n                    \"(https://github.com/roboflow/inference/issues) providing full context of the problem\"\n                )\n\n        elif self.resize_method == \"Fit (black edges) in\":\n            resized = letterbox_image(\n                preprocessed_image, (self.img_size_w, self.img_size_h)\n            )\n        elif self.resize_method == \"Fit (white edges) in\":\n            resized = letterbox_image(\n                preprocessed_image,\n                (self.img_size_w, self.img_size_h),\n                color=(255, 255, 255),\n            )\n        elif self.resize_method == \"Fit (grey edges) in\":\n            resized = letterbox_image(\n                preprocessed_image,\n                (self.img_size_w, self.img_size_h),\n                color=(114, 114, 114),\n            )\n\n        if is_bgr:\n            if isinstance(resized, np.ndarray):\n                resized = cv2.cvtColor(resized, cv2.COLOR_BGR2RGB)\n            else:\n                resized = resized[:, [2, 1, 0], :, :]\n\n        if isinstance(resized, np.ndarray):\n            img_in = np.transpose(resized, (2, 0, 1))\n            img_in = img_in.astype(np.float32)\n            img_in = np.expand_dims(img_in, axis=0)\n        elif USE_PYTORCH_FOR_PREPROCESSING:\n            img_in = resized.float()\n        else:\n            raise ValueError(\n                f\"Received an image of unknown type, {type(resized)}; \"\n                \"This is most likely a bug. Contact Roboflow team through github issues \"\n                \"(https://github.com/roboflow/inference/issues) providing full context of the problem\"\n            )\n        return img_in, img_dims\n\n    def preprocess(\n        self,\n        image: Any,\n        disable_preproc_auto_orient: bool = False,\n        disable_preproc_contrast: bool = False,\n        disable_preproc_grayscale: bool = False,\n        disable_preproc_static_crop: bool = False,\n        fix_batch_size: bool = False,\n        **kwargs,\n    ) -> Tuple[np.ndarray, PreprocessReturnMetadata]:\n        img_in, img_dims = self.load_image(\n            image,\n            disable_preproc_auto_orient=disable_preproc_auto_orient,\n            disable_preproc_contrast=disable_preproc_contrast,\n            disable_preproc_grayscale=disable_preproc_grayscale,\n            disable_preproc_static_crop=disable_preproc_static_crop,\n        )\n        img_in = img_in.astype(np.float32)\n\n        if self.batching_enabled:\n            batch_padding = 0\n            if FIX_BATCH_SIZE or fix_batch_size:\n                if MAX_BATCH_SIZE == float(\"inf\"):\n                    logger.warning(\n                        \"Requested fix_batch_size but MAX_BATCH_SIZE is not set. Using dynamic batching.\"\n                    )\n                    batch_padding = 0\n                else:\n                    batch_padding = MAX_BATCH_SIZE - img_in.shape[0]\n            if batch_padding < 0:\n                raise ValueError(\n                    f\"Requested fix_batch_size but passed in {img_in.shape[0]} images \"\n                    f\"when the model's batch size is {MAX_BATCH_SIZE}\\n\"\n                    f\"Consider turning off fix_batch_size, changing `MAX_BATCH_SIZE` in\"\n                    f\"your inference server config, or passing at most {MAX_BATCH_SIZE} images at a time\"\n                )\n            else:\n                raise ValueError(\n                    f\"Received an image of unknown type, {type(img_in)}; \"\n                    \"This is most likely a bug. Contact Roboflow team through github issues \"\n                    \"(https://github.com/roboflow/inference/issues) providing full context of the problem\"\n                )\n\n        return img_in, PreprocessReturnMetadata(\n            {\n                \"img_dims\": img_dims,\n                \"disable_preproc_static_crop\": disable_preproc_static_crop,\n            }\n        )\n\n    def predict(self, img_in: ImageMetaType, **kwargs) -> Tuple[np.ndarray]:\n        \"\"\"Performs object detection on the given image using the ONNX session with the RFDETR model.\n\n        Args:\n            img_in (np.ndarray): Input image as a NumPy array.\n\n        Returns:\n            Tuple[np.ndarray]: NumPy array representing the predictions, including boxes, confidence scores, and class IDs.\n        \"\"\"\n        predictions = run_session_via_iobinding(\n            self.onnx_session, self.input_name, img_in\n        )\n        bboxes = predictions[0]\n        logits = predictions[1]\n\n        return (bboxes, logits)\n\n    def sigmoid_stable(self, x):\n        return np.where(x >= 0, 1 / (1 + np.exp(-x)), np.exp(x) / (1 + np.exp(x)))\n\n    def postprocess(\n        self,\n        predictions: Tuple[np.ndarray, ...],\n        preproc_return_metadata: PreprocessReturnMetadata,\n        confidence: float = DEFAULT_CONFIDENCE,\n        max_detections: int = DEFAUlT_MAX_DETECTIONS,\n        **kwargs,\n    ) -> List[ObjectDetectionInferenceResponse]:\n        bboxes, logits = predictions\n        bboxes = bboxes.astype(np.float32)\n        logits = logits.astype(np.float32)\n\n        batch_size, num_queries, num_classes = logits.shape\n        logits_sigmoid = self.sigmoid_stable(logits)\n\n        img_dims = preproc_return_metadata[\"img_dims\"]\n\n        processed_predictions = []\n\n        for batch_idx in range(batch_size):\n            orig_h, orig_w = img_dims[batch_idx]\n\n            logits_flat = logits_sigmoid[batch_idx].reshape(-1)\n\n            sorted_indices = np.argsort(-logits_flat)[:max_detections]\n            topk_scores = logits_flat[sorted_indices]\n\n            conf_mask = topk_scores > confidence\n            sorted_indices = sorted_indices[conf_mask]\n            topk_scores = topk_scores[conf_mask]\n\n            topk_boxes = sorted_indices // num_classes\n            topk_labels = sorted_indices % num_classes\n\n            if self.is_one_indexed:\n                class_filter_mask = topk_labels != self.background_class_index\n\n                topk_labels[topk_labels > self.background_class_index] -= 1\n                topk_scores = topk_scores[class_filter_mask]\n                topk_labels = topk_labels[class_filter_mask]\n                topk_boxes = topk_boxes[class_filter_mask]\n\n            selected_boxes = bboxes[batch_idx, topk_boxes]\n\n            cxcy = selected_boxes[:, :2]\n            wh = selected_boxes[:, 2:]\n            xy_min = cxcy - 0.5 * wh\n            xy_max = cxcy + 0.5 * wh\n            boxes_xyxy = np.concatenate([xy_min, xy_max], axis=1)\n\n            if self.resize_method == \"Stretch to\":\n                scale_fct = np.array([orig_w, orig_h, orig_w, orig_h], dtype=np.float32)\n                boxes_xyxy *= scale_fct\n            else:\n                input_h, input_w = self.img_size_h, self.img_size_w\n\n                scale = min(input_w / orig_w, input_h / orig_h)\n                scaled_w = int(orig_w * scale)\n                scaled_h = int(orig_h * scale)\n\n                pad_x = (input_w - scaled_w) / 2\n                pad_y = (input_h - scaled_h) / 2\n\n                boxes_input = boxes_xyxy * np.array(\n                    [input_w, input_h, input_w, input_h], dtype=np.float32\n                )\n\n                boxes_input[:, 0] -= pad_x\n                boxes_input[:, 1] -= pad_y\n                boxes_input[:, 2] -= pad_x\n                boxes_input[:, 3] -= pad_y\n\n                boxes_xyxy = boxes_input / scale\n\n            np.clip(\n                boxes_xyxy,\n                [0, 0, 0, 0],\n                [orig_w, orig_h, orig_w, orig_h],\n                out=boxes_xyxy,\n            )\n\n            batch_predictions = np.column_stack(\n                (\n                    boxes_xyxy,\n                    topk_scores,\n                    np.zeros((len(topk_scores), 1), dtype=np.float32),\n                    topk_labels,\n                )\n            )\n\n            processed_predictions.append(batch_predictions)\n\n        return self.make_response(processed_predictions, img_dims, **kwargs)\n\n    def initialize_model(self) -> None:\n        \"\"\"Initializes the ONNX model, setting up the inference session and other necessary properties.\"\"\"\n        logger.debug(\"Getting model artefacts\")\n        self.get_model_artifacts()\n        logger.debug(\"Creating inference session\")\n        if self.load_weights or not self.has_model_metadata:\n            t1_session = perf_counter()\n            # We exclude CoreMLExecutionProvider as it is showing worse performance than CPUExecutionProvider\n            providers = [\n                \"CUDAExecutionProvider\",\n                \"CPUExecutionProvider\",\n            ]  # \"OpenVINOExecutionProvider\" dropped until further investigation is done\n\n            if not self.load_weights:\n                providers = [\n                    \"CPUExecutionProvider\"\n                ]  # \"OpenVINOExecutionProvider\" dropped until further investigation is done\n\n            try:\n                session_options = onnxruntime.SessionOptions()\n                session_options.log_severity_level = 3\n                # TensorRT does better graph optimization for its EP than onnx\n                if has_trt(providers):\n                    session_options.graph_optimization_level = (\n                        onnxruntime.GraphOptimizationLevel.ORT_DISABLE_ALL\n                    )\n                self.onnx_session = onnxruntime.InferenceSession(\n                    self.cache_file(self.weights_file),\n                    providers=providers,\n                    sess_options=session_options,\n                )\n            except Exception as e:\n                self.clear_cache()\n                raise ModelArtefactError(\n                    f\"Unable to load ONNX session. Cause: {e}\"\n                ) from e\n            logger.debug(f\"Session created in {perf_counter() - t1_session} seconds\")\n\n            if REQUIRED_ONNX_PROVIDERS:\n                available_providers = onnxruntime.get_available_providers()\n                for provider in REQUIRED_ONNX_PROVIDERS:\n                    if provider not in available_providers:\n                        raise OnnxProviderNotAvailable(\n                            f\"Required ONNX Execution Provider {provider} is not availble. \"\n                            \"Check that you are using the correct docker image on a supported device. \"\n                            \"Export list of available providers as ONNXRUNTIME_EXECUTION_PROVIDERS environmental variable, \"\n                            \"consult documentation for more details.\"\n                        )\n\n            inputs = self.onnx_session.get_inputs()[0]\n            input_shape = inputs.shape\n            self.batch_size = input_shape[0]\n            self.img_size_h = input_shape[2]\n            self.img_size_w = input_shape[3]\n            self.input_name = inputs.name\n            if isinstance(self.img_size_h, str) or isinstance(self.img_size_w, str):\n                if \"resize\" in self.preproc:\n                    self.img_size_h = int(self.preproc[\"resize\"][\"height\"])\n                    self.img_size_w = int(self.preproc[\"resize\"][\"width\"])\n                else:\n                    self.img_size_h = 640\n                    self.img_size_w = 640\n\n            if isinstance(self.batch_size, str):\n                self.batching_enabled = True\n                logger.debug(\n                    f\"Model {self.endpoint} is loaded with dynamic batching enabled\"\n                )\n            else:\n                self.batching_enabled = False\n                logger.debug(\n                    f\"Model {self.endpoint} is loaded with dynamic batching disabled\"\n                )\n\n            model_metadata = {\n                \"batch_size\": self.batch_size,\n                \"img_size_h\": self.img_size_h,\n                \"img_size_w\": self.img_size_w,\n            }\n            logger.debug(f\"Writing model metadata to memcache\")\n            self.write_model_metadata_to_memcache(model_metadata)\n            if not self.load_weights:  # had to load weights to get metadata\n                del self.onnx_session\n        else:\n            if not self.has_model_metadata:\n                raise ValueError(\n                    \"This should be unreachable, should get weights if we don't have model metadata\"\n                )\n            logger.debug(f\"Loading model metadata from memcache\")\n            metadata = self.model_metadata_from_memcache()\n            self.batch_size = metadata[\"batch_size\"]\n            self.img_size_h = metadata[\"img_size_h\"]\n            self.img_size_w = metadata[\"img_size_w\"]\n            if isinstance(self.batch_size, str):\n                self.batching_enabled = True\n                logger.debug(\n                    f\"Model {self.endpoint} is loaded with dynamic batching enabled\"\n                )\n            else:\n                self.batching_enabled = False\n                logger.debug(\n                    f\"Model {self.endpoint} is loaded with dynamic batching disabled\"\n                )\n\n        if ROBOFLOW_BACKGROUND_CLASS in self.class_names:\n            self.is_one_indexed = True\n            self.background_class_index = self.class_names.index(\n                ROBOFLOW_BACKGROUND_CLASS\n            )\n            self.class_names = (\n                self.class_names[: self.background_class_index]\n                + self.class_names[self.background_class_index + 1 :]\n            )\n        else:\n            self.is_one_indexed = False\n        logger.debug(\"Model initialisation finished.\")\n\n    def validate_model_classes(self) -> None:\n        pass\n",
    "patch": "diff --git a/inference/models/rfdetr/rfdetr.py b/inference/models/rfdetr/rfdetr.py\nindex aab250cab..bff2dec28 100644\n--- a/inference/models/rfdetr/rfdetr.py\n+++ b/inference/models/rfdetr/rfdetr.py\n@@ -26,6 +26,7 @@ from inference.core.models.utils.onnx import has_trt\n from inference.core.utils.image_utils import load_image\n from inference.core.utils.onnx import ImageMetaType, run_session_via_iobinding\n from inference.core.utils.preprocess import letterbox_image\n+from inference.core.entities.responses.inference import ObjectDetectionInferenceResponse\n \n if USE_PYTORCH_FOR_PREPROCESSING:\n     import torch\n@@ -240,7 +241,9 @@ class RFDETRObjectDetection(ObjectDetectionBaseOnnxRoboflowInferenceModel):\n         return (bboxes, logits)\n \n     def sigmoid_stable(self, x):\n-        return np.where(x >= 0, 1 / (1 + np.exp(-x)), np.exp(x) / (1 + np.exp(x)))\n+        # More efficient, branchless, numerically stable sigmoid computation\n+        z = np.exp(-np.abs(x))\n+        return np.where(x >= 0, 1 / (1 + z), z / (1 + z))\n \n     def postprocess(\n         self,\n@@ -266,7 +269,13 @@ class RFDETRObjectDetection(ObjectDetectionBaseOnnxRoboflowInferenceModel):\n \n             logits_flat = logits_sigmoid[batch_idx].reshape(-1)\n \n-            sorted_indices = np.argsort(-logits_flat)[:max_detections]\n+            # Use argpartition for better performance when max_detections is smaller than logits_flat\n+            partition_indices = np.argpartition(-logits_flat, max_detections)[\n+                :max_detections\n+            ]\n+            sorted_indices = partition_indices[\n+                np.argsort(-logits_flat[partition_indices])\n+            ]\n             topk_scores = logits_flat[sorted_indices]\n \n             conf_mask = topk_scores > confidence\n"
  },
  {
    "trace_id": "575ba5c8-128b-4265-9c40-ea37c2cc42f2",
    "function_name": "InferenceModelsObjectDetectionAdapter.preprocess",
    "file_path": "inference/core/models/inference_models_adapters.py",
    "speedup_x": 0.12,
    "review_quality": "high",
    "pre_optimization_commit": "459f2b015b4df2c21d99608520607c01d3460822",
    "resolution_method": "db_code_match",
    "source": "db_events",
    "original_function_code": "    def preprocess(self, image: Any, **kwargs):\n        is_batch = isinstance(image, list)\n        images = image if is_batch else [image]\n        np_images: List[np.ndarray] = [\n            load_image_bgr(\n                v,\n                disable_preproc_auto_orient=kwargs.get(\n                    \"disable_preproc_auto_orient\", False\n                ),\n            )\n            for v in images\n        ]\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.pre_process(np_images, **mapped_kwargs)\n",
    "optimized_function_code": "from typing import Any, List\n\nimport numpy as np\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES, API_KEY)\nfrom inference.core.models.base import Model\nfrom inference.core.utils.image_utils import load_image_bgr\nfrom inference.models.aliases import resolve_roboflow_model_alias\nfrom inference_models import AutoModel, ObjectDetectionModel\n\n\nclass InferenceModelsObjectDetectionAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n        model_id = resolve_roboflow_model_alias(model_id=model_id)\n\n        self.task_type = \"object-detection\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers()\n\n        self._model: ObjectDetectionModel = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            extra_weights_provider_headers=extra_weights_provider_headers,\n            **kwargs,\n        )\n        self.class_names = list(self._model.class_names)\n\n    def preprocess(self, image: Any, **kwargs):\n        is_batch = isinstance(image, list)\n        images = image if is_batch else [image]\n        disable_preproc_auto_orient = kwargs.get(\"disable_preproc_auto_orient\", False)\n        np_images: List[np.ndarray] = [\n            load_image_bgr(v, disable_preproc_auto_orient=disable_preproc_auto_orient)\n            for v in images\n        ]\n        return self._model.pre_process(np_images, **kwargs)",
    "optimized_raw_markdown": "```python:inference/core/utils/image_utils.py\nimport cv2\nimport re\nimport numpy as np\nfrom typing import Any\n\nBASE64_DATA_TYPE_PATTERN = re.compile(r\"^data:image\\/[a-z]+;base64,\")\n\n\ndef load_image_bgr(value: Any, disable_preproc_auto_orient: bool = False) -> np.ndarray:\n    np_image, is_bgr = load_image(\n        value=value, disable_preproc_auto_orient=disable_preproc_auto_orient\n    )\n    if not is_bgr:\n        np_image = cv2.cvtColor(np_image, cv2.COLOR_BGR2RGB)\n    return np_image\n\n\nIMAGE_LOADERS = {\n    ImageType.BASE64: load_image_base64,\n    ImageType.FILE: cv2.imread,\n    ImageType.MULTIPART: load_image_from_buffer,\n    ImageType.NUMPY: lambda v, _: load_image_from_numpy_str(v),\n    ImageType.NUMPY_OBJECT: lambda v, _: load_image_from_numpy_object(v),\n    ImageType.PILLOW: lambda v, _: np.asarray(v.convert(\"RGB\")),\n    ImageType.URL: load_image_from_url,\n}\n```\n```python:inference/core/models/inference_models_adapters.py\nfrom typing import Any, List\n\nimport numpy as np\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES, API_KEY)\nfrom inference.core.models.base import Model\nfrom inference.core.utils.image_utils import load_image_bgr\nfrom inference.models.aliases import resolve_roboflow_model_alias\nfrom inference_models import AutoModel, ObjectDetectionModel\n\n\nclass InferenceModelsObjectDetectionAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n        model_id = resolve_roboflow_model_alias(model_id=model_id)\n\n        self.task_type = \"object-detection\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers()\n\n        self._model: ObjectDetectionModel = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            extra_weights_provider_headers=extra_weights_provider_headers,\n            **kwargs,\n        )\n        self.class_names = list(self._model.class_names)\n\n    def preprocess(self, image: Any, **kwargs):\n        is_batch = isinstance(image, list)\n        images = image if is_batch else [image]\n        disable_preproc_auto_orient = kwargs.get(\"disable_preproc_auto_orient\", False)\n        np_images: List[np.ndarray] = [\n            load_image_bgr(v, disable_preproc_auto_orient=disable_preproc_auto_orient)\n            for v in images\n        ]\n        return self._model.pre_process(np_images, **kwargs)\n```",
    "optimized_function_only": "    def preprocess(self, image: Any, **kwargs):\n        is_batch = isinstance(image, list)\n        images = image if is_batch else [image]\n        disable_preproc_auto_orient = kwargs.get(\"disable_preproc_auto_orient\", False)\n        np_images: List[np.ndarray] = [\n            load_image_bgr(v, disable_preproc_auto_orient=disable_preproc_auto_orient)\n            for v in images\n        ]\n        return self._model.pre_process(np_images, **kwargs)",
    "original_file_content": "import base64\nimport io\nfrom io import BytesIO\nfrom time import perf_counter\nfrom typing import Any, List, Optional, Tuple, Union\n\nimport numpy as np\nimport torch\nfrom PIL import Image, ImageDraw, ImageFont\n\nfrom inference.core.entities.requests import (\n    ClassificationInferenceRequest,\n    InferenceRequest,\n)\nfrom inference.core.entities.responses.inference import (\n    ClassificationInferenceResponse,\n    InferenceResponse,\n    InferenceResponseImage,\n    InstanceSegmentationInferenceResponse,\n    InstanceSegmentationPrediction,\n    Keypoint,\n    KeypointsDetectionInferenceResponse,\n    KeypointsPrediction,\n    MultiLabelClassificationInferenceResponse,\n    ObjectDetectionInferenceResponse,\n    ObjectDetectionPrediction,\n    Point,\n    SemanticSegmentationInferenceResponse,\n    SemanticSegmentationPrediction,\n)\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n    API_KEY,\n    DISABLED_INFERENCE_MODELS_BACKENDS,\n    RFDETR_ONNX_MAX_RESOLUTION,\n    VALID_INFERENCE_MODELS_BACKENDS,\n)\nfrom inference.core.models.base import Model\nfrom inference.core.roboflow_api import get_extra_weights_provider_headers\nfrom inference.core.utils.image_utils import load_image_bgr, load_image_rgb\nfrom inference.core.utils.postprocess import masks2poly\nfrom inference.core.utils.visualisation import draw_detection_predictions\nfrom inference.models.aliases import resolve_roboflow_model_alias\nfrom inference_models import (\n    AutoModel,\n    ClassificationModel,\n    ClassificationPrediction,\n    Detections,\n    InstanceDetections,\n    InstanceSegmentationModel,\n    KeyPoints,\n    KeyPointsDetectionModel,\n    MultiLabelClassificationModel,\n    MultiLabelClassificationPrediction,\n    ObjectDetectionModel,\n    PreProcessingOverrides,\n    SemanticSegmentationModel,\n)\nfrom inference_models.models.base.semantic_segmentation import (\n    SemanticSegmentationResult,\n)\nfrom inference_models.models.base.types import PreprocessingMetadata\n\ndef _resolve_cached_model_path(model_id: str) -> str:\n    \"\"\"If the model is already in the inference-models local cache, return the\n    package directory path so ``AutoModel.from_pretrained`` can load directly\n    from disk without calling the Roboflow API.  Returns the original\n    *model_id* unchanged when no local cache hit is found.\n    \"\"\"\n    try:\n        from inference.core.cache.air_gapped import (\n            _get_inference_models_home,\n            _slugify_model_id,\n        )\n        from inference.core.env import MODEL_CACHE_DIR\n\n        slug = _slugify_model_id(model_id)\n        bases = [MODEL_CACHE_DIR]\n        inference_home = _get_inference_models_home()\n        if inference_home is not None and inference_home != MODEL_CACHE_DIR:\n            bases.append(inference_home)\n\n        for base in bases:\n            import os\n\n            slug_dir = os.path.join(base, \"models-cache\", slug)\n            if not os.path.isdir(slug_dir):\n                continue\n            for package_id in os.listdir(slug_dir):\n                package_dir = os.path.join(slug_dir, package_id)\n                if os.path.isfile(os.path.join(package_dir, \"model_config.json\")):\n                    return package_dir\n    except Exception:\n        pass\n    return model_id\n\n\nDEFAULT_COLOR_PALETTE = [\n    \"#A351FB\",\n    \"#FF4040\",\n    \"#FFA1A0\",\n    \"#FF7633\",\n    \"#FFB633\",\n    \"#D1D435\",\n    \"#4CFB12\",\n    \"#94CF1A\",\n    \"#40DE8A\",\n    \"#1B9640\",\n    \"#00D6C1\",\n    \"#2E9CAA\",\n    \"#00C4FF\",\n    \"#364797\",\n    \"#6675FF\",\n    \"#0019EF\",\n    \"#863AFF\",\n    \"#530087\",\n    \"#CD3AFF\",\n    \"#FF97CA\",\n    \"#FF39C9\",\n]\n\n\nclass InferenceModelsObjectDetectionAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n        model_id = resolve_roboflow_model_alias(model_id=model_id)\n\n        self.task_type = \"object-detection\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n        backend = list(\n            VALID_INFERENCE_MODELS_BACKENDS.difference(\n                DISABLED_INFERENCE_MODELS_BACKENDS\n            )\n        )\n        self._model: ObjectDetectionModel = AutoModel.from_pretrained(\n            model_id_or_path=_resolve_cached_model_path(model_id),\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            backend=backend,\n            rf_detr_max_input_resolution=RFDETR_ONNX_MAX_RESOLUTION,\n            **kwargs,\n        )\n        self.class_names = list(self._model.class_names)\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        pre_processing_overrides = PreProcessingOverrides(\n            disable_contrast_enhancement=kwargs.get(\"disable_preproc_contrast\", False),\n            disable_grayscale=kwargs.get(\"disable_preproc_grayscale\", False),\n            disable_static_crop=kwargs.get(\"disable_preproc_static_crop\", False),\n        )\n        kwargs[\"pre_processing_overrides\"] = pre_processing_overrides\n        return kwargs\n\n    def preprocess(self, image: Any, **kwargs):\n        is_batch = isinstance(image, list)\n        images = image if is_batch else [image]\n        np_images: List[np.ndarray] = [\n            load_image_bgr(\n                v,\n                disable_preproc_auto_orient=kwargs.get(\n                    \"disable_preproc_auto_orient\", False\n                ),\n            )\n            for v in images\n        ]\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.pre_process(np_images, **mapped_kwargs)\n\n    def predict(self, img_in, **kwargs):\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.forward(img_in, **mapped_kwargs)\n\n    def postprocess(\n        self,\n        predictions: List[Detections],\n        preprocess_return_metadata: PreprocessingMetadata,\n        **kwargs,\n    ) -> List[ObjectDetectionInferenceResponse]:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        detections_list = self._model.post_process(\n            predictions, preprocess_return_metadata, **mapped_kwargs\n        )\n\n        responses: List[ObjectDetectionInferenceResponse] = []\n        for preproc_metadata, det in zip(preprocess_return_metadata, detections_list):\n            H = preproc_metadata.original_size.height\n            W = preproc_metadata.original_size.width\n\n            xyxy = det.xyxy.detach().cpu().numpy()\n            confs = det.confidence.detach().cpu().numpy()\n            class_ids = det.class_id.detach().cpu().numpy()\n\n            predictions: List[ObjectDetectionPrediction] = []\n\n            for (x1, y1, x2, y2), conf, class_id in zip(xyxy, confs, class_ids):\n                cx = (float(x1) + float(x2)) / 2.0\n                cy = (float(y1) + float(y2)) / 2.0\n                w = float(x2) - float(x1)\n                h = float(y2) - float(y1)\n                class_id_int = int(class_id)\n                class_name = (\n                    self.class_names[class_id_int]\n                    if 0 <= class_id_int < len(self.class_names)\n                    else str(class_id_int)\n                )\n                if (\n                    kwargs.get(\"class_filter\")\n                    and class_name not in kwargs[\"class_filter\"]\n                ):\n                    continue\n                predictions.append(\n                    ObjectDetectionPrediction(\n                        x=cx,\n                        y=cy,\n                        width=w,\n                        height=h,\n                        confidence=float(conf),\n                        **{\"class\": class_name},\n                        class_id=class_id_int,\n                    )\n                )\n\n            responses.append(\n                ObjectDetectionInferenceResponse(\n                    predictions=predictions,\n                    image=InferenceResponseImage(width=W, height=H),\n                )\n            )\n        return responses\n\n    def clear_cache(self, delete_from_disk: bool = True) -> None:\n        \"\"\"Clears any cache if necessary. TODO: Implement this to delete the cache from the experimental model.\n\n        Args:\n            delete_from_disk (bool, optional): Whether to delete cached files from disk. Defaults to True.\n        \"\"\"\n        pass\n\n    def draw_predictions(\n        self,\n        inference_request: InferenceRequest,\n        inference_response: InferenceResponse,\n    ) -> bytes:\n        \"\"\"Draw predictions from an inference response onto the original image provided by an inference request\n\n        Args:\n            inference_request (ObjectDetectionInferenceRequest): The inference request containing the image on which to draw predictions\n            inference_response (ObjectDetectionInferenceResponse): The inference response containing predictions to be drawn\n\n        Returns:\n            str: A base64 encoded image string\n        \"\"\"\n        class_id_2_color = {\n            i: DEFAULT_COLOR_PALETTE[i % len(DEFAULT_COLOR_PALETTE)]\n            for i, class_name in enumerate(self._model.class_names)\n        }\n        return draw_detection_predictions(\n            inference_request=inference_request,\n            inference_response=inference_response,\n            colors=class_id_2_color,\n        )\n\n\nclass InferenceModelsInstanceSegmentationAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n        model_id = resolve_roboflow_model_alias(model_id=model_id)\n\n        self.task_type = \"instance-segmentation\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n        backend = list(\n            VALID_INFERENCE_MODELS_BACKENDS.difference(\n                DISABLED_INFERENCE_MODELS_BACKENDS\n            )\n        )\n        self._model: InstanceSegmentationModel = AutoModel.from_pretrained(\n            model_id_or_path=_resolve_cached_model_path(model_id),\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            backend=backend,\n            rf_detr_max_input_resolution=RFDETR_ONNX_MAX_RESOLUTION,\n            **kwargs,\n        )\n        self.class_names = list(self._model.class_names)\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        pre_processing_overrides = PreProcessingOverrides(\n            disable_contrast_enhancement=kwargs.get(\"disable_preproc_contrast\", False),\n            disable_grayscale=kwargs.get(\"disable_preproc_grayscale\", False),\n            disable_static_crop=kwargs.get(\"disable_preproc_static_crop\", False),\n        )\n        kwargs[\"pre_processing_overrides\"] = pre_processing_overrides\n        return kwargs\n\n    def preprocess(self, image: Any, **kwargs):\n        is_batch = isinstance(image, list)\n        images = image if is_batch else [image]\n        np_images: List[np.ndarray] = [\n            load_image_bgr(\n                v,\n                disable_preproc_auto_orient=kwargs.get(\n                    \"disable_preproc_auto_orient\", False\n                ),\n            )\n            for v in images\n        ]\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.pre_process(np_images, **mapped_kwargs)\n\n    def predict(self, img_in, **kwargs):\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.forward(img_in, **mapped_kwargs)\n\n    def postprocess(\n        self,\n        predictions: List[InstanceDetections],\n        preprocess_return_metadata: PreprocessingMetadata,\n        **kwargs,\n    ) -> List[InstanceSegmentationInferenceResponse]:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        detections_list = self._model.post_process(\n            predictions, preprocess_return_metadata, **mapped_kwargs\n        )\n\n        responses: List[InstanceSegmentationInferenceResponse] = []\n        for preproc_metadata, det in zip(preprocess_return_metadata, detections_list):\n            H = preproc_metadata.original_size.height\n            W = preproc_metadata.original_size.width\n\n            xyxy = det.xyxy.detach().cpu().numpy()\n            confs = det.confidence.detach().cpu().numpy()\n            masks = det.mask.detach().cpu().numpy()\n            polys = masks2poly(masks)\n            class_ids = det.class_id.detach().cpu().numpy()\n\n            predictions: List[InstanceSegmentationPrediction] = []\n\n            for (x1, y1, x2, y2), mask_as_poly, conf, class_id in zip(\n                xyxy, polys, confs, class_ids\n            ):\n                cx = (float(x1) + float(x2)) / 2.0\n                cy = (float(y1) + float(y2)) / 2.0\n                w = float(x2) - float(x1)\n                h = float(y2) - float(y1)\n                class_id_int = int(class_id)\n                class_name = (\n                    self.class_names[class_id_int]\n                    if 0 <= class_id_int < len(self.class_names)\n                    else str(class_id_int)\n                )\n                if (\n                    kwargs.get(\"class_filter\")\n                    and class_name not in kwargs[\"class_filter\"]\n                ):\n                    continue\n                predictions.append(\n                    InstanceSegmentationPrediction(\n                        x=cx,\n                        y=cy,\n                        width=w,\n                        height=h,\n                        confidence=float(conf),\n                        points=[\n                            Point(x=point[0], y=point[1]) for point in mask_as_poly\n                        ],\n                        **{\"class\": class_name},\n                        class_id=class_id_int,\n                    )\n                )\n\n            responses.append(\n                InstanceSegmentationInferenceResponse(\n                    predictions=predictions,\n                    image=InferenceResponseImage(width=W, height=H),\n                )\n            )\n        return responses\n\n    def clear_cache(self, delete_from_disk: bool = True) -> None:\n        \"\"\"Clears any cache if necessary. TODO: Implement this to delete the cache from the experimental model.\n\n        Args:\n            delete_from_disk (bool, optional): Whether to delete cached files from disk. Defaults to True.\n        \"\"\"\n        pass\n\n    def draw_predictions(\n        self,\n        inference_request: InferenceRequest,\n        inference_response: InferenceResponse,\n    ) -> bytes:\n        \"\"\"Draw predictions from an inference response onto the original image provided by an inference request\n\n        Args:\n            inference_request (ObjectDetectionInferenceRequest): The inference request containing the image on which to draw predictions\n            inference_response (ObjectDetectionInferenceResponse): The inference response containing predictions to be drawn\n\n        Returns:\n            str: A base64 encoded image string\n        \"\"\"\n        class_id_2_color = {\n            i: DEFAULT_COLOR_PALETTE[i % len(DEFAULT_COLOR_PALETTE)]\n            for i, class_name in enumerate(self._model.class_names)\n        }\n        return draw_detection_predictions(\n            inference_request=inference_request,\n            inference_response=inference_response,\n            colors=class_id_2_color,\n        )\n\n\nclass InferenceModelsKeyPointsDetectionAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n        model_id = resolve_roboflow_model_alias(model_id=model_id)\n\n        self.task_type = \"keypoint-detection\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n        backend = list(\n            VALID_INFERENCE_MODELS_BACKENDS.difference(\n                DISABLED_INFERENCE_MODELS_BACKENDS\n            )\n        )\n        self._model: KeyPointsDetectionModel = AutoModel.from_pretrained(\n            model_id_or_path=_resolve_cached_model_path(model_id),\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            backend=backend,\n            **kwargs,\n        )\n        self.class_names = list(self._model.class_names)\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        if \"request\" in kwargs:\n            keypoint_confidence_threshold = kwargs[\"request\"].keypoint_confidence\n            kwargs[\"key_points_threshold\"] = keypoint_confidence_threshold\n        pre_processing_overrides = PreProcessingOverrides(\n            disable_contrast_enhancement=kwargs.get(\"disable_preproc_contrast\", False),\n            disable_grayscale=kwargs.get(\"disable_preproc_grayscale\", False),\n            disable_static_crop=kwargs.get(\"disable_preproc_static_crop\", False),\n        )\n        kwargs[\"pre_processing_overrides\"] = pre_processing_overrides\n        return kwargs\n\n    def preprocess(self, image: Any, **kwargs):\n        is_batch = isinstance(image, list)\n        images = image if is_batch else [image]\n        np_images: List[np.ndarray] = [\n            load_image_bgr(\n                v,\n                disable_preproc_auto_orient=kwargs.get(\n                    \"disable_preproc_auto_orient\", False\n                ),\n            )\n            for v in images\n        ]\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.pre_process(np_images, **mapped_kwargs)\n\n    def predict(self, img_in, **kwargs):\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.forward(img_in, **mapped_kwargs)\n\n    def postprocess(\n        self,\n        predictions: Tuple[List[KeyPoints], Optional[List[Detections]]],\n        preprocess_return_metadata: PreprocessingMetadata,\n        **kwargs,\n    ) -> List[KeypointsDetectionInferenceResponse]:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        keypoints_list, detections_list = self._model.post_process(\n            predictions, preprocess_return_metadata, **mapped_kwargs\n        )\n        if detections_list is None:\n            raise RuntimeError(\n                \"Keypoints detection model does not provide instances detection - this is not supported for \"\n                \"models from `inference-models` package which are adapted to work with `inference`.\"\n            )\n        key_points_classes = self._model.key_points_classes\n        responses: List[KeypointsDetectionInferenceResponse] = []\n        for preproc_metadata, keypoints, det in zip(\n            preprocess_return_metadata, keypoints_list, detections_list\n        ):\n\n            H = preproc_metadata.original_size.height\n            W = preproc_metadata.original_size.width\n\n            xyxy = det.xyxy.detach().cpu().numpy()\n            confs = det.confidence.detach().cpu().numpy()\n            class_ids = det.class_id.detach().cpu().numpy()\n            keypoints_xy = keypoints.xy.detach().cpu().tolist()\n            keypoints_class_id = keypoints.class_id.detach().cpu().tolist()\n            keypoints_confidence = keypoints.confidence.detach().cpu().tolist()\n            predictions: List[KeypointsPrediction] = []\n\n            for (\n                (x1, y1, x2, y2),\n                conf,\n                class_id,\n                instance_keypoints_xy,\n                instance_keypoints_class_id,\n                instance_keypoints_confidence,\n            ) in zip(\n                xyxy,\n                confs,\n                class_ids,\n                keypoints_xy,\n                keypoints_class_id,\n                keypoints_confidence,\n            ):\n                cx = (float(x1) + float(x2)) / 2.0\n                cy = (float(y1) + float(y2)) / 2.0\n                w = float(x2) - float(x1)\n                h = float(y2) - float(y1)\n                class_id_int = int(class_id)\n                class_name = (\n                    self.class_names[class_id_int]\n                    if 0 <= class_id_int < len(self.class_names)\n                    else str(class_id_int)\n                )\n                if (\n                    kwargs.get(\"class_filter\")\n                    and class_name not in kwargs[\"class_filter\"]\n                ):\n                    continue\n                predictions.append(\n                    KeypointsPrediction(\n                        x=cx,\n                        y=cy,\n                        width=w,\n                        height=h,\n                        confidence=float(conf),\n                        **{\"class\": class_name},\n                        class_id=class_id_int,\n                        keypoints=model_keypoints_to_response(\n                            instance_keypoints_xy=instance_keypoints_xy,\n                            instance_keypoints_confidence=instance_keypoints_confidence,\n                            instance_keypoints_class_id=instance_keypoints_class_id,\n                            key_points_classes=key_points_classes,\n                        ),\n                    )\n                )\n\n            responses.append(\n                KeypointsDetectionInferenceResponse(\n                    predictions=predictions,\n                    image=InferenceResponseImage(width=W, height=H),\n                )\n            )\n\n        return responses\n\n    def clear_cache(self, delete_from_disk: bool = True) -> None:\n        \"\"\"Clears any cache if necessary. TODO: Implement this to delete the cache from the experimental model.\n\n        Args:\n            delete_from_disk (bool, optional): Whether to delete cached files from disk. Defaults to True.\n        \"\"\"\n        pass\n\n    def draw_predictions(\n        self,\n        inference_request: InferenceRequest,\n        inference_response: InferenceResponse,\n    ) -> bytes:\n        \"\"\"Draw predictions from an inference response onto the original image provided by an inference request\n\n        Args:\n            inference_request (ObjectDetectionInferenceRequest): The inference request containing the image on which to draw predictions\n            inference_response (ObjectDetectionInferenceResponse): The inference response containing predictions to be drawn\n\n        Returns:\n            str: A base64 encoded image string\n        \"\"\"\n        class_id_2_color = {\n            i: DEFAULT_COLOR_PALETTE[i % len(DEFAULT_COLOR_PALETTE)]\n            for i, class_name in enumerate(self._model.class_names)\n        }\n        return draw_detection_predictions(\n            inference_request=inference_request,\n            inference_response=inference_response,\n            colors=class_id_2_color,\n        )\n\n\ndef model_keypoints_to_response(\n    instance_keypoints_xy: List[\n        List[Union[float, int]]\n    ],  # (num_key_points_foc_class_of_object, 2)\n    instance_keypoints_confidence: List[float],  # (instance_key_points, )\n    instance_keypoints_class_id: int,\n    key_points_classes: List[List[str]],\n) -> List[Keypoint]:\n    keypoint_classes = key_points_classes[instance_keypoints_class_id]\n    results = []\n    for keypoint_class_id, ((x, y), confidence, keypoint_class_name) in enumerate(\n        zip(instance_keypoints_xy, instance_keypoints_confidence, keypoint_classes)\n    ):\n        if confidence <= 0.0:\n            continue\n        keypoint = Keypoint(\n            x=x,\n            y=y,\n            confidence=confidence,\n            class_id=keypoint_class_id,\n            **{\"class\": keypoint_class_name},\n        )\n        results.append(keypoint)\n    return results\n\n\nclass InferenceModelsClassificationAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n        model_id = resolve_roboflow_model_alias(model_id=model_id)\n\n        self.task_type = \"classification\"\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n        backend = list(\n            VALID_INFERENCE_MODELS_BACKENDS.difference(\n                DISABLED_INFERENCE_MODELS_BACKENDS\n            )\n        )\n        self._model: Union[ClassificationModel, MultiLabelClassificationModel] = (\n            AutoModel.from_pretrained(\n                model_id_or_path=_resolve_cached_model_path(model_id),\n                api_key=self.api_key,\n                allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n                allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n                weights_provider_extra_headers=extra_weights_provider_headers,\n                backend=backend,\n                **kwargs,\n            )\n        )\n        self.class_names = list(self._model.class_names)\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        pre_processing_overrides = PreProcessingOverrides(\n            disable_contrast_enhancement=kwargs.get(\"disable_preproc_contrast\", False),\n            disable_grayscale=kwargs.get(\"disable_preproc_grayscale\", False),\n            disable_static_crop=kwargs.get(\"disable_preproc_static_crop\", False),\n        )\n        kwargs[\"pre_processing_overrides\"] = pre_processing_overrides\n        return kwargs\n\n    def preprocess(self, image: Any, **kwargs):\n        is_batch = isinstance(image, list)\n        images = image if is_batch else [image]\n        np_images: List[np.ndarray] = [\n            load_image_bgr(\n                v,\n                disable_preproc_auto_orient=kwargs.get(\n                    \"disable_preproc_auto_orient\", False\n                ),\n            )\n            for v in images\n        ]\n        images_shapes = [i.shape[:2] for i in np_images]\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.pre_process(np_images, **mapped_kwargs), images_shapes\n\n    def predict(self, img_in, **kwargs):\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.forward(img_in, **mapped_kwargs)\n\n    def postprocess(\n        self,\n        predictions: Tuple[List[KeyPoints], Optional[List[Detections]]],\n        returned_metadata: List[Tuple[int, int]],\n        **kwargs,\n    ) -> Union[\n        List[MultiLabelClassificationInferenceResponse],\n        List[ClassificationInferenceResponse],\n    ]:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        post_processed_predictions = self._model.post_process(\n            predictions, **mapped_kwargs\n        )\n        if isinstance(post_processed_predictions, list):\n            # multi-label classification\n            return prepare_multi_label_classification_response(\n                post_processed_predictions,\n                image_sizes=returned_metadata,\n                class_names=self.class_names,\n                confidence_threshold=kwargs.get(\"confidence\", 0.5),\n            )\n        else:\n            # single-label classification\n            return prepare_classification_response(\n                post_processed_predictions,\n                image_sizes=returned_metadata,\n                class_names=self.class_names,\n                confidence_threshold=kwargs.get(\"confidence\", 0.5),\n            )\n\n    def clear_cache(self, delete_from_disk: bool = True) -> None:\n        \"\"\"Clears any cache if necessary. TODO: Implement this to delete the cache from the experimental model.\n\n        Args:\n            delete_from_disk (bool, optional): Whether to delete cached files from disk. Defaults to True.\n        \"\"\"\n        pass\n\n    def infer_from_request(\n        self,\n        request: ClassificationInferenceRequest,\n    ) -> Union[List[InferenceResponse], InferenceResponse]:\n        \"\"\"\n        Handle an inference request to produce an appropriate response.\n\n        Args:\n            request (ClassificationInferenceRequest): The request object encapsulating the image(s) and relevant parameters.\n\n        Returns:\n            Union[List[InferenceResponse], InferenceResponse]: The response object(s) containing the predictions, visualization, and other pertinent details. If a list of images was provided, a list of responses is returned. Otherwise, a single response is returned.\n\n        Notes:\n            - Starts a timer at the beginning to calculate inference time.\n            - Processes the image(s) through the `infer` method.\n            - Generates the appropriate response object(s) using `make_response`.\n            - Calculates and sets the time taken for inference.\n            - If visualization is requested, the predictions are drawn on the image.\n        \"\"\"\n        t1 = perf_counter()\n        responses = self.infer(**request.dict(), return_image_dims=True)\n        for response in responses:\n            response.time = perf_counter() - t1\n            response.inference_id = getattr(request, \"id\", None)\n\n        if request.visualize_predictions:\n            for response in responses:\n                response.visualization = draw_predictions(\n                    request, response, self.class_names\n                )\n\n        if not isinstance(request.image, list):\n            responses = responses[0]\n\n        return responses\n\n\ndef prepare_multi_label_classification_response(\n    post_processed_predictions: List[MultiLabelClassificationPrediction],\n    image_sizes: List[Tuple[int, int]],\n    class_names: List[str],\n    confidence_threshold: float,\n) -> List[MultiLabelClassificationInferenceResponse]:\n    results = []\n    for prediction, image_size in zip(post_processed_predictions, image_sizes):\n        image_predictions_dict = dict()\n        predicted_classes = []\n        for class_id, confidence in enumerate(prediction.confidence.cpu().tolist()):\n            cls_name = class_names[class_id]\n            image_predictions_dict[cls_name] = {\n                \"confidence\": confidence,\n                \"class_id\": class_id,\n            }\n            if confidence > confidence_threshold:\n                predicted_classes.append(cls_name)\n        results.append(\n            MultiLabelClassificationInferenceResponse(\n                predictions=image_predictions_dict,\n                predicted_classes=predicted_classes,\n                image=InferenceResponseImage(width=image_size[1], height=image_size[0]),\n                # essentially pushing a dummy values as I have no intention breaking the new API for the sake of delivering value that has no practical use\n            )\n        )\n    return results\n\n\ndef prepare_classification_response(\n    post_processed_predictions: ClassificationPrediction,\n    image_sizes: List[Tuple[int, int]],\n    class_names: List[str],\n    confidence_threshold: float,\n) -> List[ClassificationInferenceResponse]:\n    responses = []\n    for classes_confidence, image_size in zip(\n        post_processed_predictions.confidence.cpu().tolist(), image_sizes\n    ):\n        individual_classes_predictions = []\n        for i, cls_name in enumerate(class_names):\n            class_score = float(classes_confidence[i])\n            if class_score < confidence_threshold:\n                continue\n            class_prediction = {\n                \"class_id\": i,\n                \"class\": cls_name,\n                \"confidence\": round(class_score, 4),\n            }\n            individual_classes_predictions.append(class_prediction)\n        individual_classes_predictions = sorted(\n            individual_classes_predictions, key=lambda x: x[\"confidence\"], reverse=True\n        )\n        response = ClassificationInferenceResponse(\n            image=InferenceResponseImage(width=image_size[1], height=image_size[0]),\n            # essentially pushing a dummy values as I have no intention breaking the new API for the sake of delivering value that has no practical use\n            predictions=individual_classes_predictions,\n            top=(\n                individual_classes_predictions[0][\"class\"]\n                if individual_classes_predictions\n                else \"\"\n            ),\n            confidence=(\n                individual_classes_predictions[0][\"confidence\"]\n                if individual_classes_predictions\n                else 0.0\n            ),\n        )\n        responses.append(response)\n    return responses\n\n\ndef draw_predictions(inference_request, inference_response, class_names: List[str]):\n    \"\"\"Draw prediction visuals on an image.\n\n    This method overlays the predictions on the input image, including drawing rectangles and text to visualize the predicted classes.\n\n    Args:\n        inference_request: The request object containing the image and parameters.\n        inference_response: The response object containing the predictions and other details.\n        class_names: List of class names corresponding to the model's classes.\n\n    Returns:\n        bytes: The bytes of the visualized image in JPEG format.\n    \"\"\"\n    image = load_image_rgb(inference_request.image)\n    image = Image.fromarray(image)\n    draw = ImageDraw.Draw(image)\n    font = ImageFont.load_default()\n    class_id_2_color = {\n        i: DEFAULT_COLOR_PALETTE[i % len(DEFAULT_COLOR_PALETTE)]\n        for i, class_name in enumerate(class_names)\n    }\n    if isinstance(inference_response.predictions, list):\n        prediction = inference_response.predictions[0]\n        color = class_id_2_color.get(prediction.class_id, \"#4892EA\")\n        draw.rectangle(\n            [0, 0, image.size[1], image.size[0]],\n            outline=color,\n            width=inference_request.visualization_stroke_width,\n        )\n        text = f\"{prediction.class_id} - {prediction.class_name} {prediction.confidence:.2f}\"\n        text_size = font.getbbox(text)\n\n        # set button size + 10px margins\n        button_size = (text_size[2] + 20, text_size[3] + 20)\n        button_img = Image.new(\"RGBA\", button_size, color)\n        # put text on button with 10px margins\n        button_draw = ImageDraw.Draw(button_img)\n        button_draw.text((10, 10), text, font=font, fill=(255, 255, 255, 255))\n\n        # put button on source image in position (0, 0)\n        image.paste(button_img, (0, 0))\n    else:\n        if len(inference_response.predictions) > 0:\n            box_color = \"#4892EA\"\n            draw.rectangle(\n                [0, 0, image.size[1], image.size[0]],\n                outline=box_color,\n                width=inference_request.visualization_stroke_width,\n            )\n        row = 0\n        predictions = [\n            (cls_name, pred)\n            for cls_name, pred in inference_response.predictions.items()\n        ]\n        predictions = sorted(predictions, key=lambda x: x[1].confidence, reverse=True)\n        for i, (cls_name, pred) in enumerate(predictions):\n            color = class_id_2_color.get(cls_name, \"#4892EA\")\n            text = f\"{cls_name} {pred.confidence:.2f}\"\n            text_size = font.getbbox(text)\n\n            # set button size + 10px margins\n            button_size = (text_size[2] + 20, text_size[3] + 20)\n            button_img = Image.new(\"RGBA\", button_size, color)\n            # put text on button with 10px margins\n            button_draw = ImageDraw.Draw(button_img)\n            button_draw.text((10, 10), text, font=font, fill=(255, 255, 255, 255))\n\n            # put button on source image in position (0, 0)\n            image.paste(button_img, (0, row))\n            row += button_size[1]\n\n    buffered = BytesIO()\n    image = image.convert(\"RGB\")\n    image.save(buffered, format=\"JPEG\")\n    return buffered.getvalue()\n\n\nclass InferenceModelsSemanticSegmentationAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n        model_id = resolve_roboflow_model_alias(model_id=model_id)\n\n        self.task_type = \"semantic-segmentation\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n        backend = list(\n            VALID_INFERENCE_MODELS_BACKENDS.difference(\n                DISABLED_INFERENCE_MODELS_BACKENDS\n            )\n        )\n        self._model: SemanticSegmentationModel = AutoModel.from_pretrained(\n            model_id_or_path=_resolve_cached_model_path(model_id),\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            backend=backend,\n            **kwargs,\n        )\n        self.class_names = list(self._model.class_names)\n\n    @property\n    def class_map(self):\n        # match segment.roboflow.com\n        return {str(k): v for k, v in enumerate(self.class_names)}\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        pre_processing_overrides = PreProcessingOverrides(\n            disable_contrast_enhancement=kwargs.get(\"disable_preproc_contrast\", False),\n            disable_grayscale=kwargs.get(\"disable_preproc_grayscale\", False),\n            disable_static_crop=kwargs.get(\"disable_preproc_static_crop\", False),\n        )\n        kwargs[\"pre_processing_overrides\"] = pre_processing_overrides\n        return kwargs\n\n    def preprocess(self, image: Any, **kwargs):\n        is_batch = isinstance(image, list)\n        images = image if is_batch else [image]\n        np_images: List[np.ndarray] = [\n            load_image_bgr(\n                v,\n                disable_preproc_auto_orient=kwargs.get(\n                    \"disable_preproc_auto_orient\", False\n                ),\n            )\n            for v in images\n        ]\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.pre_process(np_images, **mapped_kwargs)\n\n    def predict(self, img_in, **kwargs):\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.forward(img_in, **mapped_kwargs)\n\n    def postprocess(\n        self,\n        predictions: torch.Tensor,\n        preprocess_return_metadata: PreprocessingMetadata,\n        **kwargs,\n    ) -> List[SemanticSegmentationInferenceResponse]:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        segmentation_results = self._model.post_process(\n            predictions, preprocess_return_metadata, **mapped_kwargs\n        )\n\n        responses: List[SemanticSegmentationInferenceResponse] = []\n        for preproc_metadata, segmentation in zip(\n            preprocess_return_metadata, segmentation_results\n        ):\n            height = preproc_metadata.original_size.height\n            width = preproc_metadata.original_size.width\n            response_image = InferenceResponseImage(width=width, height=height)\n            # WARNING! This way of conversion is hazardous - first of all, if background class is not in class names,\n            # for certain pre-processing, we end up with -1 values which will be wrapped to 255 - second of all,\n            # we can support only 256 classes - those constraints should be fine until inference 2.0\n            response_predictions = SemanticSegmentationPrediction(\n                segmentation_mask=self.img_to_b64_str(\n                    segmentation.segmentation_map.to(torch.uint8)\n                ),\n                confidence_mask=self.img_to_b64_str(\n                    (segmentation.confidence * 255).to(torch.uint8)\n                ),\n                class_map=self.class_map,\n                image=dict(response_image),\n            )\n            response = SemanticSegmentationInferenceResponse(\n                predictions=response_predictions,\n                image=response_image,\n            )\n            responses.append(response)\n        return responses\n\n    def clear_cache(self, delete_from_disk: bool = True) -> None:\n        \"\"\"Clears any cache if necessary. TODO: Implement this to delete the cache from the experimental model.\n\n        Args:\n            delete_from_disk (bool, optional): Whether to delete cached files from disk. Defaults to True.\n        \"\"\"\n        pass\n\n    def img_to_b64_str(self, img: torch.Tensor) -> str:\n        if img.dtype != torch.uint8:\n            raise ValueError(\n                f\"img_to_b64_str requires uint8 tensor but got dtype {img.dtype}\"\n            )\n\n        img = Image.fromarray(img.cpu().numpy())\n        buffered = io.BytesIO()\n        img.save(buffered, format=\"PNG\")\n\n        img_str = base64.b64encode(buffered.getvalue())\n        img_str = img_str.decode(\"ascii\")\n\n        return img_str\n\n    def draw_predictions(\n        self,\n        inference_request: InferenceRequest,\n        inference_response: InferenceResponse,\n    ) -> bytes:\n        raise NotImplementedError(\n            \"draw_predictions(...) is not implemented for semantic segmentation models - responses contain \"\n            \"visualization already.\"\n        )\n",
    "patch": null
  },
  {
    "trace_id": "e96eab48-c0ed-4bc6-84f4-ff6f4ccb39cb",
    "function_name": "InferenceModelsMoondream2Adapter.caption",
    "file_path": "inference/models/moondream2/moondream2_inference_models.py",
    "speedup_x": 0.11,
    "review_quality": "high",
    "pre_optimization_commit": "7648e452a70ff1aad09f017a0eb2ea4022b7e177",
    "resolution_method": "db_code_match",
    "source": "db_events",
    "original_function_code": "    def caption(self, image_in: Union[Image.Image, np.array], **kwargs):\n        if not isinstance(image_in, np.ndarray):\n            np_img = np.array(image_in)  # RGB\n            bgr_img = cv2.cvtColor(np_img, cv2.COLOR_RGB2BGR)\n        else:\n            bgr_img = image_in\n        return self._model.caption(bgr_img)[0]\n",
    "optimized_function_code": "from typing import Union\n\nimport cv2\nimport numpy as np\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES, API_KEY)\nfrom inference.core.models.base import Model\nfrom inference.core.models.inference_models_adapters import \\\n    get_extra_weights_provider_headers\nfrom inference_models import AutoModel\nfrom inference_models.models.moondream2.moondream2_hf import MoonDream2HF\nfrom PIL import Image\n\n\nclass InferenceModelsMoondream2Adapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n\n        self.task_type = \"llm\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers()\n\n        self._model: MoonDream2HF = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            extra_weights_provider_headers=extra_weights_provider_headers,\n            **kwargs,\n        )\n\n    def caption(self, image_in: Union[Image.Image, np.array], **kwargs):\n        if not isinstance(image_in, np.ndarray):\n            np_img = np.asarray(image_in)  # RGB\n            bgr_img = cv2.cvtColor(np_img, cv2.COLOR_RGB2BGR)\n        else:\n            bgr_img = image_in\n        return self._model.caption(bgr_img)[0]",
    "optimized_raw_markdown": "```python:inference/models/moondream2/moondream2_inference_models.py\nfrom typing import Union\n\nimport cv2\nimport numpy as np\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES, API_KEY)\nfrom inference.core.models.base import Model\nfrom inference.core.models.inference_models_adapters import \\\n    get_extra_weights_provider_headers\nfrom inference_models import AutoModel\nfrom inference_models.models.moondream2.moondream2_hf import MoonDream2HF\nfrom PIL import Image\n\n\nclass InferenceModelsMoondream2Adapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n\n        self.task_type = \"llm\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers()\n\n        self._model: MoonDream2HF = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            extra_weights_provider_headers=extra_weights_provider_headers,\n            **kwargs,\n        )\n\n    def caption(self, image_in: Union[Image.Image, np.array], **kwargs):\n        if not isinstance(image_in, np.ndarray):\n            np_img = np.asarray(image_in)  # RGB\n            bgr_img = cv2.cvtColor(np_img, cv2.COLOR_RGB2BGR)\n        else:\n            bgr_img = image_in\n        return self._model.caption(bgr_img)[0]\n```",
    "optimized_function_only": "    def caption(self, image_in: Union[Image.Image, np.array], **kwargs):\n        if not isinstance(image_in, np.ndarray):\n            np_img = np.asarray(image_in)  # RGB\n            bgr_img = cv2.cvtColor(np_img, cv2.COLOR_RGB2BGR)\n        else:\n            bgr_img = image_in\n        return self._model.caption(bgr_img)[0]",
    "original_file_content": "from typing import Any, List, Tuple, Union\n\nimport cv2\nimport numpy as np\nfrom PIL import Image\n\nfrom inference.core.entities.responses.inference import (\n    InferenceResponseImage,\n    ObjectDetectionInferenceResponse,\n    ObjectDetectionPrediction,\n)\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n    API_KEY,\n    DISABLED_INFERENCE_MODELS_BACKENDS,\n    VALID_INFERENCE_MODELS_BACKENDS,\n)\nfrom inference.core.models.base import Model, PreprocessReturnMetadata\nfrom inference.core.roboflow_api import get_extra_weights_provider_headers\nfrom inference.core.utils.image_utils import load_image_bgr\nfrom inference_models import AutoModel, Detections\nfrom inference_models.models.moondream2.moondream2_hf import MoonDream2HF\n\n\nclass InferenceModelsMoondream2Adapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n\n        self.task_type = \"llm\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n        backend = list(\n            VALID_INFERENCE_MODELS_BACKENDS.difference(\n                DISABLED_INFERENCE_MODELS_BACKENDS\n            )\n        )\n        self._model: MoonDream2HF = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            backend=backend,\n            **kwargs,\n        )\n\n    def preprocess(self, image: Any, **kwargs):\n        is_batch = isinstance(image, list)\n        if is_batch:\n            raise ValueError(\"This model does not support batched-inference.\")\n        np_image = load_image_bgr(\n            image,\n            disable_preproc_auto_orient=kwargs.get(\n                \"disable_preproc_auto_orient\", False\n            ),\n        )\n        input_shape = PreprocessReturnMetadata({\"image_dims\": np_image.shape[:2][::-1]})\n        return (\n            np_image,\n            input_shape,\n        )\n\n    def predict(\n        self,\n        image_in: Union[Image.Image, np.array],\n        prompt: Union[str, List[str]] = \"\",\n        **kwargs,\n    ):\n        return self.detect(image_in, prompt=prompt, **kwargs)\n\n    def postprocess(\n        self,\n        predictions: List[ObjectDetectionInferenceResponse],\n        preprocess_return_metadata: PreprocessReturnMetadata,\n        **kwargs,\n    ) -> List[ObjectDetectionInferenceResponse]:\n        return predictions\n\n    def caption(self, image_in: Union[Image.Image, np.array], **kwargs):\n        if not isinstance(image_in, np.ndarray):\n            np_img = np.array(image_in)  # RGB\n            bgr_img = cv2.cvtColor(np_img, cv2.COLOR_RGB2BGR)\n        else:\n            bgr_img = image_in\n        return self._model.caption(bgr_img)[0]\n\n    def query(self, image_in: Union[Image.Image, np.array], prompt=\"\", **kwargs):\n        if not isinstance(image_in, np.ndarray):\n            np_img = np.array(image_in)  # RGB\n            bgr_img = cv2.cvtColor(np_img, cv2.COLOR_RGB2BGR)\n        else:\n            bgr_img = image_in\n        return self._model.query(bgr_img, question=prompt)[0]\n\n    def detect(\n        self,\n        image_in: Union[Image.Image, np.array],\n        prompt: str = \"\",\n        **kwargs,\n    ):\n        if not isinstance(image_in, np.ndarray):\n            np_img = np.array(image_in)  # RGB\n            bgr_img = cv2.cvtColor(np_img, cv2.COLOR_RGB2BGR)\n        else:\n            bgr_img = image_in\n        detections = self._model.detect(bgr_img, classes=[prompt])\n        return self.make_response(detections, [bgr_img.shape[:2]], prompt=prompt)\n\n    def make_response(\n        self,\n        predictions: List[Detections],\n        image_sizes,\n        prompt: str,\n    ):\n        responses = []\n\n        for ind, image_detections in enumerate(predictions):\n            predictions_for_image = []\n            for instance_id in range(image_detections.xyxy.shape[0]):\n                x_min, y_min, x_max, y_max = image_detections.xyxy[instance_id].tolist()\n                width = x_max - x_min\n                height = y_max - y_min\n                center_x = (x_min + x_max) / 2\n                center_y = (y_min + y_max) / 2\n                predictions_for_image.append(\n                    ObjectDetectionPrediction(\n                        # Passing args as a dictionary here since one of the args is 'class' (a protected term in Python)\n                        **{\n                            \"x\": center_x,\n                            \"y\": center_y,\n                            \"width\": width,\n                            \"height\": height,\n                            \"confidence\": 1.0,  # confidence is not returned by the model\n                            \"class\": prompt if prompt is not None else \"\",\n                            \"class_id\": 0,  # you can only prompt for one object at once\n                        }\n                    )\n                )\n            responses.append(\n                ObjectDetectionInferenceResponse(\n                    predictions=predictions_for_image,\n                    image=InferenceResponseImage(\n                        width=image_sizes[ind][1], height=image_sizes[ind][0]\n                    ),\n                )\n            )\n        return responses\n\n    def postprocess(\n        self,\n        predictions: Tuple[str],\n        preprocess_return_metadata: PreprocessReturnMetadata,\n        **kwargs,\n    ) -> List[ObjectDetectionInferenceResponse]:\n        return predictions\n",
    "patch": null
  },
  {
    "trace_id": "ebb67e12-d3a7-43a0-bad6-23cd44314b61",
    "function_name": "load_blocks",
    "file_path": "inference/core/workflows/core_steps/loader.py",
    "speedup_x": 4.09,
    "review_quality": "medium",
    "pre_optimization_commit": "cd270250ecccf2ca814425c27be92511f8e0fa6a",
    "resolution_method": "git_parent",
    "source": "git",
    "original_function_code": "def load_blocks() -> List[Type[WorkflowBlock]]:\n    return [\n        AbsoluteStaticCropBlockV1,\n        DynamicCropBlockV1,\n        DetectionsFilterBlockV1,\n        DetectionOffsetBlockV1,\n        DepthEstimationBlockV1,\n        ByteTrackerBlockV1,\n        RelativeStaticCropBlockV1,\n        DetectionsTransformationBlockV1,\n        RoboflowDatasetUploadBlockV1,\n        ContinueIfBlockV1,\n        RateLimiterBlockV1,\n        PerspectiveCorrectionBlockV1,\n        DeltaFilterBlockV1,\n        CameraCalibrationBlockV1,\n        DynamicZonesBlockV1,\n        SizeMeasurementBlockV1,\n        BufferBlockV1,\n        DetectionsClassesReplacementBlockV1,\n        ExpressionBlockV1,\n        PropertyDefinitionBlockV1,\n        DimensionCollapseBlockV1,\n        FirstNonEmptyOrDefaultBlockV1,\n        AnthropicClaudeBlockV1,\n        CosineSimilarityBlockV1,\n        BackgroundColorVisualizationBlockV1,\n        BarcodeDetectorBlockV1,\n        BlurVisualizationBlockV1,\n        BoundingBoxVisualizationBlockV1,\n        BoundingRectBlockV1,\n        DetectionsMergeBlockV1,\n        ByteTrackerBlockV2,\n        CacheGetBlockV1,\n        CacheSetBlockV1,\n        CameraFocusBlockV1,\n        CircleVisualizationBlockV1,\n        ClipComparisonBlockV1,\n        ClipComparisonBlockV2,\n        ClipModelBlockV1,\n        CogVLMBlockV1,\n        ColorVisualizationBlockV1,\n        ConvertGrayscaleBlockV1,\n        CornerVisualizationBlockV1,\n        CropVisualizationBlockV1,\n        DetectionsConsensusBlockV1,\n        DetectionsStitchBlockV1,\n        DistanceMeasurementBlockV1,\n        DominantColorBlockV1,\n        DotVisualizationBlockV1,\n        EllipseVisualizationBlockV1,\n        Florence2BlockV1,\n        Florence2BlockV2,\n        GoogleGeminiBlockV1,\n        GoogleVisionOCRBlockV1,\n        GridVisualizationBlockV1,\n        HaloVisualizationBlockV1,\n        ImageBlurBlockV1,\n        ImageContoursDetectionBlockV1,\n        ImagePreprocessingBlockV1,\n        ImageSlicerBlockV1,\n        ImageThresholdBlockV1,\n        JSONParserBlockV1,\n        LMMBlockV1,\n        LMMForClassificationBlockV1,\n        LabelVisualizationBlockV1,\n        ClassificationLabelVisualizationBlockV1,\n        LineCounterBlockV1,\n        LineCounterBlockV2,\n        LineCounterZoneVisualizationBlockV1,\n        MaskVisualizationBlockV1,\n        ModelComparisonVisualizationBlockV1,\n        OCRModelBlockV1,\n        OpenAIBlockV1,\n        OpenAIBlockV2,\n        OpenAIBlockV3,\n        PathDeviationAnalyticsBlockV1,\n        PathDeviationAnalyticsBlockV2,\n        PixelateVisualizationBlockV1,\n        PixelationCountBlockV1,\n        PolygonVisualizationBlockV1,\n        PolygonZoneVisualizationBlockV1,\n        QRCodeDetectorBlockV1,\n        RoboflowClassificationModelBlockV1,\n        RoboflowCustomMetadataBlockV1,\n        ModelMonitoringInferenceAggregatorBlockV1,\n        RoboflowDatasetUploadBlockV2,\n        RoboflowInstanceSegmentationModelBlockV1,\n        RoboflowKeypointDetectionModelBlockV1,\n        RoboflowMultiLabelClassificationModelBlockV1,\n        RoboflowObjectDetectionModelBlockV1,\n        SIFTBlockV1,\n        SIFTComparisonBlockV1,\n        SIFTComparisonBlockV2,\n        SegmentAnything2BlockV1,\n        StabilityAIInpaintingBlockV1,\n        StabilityAIImageGenBlockV1,\n        StabilizeTrackedDetectionsBlockV1,\n        StitchImagesBlockV1,\n        StitchOCRDetectionsBlockV1,\n        TemplateMatchingBlockV1,\n        TimeInZoneBlockV1,\n        TimeInZoneBlockV2,\n        TriangleVisualizationBlockV1,\n        VLMAsClassifierBlockV1,\n        VLMAsDetectorBlockV1,\n        YoloWorldModelBlockV1,\n        KeypointVisualizationBlockV1,\n        DataAggregatorBlockV1,\n        CSVFormatterBlockV1,\n        EmailNotificationBlockV1,\n        LocalFileSinkBlockV1,\n        TraceVisualizationBlockV1,\n        ReferencePathVisualizationBlockV1,\n        ByteTrackerBlockV3,\n        WebhookSinkBlockV1,\n        VelocityBlockV1,\n        RoboflowInstanceSegmentationModelBlockV2,\n        RoboflowKeypointDetectionModelBlockV2,\n        RoboflowClassificationModelBlockV2,\n        RoboflowMultiLabelClassificationModelBlockV2,\n        RoboflowObjectDetectionModelBlockV2,\n        VLMAsClassifierBlockV2,\n        VLMAsDetectorBlockV2,\n        IdentifyOutliersBlockV1,\n        IdentifyChangesBlockV1,\n        EnvironmentSecretsStoreBlockV1,\n        SlackNotificationBlockV1,\n        TwilioSMSNotificationBlockV1,\n        GazeBlockV1,\n        LlamaVisionBlockV1,\n        ImageSlicerBlockV2,\n        Qwen25VLBlockV1,\n        SmolVLM2BlockV1,\n        Moondream2BlockV1,\n        OverlapBlockV1,\n        ONVIFSinkBlockV1,\n    ]\n",
    "optimized_function_code": "from typing import List, Type\n\nfrom inference.core.cache import cache\nfrom inference.core.env import (\n    ALLOW_WORKFLOW_BLOCKS_ACCESSING_ENVIRONMENTAL_VARIABLES,\n    ALLOW_WORKFLOW_BLOCKS_ACCESSING_LOCAL_STORAGE,\n    API_KEY,\n    WORKFLOW_BLOCKS_WRITE_DIRECTORY,\n    WORKFLOWS_STEP_EXECUTION_MODE,\n)\nfrom inference.core.workflows.core_steps.analytics.data_aggregator.v1 import (\n    DataAggregatorBlockV1,\n)\nfrom inference.core.workflows.core_steps.analytics.line_counter.v1 import (\n    LineCounterBlockV1,\n)\nfrom inference.core.workflows.core_steps.analytics.line_counter.v2 import (\n    LineCounterBlockV2,\n)\nfrom inference.core.workflows.core_steps.analytics.overlap.v1 import OverlapBlockV1\nfrom inference.core.workflows.core_steps.analytics.path_deviation.v1 import (\n    PathDeviationAnalyticsBlockV1,\n)\nfrom inference.core.workflows.core_steps.analytics.path_deviation.v2 import (\n    PathDeviationAnalyticsBlockV2,\n)\nfrom inference.core.workflows.core_steps.analytics.time_in_zone.v1 import (\n    TimeInZoneBlockV1,\n)\nfrom inference.core.workflows.core_steps.analytics.time_in_zone.v2 import (\n    TimeInZoneBlockV2,\n)\nfrom inference.core.workflows.core_steps.analytics.velocity.v1 import VelocityBlockV1\nfrom inference.core.workflows.core_steps.cache.cache_get.v1 import CacheGetBlockV1\nfrom inference.core.workflows.core_steps.cache.cache_set.v1 import CacheSetBlockV1\nfrom inference.core.workflows.core_steps.classical_cv.camera_focus.v1 import (\n    CameraFocusBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.contours.v1 import (\n    ImageContoursDetectionBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.convert_grayscale.v1 import (\n    ConvertGrayscaleBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.distance_measurement.v1 import (\n    DistanceMeasurementBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.dominant_color.v1 import (\n    DominantColorBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.image_blur.v1 import (\n    ImageBlurBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.image_preprocessing.v1 import (\n    ImagePreprocessingBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.pixel_color_count.v1 import (\n    PixelationCountBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.sift.v1 import SIFTBlockV1\nfrom inference.core.workflows.core_steps.classical_cv.sift_comparison.v1 import (\n    SIFTComparisonBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.sift_comparison.v2 import (\n    SIFTComparisonBlockV2,\n)\nfrom inference.core.workflows.core_steps.classical_cv.size_measurement.v1 import (\n    SizeMeasurementBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.template_matching.v1 import (\n    TemplateMatchingBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.threshold.v1 import (\n    ImageThresholdBlockV1,\n)\nfrom inference.core.workflows.core_steps.common.deserializers import (\n    deserialize_boolean_kind,\n    deserialize_bytes_kind,\n    deserialize_classification_prediction_kind,\n    deserialize_detections_kind,\n    deserialize_dictionary_kind,\n    deserialize_float_kind,\n    deserialize_float_zero_to_one_kind,\n    deserialize_image_kind,\n    deserialize_integer_kind,\n    deserialize_list_of_values_kind,\n    deserialize_numpy_array,\n    deserialize_optional_string_kind,\n    deserialize_point_kind,\n    deserialize_rgb_color_kind,\n    deserialize_string_kind,\n    deserialize_timestamp,\n    deserialize_video_metadata_kind,\n    deserialize_zone_kind,\n)\nfrom inference.core.workflows.core_steps.common.entities import StepExecutionMode\nfrom inference.core.workflows.core_steps.common.serializers import (\n    serialise_image,\n    serialise_sv_detections,\n    serialize_secret,\n    serialize_timestamp,\n    serialize_video_metadata_kind,\n    serialize_wildcard_kind,\n)\nfrom inference.core.workflows.core_steps.flow_control.continue_if.v1 import (\n    ContinueIfBlockV1,\n)\nfrom inference.core.workflows.core_steps.flow_control.delta_filter.v1 import (\n    DeltaFilterBlockV1,\n)\nfrom inference.core.workflows.core_steps.flow_control.rate_limiter.v1 import (\n    RateLimiterBlockV1,\n)\nfrom inference.core.workflows.core_steps.formatters.csv.v1 import CSVFormatterBlockV1\nfrom inference.core.workflows.core_steps.formatters.expression.v1 import (\n    ExpressionBlockV1,\n)\nfrom inference.core.workflows.core_steps.formatters.first_non_empty_or_default.v1 import (\n    FirstNonEmptyOrDefaultBlockV1,\n)\nfrom inference.core.workflows.core_steps.formatters.json_parser.v1 import (\n    JSONParserBlockV1,\n)\nfrom inference.core.workflows.core_steps.formatters.property_definition.v1 import (\n    PropertyDefinitionBlockV1,\n)\nfrom inference.core.workflows.core_steps.formatters.vlm_as_classifier.v1 import (\n    VLMAsClassifierBlockV1,\n)\nfrom inference.core.workflows.core_steps.formatters.vlm_as_classifier.v2 import (\n    VLMAsClassifierBlockV2,\n)\nfrom inference.core.workflows.core_steps.formatters.vlm_as_detector.v1 import (\n    VLMAsDetectorBlockV1,\n)\nfrom inference.core.workflows.core_steps.formatters.vlm_as_detector.v2 import (\n    VLMAsDetectorBlockV2,\n)\nfrom inference.core.workflows.core_steps.fusion.buffer.v1 import BufferBlockV1\nfrom inference.core.workflows.core_steps.fusion.detections_classes_replacement.v1 import (\n    DetectionsClassesReplacementBlockV1,\n)\nfrom inference.core.workflows.core_steps.fusion.detections_consensus.v1 import (\n    DetectionsConsensusBlockV1,\n)\nfrom inference.core.workflows.core_steps.fusion.detections_stitch.v1 import (\n    DetectionsStitchBlockV1,\n)\nfrom inference.core.workflows.core_steps.fusion.dimension_collapse.v1 import (\n    DimensionCollapseBlockV1,\n)\nfrom inference.core.workflows.core_steps.math.cosine_similarity.v1 import (\n    CosineSimilarityBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.anthropic_claude.v1 import (\n    AnthropicClaudeBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.clip.v1 import (\n    ClipModelBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.clip_comparison.v1 import (\n    ClipComparisonBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.clip_comparison.v2 import (\n    ClipComparisonBlockV2,\n)\nfrom inference.core.workflows.core_steps.models.foundation.cog_vlm.v1 import (\n    CogVLMBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.depth_estimation.v1 import (\n    DepthEstimationBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.florence2.v1 import (\n    Florence2BlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.florence2.v2 import (\n    Florence2BlockV2,\n)\nfrom inference.core.workflows.core_steps.models.foundation.gaze.v1 import GazeBlockV1\nfrom inference.core.workflows.core_steps.models.foundation.google_gemini.v1 import (\n    GoogleGeminiBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.google_vision_ocr.v1 import (\n    GoogleVisionOCRBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.llama_vision.v1 import (\n    LlamaVisionBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.lmm.v1 import LMMBlockV1\nfrom inference.core.workflows.core_steps.models.foundation.lmm_classifier.v1 import (\n    LMMForClassificationBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.moondream2.v1 import (\n    Moondream2BlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.ocr.v1 import OCRModelBlockV1\nfrom inference.core.workflows.core_steps.models.foundation.openai.v1 import (\n    OpenAIBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.openai.v2 import (\n    OpenAIBlockV2,\n)\nfrom inference.core.workflows.core_steps.models.foundation.openai.v3 import (\n    OpenAIBlockV3,\n)\nfrom inference.core.workflows.core_steps.models.foundation.qwen.v1 import (\n    Qwen25VLBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.segment_anything2.v1 import (\n    SegmentAnything2BlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.smolvlm.v1 import (\n    SmolVLM2BlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.stability_ai.image_gen.v1 import (\n    StabilityAIImageGenBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.stability_ai.inpainting.v1 import (\n    StabilityAIInpaintingBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.yolo_world.v1 import (\n    YoloWorldModelBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.roboflow.instance_segmentation.v1 import (\n    RoboflowInstanceSegmentationModelBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.roboflow.instance_segmentation.v2 import (\n    RoboflowInstanceSegmentationModelBlockV2,\n)\nfrom inference.core.workflows.core_steps.models.roboflow.keypoint_detection.v1 import (\n    RoboflowKeypointDetectionModelBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.roboflow.keypoint_detection.v2 import (\n    RoboflowKeypointDetectionModelBlockV2,\n)\nfrom inference.core.workflows.core_steps.models.roboflow.multi_class_classification.v1 import (\n    RoboflowClassificationModelBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.roboflow.multi_class_classification.v2 import (\n    RoboflowClassificationModelBlockV2,\n)\nfrom inference.core.workflows.core_steps.models.roboflow.multi_label_classification.v1 import (\n    RoboflowMultiLabelClassificationModelBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.roboflow.multi_label_classification.v2 import (\n    RoboflowMultiLabelClassificationModelBlockV2,\n)\nfrom inference.core.workflows.core_steps.models.roboflow.object_detection.v1 import (\n    RoboflowObjectDetectionModelBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.roboflow.object_detection.v2 import (\n    RoboflowObjectDetectionModelBlockV2,\n)\nfrom inference.core.workflows.core_steps.models.third_party.barcode_detection.v1 import (\n    BarcodeDetectorBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.third_party.qr_code_detection.v1 import (\n    QRCodeDetectorBlockV1,\n)\nfrom inference.core.workflows.core_steps.sampling.identify_changes.v1 import (\n    IdentifyChangesBlockV1,\n)\nfrom inference.core.workflows.core_steps.sampling.identify_outliers.v1 import (\n    IdentifyOutliersBlockV1,\n)\nfrom inference.core.workflows.core_steps.secrets_providers.environment_secrets_store.v1 import (\n    EnvironmentSecretsStoreBlockV1,\n)\nfrom inference.core.workflows.core_steps.sinks.email_notification.v1 import (\n    EmailNotificationBlockV1,\n)\nfrom inference.core.workflows.core_steps.sinks.local_file.v1 import LocalFileSinkBlockV1\nfrom inference.core.workflows.core_steps.sinks.onvif_movement.v1 import ONVIFSinkBlockV1\nfrom inference.core.workflows.core_steps.sinks.roboflow.custom_metadata.v1 import (\n    RoboflowCustomMetadataBlockV1,\n)\nfrom inference.core.workflows.core_steps.sinks.roboflow.dataset_upload.v1 import (\n    RoboflowDatasetUploadBlockV1,\n)\nfrom inference.core.workflows.core_steps.sinks.roboflow.dataset_upload.v2 import (\n    RoboflowDatasetUploadBlockV2,\n)\nfrom inference.core.workflows.core_steps.sinks.roboflow.model_monitoring_inference_aggregator.v1 import (\n    ModelMonitoringInferenceAggregatorBlockV1,\n)\nfrom inference.core.workflows.core_steps.sinks.slack.notification.v1 import (\n    SlackNotificationBlockV1,\n)\nfrom inference.core.workflows.core_steps.sinks.twilio.sms.v1 import (\n    TwilioSMSNotificationBlockV1,\n)\nfrom inference.core.workflows.core_steps.sinks.webhook.v1 import WebhookSinkBlockV1\nfrom inference.core.workflows.core_steps.transformations.absolute_static_crop.v1 import (\n    AbsoluteStaticCropBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.bounding_rect.v1 import (\n    BoundingRectBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.byte_tracker.v1 import (\n    ByteTrackerBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.byte_tracker.v2 import (\n    ByteTrackerBlockV2,\n)\nfrom inference.core.workflows.core_steps.transformations.byte_tracker.v3 import (\n    ByteTrackerBlockV3,\n)\nfrom inference.core.workflows.core_steps.transformations.camera_calibration.v1 import (\n    CameraCalibrationBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.detection_offset.v1 import (\n    DetectionOffsetBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.detections_filter.v1 import (\n    DetectionsFilterBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.detections_merge.v1 import (\n    DetectionsMergeBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.detections_transformation.v1 import (\n    DetectionsTransformationBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.dynamic_crop.v1 import (\n    DynamicCropBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.dynamic_zones.v1 import (\n    DynamicZonesBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.image_slicer.v1 import (\n    ImageSlicerBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.image_slicer.v2 import (\n    ImageSlicerBlockV2,\n)\nfrom inference.core.workflows.core_steps.transformations.perspective_correction.v1 import (\n    PerspectiveCorrectionBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.relative_static_crop.v1 import (\n    RelativeStaticCropBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.stabilize_detections.v1 import (\n    StabilizeTrackedDetectionsBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.stitch_images.v1 import (\n    StitchImagesBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.stitch_ocr_detections.v1 import (\n    StitchOCRDetectionsBlockV1,\n)\n\n# Visualizers\nfrom inference.core.workflows.core_steps.visualizations.background_color.v1 import (\n    BackgroundColorVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.blur.v1 import (\n    BlurVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.bounding_box.v1 import (\n    BoundingBoxVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.circle.v1 import (\n    CircleVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.classification_label.v1 import (\n    ClassificationLabelVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.color.v1 import (\n    ColorVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.corner.v1 import (\n    CornerVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.crop.v1 import (\n    CropVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.dot.v1 import (\n    DotVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.ellipse.v1 import (\n    EllipseVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.grid.v1 import (\n    GridVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.halo.v1 import (\n    HaloVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.keypoint.v1 import (\n    KeypointVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.label.v1 import (\n    LabelVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.line_zone.v1 import (\n    LineCounterZoneVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.mask.v1 import (\n    MaskVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.model_comparison.v1 import (\n    ModelComparisonVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.pixelate.v1 import (\n    PixelateVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.polygon.v1 import (\n    PolygonVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.polygon_zone.v1 import (\n    PolygonZoneVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.reference_path.v1 import (\n    ReferencePathVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.trace.v1 import (\n    TraceVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.triangle.v1 import (\n    TriangleVisualizationBlockV1,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    BAR_CODE_DETECTION_KIND,\n    BOOLEAN_KIND,\n    BYTES_KIND,\n    CLASSIFICATION_PREDICTION_KIND,\n    CONTOURS_KIND,\n    DETECTION_KIND,\n    DICTIONARY_KIND,\n    EMBEDDING_KIND,\n    FLOAT_KIND,\n    FLOAT_ZERO_TO_ONE_KIND,\n    IMAGE_KEYPOINTS_KIND,\n    IMAGE_KIND,\n    IMAGE_METADATA_KIND,\n    INFERENCE_ID_KIND,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    INTEGER_KIND,\n    KEYPOINT_DETECTION_PREDICTION_KIND,\n    LANGUAGE_MODEL_OUTPUT_KIND,\n    LIST_OF_VALUES_KIND,\n    NUMPY_ARRAY_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    PARENT_ID_KIND,\n    POINT_KIND,\n    PREDICTION_TYPE_KIND,\n    QR_CODE_DETECTION_KIND,\n    RGB_COLOR_KIND,\n    ROBOFLOW_API_KEY_KIND,\n    ROBOFLOW_MANAGED_KEY,\n    ROBOFLOW_MODEL_ID_KIND,\n    ROBOFLOW_PROJECT_KIND,\n    SECRET_KIND,\n    SERIALISED_PAYLOADS_KIND,\n    STRING_KIND,\n    TIMESTAMP_KIND,\n    TOP_CLASS_KIND,\n    VIDEO_METADATA_KIND,\n    WILDCARD_KIND,\n    ZONE_KIND,\n    Kind,\n)\nfrom inference.core.workflows.prototypes.block import WorkflowBlock\n\nREGISTERED_INITIALIZERS = {\n    \"api_key\": API_KEY,\n    \"cache\": cache,\n    \"step_execution_mode\": StepExecutionMode(WORKFLOWS_STEP_EXECUTION_MODE),\n    \"background_tasks\": None,\n    \"thread_pool_executor\": None,\n    \"allow_access_to_file_system\": ALLOW_WORKFLOW_BLOCKS_ACCESSING_LOCAL_STORAGE,\n    \"allowed_write_directory\": WORKFLOW_BLOCKS_WRITE_DIRECTORY,\n    \"allow_access_to_environmental_variables\": ALLOW_WORKFLOW_BLOCKS_ACCESSING_ENVIRONMENTAL_VARIABLES,\n}\n\nKINDS_SERIALIZERS = {\n    IMAGE_KIND.name: serialise_image,\n    VIDEO_METADATA_KIND.name: serialize_video_metadata_kind,\n    OBJECT_DETECTION_PREDICTION_KIND.name: serialise_sv_detections,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND.name: serialise_sv_detections,\n    KEYPOINT_DETECTION_PREDICTION_KIND.name: serialise_sv_detections,\n    QR_CODE_DETECTION_KIND.name: serialise_sv_detections,\n    BAR_CODE_DETECTION_KIND.name: serialise_sv_detections,\n    SECRET_KIND.name: serialize_secret,\n    WILDCARD_KIND.name: serialize_wildcard_kind,\n    TIMESTAMP_KIND.name: serialize_timestamp,\n}\nKINDS_DESERIALIZERS = {\n    IMAGE_KIND.name: deserialize_image_kind,\n    VIDEO_METADATA_KIND.name: deserialize_video_metadata_kind,\n    OBJECT_DETECTION_PREDICTION_KIND.name: deserialize_detections_kind,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND.name: deserialize_detections_kind,\n    KEYPOINT_DETECTION_PREDICTION_KIND.name: deserialize_detections_kind,\n    QR_CODE_DETECTION_KIND.name: deserialize_detections_kind,\n    BAR_CODE_DETECTION_KIND.name: deserialize_detections_kind,\n    NUMPY_ARRAY_KIND.name: deserialize_numpy_array,\n    ROBOFLOW_MODEL_ID_KIND.name: deserialize_string_kind,\n    ROBOFLOW_PROJECT_KIND.name: deserialize_string_kind,\n    ROBOFLOW_API_KEY_KIND.name: deserialize_optional_string_kind,\n    ROBOFLOW_MANAGED_KEY.name: deserialize_optional_string_kind,\n    FLOAT_ZERO_TO_ONE_KIND.name: deserialize_float_zero_to_one_kind,\n    LIST_OF_VALUES_KIND.name: deserialize_list_of_values_kind,\n    BOOLEAN_KIND.name: deserialize_boolean_kind,\n    INTEGER_KIND.name: deserialize_integer_kind,\n    STRING_KIND.name: deserialize_string_kind,\n    TOP_CLASS_KIND.name: deserialize_string_kind,\n    FLOAT_KIND.name: deserialize_float_kind,\n    DICTIONARY_KIND.name: deserialize_dictionary_kind,\n    CLASSIFICATION_PREDICTION_KIND.name: deserialize_classification_prediction_kind,\n    POINT_KIND.name: deserialize_point_kind,\n    ZONE_KIND.name: deserialize_zone_kind,\n    RGB_COLOR_KIND.name: deserialize_rgb_color_kind,\n    LANGUAGE_MODEL_OUTPUT_KIND.name: deserialize_string_kind,\n    PREDICTION_TYPE_KIND.name: deserialize_string_kind,\n    PARENT_ID_KIND.name: deserialize_string_kind,\n    BYTES_KIND.name: deserialize_bytes_kind,\n    INFERENCE_ID_KIND.name: deserialize_string_kind,\n    TIMESTAMP_KIND.name: deserialize_timestamp,\n}\n\n\ndef load_blocks() -> List[Type[WorkflowBlock]]:\n    if not hasattr(load_blocks, \"_blocks\"):\n        load_blocks._blocks = [\n            AbsoluteStaticCropBlockV1,\n            DynamicCropBlockV1,\n            DetectionsFilterBlockV1,\n            DetectionOffsetBlockV1,\n            DepthEstimationBlockV1,\n            ByteTrackerBlockV1,\n            RelativeStaticCropBlockV1,\n            DetectionsTransformationBlockV1,\n            RoboflowDatasetUploadBlockV1,\n            ContinueIfBlockV1,\n            RateLimiterBlockV1,\n            PerspectiveCorrectionBlockV1,\n            DeltaFilterBlockV1,\n            CameraCalibrationBlockV1,\n            DynamicZonesBlockV1,\n            SizeMeasurementBlockV1,\n            BufferBlockV1,\n            DetectionsClassesReplacementBlockV1,\n            ExpressionBlockV1,\n            PropertyDefinitionBlockV1,\n            DimensionCollapseBlockV1,\n            FirstNonEmptyOrDefaultBlockV1,\n            AnthropicClaudeBlockV1,\n            CosineSimilarityBlockV1,\n            BackgroundColorVisualizationBlockV1,\n            BarcodeDetectorBlockV1,\n            BlurVisualizationBlockV1,\n            BoundingBoxVisualizationBlockV1,\n            BoundingRectBlockV1,\n            DetectionsMergeBlockV1,\n            ByteTrackerBlockV2,\n            CacheGetBlockV1,\n            CacheSetBlockV1,\n            CameraFocusBlockV1,\n            CircleVisualizationBlockV1,\n            ClipComparisonBlockV1,\n            ClipComparisonBlockV2,\n            ClipModelBlockV1,\n            CogVLMBlockV1,\n            ColorVisualizationBlockV1,\n            ConvertGrayscaleBlockV1,\n            CornerVisualizationBlockV1,\n            CropVisualizationBlockV1,\n            DetectionsConsensusBlockV1,\n            DetectionsStitchBlockV1,\n            DistanceMeasurementBlockV1,\n            DominantColorBlockV1,\n            DotVisualizationBlockV1,\n            EllipseVisualizationBlockV1,\n            Florence2BlockV1,\n            Florence2BlockV2,\n            GoogleGeminiBlockV1,\n            GoogleVisionOCRBlockV1,\n            GridVisualizationBlockV1,\n            HaloVisualizationBlockV1,\n            ImageBlurBlockV1,\n            ImageContoursDetectionBlockV1,\n            ImagePreprocessingBlockV1,\n            ImageSlicerBlockV1,\n            ImageThresholdBlockV1,\n            JSONParserBlockV1,\n            LMMBlockV1,\n            LMMForClassificationBlockV1,\n            LabelVisualizationBlockV1,\n            ClassificationLabelVisualizationBlockV1,\n            LineCounterBlockV1,\n            LineCounterBlockV2,\n            LineCounterZoneVisualizationBlockV1,\n            MaskVisualizationBlockV1,\n            ModelComparisonVisualizationBlockV1,\n            OCRModelBlockV1,\n            OpenAIBlockV1,\n            OpenAIBlockV2,\n            OpenAIBlockV3,\n            PathDeviationAnalyticsBlockV1,\n            PathDeviationAnalyticsBlockV2,\n            PixelateVisualizationBlockV1,\n            PixelationCountBlockV1,\n            PolygonVisualizationBlockV1,\n            PolygonZoneVisualizationBlockV1,\n            QRCodeDetectorBlockV1,\n            RoboflowClassificationModelBlockV1,\n            RoboflowCustomMetadataBlockV1,\n            ModelMonitoringInferenceAggregatorBlockV1,\n            RoboflowDatasetUploadBlockV2,\n            RoboflowInstanceSegmentationModelBlockV1,\n            RoboflowKeypointDetectionModelBlockV1,\n            RoboflowMultiLabelClassificationModelBlockV1,\n            RoboflowObjectDetectionModelBlockV1,\n            SIFTBlockV1,\n            SIFTComparisonBlockV1,\n            SIFTComparisonBlockV2,\n            SegmentAnything2BlockV1,\n            StabilityAIInpaintingBlockV1,\n            StabilityAIImageGenBlockV1,\n            StabilizeTrackedDetectionsBlockV1,\n            StitchImagesBlockV1,\n            StitchOCRDetectionsBlockV1,\n            TemplateMatchingBlockV1,\n            TimeInZoneBlockV1,\n            TimeInZoneBlockV2,\n            TriangleVisualizationBlockV1,\n            VLMAsClassifierBlockV1,\n            VLMAsDetectorBlockV1,\n            YoloWorldModelBlockV1,\n            KeypointVisualizationBlockV1,\n            DataAggregatorBlockV1,\n            CSVFormatterBlockV1,\n            EmailNotificationBlockV1,\n            LocalFileSinkBlockV1,\n            TraceVisualizationBlockV1,\n            ReferencePathVisualizationBlockV1,\n            ByteTrackerBlockV3,\n            WebhookSinkBlockV1,\n            VelocityBlockV1,\n            RoboflowInstanceSegmentationModelBlockV2,\n            RoboflowKeypointDetectionModelBlockV2,\n            RoboflowClassificationModelBlockV2,\n            RoboflowMultiLabelClassificationModelBlockV2,\n            RoboflowObjectDetectionModelBlockV2,\n            VLMAsClassifierBlockV2,\n            VLMAsDetectorBlockV2,\n            IdentifyOutliersBlockV1,\n            IdentifyChangesBlockV1,\n            EnvironmentSecretsStoreBlockV1,\n            SlackNotificationBlockV1,\n            TwilioSMSNotificationBlockV1,\n            GazeBlockV1,\n            LlamaVisionBlockV1,\n            ImageSlicerBlockV2,\n            Qwen25VLBlockV1,\n            SmolVLM2BlockV1,\n            Moondream2BlockV1,\n            OverlapBlockV1,\n            ONVIFSinkBlockV1,\n        ]\n    return load_blocks._blocks\n\n\ndef load_kinds() -> List[Kind]:\n    return [\n        WILDCARD_KIND,\n        IMAGE_KIND,\n        VIDEO_METADATA_KIND,\n        ROBOFLOW_MODEL_ID_KIND,\n        ROBOFLOW_PROJECT_KIND,\n        ROBOFLOW_API_KEY_KIND,\n        FLOAT_ZERO_TO_ONE_KIND,\n        LIST_OF_VALUES_KIND,\n        SERIALISED_PAYLOADS_KIND,\n        BOOLEAN_KIND,\n        INTEGER_KIND,\n        STRING_KIND,\n        TOP_CLASS_KIND,\n        FLOAT_KIND,\n        DICTIONARY_KIND,\n        DETECTION_KIND,\n        CLASSIFICATION_PREDICTION_KIND,\n        POINT_KIND,\n        ZONE_KIND,\n        OBJECT_DETECTION_PREDICTION_KIND,\n        INSTANCE_SEGMENTATION_PREDICTION_KIND,\n        KEYPOINT_DETECTION_PREDICTION_KIND,\n        RGB_COLOR_KIND,\n        IMAGE_KEYPOINTS_KIND,\n        CONTOURS_KIND,\n        LANGUAGE_MODEL_OUTPUT_KIND,\n        NUMPY_ARRAY_KIND,\n        QR_CODE_DETECTION_KIND,\n        BAR_CODE_DETECTION_KIND,\n        PREDICTION_TYPE_KIND,\n        ROBOFLOW_MANAGED_KEY,\n        PARENT_ID_KIND,\n        IMAGE_METADATA_KIND,\n        BYTES_KIND,\n        INFERENCE_ID_KIND,\n        SECRET_KIND,\n        EMBEDDING_KIND,\n        TIMESTAMP_KIND,\n    ]\n",
    "optimized_raw_markdown": "",
    "optimized_function_only": "def load_blocks() -> List[Type[WorkflowBlock]]:\n    if not hasattr(load_blocks, \"_blocks\"):\n        load_blocks._blocks = [\n            AbsoluteStaticCropBlockV1,\n            DynamicCropBlockV1,\n            DetectionsFilterBlockV1,\n            DetectionOffsetBlockV1,\n            DepthEstimationBlockV1,\n            ByteTrackerBlockV1,\n            RelativeStaticCropBlockV1,\n            DetectionsTransformationBlockV1,\n            RoboflowDatasetUploadBlockV1,\n            ContinueIfBlockV1,\n            RateLimiterBlockV1,\n            PerspectiveCorrectionBlockV1,\n            DeltaFilterBlockV1,\n            CameraCalibrationBlockV1,\n            DynamicZonesBlockV1,\n            SizeMeasurementBlockV1,\n            BufferBlockV1,\n            DetectionsClassesReplacementBlockV1,\n            ExpressionBlockV1,\n            PropertyDefinitionBlockV1,\n            DimensionCollapseBlockV1,\n            FirstNonEmptyOrDefaultBlockV1,\n            AnthropicClaudeBlockV1,\n            CosineSimilarityBlockV1,\n            BackgroundColorVisualizationBlockV1,\n            BarcodeDetectorBlockV1,\n            BlurVisualizationBlockV1,\n            BoundingBoxVisualizationBlockV1,\n            BoundingRectBlockV1,\n            DetectionsMergeBlockV1,\n            ByteTrackerBlockV2,\n            CacheGetBlockV1,\n            CacheSetBlockV1,\n            CameraFocusBlockV1,\n            CircleVisualizationBlockV1,\n            ClipComparisonBlockV1,\n            ClipComparisonBlockV2,\n            ClipModelBlockV1,\n            CogVLMBlockV1,\n            ColorVisualizationBlockV1,\n            ConvertGrayscaleBlockV1,\n            CornerVisualizationBlockV1,\n            CropVisualizationBlockV1,\n            DetectionsConsensusBlockV1,\n            DetectionsStitchBlockV1,\n            DistanceMeasurementBlockV1,\n            DominantColorBlockV1,\n            DotVisualizationBlockV1,\n            EllipseVisualizationBlockV1,\n            Florence2BlockV1,\n            Florence2BlockV2,\n            GoogleGeminiBlockV1,\n            GoogleVisionOCRBlockV1,\n            GridVisualizationBlockV1,\n            HaloVisualizationBlockV1,\n            ImageBlurBlockV1,\n            ImageContoursDetectionBlockV1,\n            ImagePreprocessingBlockV1,\n            ImageSlicerBlockV1,\n            ImageThresholdBlockV1,\n            JSONParserBlockV1,\n            LMMBlockV1,\n            LMMForClassificationBlockV1,\n            LabelVisualizationBlockV1,\n            ClassificationLabelVisualizationBlockV1,\n            LineCounterBlockV1,\n            LineCounterBlockV2,\n            LineCounterZoneVisualizationBlockV1,\n            MaskVisualizationBlockV1,\n            ModelComparisonVisualizationBlockV1,\n            OCRModelBlockV1,\n            OpenAIBlockV1,\n            OpenAIBlockV2,\n            OpenAIBlockV3,\n            PathDeviationAnalyticsBlockV1,\n            PathDeviationAnalyticsBlockV2,\n            PixelateVisualizationBlockV1,\n            PixelationCountBlockV1,\n            PolygonVisualizationBlockV1,\n            PolygonZoneVisualizationBlockV1,\n            QRCodeDetectorBlockV1,\n            RoboflowClassificationModelBlockV1,\n            RoboflowCustomMetadataBlockV1,\n            ModelMonitoringInferenceAggregatorBlockV1,\n            RoboflowDatasetUploadBlockV2,\n            RoboflowInstanceSegmentationModelBlockV1,\n            RoboflowKeypointDetectionModelBlockV1,\n            RoboflowMultiLabelClassificationModelBlockV1,\n            RoboflowObjectDetectionModelBlockV1,\n            SIFTBlockV1,\n            SIFTComparisonBlockV1,\n            SIFTComparisonBlockV2,\n            SegmentAnything2BlockV1,\n            StabilityAIInpaintingBlockV1,\n            StabilityAIImageGenBlockV1,\n            StabilizeTrackedDetectionsBlockV1,\n            StitchImagesBlockV1,\n            StitchOCRDetectionsBlockV1,\n            TemplateMatchingBlockV1,\n            TimeInZoneBlockV1,\n            TimeInZoneBlockV2,\n            TriangleVisualizationBlockV1,\n            VLMAsClassifierBlockV1,\n            VLMAsDetectorBlockV1,\n            YoloWorldModelBlockV1,\n            KeypointVisualizationBlockV1,\n            DataAggregatorBlockV1,\n            CSVFormatterBlockV1,\n            EmailNotificationBlockV1,\n            LocalFileSinkBlockV1,\n            TraceVisualizationBlockV1,\n            ReferencePathVisualizationBlockV1,\n            ByteTrackerBlockV3,\n            WebhookSinkBlockV1,\n            VelocityBlockV1,\n            RoboflowInstanceSegmentationModelBlockV2,\n            RoboflowKeypointDetectionModelBlockV2,\n            RoboflowClassificationModelBlockV2,\n            RoboflowMultiLabelClassificationModelBlockV2,\n            RoboflowObjectDetectionModelBlockV2,\n            VLMAsClassifierBlockV2,\n            VLMAsDetectorBlockV2,\n            IdentifyOutliersBlockV1,\n            IdentifyChangesBlockV1,\n            EnvironmentSecretsStoreBlockV1,\n            SlackNotificationBlockV1,\n            TwilioSMSNotificationBlockV1,\n            GazeBlockV1,\n            LlamaVisionBlockV1,\n            ImageSlicerBlockV2,\n            Qwen25VLBlockV1,\n            SmolVLM2BlockV1,\n            Moondream2BlockV1,\n            OverlapBlockV1,\n            ONVIFSinkBlockV1,\n        ]\n    return load_blocks._blocks\n",
    "original_file_content": "from typing import List, Type\n\nfrom inference.core.cache import cache\nfrom inference.core.env import (\n    ALLOW_WORKFLOW_BLOCKS_ACCESSING_ENVIRONMENTAL_VARIABLES,\n    ALLOW_WORKFLOW_BLOCKS_ACCESSING_LOCAL_STORAGE,\n    API_KEY,\n    WORKFLOW_BLOCKS_WRITE_DIRECTORY,\n    WORKFLOWS_STEP_EXECUTION_MODE,\n)\nfrom inference.core.workflows.core_steps.analytics.data_aggregator.v1 import (\n    DataAggregatorBlockV1,\n)\nfrom inference.core.workflows.core_steps.analytics.line_counter.v1 import (\n    LineCounterBlockV1,\n)\nfrom inference.core.workflows.core_steps.analytics.line_counter.v2 import (\n    LineCounterBlockV2,\n)\nfrom inference.core.workflows.core_steps.analytics.overlap.v1 import OverlapBlockV1\nfrom inference.core.workflows.core_steps.analytics.path_deviation.v1 import (\n    PathDeviationAnalyticsBlockV1,\n)\nfrom inference.core.workflows.core_steps.analytics.path_deviation.v2 import (\n    PathDeviationAnalyticsBlockV2,\n)\nfrom inference.core.workflows.core_steps.analytics.time_in_zone.v1 import (\n    TimeInZoneBlockV1,\n)\nfrom inference.core.workflows.core_steps.analytics.time_in_zone.v2 import (\n    TimeInZoneBlockV2,\n)\nfrom inference.core.workflows.core_steps.analytics.velocity.v1 import VelocityBlockV1\nfrom inference.core.workflows.core_steps.cache.cache_get.v1 import CacheGetBlockV1\nfrom inference.core.workflows.core_steps.cache.cache_set.v1 import CacheSetBlockV1\nfrom inference.core.workflows.core_steps.classical_cv.camera_focus.v1 import (\n    CameraFocusBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.contours.v1 import (\n    ImageContoursDetectionBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.convert_grayscale.v1 import (\n    ConvertGrayscaleBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.distance_measurement.v1 import (\n    DistanceMeasurementBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.dominant_color.v1 import (\n    DominantColorBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.image_blur.v1 import (\n    ImageBlurBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.image_preprocessing.v1 import (\n    ImagePreprocessingBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.pixel_color_count.v1 import (\n    PixelationCountBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.sift.v1 import SIFTBlockV1\nfrom inference.core.workflows.core_steps.classical_cv.sift_comparison.v1 import (\n    SIFTComparisonBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.sift_comparison.v2 import (\n    SIFTComparisonBlockV2,\n)\nfrom inference.core.workflows.core_steps.classical_cv.size_measurement.v1 import (\n    SizeMeasurementBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.template_matching.v1 import (\n    TemplateMatchingBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.threshold.v1 import (\n    ImageThresholdBlockV1,\n)\nfrom inference.core.workflows.core_steps.common.deserializers import (\n    deserialize_boolean_kind,\n    deserialize_bytes_kind,\n    deserialize_classification_prediction_kind,\n    deserialize_detections_kind,\n    deserialize_dictionary_kind,\n    deserialize_float_kind,\n    deserialize_float_zero_to_one_kind,\n    deserialize_image_kind,\n    deserialize_integer_kind,\n    deserialize_list_of_values_kind,\n    deserialize_numpy_array,\n    deserialize_optional_string_kind,\n    deserialize_point_kind,\n    deserialize_rgb_color_kind,\n    deserialize_string_kind,\n    deserialize_timestamp,\n    deserialize_video_metadata_kind,\n    deserialize_zone_kind,\n)\nfrom inference.core.workflows.core_steps.common.entities import StepExecutionMode\nfrom inference.core.workflows.core_steps.common.serializers import (\n    serialise_image,\n    serialise_sv_detections,\n    serialize_secret,\n    serialize_timestamp,\n    serialize_video_metadata_kind,\n    serialize_wildcard_kind,\n)\nfrom inference.core.workflows.core_steps.flow_control.continue_if.v1 import (\n    ContinueIfBlockV1,\n)\nfrom inference.core.workflows.core_steps.flow_control.delta_filter.v1 import (\n    DeltaFilterBlockV1,\n)\nfrom inference.core.workflows.core_steps.flow_control.rate_limiter.v1 import (\n    RateLimiterBlockV1,\n)\nfrom inference.core.workflows.core_steps.formatters.csv.v1 import CSVFormatterBlockV1\nfrom inference.core.workflows.core_steps.formatters.expression.v1 import (\n    ExpressionBlockV1,\n)\nfrom inference.core.workflows.core_steps.formatters.first_non_empty_or_default.v1 import (\n    FirstNonEmptyOrDefaultBlockV1,\n)\nfrom inference.core.workflows.core_steps.formatters.json_parser.v1 import (\n    JSONParserBlockV1,\n)\nfrom inference.core.workflows.core_steps.formatters.property_definition.v1 import (\n    PropertyDefinitionBlockV1,\n)\nfrom inference.core.workflows.core_steps.formatters.vlm_as_classifier.v1 import (\n    VLMAsClassifierBlockV1,\n)\nfrom inference.core.workflows.core_steps.formatters.vlm_as_classifier.v2 import (\n    VLMAsClassifierBlockV2,\n)\nfrom inference.core.workflows.core_steps.formatters.vlm_as_detector.v1 import (\n    VLMAsDetectorBlockV1,\n)\nfrom inference.core.workflows.core_steps.formatters.vlm_as_detector.v2 import (\n    VLMAsDetectorBlockV2,\n)\nfrom inference.core.workflows.core_steps.fusion.buffer.v1 import BufferBlockV1\nfrom inference.core.workflows.core_steps.fusion.detections_classes_replacement.v1 import (\n    DetectionsClassesReplacementBlockV1,\n)\nfrom inference.core.workflows.core_steps.fusion.detections_consensus.v1 import (\n    DetectionsConsensusBlockV1,\n)\nfrom inference.core.workflows.core_steps.fusion.detections_stitch.v1 import (\n    DetectionsStitchBlockV1,\n)\nfrom inference.core.workflows.core_steps.fusion.dimension_collapse.v1 import (\n    DimensionCollapseBlockV1,\n)\nfrom inference.core.workflows.core_steps.math.cosine_similarity.v1 import (\n    CosineSimilarityBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.anthropic_claude.v1 import (\n    AnthropicClaudeBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.clip.v1 import (\n    ClipModelBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.clip_comparison.v1 import (\n    ClipComparisonBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.clip_comparison.v2 import (\n    ClipComparisonBlockV2,\n)\nfrom inference.core.workflows.core_steps.models.foundation.cog_vlm.v1 import (\n    CogVLMBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.depth_estimation.v1 import (\n    DepthEstimationBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.florence2.v1 import (\n    Florence2BlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.florence2.v2 import (\n    Florence2BlockV2,\n)\nfrom inference.core.workflows.core_steps.models.foundation.gaze.v1 import GazeBlockV1\nfrom inference.core.workflows.core_steps.models.foundation.google_gemini.v1 import (\n    GoogleGeminiBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.google_vision_ocr.v1 import (\n    GoogleVisionOCRBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.llama_vision.v1 import (\n    LlamaVisionBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.lmm.v1 import LMMBlockV1\nfrom inference.core.workflows.core_steps.models.foundation.lmm_classifier.v1 import (\n    LMMForClassificationBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.moondream2.v1 import (\n    Moondream2BlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.ocr.v1 import OCRModelBlockV1\nfrom inference.core.workflows.core_steps.models.foundation.openai.v1 import (\n    OpenAIBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.openai.v2 import (\n    OpenAIBlockV2,\n)\nfrom inference.core.workflows.core_steps.models.foundation.openai.v3 import (\n    OpenAIBlockV3,\n)\nfrom inference.core.workflows.core_steps.models.foundation.qwen.v1 import (\n    Qwen25VLBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.segment_anything2.v1 import (\n    SegmentAnything2BlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.smolvlm.v1 import (\n    SmolVLM2BlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.stability_ai.image_gen.v1 import (\n    StabilityAIImageGenBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.stability_ai.inpainting.v1 import (\n    StabilityAIInpaintingBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.yolo_world.v1 import (\n    YoloWorldModelBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.roboflow.instance_segmentation.v1 import (\n    RoboflowInstanceSegmentationModelBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.roboflow.instance_segmentation.v2 import (\n    RoboflowInstanceSegmentationModelBlockV2,\n)\nfrom inference.core.workflows.core_steps.models.roboflow.keypoint_detection.v1 import (\n    RoboflowKeypointDetectionModelBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.roboflow.keypoint_detection.v2 import (\n    RoboflowKeypointDetectionModelBlockV2,\n)\nfrom inference.core.workflows.core_steps.models.roboflow.multi_class_classification.v1 import (\n    RoboflowClassificationModelBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.roboflow.multi_class_classification.v2 import (\n    RoboflowClassificationModelBlockV2,\n)\nfrom inference.core.workflows.core_steps.models.roboflow.multi_label_classification.v1 import (\n    RoboflowMultiLabelClassificationModelBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.roboflow.multi_label_classification.v2 import (\n    RoboflowMultiLabelClassificationModelBlockV2,\n)\nfrom inference.core.workflows.core_steps.models.roboflow.object_detection.v1 import (\n    RoboflowObjectDetectionModelBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.roboflow.object_detection.v2 import (\n    RoboflowObjectDetectionModelBlockV2,\n)\nfrom inference.core.workflows.core_steps.models.third_party.barcode_detection.v1 import (\n    BarcodeDetectorBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.third_party.qr_code_detection.v1 import (\n    QRCodeDetectorBlockV1,\n)\nfrom inference.core.workflows.core_steps.sampling.identify_changes.v1 import (\n    IdentifyChangesBlockV1,\n)\nfrom inference.core.workflows.core_steps.sampling.identify_outliers.v1 import (\n    IdentifyOutliersBlockV1,\n)\nfrom inference.core.workflows.core_steps.secrets_providers.environment_secrets_store.v1 import (\n    EnvironmentSecretsStoreBlockV1,\n)\nfrom inference.core.workflows.core_steps.sinks.email_notification.v1 import (\n    EmailNotificationBlockV1,\n)\nfrom inference.core.workflows.core_steps.sinks.local_file.v1 import LocalFileSinkBlockV1\nfrom inference.core.workflows.core_steps.sinks.onvif_movement.v1 import ONVIFSinkBlockV1\nfrom inference.core.workflows.core_steps.sinks.roboflow.custom_metadata.v1 import (\n    RoboflowCustomMetadataBlockV1,\n)\nfrom inference.core.workflows.core_steps.sinks.roboflow.dataset_upload.v1 import (\n    RoboflowDatasetUploadBlockV1,\n)\nfrom inference.core.workflows.core_steps.sinks.roboflow.dataset_upload.v2 import (\n    RoboflowDatasetUploadBlockV2,\n)\nfrom inference.core.workflows.core_steps.sinks.roboflow.model_monitoring_inference_aggregator.v1 import (\n    ModelMonitoringInferenceAggregatorBlockV1,\n)\nfrom inference.core.workflows.core_steps.sinks.slack.notification.v1 import (\n    SlackNotificationBlockV1,\n)\nfrom inference.core.workflows.core_steps.sinks.twilio.sms.v1 import (\n    TwilioSMSNotificationBlockV1,\n)\nfrom inference.core.workflows.core_steps.sinks.webhook.v1 import WebhookSinkBlockV1\nfrom inference.core.workflows.core_steps.transformations.absolute_static_crop.v1 import (\n    AbsoluteStaticCropBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.bounding_rect.v1 import (\n    BoundingRectBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.byte_tracker.v1 import (\n    ByteTrackerBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.byte_tracker.v2 import (\n    ByteTrackerBlockV2,\n)\nfrom inference.core.workflows.core_steps.transformations.byte_tracker.v3 import (\n    ByteTrackerBlockV3,\n)\nfrom inference.core.workflows.core_steps.transformations.camera_calibration.v1 import (\n    CameraCalibrationBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.detection_offset.v1 import (\n    DetectionOffsetBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.detections_filter.v1 import (\n    DetectionsFilterBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.detections_merge.v1 import (\n    DetectionsMergeBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.detections_transformation.v1 import (\n    DetectionsTransformationBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.dynamic_crop.v1 import (\n    DynamicCropBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.dynamic_zones.v1 import (\n    DynamicZonesBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.image_slicer.v1 import (\n    ImageSlicerBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.image_slicer.v2 import (\n    ImageSlicerBlockV2,\n)\nfrom inference.core.workflows.core_steps.transformations.perspective_correction.v1 import (\n    PerspectiveCorrectionBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.relative_static_crop.v1 import (\n    RelativeStaticCropBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.stabilize_detections.v1 import (\n    StabilizeTrackedDetectionsBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.stitch_images.v1 import (\n    StitchImagesBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.stitch_ocr_detections.v1 import (\n    StitchOCRDetectionsBlockV1,\n)\n\n# Visualizers\nfrom inference.core.workflows.core_steps.visualizations.background_color.v1 import (\n    BackgroundColorVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.blur.v1 import (\n    BlurVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.bounding_box.v1 import (\n    BoundingBoxVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.circle.v1 import (\n    CircleVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.classification_label.v1 import (\n    ClassificationLabelVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.color.v1 import (\n    ColorVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.corner.v1 import (\n    CornerVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.crop.v1 import (\n    CropVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.dot.v1 import (\n    DotVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.ellipse.v1 import (\n    EllipseVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.grid.v1 import (\n    GridVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.halo.v1 import (\n    HaloVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.keypoint.v1 import (\n    KeypointVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.label.v1 import (\n    LabelVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.line_zone.v1 import (\n    LineCounterZoneVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.mask.v1 import (\n    MaskVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.model_comparison.v1 import (\n    ModelComparisonVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.pixelate.v1 import (\n    PixelateVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.polygon.v1 import (\n    PolygonVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.polygon_zone.v1 import (\n    PolygonZoneVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.reference_path.v1 import (\n    ReferencePathVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.trace.v1 import (\n    TraceVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.triangle.v1 import (\n    TriangleVisualizationBlockV1,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    BAR_CODE_DETECTION_KIND,\n    BOOLEAN_KIND,\n    BYTES_KIND,\n    CLASSIFICATION_PREDICTION_KIND,\n    CONTOURS_KIND,\n    DETECTION_KIND,\n    DICTIONARY_KIND,\n    EMBEDDING_KIND,\n    FLOAT_KIND,\n    FLOAT_ZERO_TO_ONE_KIND,\n    IMAGE_KEYPOINTS_KIND,\n    IMAGE_KIND,\n    IMAGE_METADATA_KIND,\n    INFERENCE_ID_KIND,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    INTEGER_KIND,\n    KEYPOINT_DETECTION_PREDICTION_KIND,\n    LANGUAGE_MODEL_OUTPUT_KIND,\n    LIST_OF_VALUES_KIND,\n    NUMPY_ARRAY_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    PARENT_ID_KIND,\n    POINT_KIND,\n    PREDICTION_TYPE_KIND,\n    QR_CODE_DETECTION_KIND,\n    RGB_COLOR_KIND,\n    ROBOFLOW_API_KEY_KIND,\n    ROBOFLOW_MANAGED_KEY,\n    ROBOFLOW_MODEL_ID_KIND,\n    ROBOFLOW_PROJECT_KIND,\n    SECRET_KIND,\n    SERIALISED_PAYLOADS_KIND,\n    STRING_KIND,\n    TIMESTAMP_KIND,\n    TOP_CLASS_KIND,\n    VIDEO_METADATA_KIND,\n    WILDCARD_KIND,\n    ZONE_KIND,\n    Kind,\n)\nfrom inference.core.workflows.prototypes.block import WorkflowBlock\n\nREGISTERED_INITIALIZERS = {\n    \"api_key\": API_KEY,\n    \"cache\": cache,\n    \"step_execution_mode\": StepExecutionMode(WORKFLOWS_STEP_EXECUTION_MODE),\n    \"background_tasks\": None,\n    \"thread_pool_executor\": None,\n    \"allow_access_to_file_system\": ALLOW_WORKFLOW_BLOCKS_ACCESSING_LOCAL_STORAGE,\n    \"allowed_write_directory\": WORKFLOW_BLOCKS_WRITE_DIRECTORY,\n    \"allow_access_to_environmental_variables\": ALLOW_WORKFLOW_BLOCKS_ACCESSING_ENVIRONMENTAL_VARIABLES,\n}\n\nKINDS_SERIALIZERS = {\n    IMAGE_KIND.name: serialise_image,\n    VIDEO_METADATA_KIND.name: serialize_video_metadata_kind,\n    OBJECT_DETECTION_PREDICTION_KIND.name: serialise_sv_detections,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND.name: serialise_sv_detections,\n    KEYPOINT_DETECTION_PREDICTION_KIND.name: serialise_sv_detections,\n    QR_CODE_DETECTION_KIND.name: serialise_sv_detections,\n    BAR_CODE_DETECTION_KIND.name: serialise_sv_detections,\n    SECRET_KIND.name: serialize_secret,\n    WILDCARD_KIND.name: serialize_wildcard_kind,\n    TIMESTAMP_KIND.name: serialize_timestamp,\n}\nKINDS_DESERIALIZERS = {\n    IMAGE_KIND.name: deserialize_image_kind,\n    VIDEO_METADATA_KIND.name: deserialize_video_metadata_kind,\n    OBJECT_DETECTION_PREDICTION_KIND.name: deserialize_detections_kind,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND.name: deserialize_detections_kind,\n    KEYPOINT_DETECTION_PREDICTION_KIND.name: deserialize_detections_kind,\n    QR_CODE_DETECTION_KIND.name: deserialize_detections_kind,\n    BAR_CODE_DETECTION_KIND.name: deserialize_detections_kind,\n    NUMPY_ARRAY_KIND.name: deserialize_numpy_array,\n    ROBOFLOW_MODEL_ID_KIND.name: deserialize_string_kind,\n    ROBOFLOW_PROJECT_KIND.name: deserialize_string_kind,\n    ROBOFLOW_API_KEY_KIND.name: deserialize_optional_string_kind,\n    ROBOFLOW_MANAGED_KEY.name: deserialize_optional_string_kind,\n    FLOAT_ZERO_TO_ONE_KIND.name: deserialize_float_zero_to_one_kind,\n    LIST_OF_VALUES_KIND.name: deserialize_list_of_values_kind,\n    BOOLEAN_KIND.name: deserialize_boolean_kind,\n    INTEGER_KIND.name: deserialize_integer_kind,\n    STRING_KIND.name: deserialize_string_kind,\n    TOP_CLASS_KIND.name: deserialize_string_kind,\n    FLOAT_KIND.name: deserialize_float_kind,\n    DICTIONARY_KIND.name: deserialize_dictionary_kind,\n    CLASSIFICATION_PREDICTION_KIND.name: deserialize_classification_prediction_kind,\n    POINT_KIND.name: deserialize_point_kind,\n    ZONE_KIND.name: deserialize_zone_kind,\n    RGB_COLOR_KIND.name: deserialize_rgb_color_kind,\n    LANGUAGE_MODEL_OUTPUT_KIND.name: deserialize_string_kind,\n    PREDICTION_TYPE_KIND.name: deserialize_string_kind,\n    PARENT_ID_KIND.name: deserialize_string_kind,\n    BYTES_KIND.name: deserialize_bytes_kind,\n    INFERENCE_ID_KIND.name: deserialize_string_kind,\n    TIMESTAMP_KIND.name: deserialize_timestamp,\n}\n\n\ndef load_blocks() -> List[Type[WorkflowBlock]]:\n    return [\n        AbsoluteStaticCropBlockV1,\n        DynamicCropBlockV1,\n        DetectionsFilterBlockV1,\n        DetectionOffsetBlockV1,\n        DepthEstimationBlockV1,\n        ByteTrackerBlockV1,\n        RelativeStaticCropBlockV1,\n        DetectionsTransformationBlockV1,\n        RoboflowDatasetUploadBlockV1,\n        ContinueIfBlockV1,\n        RateLimiterBlockV1,\n        PerspectiveCorrectionBlockV1,\n        DeltaFilterBlockV1,\n        CameraCalibrationBlockV1,\n        DynamicZonesBlockV1,\n        SizeMeasurementBlockV1,\n        BufferBlockV1,\n        DetectionsClassesReplacementBlockV1,\n        ExpressionBlockV1,\n        PropertyDefinitionBlockV1,\n        DimensionCollapseBlockV1,\n        FirstNonEmptyOrDefaultBlockV1,\n        AnthropicClaudeBlockV1,\n        CosineSimilarityBlockV1,\n        BackgroundColorVisualizationBlockV1,\n        BarcodeDetectorBlockV1,\n        BlurVisualizationBlockV1,\n        BoundingBoxVisualizationBlockV1,\n        BoundingRectBlockV1,\n        DetectionsMergeBlockV1,\n        ByteTrackerBlockV2,\n        CacheGetBlockV1,\n        CacheSetBlockV1,\n        CameraFocusBlockV1,\n        CircleVisualizationBlockV1,\n        ClipComparisonBlockV1,\n        ClipComparisonBlockV2,\n        ClipModelBlockV1,\n        CogVLMBlockV1,\n        ColorVisualizationBlockV1,\n        ConvertGrayscaleBlockV1,\n        CornerVisualizationBlockV1,\n        CropVisualizationBlockV1,\n        DetectionsConsensusBlockV1,\n        DetectionsStitchBlockV1,\n        DistanceMeasurementBlockV1,\n        DominantColorBlockV1,\n        DotVisualizationBlockV1,\n        EllipseVisualizationBlockV1,\n        Florence2BlockV1,\n        Florence2BlockV2,\n        GoogleGeminiBlockV1,\n        GoogleVisionOCRBlockV1,\n        GridVisualizationBlockV1,\n        HaloVisualizationBlockV1,\n        ImageBlurBlockV1,\n        ImageContoursDetectionBlockV1,\n        ImagePreprocessingBlockV1,\n        ImageSlicerBlockV1,\n        ImageThresholdBlockV1,\n        JSONParserBlockV1,\n        LMMBlockV1,\n        LMMForClassificationBlockV1,\n        LabelVisualizationBlockV1,\n        ClassificationLabelVisualizationBlockV1,\n        LineCounterBlockV1,\n        LineCounterBlockV2,\n        LineCounterZoneVisualizationBlockV1,\n        MaskVisualizationBlockV1,\n        ModelComparisonVisualizationBlockV1,\n        OCRModelBlockV1,\n        OpenAIBlockV1,\n        OpenAIBlockV2,\n        OpenAIBlockV3,\n        PathDeviationAnalyticsBlockV1,\n        PathDeviationAnalyticsBlockV2,\n        PixelateVisualizationBlockV1,\n        PixelationCountBlockV1,\n        PolygonVisualizationBlockV1,\n        PolygonZoneVisualizationBlockV1,\n        QRCodeDetectorBlockV1,\n        RoboflowClassificationModelBlockV1,\n        RoboflowCustomMetadataBlockV1,\n        ModelMonitoringInferenceAggregatorBlockV1,\n        RoboflowDatasetUploadBlockV2,\n        RoboflowInstanceSegmentationModelBlockV1,\n        RoboflowKeypointDetectionModelBlockV1,\n        RoboflowMultiLabelClassificationModelBlockV1,\n        RoboflowObjectDetectionModelBlockV1,\n        SIFTBlockV1,\n        SIFTComparisonBlockV1,\n        SIFTComparisonBlockV2,\n        SegmentAnything2BlockV1,\n        StabilityAIInpaintingBlockV1,\n        StabilityAIImageGenBlockV1,\n        StabilizeTrackedDetectionsBlockV1,\n        StitchImagesBlockV1,\n        StitchOCRDetectionsBlockV1,\n        TemplateMatchingBlockV1,\n        TimeInZoneBlockV1,\n        TimeInZoneBlockV2,\n        TriangleVisualizationBlockV1,\n        VLMAsClassifierBlockV1,\n        VLMAsDetectorBlockV1,\n        YoloWorldModelBlockV1,\n        KeypointVisualizationBlockV1,\n        DataAggregatorBlockV1,\n        CSVFormatterBlockV1,\n        EmailNotificationBlockV1,\n        LocalFileSinkBlockV1,\n        TraceVisualizationBlockV1,\n        ReferencePathVisualizationBlockV1,\n        ByteTrackerBlockV3,\n        WebhookSinkBlockV1,\n        VelocityBlockV1,\n        RoboflowInstanceSegmentationModelBlockV2,\n        RoboflowKeypointDetectionModelBlockV2,\n        RoboflowClassificationModelBlockV2,\n        RoboflowMultiLabelClassificationModelBlockV2,\n        RoboflowObjectDetectionModelBlockV2,\n        VLMAsClassifierBlockV2,\n        VLMAsDetectorBlockV2,\n        IdentifyOutliersBlockV1,\n        IdentifyChangesBlockV1,\n        EnvironmentSecretsStoreBlockV1,\n        SlackNotificationBlockV1,\n        TwilioSMSNotificationBlockV1,\n        GazeBlockV1,\n        LlamaVisionBlockV1,\n        ImageSlicerBlockV2,\n        Qwen25VLBlockV1,\n        SmolVLM2BlockV1,\n        Moondream2BlockV1,\n        OverlapBlockV1,\n        ONVIFSinkBlockV1,\n    ]\n\n\ndef load_kinds() -> List[Kind]:\n    return [\n        WILDCARD_KIND,\n        IMAGE_KIND,\n        VIDEO_METADATA_KIND,\n        ROBOFLOW_MODEL_ID_KIND,\n        ROBOFLOW_PROJECT_KIND,\n        ROBOFLOW_API_KEY_KIND,\n        FLOAT_ZERO_TO_ONE_KIND,\n        LIST_OF_VALUES_KIND,\n        SERIALISED_PAYLOADS_KIND,\n        BOOLEAN_KIND,\n        INTEGER_KIND,\n        STRING_KIND,\n        TOP_CLASS_KIND,\n        FLOAT_KIND,\n        DICTIONARY_KIND,\n        DETECTION_KIND,\n        CLASSIFICATION_PREDICTION_KIND,\n        POINT_KIND,\n        ZONE_KIND,\n        OBJECT_DETECTION_PREDICTION_KIND,\n        INSTANCE_SEGMENTATION_PREDICTION_KIND,\n        KEYPOINT_DETECTION_PREDICTION_KIND,\n        RGB_COLOR_KIND,\n        IMAGE_KEYPOINTS_KIND,\n        CONTOURS_KIND,\n        LANGUAGE_MODEL_OUTPUT_KIND,\n        NUMPY_ARRAY_KIND,\n        QR_CODE_DETECTION_KIND,\n        BAR_CODE_DETECTION_KIND,\n        PREDICTION_TYPE_KIND,\n        ROBOFLOW_MANAGED_KEY,\n        PARENT_ID_KIND,\n        IMAGE_METADATA_KIND,\n        BYTES_KIND,\n        INFERENCE_ID_KIND,\n        SECRET_KIND,\n        EMBEDDING_KIND,\n        TIMESTAMP_KIND,\n    ]\n",
    "patch": "diff --git a/inference/core/workflows/core_steps/loader.py b/inference/core/workflows/core_steps/loader.py\nindex 346eb6b3b..bd9a99e18 100644\n--- a/inference/core/workflows/core_steps/loader.py\n+++ b/inference/core/workflows/core_steps/loader.py\n@@ -519,143 +519,145 @@ KINDS_DESERIALIZERS = {\n \n \n def load_blocks() -> List[Type[WorkflowBlock]]:\n-    return [\n-        AbsoluteStaticCropBlockV1,\n-        DynamicCropBlockV1,\n-        DetectionsFilterBlockV1,\n-        DetectionOffsetBlockV1,\n-        DepthEstimationBlockV1,\n-        ByteTrackerBlockV1,\n-        RelativeStaticCropBlockV1,\n-        DetectionsTransformationBlockV1,\n-        RoboflowDatasetUploadBlockV1,\n-        ContinueIfBlockV1,\n-        RateLimiterBlockV1,\n-        PerspectiveCorrectionBlockV1,\n-        DeltaFilterBlockV1,\n-        CameraCalibrationBlockV1,\n-        DynamicZonesBlockV1,\n-        SizeMeasurementBlockV1,\n-        BufferBlockV1,\n-        DetectionsClassesReplacementBlockV1,\n-        ExpressionBlockV1,\n-        PropertyDefinitionBlockV1,\n-        DimensionCollapseBlockV1,\n-        FirstNonEmptyOrDefaultBlockV1,\n-        AnthropicClaudeBlockV1,\n-        CosineSimilarityBlockV1,\n-        BackgroundColorVisualizationBlockV1,\n-        BarcodeDetectorBlockV1,\n-        BlurVisualizationBlockV1,\n-        BoundingBoxVisualizationBlockV1,\n-        BoundingRectBlockV1,\n-        DetectionsMergeBlockV1,\n-        ByteTrackerBlockV2,\n-        CacheGetBlockV1,\n-        CacheSetBlockV1,\n-        CameraFocusBlockV1,\n-        CircleVisualizationBlockV1,\n-        ClipComparisonBlockV1,\n-        ClipComparisonBlockV2,\n-        ClipModelBlockV1,\n-        CogVLMBlockV1,\n-        ColorVisualizationBlockV1,\n-        ConvertGrayscaleBlockV1,\n-        CornerVisualizationBlockV1,\n-        CropVisualizationBlockV1,\n-        DetectionsConsensusBlockV1,\n-        DetectionsStitchBlockV1,\n-        DistanceMeasurementBlockV1,\n-        DominantColorBlockV1,\n-        DotVisualizationBlockV1,\n-        EllipseVisualizationBlockV1,\n-        Florence2BlockV1,\n-        Florence2BlockV2,\n-        GoogleGeminiBlockV1,\n-        GoogleVisionOCRBlockV1,\n-        GridVisualizationBlockV1,\n-        HaloVisualizationBlockV1,\n-        ImageBlurBlockV1,\n-        ImageContoursDetectionBlockV1,\n-        ImagePreprocessingBlockV1,\n-        ImageSlicerBlockV1,\n-        ImageThresholdBlockV1,\n-        JSONParserBlockV1,\n-        LMMBlockV1,\n-        LMMForClassificationBlockV1,\n-        LabelVisualizationBlockV1,\n-        ClassificationLabelVisualizationBlockV1,\n-        LineCounterBlockV1,\n-        LineCounterBlockV2,\n-        LineCounterZoneVisualizationBlockV1,\n-        MaskVisualizationBlockV1,\n-        ModelComparisonVisualizationBlockV1,\n-        OCRModelBlockV1,\n-        OpenAIBlockV1,\n-        OpenAIBlockV2,\n-        OpenAIBlockV3,\n-        PathDeviationAnalyticsBlockV1,\n-        PathDeviationAnalyticsBlockV2,\n-        PixelateVisualizationBlockV1,\n-        PixelationCountBlockV1,\n-        PolygonVisualizationBlockV1,\n-        PolygonZoneVisualizationBlockV1,\n-        QRCodeDetectorBlockV1,\n-        RoboflowClassificationModelBlockV1,\n-        RoboflowCustomMetadataBlockV1,\n-        ModelMonitoringInferenceAggregatorBlockV1,\n-        RoboflowDatasetUploadBlockV2,\n-        RoboflowInstanceSegmentationModelBlockV1,\n-        RoboflowKeypointDetectionModelBlockV1,\n-        RoboflowMultiLabelClassificationModelBlockV1,\n-        RoboflowObjectDetectionModelBlockV1,\n-        SIFTBlockV1,\n-        SIFTComparisonBlockV1,\n-        SIFTComparisonBlockV2,\n-        SegmentAnything2BlockV1,\n-        StabilityAIInpaintingBlockV1,\n-        StabilityAIImageGenBlockV1,\n-        StabilizeTrackedDetectionsBlockV1,\n-        StitchImagesBlockV1,\n-        StitchOCRDetectionsBlockV1,\n-        TemplateMatchingBlockV1,\n-        TimeInZoneBlockV1,\n-        TimeInZoneBlockV2,\n-        TriangleVisualizationBlockV1,\n-        VLMAsClassifierBlockV1,\n-        VLMAsDetectorBlockV1,\n-        YoloWorldModelBlockV1,\n-        KeypointVisualizationBlockV1,\n-        DataAggregatorBlockV1,\n-        CSVFormatterBlockV1,\n-        EmailNotificationBlockV1,\n-        LocalFileSinkBlockV1,\n-        TraceVisualizationBlockV1,\n-        ReferencePathVisualizationBlockV1,\n-        ByteTrackerBlockV3,\n-        WebhookSinkBlockV1,\n-        VelocityBlockV1,\n-        RoboflowInstanceSegmentationModelBlockV2,\n-        RoboflowKeypointDetectionModelBlockV2,\n-        RoboflowClassificationModelBlockV2,\n-        RoboflowMultiLabelClassificationModelBlockV2,\n-        RoboflowObjectDetectionModelBlockV2,\n-        VLMAsClassifierBlockV2,\n-        VLMAsDetectorBlockV2,\n-        IdentifyOutliersBlockV1,\n-        IdentifyChangesBlockV1,\n-        EnvironmentSecretsStoreBlockV1,\n-        SlackNotificationBlockV1,\n-        TwilioSMSNotificationBlockV1,\n-        GazeBlockV1,\n-        LlamaVisionBlockV1,\n-        ImageSlicerBlockV2,\n-        Qwen25VLBlockV1,\n-        SmolVLM2BlockV1,\n-        Moondream2BlockV1,\n-        OverlapBlockV1,\n-        ONVIFSinkBlockV1,\n-    ]\n+    if not hasattr(load_blocks, \"_blocks\"):\n+        load_blocks._blocks = [\n+            AbsoluteStaticCropBlockV1,\n+            DynamicCropBlockV1,\n+            DetectionsFilterBlockV1,\n+            DetectionOffsetBlockV1,\n+            DepthEstimationBlockV1,\n+            ByteTrackerBlockV1,\n+            RelativeStaticCropBlockV1,\n+            DetectionsTransformationBlockV1,\n+            RoboflowDatasetUploadBlockV1,\n+            ContinueIfBlockV1,\n+            RateLimiterBlockV1,\n+            PerspectiveCorrectionBlockV1,\n+            DeltaFilterBlockV1,\n+            CameraCalibrationBlockV1,\n+            DynamicZonesBlockV1,\n+            SizeMeasurementBlockV1,\n+            BufferBlockV1,\n+            DetectionsClassesReplacementBlockV1,\n+            ExpressionBlockV1,\n+            PropertyDefinitionBlockV1,\n+            DimensionCollapseBlockV1,\n+            FirstNonEmptyOrDefaultBlockV1,\n+            AnthropicClaudeBlockV1,\n+            CosineSimilarityBlockV1,\n+            BackgroundColorVisualizationBlockV1,\n+            BarcodeDetectorBlockV1,\n+            BlurVisualizationBlockV1,\n+            BoundingBoxVisualizationBlockV1,\n+            BoundingRectBlockV1,\n+            DetectionsMergeBlockV1,\n+            ByteTrackerBlockV2,\n+            CacheGetBlockV1,\n+            CacheSetBlockV1,\n+            CameraFocusBlockV1,\n+            CircleVisualizationBlockV1,\n+            ClipComparisonBlockV1,\n+            ClipComparisonBlockV2,\n+            ClipModelBlockV1,\n+            CogVLMBlockV1,\n+            ColorVisualizationBlockV1,\n+            ConvertGrayscaleBlockV1,\n+            CornerVisualizationBlockV1,\n+            CropVisualizationBlockV1,\n+            DetectionsConsensusBlockV1,\n+            DetectionsStitchBlockV1,\n+            DistanceMeasurementBlockV1,\n+            DominantColorBlockV1,\n+            DotVisualizationBlockV1,\n+            EllipseVisualizationBlockV1,\n+            Florence2BlockV1,\n+            Florence2BlockV2,\n+            GoogleGeminiBlockV1,\n+            GoogleVisionOCRBlockV1,\n+            GridVisualizationBlockV1,\n+            HaloVisualizationBlockV1,\n+            ImageBlurBlockV1,\n+            ImageContoursDetectionBlockV1,\n+            ImagePreprocessingBlockV1,\n+            ImageSlicerBlockV1,\n+            ImageThresholdBlockV1,\n+            JSONParserBlockV1,\n+            LMMBlockV1,\n+            LMMForClassificationBlockV1,\n+            LabelVisualizationBlockV1,\n+            ClassificationLabelVisualizationBlockV1,\n+            LineCounterBlockV1,\n+            LineCounterBlockV2,\n+            LineCounterZoneVisualizationBlockV1,\n+            MaskVisualizationBlockV1,\n+            ModelComparisonVisualizationBlockV1,\n+            OCRModelBlockV1,\n+            OpenAIBlockV1,\n+            OpenAIBlockV2,\n+            OpenAIBlockV3,\n+            PathDeviationAnalyticsBlockV1,\n+            PathDeviationAnalyticsBlockV2,\n+            PixelateVisualizationBlockV1,\n+            PixelationCountBlockV1,\n+            PolygonVisualizationBlockV1,\n+            PolygonZoneVisualizationBlockV1,\n+            QRCodeDetectorBlockV1,\n+            RoboflowClassificationModelBlockV1,\n+            RoboflowCustomMetadataBlockV1,\n+            ModelMonitoringInferenceAggregatorBlockV1,\n+            RoboflowDatasetUploadBlockV2,\n+            RoboflowInstanceSegmentationModelBlockV1,\n+            RoboflowKeypointDetectionModelBlockV1,\n+            RoboflowMultiLabelClassificationModelBlockV1,\n+            RoboflowObjectDetectionModelBlockV1,\n+            SIFTBlockV1,\n+            SIFTComparisonBlockV1,\n+            SIFTComparisonBlockV2,\n+            SegmentAnything2BlockV1,\n+            StabilityAIInpaintingBlockV1,\n+            StabilityAIImageGenBlockV1,\n+            StabilizeTrackedDetectionsBlockV1,\n+            StitchImagesBlockV1,\n+            StitchOCRDetectionsBlockV1,\n+            TemplateMatchingBlockV1,\n+            TimeInZoneBlockV1,\n+            TimeInZoneBlockV2,\n+            TriangleVisualizationBlockV1,\n+            VLMAsClassifierBlockV1,\n+            VLMAsDetectorBlockV1,\n+            YoloWorldModelBlockV1,\n+            KeypointVisualizationBlockV1,\n+            DataAggregatorBlockV1,\n+            CSVFormatterBlockV1,\n+            EmailNotificationBlockV1,\n+            LocalFileSinkBlockV1,\n+            TraceVisualizationBlockV1,\n+            ReferencePathVisualizationBlockV1,\n+            ByteTrackerBlockV3,\n+            WebhookSinkBlockV1,\n+            VelocityBlockV1,\n+            RoboflowInstanceSegmentationModelBlockV2,\n+            RoboflowKeypointDetectionModelBlockV2,\n+            RoboflowClassificationModelBlockV2,\n+            RoboflowMultiLabelClassificationModelBlockV2,\n+            RoboflowObjectDetectionModelBlockV2,\n+            VLMAsClassifierBlockV2,\n+            VLMAsDetectorBlockV2,\n+            IdentifyOutliersBlockV1,\n+            IdentifyChangesBlockV1,\n+            EnvironmentSecretsStoreBlockV1,\n+            SlackNotificationBlockV1,\n+            TwilioSMSNotificationBlockV1,\n+            GazeBlockV1,\n+            LlamaVisionBlockV1,\n+            ImageSlicerBlockV2,\n+            Qwen25VLBlockV1,\n+            SmolVLM2BlockV1,\n+            Moondream2BlockV1,\n+            OverlapBlockV1,\n+            ONVIFSinkBlockV1,\n+        ]\n+    return load_blocks._blocks\n \n \n def load_kinds() -> List[Kind]:\n"
  },
  {
    "trace_id": "3dd00fd4-4a23-4fe0-934b-e123db8b56ee",
    "function_name": "OverlapManifest.describe_outputs",
    "file_path": "inference/core/workflows/core_steps/analytics/overlap/v1.py",
    "speedup_x": 5.36,
    "review_quality": "high",
    "pre_optimization_commit": "4f2ee45868ebbdd71107e604c762b58c53f6b721",
    "resolution_method": "git_parent",
    "source": "git",
    "original_function_code": "    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(\n                name=OUTPUT_KEY,\n                kind=[\n                    OBJECT_DETECTION_PREDICTION_KIND,\n                ],\n            ),\n        ]\n",
    "optimized_function_code": "from typing import List, Optional, Union\n\nimport numpy as np\nimport supervision as sv\nfrom pydantic import ConfigDict, Field\nfrom supervision.detection.utils import get_data_item\nfrom typing_extensions import Literal, Type\n\nfrom inference.core.workflows.execution_engine.entities.base import (\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    OBJECT_DETECTION_PREDICTION_KIND,\n    Selector,\n    WorkflowImageSelector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\nfrom functools import lru_cache\n\nOUTPUT_KEY: str = \"overlaps\"\nSHORT_DESCRIPTION = \"Filter objects overlapping some other class\"\nLONG_DESCRIPTION = \"\"\"\nThe `OverlapFilter` is an analytics block that filters out objects overlapping instances of some other class\n\"\"\"\n\n\nclass OverlapManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Overlap Filter\",\n            \"version\": \"v1\",\n            \"short_description\": SHORT_DESCRIPTION,\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"analytics\",\n            \"ui_manifest\": {\n                \"icon\": \"far fa-square-o\",\n                \"blockPriority\": 1,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/overlap@v1\", \"Overlap\"]\n    image: Union[WorkflowImageSelector] = Field(\n        title=\"Image\",\n        description=\"The input image for this step.\",\n        examples=[\"$inputs.image\", \"$steps.cropping.crops\"],\n    )\n    predictions: Selector(\n        kind=[\n            OBJECT_DETECTION_PREDICTION_KIND,\n        ]\n    ) = Field(  # type: ignore\n        description=\"Object predictions\",\n        examples=[\"$steps.object_detection_model.predictions\"],\n    )\n    overlap_type: Literal[\"Center Overlap\", \"Any Overlap\"] = Field(\n        default=\"Center Overlap\",\n        description=\"Overlap Type.\",\n        examples=[\"Center Overlap\", \"Any Overlap\"],\n    )\n    overlap_class_name: Union[str] = Field(\n        description=\"Overlap Class Name\",\n        json_schema_extra={\n            \"hide_description\": True,\n        },\n    )\n\n    @classmethod\n    @lru_cache(maxsize=None)\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(\n                name=OUTPUT_KEY,\n                kind=[\n                    OBJECT_DETECTION_PREDICTION_KIND,\n                ],\n            ),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass OverlapBlockV1(WorkflowBlock):\n    def __init__(self):\n        pass\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return OverlapManifest\n\n    @classmethod\n    def coords_overlap(cls, overlap, other, overlap_type):\n\n        # coords are [x1, y1, x2, y2]\n        if overlap_type == \"Center Overlap\":\n            size = [other[2] - other[0], other[3] - other[1]]\n            (x, y) = [other[0] + size[0] / 2, other[1] + size[1] / 2]\n            return (\n                x > overlap[0] and x < overlap[2] and y > overlap[1] and y < overlap[3]\n            )\n        else:\n            return not (\n                other[2] < overlap[0]\n                or other[0] > overlap[2]\n                or other[3] < overlap[1]\n                or other[1] > overlap[3]\n            )\n\n    def run(\n        self,\n        image: WorkflowImageData,\n        predictions: sv.Detections,\n        overlap_type: str,\n        overlap_class_name: str,\n    ) -> BlockResult:\n\n        overlaps = []\n        others = []\n        for i in range(len(predictions.xyxy)):\n            data = get_data_item(predictions.data, i)\n            if data[\"class_name\"] == overlap_class_name:\n                overlaps.append(predictions.xyxy[i])\n            else:\n                others.append((predictions.xyxy[i], i))\n\n        idx = set()\n        for overlap in overlaps:\n            if not others:\n                break\n            idx = idx.union(\n                {\n                    other[1]\n                    for other in others\n                    if OverlapBlockV1.coords_overlap(overlap, other[0], overlap_type)\n                }\n            )\n            # once it's overlapped we don't need to check again\n            others = [o for o in others if o[1] not in idx]\n\n        return {OUTPUT_KEY: predictions[list(idx)]}\n",
    "optimized_raw_markdown": "",
    "optimized_function_only": "    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(\n                name=OUTPUT_KEY,\n                kind=[\n                    OBJECT_DETECTION_PREDICTION_KIND,\n                ],\n            ),\n        ]\n",
    "original_file_content": "from typing import List, Optional, Union\n\nimport numpy as np\nimport supervision as sv\nfrom pydantic import ConfigDict, Field\nfrom supervision.detection.utils import get_data_item\nfrom typing_extensions import Literal, Type\n\nfrom inference.core.workflows.execution_engine.entities.base import (\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    OBJECT_DETECTION_PREDICTION_KIND,\n    Selector,\n    WorkflowImageSelector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nOUTPUT_KEY: str = \"overlaps\"\nSHORT_DESCRIPTION = \"Filter objects overlapping some other class\"\nLONG_DESCRIPTION = \"\"\"\nThe `OverlapFilter` is an analytics block that filters out objects overlapping instances of some other class\n\"\"\"\n\n\nclass OverlapManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Overlap Filter\",\n            \"version\": \"v1\",\n            \"short_description\": SHORT_DESCRIPTION,\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"analytics\",\n            \"ui_manifest\": {\n                \"icon\": \"far fa-square-o\",\n                \"blockPriority\": 1,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/overlap@v1\", \"Overlap\"]\n    image: Union[WorkflowImageSelector] = Field(\n        title=\"Image\",\n        description=\"The input image for this step.\",\n        examples=[\"$inputs.image\", \"$steps.cropping.crops\"],\n    )\n    predictions: Selector(\n        kind=[\n            OBJECT_DETECTION_PREDICTION_KIND,\n        ]\n    ) = Field(  # type: ignore\n        description=\"Object predictions\",\n        examples=[\"$steps.object_detection_model.predictions\"],\n    )\n    overlap_type: Literal[\"Center Overlap\", \"Any Overlap\"] = Field(\n        default=\"Center Overlap\",\n        description=\"Overlap Type.\",\n        examples=[\"Center Overlap\", \"Any Overlap\"],\n    )\n    overlap_class_name: Union[str] = Field(\n        description=\"Overlap Class Name\",\n        json_schema_extra={\n            \"hide_description\": True,\n        },\n    )\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(\n                name=OUTPUT_KEY,\n                kind=[\n                    OBJECT_DETECTION_PREDICTION_KIND,\n                ],\n            ),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass OverlapBlockV1(WorkflowBlock):\n    def __init__(self):\n        pass\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return OverlapManifest\n\n    @classmethod\n    def coords_overlap(cls, overlap, other, overlap_type):\n\n        # coords are [x1, y1, x2, y2]\n        if overlap_type == \"Center Overlap\":\n            size = [other[2] - other[0], other[3] - other[1]]\n            (x, y) = [other[0] + size[0] / 2, other[1] + size[1] / 2]\n            return (\n                x > overlap[0] and x < overlap[2] and y > overlap[1] and y < overlap[3]\n            )\n        else:\n            return not (\n                other[2] < overlap[0]\n                or other[0] > overlap[2]\n                or other[3] < overlap[1]\n                or other[1] > overlap[3]\n            )\n\n    def run(\n        self,\n        image: WorkflowImageData,\n        predictions: sv.Detections,\n        overlap_type: str,\n        overlap_class_name: str,\n    ) -> BlockResult:\n\n        overlaps = []\n        others = []\n        for i in range(len(predictions.xyxy)):\n            data = get_data_item(predictions.data, i)\n            if data[\"class_name\"] == overlap_class_name:\n                overlaps.append(predictions.xyxy[i])\n            else:\n                others.append((predictions.xyxy[i], i))\n\n        idx = set()\n        for overlap in overlaps:\n            if not others:\n                break\n            idx = idx.union(\n                {\n                    other[1]\n                    for other in others\n                    if OverlapBlockV1.coords_overlap(overlap, other[0], overlap_type)\n                }\n            )\n            # once it's overlapped we don't need to check again\n            others = [o for o in others if o[1] not in idx]\n\n        return {OUTPUT_KEY: predictions[list(idx)]}\n",
    "patch": "diff --git a/inference/core/workflows/core_steps/analytics/overlap/v1.py b/inference/core/workflows/core_steps/analytics/overlap/v1.py\nindex da4e2c192..b16630feb 100644\n--- a/inference/core/workflows/core_steps/analytics/overlap/v1.py\n+++ b/inference/core/workflows/core_steps/analytics/overlap/v1.py\n@@ -20,6 +20,7 @@ from inference.core.workflows.prototypes.block import (\n     WorkflowBlock,\n     WorkflowBlockManifest,\n )\n+from functools import lru_cache\n \n OUTPUT_KEY: str = \"overlaps\"\n SHORT_DESCRIPTION = \"Filter objects overlapping some other class\"\n@@ -70,6 +71,7 @@ class OverlapManifest(WorkflowBlockManifest):\n     )\n \n     @classmethod\n+    @lru_cache(maxsize=None)\n     def describe_outputs(cls) -> List[OutputDefinition]:\n         return [\n             OutputDefinition(\n"
  },
  {
    "trace_id": "5284a71e-3d51-4c4c-9165-e4da69d70456",
    "function_name": "BlockManifest.get_compatible_task_types",
    "file_path": "inference/core/workflows/core_steps/models/roboflow/semantic_segmentation/v1.py",
    "speedup_x": 0.11266584917228695,
    "review_quality": "high",
    "pre_optimization_commit": "c20359386c628a08bde69f5f3f780cedd782c50c",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def get_compatible_task_types(cls) -> Optional[List[str]]:\n        return [\"semantic-segmentation\"]\n",
    "optimized_function_code": "from typing import List, Optional\n\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nLONG_DESCRIPTION = \"\"\"\nRun inference on a semantic segmentation model hosted on or uploaded to Roboflow.\n\nSemantic segmentation assigns a class label to every pixel in the image, producing a\ndense segmentation mask rather than per-object bounding boxes or instance masks.\n\nYou can query any model that is private to your account, or any public model available\non [Roboflow Universe](https://universe.roboflow.com).\n\nYou will need to set your Roboflow API key in your Inference environment to use this\nblock. To learn more about setting your Roboflow API key, [refer to the Inference\ndocumentation](https://inference.roboflow.com/quickstart/configure_api_key/).\n\"\"\"\n\n\n\n# Cache the single-item list so repeated calls can return a fast C-level copy.\n_COMPATIBLE_TASK_TYPES: List[str] = [\"semantic-segmentation\"]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_compatible_task_types(cls) -> Optional[List[str]]:\n        return _COMPATIBLE_TASK_TYPES.copy()",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/models/roboflow/semantic_segmentation/v1.py\nfrom typing import List, Optional\n\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nLONG_DESCRIPTION = \"\"\"\nRun inference on a semantic segmentation model hosted on or uploaded to Roboflow.\n\nSemantic segmentation assigns a class label to every pixel in the image, producing a\ndense segmentation mask rather than per-object bounding boxes or instance masks.\n\nYou can query any model that is private to your account, or any public model available\non [Roboflow Universe](https://universe.roboflow.com).\n\nYou will need to set your Roboflow API key in your Inference environment to use this\nblock. To learn more about setting your Roboflow API key, [refer to the Inference\ndocumentation](https://inference.roboflow.com/quickstart/configure_api_key/).\n\"\"\"\n\n\n\n# Cache the single-item list so repeated calls can return a fast C-level copy.\n_COMPATIBLE_TASK_TYPES: List[str] = [\"semantic-segmentation\"]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_compatible_task_types(cls) -> Optional[List[str]]:\n        return _COMPATIBLE_TASK_TYPES.copy()\n```",
    "optimized_function_only": "    def get_compatible_task_types(cls) -> Optional[List[str]]:\n        return _COMPATIBLE_TASK_TYPES.copy()",
    "original_file_content": "import base64\nfrom typing import Dict, List, Literal, Optional, Type, Union\nfrom uuid import uuid4\n\nimport cv2\nimport numpy as np\nimport pycocotools.mask as mask_utils\nimport supervision as sv\nfrom pydantic import ConfigDict\n\nfrom inference.core.entities.requests.inference import (\n    SemanticSegmentationInferenceRequest,\n)\nfrom inference.core.env import (\n    HOSTED_SEMANTIC_SEGMENTATION_URL,\n    LOCAL_INFERENCE_API_URL,\n    WORKFLOWS_REMOTE_API_TARGET,\n    WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_BATCH_SIZE,\n    WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS,\n)\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.entities import StepExecutionMode\nfrom inference.core.workflows.execution_engine.constants import (\n    DETECTION_ID_KEY,\n    INFERENCE_ID_KEY,\n    RLE_MASK_KEY_IN_SV_DETECTIONS,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    IMAGE_KIND,\n    INFERENCE_ID_KIND,\n    ROBOFLOW_MODEL_ID_KIND,\n    SEMANTIC_SEGMENTATION_PREDICTION_KIND,\n    ImageInputField,\n    RoboflowModelField,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\nfrom inference_sdk import InferenceConfiguration, InferenceHTTPClient\n\nLONG_DESCRIPTION = \"\"\"\nRun inference on a semantic segmentation model hosted on or uploaded to Roboflow.\n\nSemantic segmentation assigns a class label to every pixel in the image, producing a\ndense segmentation mask rather than per-object bounding boxes or instance masks.\n\nYou can query any model that is private to your account, or any public model available\non [Roboflow Universe](https://universe.roboflow.com).\n\nYou will need to set your Roboflow API key in your Inference environment to use this\nblock. To learn more about setting your Roboflow API key, [refer to the Inference\ndocumentation](https://inference.roboflow.com/quickstart/configure_api_key/).\n\"\"\"\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Semantic Segmentation Model\",\n            \"version\": \"v1\",\n            \"short_description\": \"Assign a class label to every pixel in the image.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"model\",\n            \"search_keywords\": [\"semantic\", \"segmentation\", \"deeplab\", \"deep_lab\"],\n            \"ui_manifest\": {\n                \"section\": \"model\",\n                \"icon\": \"far fa-paint-brush\",\n                \"blockPriority\": 3,\n                \"inference\": True,\n            },\n        },\n        protected_namespaces=(),\n    )\n    type: Literal[\"roboflow_core/roboflow_semantic_segmentation_model@v1\"]\n    images: Selector(kind=[IMAGE_KIND]) = ImageInputField\n    model_id: Union[Selector(kind=[ROBOFLOW_MODEL_ID_KIND]), str] = RoboflowModelField\n\n    @classmethod\n    def get_compatible_task_types(cls) -> Optional[List[str]]:\n        return [\"semantic-segmentation\"]\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return [\"images\"]\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=INFERENCE_ID_KEY, kind=[INFERENCE_ID_KIND]),\n            OutputDefinition(\n                name=\"predictions\",\n                kind=[SEMANTIC_SEGMENTATION_PREDICTION_KIND],\n            ),\n            OutputDefinition(name=\"model_id\", kind=[ROBOFLOW_MODEL_ID_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass RoboflowSemanticSegmentationModelBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"model_manager\", \"api_key\", \"step_execution_mode\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        model_id: str,\n    ) -> BlockResult:\n        if self._step_execution_mode is StepExecutionMode.LOCAL:\n            return self.run_locally(images=images, model_id=model_id)\n        elif self._step_execution_mode is StepExecutionMode.REMOTE:\n            return self.run_remotely(images=images, model_id=model_id)\n        else:\n            raise ValueError(\n                f\"Unknown step execution mode: {self._step_execution_mode}\"\n            )\n\n    def run_locally(\n        self,\n        images: Batch[WorkflowImageData],\n        model_id: str,\n    ) -> BlockResult:\n        inference_images = [i.to_inference_format(numpy_preferred=True) for i in images]\n        request = SemanticSegmentationInferenceRequest(\n            api_key=self._api_key,\n            model_id=model_id,\n            image=inference_images,\n            source=\"workflow-execution\",\n        )\n        self._model_manager.add_model(\n            model_id=model_id,\n            api_key=self._api_key,\n        )\n        predictions = self._model_manager.infer_from_request_sync(\n            model_id=model_id, request=request\n        )\n        if not isinstance(predictions, list):\n            predictions = [predictions]\n        predictions = [\n            e.model_dump(by_alias=True, exclude_none=True) for e in predictions\n        ]\n        return self._post_process_result(predictions=predictions, model_id=model_id)\n\n    def run_remotely(\n        self,\n        images: Batch[WorkflowImageData],\n        model_id: str,\n    ) -> BlockResult:\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_SEMANTIC_SEGMENTATION_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        client_config = InferenceConfiguration(\n            max_batch_size=WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_BATCH_SIZE,\n            max_concurrent_requests=WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS,\n            source=\"workflow-execution\",\n        )\n        client.configure(inference_configuration=client_config)\n        inference_images = [i.base64_image for i in images]\n        predictions = client.infer(\n            inference_input=inference_images,\n            model_id=model_id,\n        )\n        if not isinstance(predictions, list):\n            predictions = [predictions]\n        return self._post_process_result(predictions=predictions, model_id=model_id)\n\n    def _post_process_result(\n        self,\n        predictions: List[dict],\n        model_id: str,\n    ) -> BlockResult:\n        return [\n            {\n                INFERENCE_ID_KEY: prediction.get(INFERENCE_ID_KEY),\n                \"predictions\": self._convert_to_sv_detections(\n                    prediction.get(\"predictions\") or {}\n                ),\n                \"model_id\": model_id,\n            }\n            for prediction in predictions\n        ]\n\n    @staticmethod\n    def _convert_to_sv_detections(predictions_dict: Dict) -> sv.Detections:\n        seg_mask_b64 = predictions_dict.get(\"segmentation_mask\", \"\")\n        conf_mask_b64 = predictions_dict.get(\"confidence_mask\", \"\")\n        class_map: Dict[str, str] = predictions_dict.get(\"class_map\", {})\n\n        mask_bytes = base64.b64decode(seg_mask_b64)\n        nparr = np.frombuffer(mask_bytes, np.uint8)\n        mask_array = cv2.imdecode(nparr, cv2.IMREAD_GRAYSCALE)\n\n        if mask_array is None:\n            return sv.Detections.empty()\n\n        unique_class_ids = [cid for cid in np.unique(mask_array).tolist() if cid != 0]\n        if not unique_class_ids:\n            return sv.Detections.empty()\n\n        conf_array = None\n        if conf_mask_b64:\n            conf_bytes = base64.b64decode(conf_mask_b64)\n            conf_nparr = np.frombuffer(conf_bytes, np.uint8)\n            conf_array = cv2.imdecode(conf_nparr, cv2.IMREAD_GRAYSCALE)\n\n        xyxy_list, masks_list, class_id_list, class_name_list, confidence_list = (\n            [],\n            [],\n            [],\n            [],\n            [],\n        )\n        for class_id in unique_class_ids:\n            binary_mask = mask_array == class_id\n            # xyxy is a required sv.Detections field so we make a bounding box around the entire\n            # class mask even though this is not necessarily meaningful for non-contiguous masks.\n            rows = np.where(np.any(binary_mask, axis=1))[0]\n            cols = np.where(np.any(binary_mask, axis=0))[0]\n            xyxy_list.append([cols[0], rows[0], cols[-1], rows[-1]])\n            masks_list.append(binary_mask)\n            class_id_list.append(class_id)\n            class_name_list.append(class_map.get(str(class_id), str(class_id)))\n            if conf_array is not None:\n                confidence_list.append(float(conf_array[binary_mask].mean()) / 255.0)\n            else:\n                confidence_list.append(1.0)\n\n        rle_list = []\n        for mask in masks_list:\n            rle = mask_utils.encode(np.asfortranarray(mask.astype(np.uint8)))\n            rle[\"counts\"] = rle[\"counts\"].decode(\"utf-8\")\n            rle_list.append(rle)\n\n        detection_ids = np.array([str(uuid4()) for _ in class_id_list])\n        result = sv.Detections(\n            xyxy=np.array(xyxy_list, dtype=np.float64),\n            mask=None,\n            class_id=np.array(class_id_list),\n            confidence=np.array(confidence_list, dtype=np.float32),\n            data={\n                \"class_name\": np.array(class_name_list),\n                DETECTION_ID_KEY: detection_ids,\n                RLE_MASK_KEY_IN_SV_DETECTIONS: np.array(rle_list, dtype=object),\n            },\n        )\n\n        if conf_array is not None:\n            result[\"confidence_mask\"] = conf_array\n\n        return result\n",
    "patch": null
  },
  {
    "trace_id": "4effad50-8188-4255-be8d-6c2871a66ccf",
    "function_name": "BlockManifest.get_compatible_task_types",
    "file_path": "inference/core/workflows/core_steps/models/roboflow/object_detection/v2.py",
    "speedup_x": 0.13148396788259067,
    "review_quality": "medium",
    "pre_optimization_commit": "c20359386c628a08bde69f5f3f780cedd782c50c",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def get_compatible_task_types(cls) -> Optional[List[str]]:\n        return [\"object-detection\"]\n",
    "optimized_function_code": "from typing import List, Optional\n\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nLONG_DESCRIPTION = \"\"\"\nRun inference on a object-detection model hosted on or uploaded to Roboflow.\n\nYou can query any model that is private to your account, or any public model available \non [Roboflow Universe](https://universe.roboflow.com).\n\nYou will need to set your Roboflow API key in your Inference environment to use this \nblock. To learn more about setting your Roboflow API key, [refer to the Inference \ndocumentation](https://inference.roboflow.com/quickstart/configure_api_key/).\n\"\"\"\n\n\n\n# Module-level constant created once at import time to avoid rebuilding the list on every call.\n_COMPATIBLE_TASK_TYPES: List[str] = [\"object-detection\"]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_compatible_task_types(cls) -> Optional[List[str]]:\n        return _COMPATIBLE_TASK_TYPES.copy()",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/models/roboflow/object_detection/v2.py\nfrom typing import List, Optional\n\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nLONG_DESCRIPTION = \"\"\"\nRun inference on a object-detection model hosted on or uploaded to Roboflow.\n\nYou can query any model that is private to your account, or any public model available \non [Roboflow Universe](https://universe.roboflow.com).\n\nYou will need to set your Roboflow API key in your Inference environment to use this \nblock. To learn more about setting your Roboflow API key, [refer to the Inference \ndocumentation](https://inference.roboflow.com/quickstart/configure_api_key/).\n\"\"\"\n\n\n\n# Module-level constant created once at import time to avoid rebuilding the list on every call.\n_COMPATIBLE_TASK_TYPES: List[str] = [\"object-detection\"]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_compatible_task_types(cls) -> Optional[List[str]]:\n        return _COMPATIBLE_TASK_TYPES.copy()\n```",
    "optimized_function_only": "    def get_compatible_task_types(cls) -> Optional[List[str]]:\n        return _COMPATIBLE_TASK_TYPES.copy()",
    "original_file_content": "from typing import List, Literal, Optional, Type, Union\n\nfrom pydantic import ConfigDict, Field, PositiveInt\n\nfrom inference.core.entities.requests.inference import ObjectDetectionInferenceRequest\nfrom inference.core.env import (\n    HOSTED_DETECT_URL,\n    LOCAL_INFERENCE_API_URL,\n    WORKFLOWS_REMOTE_API_TARGET,\n    WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_BATCH_SIZE,\n    WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS,\n)\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.entities import StepExecutionMode\nfrom inference.core.workflows.core_steps.common.utils import (\n    attach_parents_coordinates_to_batch_of_sv_detections,\n    attach_prediction_type_info_to_sv_detections_batch,\n    convert_inference_detections_batch_to_sv_detections,\n    filter_out_unwanted_classes_from_sv_detections_batch,\n)\nfrom inference.core.workflows.execution_engine.constants import INFERENCE_ID_KEY\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    BOOLEAN_KIND,\n    FLOAT_ZERO_TO_ONE_KIND,\n    IMAGE_KIND,\n    INFERENCE_ID_KIND,\n    INTEGER_KIND,\n    LIST_OF_VALUES_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    ROBOFLOW_MODEL_ID_KIND,\n    ROBOFLOW_PROJECT_KIND,\n    FloatZeroToOne,\n    ImageInputField,\n    RoboflowModelField,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\nfrom inference_sdk import InferenceConfiguration, InferenceHTTPClient\n\nLONG_DESCRIPTION = \"\"\"\nRun inference on a object-detection model hosted on or uploaded to Roboflow.\n\nYou can query any model that is private to your account, or any public model available \non [Roboflow Universe](https://universe.roboflow.com).\n\nYou will need to set your Roboflow API key in your Inference environment to use this \nblock. To learn more about setting your Roboflow API key, [refer to the Inference \ndocumentation](https://inference.roboflow.com/quickstart/configure_api_key/).\n\"\"\"\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Object Detection Model\",\n            \"version\": \"v2\",\n            \"short_description\": \"Predict the location of objects with bounding boxes.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"model\",\n            \"search_keywords\": [\"yolo\", \"rfdetr\", \"rf-detr\"],\n            \"ui_manifest\": {\n                \"section\": \"model\",\n                \"icon\": \"far fa-chart-network\",\n                \"blockPriority\": 0,\n                \"inference\": True,\n                \"popular\": True,\n            },\n        },\n        protected_namespaces=(),\n    )\n    type: Literal[\"roboflow_core/roboflow_object_detection_model@v2\"]\n    images: Selector(kind=[IMAGE_KIND]) = ImageInputField\n    model_id: Union[Selector(kind=[ROBOFLOW_MODEL_ID_KIND]), str] = RoboflowModelField\n    confidence: Union[\n        FloatZeroToOne,\n        Selector(kind=[FLOAT_ZERO_TO_ONE_KIND]),\n    ] = Field(\n        default=0.4,\n        description=\"Confidence threshold for predictions.\",\n        examples=[0.3, \"$inputs.confidence_threshold\"],\n    )\n    class_filter: Union[Optional[List[str]], Selector(kind=[LIST_OF_VALUES_KIND])] = (\n        Field(\n            default=None,\n            description=\"List of accepted classes. Classes must exist in the model's training set.\",\n            examples=[[\"a\", \"b\", \"c\"], \"$inputs.class_filter\"],\n        )\n    )\n    iou_threshold: Union[\n        FloatZeroToOne,\n        Selector(kind=[FLOAT_ZERO_TO_ONE_KIND]),\n    ] = Field(\n        default=0.3,\n        description=\"Minimum overlap threshold between boxes to combine them into a single detection, used in NMS. [Learn more](https://blog.roboflow.com/how-to-code-non-maximum-suppression-nms-in-plain-numpy/).\",\n        examples=[0.4, \"$inputs.iou_threshold\"],\n    )\n    max_detections: Union[PositiveInt, Selector(kind=[INTEGER_KIND])] = Field(\n        default=300,\n        description=\"Maximum number of detections to return.\",\n        examples=[300, \"$inputs.max_detections\"],\n    )\n    class_agnostic_nms: Union[Optional[bool], Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=False,\n        description=\"Boolean flag to specify if NMS is to be used in class-agnostic mode.\",\n        examples=[True, \"$inputs.class_agnostic_nms\"],\n    )\n    max_candidates: Union[PositiveInt, Selector(kind=[INTEGER_KIND])] = Field(\n        default=3000,\n        description=\"Maximum number of candidates as NMS input to be taken into account.\",\n        examples=[3000, \"$inputs.max_candidates\"],\n    )\n    disable_active_learning: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=True,\n        description=\"Boolean flag to disable project-level active learning for this block.\",\n        examples=[True, \"$inputs.disable_active_learning\"],\n    )\n    active_learning_target_dataset: Union[\n        Selector(kind=[ROBOFLOW_PROJECT_KIND]), Optional[str]\n    ] = Field(\n        default=None,\n        description=\"Target dataset for active learning, if enabled.\",\n        examples=[\"my_project\", \"$inputs.al_target_project\"],\n    )\n\n    @classmethod\n    def get_compatible_task_types(cls) -> Optional[List[str]]:\n        return [\"object-detection\"]\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return [\"images\"]\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"inference_id\", kind=[INFERENCE_ID_KIND]),\n            OutputDefinition(\n                name=\"predictions\", kind=[OBJECT_DETECTION_PREDICTION_KIND]\n            ),\n            OutputDefinition(name=\"model_id\", kind=[ROBOFLOW_MODEL_ID_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass RoboflowObjectDetectionModelBlockV2(WorkflowBlock):\n\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"model_manager\", \"api_key\", \"step_execution_mode\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        model_id: str,\n        class_agnostic_nms: Optional[bool],\n        class_filter: Optional[List[str]],\n        confidence: Optional[float],\n        iou_threshold: Optional[float],\n        max_detections: Optional[int],\n        max_candidates: Optional[int],\n        disable_active_learning: Optional[bool],\n        active_learning_target_dataset: Optional[str],\n    ) -> BlockResult:\n        if self._step_execution_mode is StepExecutionMode.LOCAL:\n            return self.run_locally(\n                images=images,\n                model_id=model_id,\n                class_agnostic_nms=class_agnostic_nms,\n                class_filter=class_filter,\n                confidence=confidence,\n                iou_threshold=iou_threshold,\n                max_detections=max_detections,\n                max_candidates=max_candidates,\n                disable_active_learning=disable_active_learning,\n                active_learning_target_dataset=active_learning_target_dataset,\n            )\n        elif self._step_execution_mode is StepExecutionMode.REMOTE:\n            return self.run_remotely(\n                images=images,\n                model_id=model_id,\n                class_agnostic_nms=class_agnostic_nms,\n                class_filter=class_filter,\n                confidence=confidence,\n                iou_threshold=iou_threshold,\n                max_detections=max_detections,\n                max_candidates=max_candidates,\n                disable_active_learning=disable_active_learning,\n                active_learning_target_dataset=active_learning_target_dataset,\n            )\n        else:\n            raise ValueError(\n                f\"Unknown step execution mode: {self._step_execution_mode}\"\n            )\n\n    def run_locally(\n        self,\n        images: Batch[WorkflowImageData],\n        model_id: str,\n        class_agnostic_nms: Optional[bool],\n        class_filter: Optional[List[str]],\n        confidence: Optional[float],\n        iou_threshold: Optional[float],\n        max_detections: Optional[int],\n        max_candidates: Optional[int],\n        disable_active_learning: Optional[bool],\n        active_learning_target_dataset: Optional[str],\n    ) -> BlockResult:\n        inference_images = [i.to_inference_format(numpy_preferred=True) for i in images]\n        request = ObjectDetectionInferenceRequest(\n            api_key=self._api_key,\n            model_id=model_id,\n            image=inference_images,\n            disable_active_learning=disable_active_learning,\n            active_learning_target_dataset=active_learning_target_dataset,\n            class_agnostic_nms=class_agnostic_nms,\n            class_filter=class_filter,\n            confidence=confidence,\n            iou_threshold=iou_threshold,\n            max_detections=max_detections,\n            max_candidates=max_candidates,\n            source=\"workflow-execution\",\n        )\n        self._model_manager.add_model(\n            model_id=model_id,\n            api_key=self._api_key,\n        )\n        predictions = self._model_manager.infer_from_request_sync(\n            model_id=model_id, request=request\n        )\n        if not isinstance(predictions, list):\n            predictions = [predictions]\n        predictions = [\n            e.model_dump(by_alias=True, exclude_none=True) for e in predictions\n        ]\n        return self._post_process_result(\n            images=images,\n            predictions=predictions,\n            class_filter=class_filter,\n            model_id=model_id,\n        )\n\n    def run_remotely(\n        self,\n        images: Batch[WorkflowImageData],\n        model_id: str,\n        class_agnostic_nms: Optional[bool],\n        class_filter: Optional[List[str]],\n        confidence: Optional[float],\n        iou_threshold: Optional[float],\n        max_detections: Optional[int],\n        max_candidates: Optional[int],\n        disable_active_learning: Optional[bool],\n        active_learning_target_dataset: Optional[str],\n    ) -> BlockResult:\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_DETECT_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        if WORKFLOWS_REMOTE_API_TARGET == \"hosted\":\n            client.select_api_v0()\n        client_config = InferenceConfiguration(\n            disable_active_learning=disable_active_learning,\n            active_learning_target_dataset=active_learning_target_dataset,\n            class_agnostic_nms=class_agnostic_nms,\n            class_filter=class_filter,\n            confidence_threshold=confidence,\n            iou_threshold=iou_threshold,\n            max_detections=max_detections,\n            max_candidates=max_candidates,\n            max_batch_size=WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_BATCH_SIZE,\n            max_concurrent_requests=WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS,\n            source=\"workflow-execution\",\n        )\n        client.configure(inference_configuration=client_config)\n        non_empty_inference_images = [i.base64_image for i in images]\n        predictions = client.infer(\n            inference_input=non_empty_inference_images,\n            model_id=model_id,\n        )\n        if not isinstance(predictions, list):\n            predictions = [predictions]\n        return self._post_process_result(\n            images=images,\n            predictions=predictions,\n            class_filter=class_filter,\n            model_id=model_id,\n        )\n\n    def _post_process_result(\n        self,\n        images: Batch[WorkflowImageData],\n        predictions: List[dict],\n        class_filter: Optional[List[str]],\n        model_id: str,\n    ) -> BlockResult:\n        inference_ids = [p.get(INFERENCE_ID_KEY, None) for p in predictions]\n        predictions = convert_inference_detections_batch_to_sv_detections(predictions)\n        predictions = attach_prediction_type_info_to_sv_detections_batch(\n            predictions=predictions,\n            prediction_type=\"object-detection\",\n        )\n        predictions = filter_out_unwanted_classes_from_sv_detections_batch(\n            predictions=predictions,\n            classes_to_accept=class_filter,\n        )\n        predictions = attach_parents_coordinates_to_batch_of_sv_detections(\n            images=images,\n            predictions=predictions,\n        )\n        return [\n            {\n                \"inference_id\": inference_id,\n                \"predictions\": prediction,\n                \"model_id\": model_id,\n            }\n            for inference_id, prediction in zip(inference_ids, predictions)\n        ]\n",
    "patch": null
  },
  {
    "trace_id": "2e8ba96f-9291-4599-a622-f40b23255e4a",
    "function_name": "BlockManifest.get_compatible_task_types",
    "file_path": "inference/core/workflows/core_steps/models/roboflow/object_detection/v1.py",
    "speedup_x": 0.11692292101372262,
    "review_quality": "medium",
    "pre_optimization_commit": "c20359386c628a08bde69f5f3f780cedd782c50c",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def get_compatible_task_types(cls) -> Optional[List[str]]:\n        return [\"object-detection\"]\n",
    "optimized_function_code": "from typing import List, Optional\n\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nLONG_DESCRIPTION = \"\"\"\nRun inference on a object-detection model hosted on or uploaded to Roboflow.\n\nYou can query any model that is private to your account, or any public model available \non [Roboflow Universe](https://universe.roboflow.com).\n\nYou will need to set your Roboflow API key in your Inference environment to use this \nblock. To learn more about setting your Roboflow API key, [refer to the Inference \ndocumentation](https://inference.roboflow.com/quickstart/configure_api_key/).\n\"\"\"\n\n\n\n# Module-level constant to avoid recreating the same literal list on every call.\n_COMPATIBLE_TASK_TYPES: List[str] = [\"object-detection\"]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_compatible_task_types(cls) -> Optional[List[str]]:\n        return _COMPATIBLE_TASK_TYPES.copy()",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/models/roboflow/object_detection/v1.py\nfrom typing import List, Optional\n\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nLONG_DESCRIPTION = \"\"\"\nRun inference on a object-detection model hosted on or uploaded to Roboflow.\n\nYou can query any model that is private to your account, or any public model available \non [Roboflow Universe](https://universe.roboflow.com).\n\nYou will need to set your Roboflow API key in your Inference environment to use this \nblock. To learn more about setting your Roboflow API key, [refer to the Inference \ndocumentation](https://inference.roboflow.com/quickstart/configure_api_key/).\n\"\"\"\n\n\n\n# Module-level constant to avoid recreating the same literal list on every call.\n_COMPATIBLE_TASK_TYPES: List[str] = [\"object-detection\"]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_compatible_task_types(cls) -> Optional[List[str]]:\n        return _COMPATIBLE_TASK_TYPES.copy()\n```",
    "optimized_function_only": "    def get_compatible_task_types(cls) -> Optional[List[str]]:\n        return _COMPATIBLE_TASK_TYPES.copy()",
    "original_file_content": "from typing import List, Literal, Optional, Type, Union\n\nfrom pydantic import ConfigDict, Field, PositiveInt\n\nfrom inference.core.entities.requests.inference import ObjectDetectionInferenceRequest\nfrom inference.core.env import (\n    HOSTED_DETECT_URL,\n    LOCAL_INFERENCE_API_URL,\n    WORKFLOWS_REMOTE_API_TARGET,\n    WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_BATCH_SIZE,\n    WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS,\n)\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.entities import StepExecutionMode\nfrom inference.core.workflows.core_steps.common.utils import (\n    attach_parents_coordinates_to_batch_of_sv_detections,\n    attach_prediction_type_info_to_sv_detections_batch,\n    convert_inference_detections_batch_to_sv_detections,\n    filter_out_unwanted_classes_from_sv_detections_batch,\n)\nfrom inference.core.workflows.execution_engine.constants import INFERENCE_ID_KEY\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    BOOLEAN_KIND,\n    FLOAT_ZERO_TO_ONE_KIND,\n    IMAGE_KIND,\n    INTEGER_KIND,\n    LIST_OF_VALUES_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    ROBOFLOW_MODEL_ID_KIND,\n    ROBOFLOW_PROJECT_KIND,\n    STRING_KIND,\n    FloatZeroToOne,\n    ImageInputField,\n    RoboflowModelField,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\nfrom inference_sdk import InferenceConfiguration, InferenceHTTPClient\n\nLONG_DESCRIPTION = \"\"\"\nRun inference on a object-detection model hosted on or uploaded to Roboflow.\n\nYou can query any model that is private to your account, or any public model available \non [Roboflow Universe](https://universe.roboflow.com).\n\nYou will need to set your Roboflow API key in your Inference environment to use this \nblock. To learn more about setting your Roboflow API key, [refer to the Inference \ndocumentation](https://inference.roboflow.com/quickstart/configure_api_key/).\n\"\"\"\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Object Detection Model\",\n            \"version\": \"v1\",\n            \"short_description\": \"Predict the location of objects with bounding boxes.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"model\",\n            \"search_keywords\": [\"yolo\", \"rfdetr\", \"rf-detr\"],\n            \"ui_manifest\": {\n                \"section\": \"model\",\n                \"icon\": \"far fa-chart-network\",\n                \"blockPriority\": 0,\n                \"inference\": True,\n                \"popular\": True,\n            },\n        },\n        protected_namespaces=(),\n    )\n    type: Literal[\n        \"roboflow_core/roboflow_object_detection_model@v1\",\n        \"RoboflowObjectDetectionModel\",\n        \"ObjectDetectionModel\",\n    ]\n    images: Selector(kind=[IMAGE_KIND]) = ImageInputField\n    model_id: Union[Selector(kind=[ROBOFLOW_MODEL_ID_KIND]), str] = RoboflowModelField\n    confidence: Union[\n        FloatZeroToOne,\n        Selector(kind=[FLOAT_ZERO_TO_ONE_KIND]),\n    ] = Field(\n        default=0.4,\n        description=\"Confidence threshold for predictions.\",\n        examples=[0.3, \"$inputs.confidence_threshold\"],\n    )\n    class_filter: Union[Optional[List[str]], Selector(kind=[LIST_OF_VALUES_KIND])] = (\n        Field(\n            default=None,\n            description=\"List of accepted classes. Classes must exist in the model's training set.\",\n            examples=[[\"a\", \"b\", \"c\"], \"$inputs.class_filter\"],\n        )\n    )\n    iou_threshold: Union[\n        FloatZeroToOne,\n        Selector(kind=[FLOAT_ZERO_TO_ONE_KIND]),\n    ] = Field(\n        default=0.3,\n        description=\"Minimum overlap threshold between boxes to combine them into a single detection, used in NMS. [Learn more](https://blog.roboflow.com/how-to-code-non-maximum-suppression-nms-in-plain-numpy/).\",\n        examples=[0.4, \"$inputs.iou_threshold\"],\n    )\n    max_detections: Union[PositiveInt, Selector(kind=[INTEGER_KIND])] = Field(\n        default=300,\n        description=\"Maximum number of detections to return.\",\n        examples=[300, \"$inputs.max_detections\"],\n    )\n    class_agnostic_nms: Union[Optional[bool], Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=False,\n        description=\"Boolean flag to specify if NMS is to be used in class-agnostic mode.\",\n        examples=[True, \"$inputs.class_agnostic_nms\"],\n    )\n    max_candidates: Union[PositiveInt, Selector(kind=[INTEGER_KIND])] = Field(\n        default=3000,\n        description=\"Maximum number of candidates as NMS input to be taken into account.\",\n        examples=[3000, \"$inputs.max_candidates\"],\n    )\n    disable_active_learning: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=True,\n        description=\"Boolean flag to disable project-level active learning for this block.\",\n        examples=[True, \"$inputs.disable_active_learning\"],\n    )\n    active_learning_target_dataset: Union[\n        Selector(kind=[ROBOFLOW_PROJECT_KIND]), Optional[str]\n    ] = Field(\n        default=None,\n        description=\"Target dataset for active learning, if enabled.\",\n        examples=[\"my_project\", \"$inputs.al_target_project\"],\n    )\n\n    @classmethod\n    def get_compatible_task_types(cls) -> Optional[List[str]]:\n        return [\"object-detection\"]\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return [\"images\"]\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"inference_id\", kind=[STRING_KIND]),\n            OutputDefinition(\n                name=\"predictions\", kind=[OBJECT_DETECTION_PREDICTION_KIND]\n            ),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass RoboflowObjectDetectionModelBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"model_manager\", \"api_key\", \"step_execution_mode\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        model_id: str,\n        class_agnostic_nms: Optional[bool],\n        class_filter: Optional[List[str]],\n        confidence: Optional[float],\n        iou_threshold: Optional[float],\n        max_detections: Optional[int],\n        max_candidates: Optional[int],\n        disable_active_learning: Optional[bool],\n        active_learning_target_dataset: Optional[str],\n    ) -> BlockResult:\n        if self._step_execution_mode is StepExecutionMode.LOCAL:\n            return self.run_locally(\n                images=images,\n                model_id=model_id,\n                class_agnostic_nms=class_agnostic_nms,\n                class_filter=class_filter,\n                confidence=confidence,\n                iou_threshold=iou_threshold,\n                max_detections=max_detections,\n                max_candidates=max_candidates,\n                disable_active_learning=disable_active_learning,\n                active_learning_target_dataset=active_learning_target_dataset,\n            )\n        elif self._step_execution_mode is StepExecutionMode.REMOTE:\n            return self.run_remotely(\n                images=images,\n                model_id=model_id,\n                class_agnostic_nms=class_agnostic_nms,\n                class_filter=class_filter,\n                confidence=confidence,\n                iou_threshold=iou_threshold,\n                max_detections=max_detections,\n                max_candidates=max_candidates,\n                disable_active_learning=disable_active_learning,\n                active_learning_target_dataset=active_learning_target_dataset,\n            )\n        else:\n            raise ValueError(\n                f\"Unknown step execution mode: {self._step_execution_mode}\"\n            )\n\n    def run_locally(\n        self,\n        images: Batch[WorkflowImageData],\n        model_id: str,\n        class_agnostic_nms: Optional[bool],\n        class_filter: Optional[List[str]],\n        confidence: Optional[float],\n        iou_threshold: Optional[float],\n        max_detections: Optional[int],\n        max_candidates: Optional[int],\n        disable_active_learning: Optional[bool],\n        active_learning_target_dataset: Optional[str],\n    ) -> BlockResult:\n        inference_images = [i.to_inference_format(numpy_preferred=True) for i in images]\n        request = ObjectDetectionInferenceRequest(\n            api_key=self._api_key,\n            model_id=model_id,\n            image=inference_images,\n            disable_active_learning=disable_active_learning,\n            active_learning_target_dataset=active_learning_target_dataset,\n            class_agnostic_nms=class_agnostic_nms,\n            class_filter=class_filter,\n            confidence=confidence,\n            iou_threshold=iou_threshold,\n            max_detections=max_detections,\n            max_candidates=max_candidates,\n            source=\"workflow-execution\",\n        )\n        self._model_manager.add_model(\n            model_id=model_id,\n            api_key=self._api_key,\n        )\n        predictions = self._model_manager.infer_from_request_sync(\n            model_id=model_id, request=request\n        )\n        if not isinstance(predictions, list):\n            predictions = [predictions]\n        predictions = [\n            e.model_dump(by_alias=True, exclude_none=True) for e in predictions\n        ]\n        return self._post_process_result(\n            images=images,\n            predictions=predictions,\n            class_filter=class_filter,\n        )\n\n    def run_remotely(\n        self,\n        images: Batch[WorkflowImageData],\n        model_id: str,\n        class_agnostic_nms: Optional[bool],\n        class_filter: Optional[List[str]],\n        confidence: Optional[float],\n        iou_threshold: Optional[float],\n        max_detections: Optional[int],\n        max_candidates: Optional[int],\n        disable_active_learning: Optional[bool],\n        active_learning_target_dataset: Optional[str],\n    ) -> BlockResult:\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_DETECT_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        if WORKFLOWS_REMOTE_API_TARGET == \"hosted\":\n            client.select_api_v0()\n        client_config = InferenceConfiguration(\n            disable_active_learning=disable_active_learning,\n            active_learning_target_dataset=active_learning_target_dataset,\n            class_agnostic_nms=class_agnostic_nms,\n            class_filter=class_filter,\n            confidence_threshold=confidence,\n            iou_threshold=iou_threshold,\n            max_detections=max_detections,\n            max_candidates=max_candidates,\n            max_batch_size=WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_BATCH_SIZE,\n            max_concurrent_requests=WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS,\n            source=\"workflow-execution\",\n        )\n        client.configure(inference_configuration=client_config)\n        non_empty_inference_images = [i.base64_image for i in images]\n        predictions = client.infer(\n            inference_input=non_empty_inference_images,\n            model_id=model_id,\n        )\n        if not isinstance(predictions, list):\n            predictions = [predictions]\n        return self._post_process_result(\n            images=images,\n            predictions=predictions,\n            class_filter=class_filter,\n        )\n\n    def _post_process_result(\n        self,\n        images: Batch[WorkflowImageData],\n        predictions: List[dict],\n        class_filter: Optional[List[str]],\n    ) -> BlockResult:\n        inference_ids = [p.get(INFERENCE_ID_KEY, None) for p in predictions]\n        predictions = convert_inference_detections_batch_to_sv_detections(predictions)\n        predictions = attach_prediction_type_info_to_sv_detections_batch(\n            predictions=predictions,\n            prediction_type=\"object-detection\",\n        )\n        predictions = filter_out_unwanted_classes_from_sv_detections_batch(\n            predictions=predictions,\n            classes_to_accept=class_filter,\n        )\n        predictions = attach_parents_coordinates_to_batch_of_sv_detections(\n            images=images,\n            predictions=predictions,\n        )\n        return [\n            {\"inference_id\": inference_id, \"predictions\": prediction}\n            for inference_id, prediction in zip(inference_ids, predictions)\n        ]\n",
    "patch": null
  },
  {
    "trace_id": "be9fee67-5052-44fd-a395-e9359f234087",
    "function_name": "BlockManifest.get_compatible_task_types",
    "file_path": "inference/core/workflows/core_steps/models/roboflow/multi_class_classification/v2.py",
    "speedup_x": 0.1380039784581049,
    "review_quality": "high",
    "pre_optimization_commit": "835af61109f8cab1d2cb51cf93d061ef3a4c5fc7",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def get_compatible_task_types(cls) -> list:\n        return [\"classification\"]\n",
    "optimized_function_code": "from inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nLONG_DESCRIPTION = \"\"\"\nRun inference on a multi-class classification model hosted on or uploaded to Roboflow.\n\nYou can query any model that is private to your account, or any public model available \non [Roboflow Universe](https://universe.roboflow.com).\n\nYou will need to set your Roboflow API key in your Inference environment to use this \nblock. To learn more about setting your Roboflow API key, [refer to the Inference \ndocumentation](https://inference.roboflow.com/quickstart/configure_api_key/).\n\"\"\"\n\n\n\n# Module-level constant to avoid reallocating the same sequence on every call.\n_COMPATIBLE_TASK_TYPES: list = [\"classification\"]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_compatible_task_types(cls) -> list:\n        # Return a shallow copy so callers receive a fresh list (preserves original behavior).\n        return _COMPATIBLE_TASK_TYPES.copy()",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/models/roboflow/multi_class_classification/v2.py\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nLONG_DESCRIPTION = \"\"\"\nRun inference on a multi-class classification model hosted on or uploaded to Roboflow.\n\nYou can query any model that is private to your account, or any public model available \non [Roboflow Universe](https://universe.roboflow.com).\n\nYou will need to set your Roboflow API key in your Inference environment to use this \nblock. To learn more about setting your Roboflow API key, [refer to the Inference \ndocumentation](https://inference.roboflow.com/quickstart/configure_api_key/).\n\"\"\"\n\n\n\n# Module-level constant to avoid reallocating the same sequence on every call.\n_COMPATIBLE_TASK_TYPES: list = [\"classification\"]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_compatible_task_types(cls) -> list:\n        # Return a shallow copy so callers receive a fresh list (preserves original behavior).\n        return _COMPATIBLE_TASK_TYPES.copy()\n```",
    "optimized_function_only": "    def get_compatible_task_types(cls) -> list:\n        # Return a shallow copy so callers receive a fresh list (preserves original behavior).\n        return _COMPATIBLE_TASK_TYPES.copy()",
    "original_file_content": "from typing import List, Literal, Optional, Type, Union\n\nfrom pydantic import ConfigDict, Field\n\nfrom inference.core.entities.requests.inference import ClassificationInferenceRequest\nfrom inference.core.env import (\n    HOSTED_CLASSIFICATION_URL,\n    LOCAL_INFERENCE_API_URL,\n    WORKFLOWS_REMOTE_API_TARGET,\n    WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_BATCH_SIZE,\n    WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS,\n)\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.entities import StepExecutionMode\nfrom inference.core.workflows.core_steps.common.utils import attach_prediction_type_info\nfrom inference.core.workflows.execution_engine.constants import (\n    INFERENCE_ID_KEY,\n    PARENT_ID_KEY,\n    ROOT_PARENT_ID_KEY,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    BOOLEAN_KIND,\n    CLASSIFICATION_PREDICTION_KIND,\n    FLOAT_ZERO_TO_ONE_KIND,\n    IMAGE_KIND,\n    INFERENCE_ID_KIND,\n    ROBOFLOW_MODEL_ID_KIND,\n    ROBOFLOW_PROJECT_KIND,\n    FloatZeroToOne,\n    ImageInputField,\n    RoboflowModelField,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\nfrom inference_sdk import InferenceConfiguration, InferenceHTTPClient\n\nLONG_DESCRIPTION = \"\"\"\nRun inference on a multi-class classification model hosted on or uploaded to Roboflow.\n\nYou can query any model that is private to your account, or any public model available \non [Roboflow Universe](https://universe.roboflow.com).\n\nYou will need to set your Roboflow API key in your Inference environment to use this \nblock. To learn more about setting your Roboflow API key, [refer to the Inference \ndocumentation](https://inference.roboflow.com/quickstart/configure_api_key/).\n\"\"\"\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Single-Label Classification Model\",\n            \"version\": \"v2\",\n            \"short_description\": \"Apply a single tag to an image.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"model\",\n            \"ui_manifest\": {\n                \"section\": \"model\",\n                \"icon\": \"far fa-chart-network\",\n                \"blockPriority\": 2,\n                \"inference\": True,\n                \"popular\": True,\n            },\n        },\n        protected_namespaces=(),\n    )\n    type: Literal[\"roboflow_core/roboflow_classification_model@v2\"]\n    images: Selector(kind=[IMAGE_KIND]) = ImageInputField\n    model_id: Union[Selector(kind=[ROBOFLOW_MODEL_ID_KIND]), str] = RoboflowModelField\n    confidence: Union[\n        FloatZeroToOne,\n        Selector(kind=[FLOAT_ZERO_TO_ONE_KIND]),\n    ] = Field(\n        default=0.4,\n        description=\"Confidence threshold for predictions.\",\n        examples=[0.3, \"$inputs.confidence_threshold\"],\n    )\n    disable_active_learning: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=True,\n        description=\"Boolean flag to disable project-level active learning for this block.\",\n        examples=[True, \"$inputs.disable_active_learning\"],\n    )\n    active_learning_target_dataset: Union[\n        Selector(kind=[ROBOFLOW_PROJECT_KIND]), Optional[str]\n    ] = Field(\n        default=None,\n        description=\"Target dataset for active learning, if enabled.\",\n        examples=[\"my_project\", \"$inputs.al_target_project\"],\n    )\n\n    @classmethod\n    def get_compatible_task_types(cls) -> list:\n        return [\"classification\"]\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return [\"images\"]\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"predictions\", kind=[CLASSIFICATION_PREDICTION_KIND]),\n            OutputDefinition(name=INFERENCE_ID_KEY, kind=[INFERENCE_ID_KIND]),\n            OutputDefinition(name=\"model_id\", kind=[ROBOFLOW_MODEL_ID_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass RoboflowClassificationModelBlockV2(WorkflowBlock):\n\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"model_manager\", \"api_key\", \"step_execution_mode\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        model_id: str,\n        confidence: Optional[float],\n        disable_active_learning: Optional[bool],\n        active_learning_target_dataset: Optional[str],\n    ) -> BlockResult:\n        if self._step_execution_mode is StepExecutionMode.LOCAL:\n            return self.run_locally(\n                images=images,\n                model_id=model_id,\n                confidence=confidence,\n                disable_active_learning=disable_active_learning,\n                active_learning_target_dataset=active_learning_target_dataset,\n            )\n        elif self._step_execution_mode is StepExecutionMode.REMOTE:\n            return self.run_remotely(\n                images=images,\n                model_id=model_id,\n                confidence=confidence,\n                disable_active_learning=disable_active_learning,\n                active_learning_target_dataset=active_learning_target_dataset,\n            )\n        else:\n            raise ValueError(\n                f\"Unknown step execution mode: {self._step_execution_mode}\"\n            )\n\n    def run_locally(\n        self,\n        images: Batch[WorkflowImageData],\n        model_id: str,\n        confidence: Optional[float],\n        disable_active_learning: Optional[bool],\n        active_learning_target_dataset: Optional[str],\n    ) -> BlockResult:\n        inference_images = [i.to_inference_format(numpy_preferred=True) for i in images]\n        request = ClassificationInferenceRequest(\n            api_key=self._api_key,\n            model_id=model_id,\n            image=inference_images,\n            confidence=confidence,\n            disable_active_learning=disable_active_learning,\n            source=\"workflow-execution\",\n            active_learning_target_dataset=active_learning_target_dataset,\n        )\n        self._model_manager.add_model(\n            model_id=model_id,\n            api_key=self._api_key,\n        )\n        predictions = self._model_manager.infer_from_request_sync(\n            model_id=model_id, request=request\n        )\n        if isinstance(predictions, list):\n            predictions = [\n                e.model_dump(by_alias=True, exclude_none=True) for e in predictions\n            ]\n        else:\n            predictions = [predictions.model_dump(by_alias=True, exclude_none=True)]\n        return self._post_process_result(\n            predictions=predictions,\n            images=images,\n            model_id=model_id,\n        )\n\n    def run_remotely(\n        self,\n        images: Batch[Optional[WorkflowImageData]],\n        model_id: str,\n        confidence: Optional[float],\n        disable_active_learning: Optional[bool],\n        active_learning_target_dataset: Optional[str],\n    ) -> BlockResult:\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_CLASSIFICATION_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        if WORKFLOWS_REMOTE_API_TARGET == \"hosted\":\n            client.select_api_v0()\n        client_config = InferenceConfiguration(\n            confidence_threshold=confidence,\n            disable_active_learning=disable_active_learning,\n            active_learning_target_dataset=active_learning_target_dataset,\n            max_batch_size=WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_BATCH_SIZE,\n            max_concurrent_requests=WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS,\n            source=\"workflow-execution\",\n        )\n        client.configure(inference_configuration=client_config)\n        non_empty_inference_images = [i.base64_image for i in images]\n        predictions = client.infer(\n            inference_input=non_empty_inference_images,\n            model_id=model_id,\n        )\n        if not isinstance(predictions, list):\n            predictions = [predictions]\n        return self._post_process_result(\n            predictions=predictions,\n            images=images,\n            model_id=model_id,\n        )\n\n    def _post_process_result(\n        self,\n        images: Batch[WorkflowImageData],\n        predictions: List[dict],\n        model_id: str,\n    ) -> BlockResult:\n        predictions = attach_prediction_type_info(\n            predictions=predictions,\n            prediction_type=\"classification\",\n        )\n        for prediction, image in zip(predictions, images):\n            prediction[PARENT_ID_KEY] = image.parent_metadata.parent_id\n            prediction[ROOT_PARENT_ID_KEY] = (\n                image.workflow_root_ancestor_metadata.parent_id\n            )\n        return [\n            {\n                \"inference_id\": prediction.get(INFERENCE_ID_KEY),\n                \"predictions\": prediction,\n                \"model_id\": model_id,\n            }\n            for prediction in predictions\n        ]\n",
    "patch": null
  },
  {
    "trace_id": "5f7df79f-5fcf-42c1-981a-cd59c087fb7a",
    "function_name": "BlockManifest.get_compatible_task_types",
    "file_path": "inference/core/workflows/core_steps/models/roboflow/keypoint_detection/v2.py",
    "speedup_x": 0.11098577366619714,
    "review_quality": "high",
    "pre_optimization_commit": "c20359386c628a08bde69f5f3f780cedd782c50c",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def get_compatible_task_types(cls) -> Optional[List[str]]:\n        return [\"keypoint-detection\"]\n",
    "optimized_function_code": "from typing import List, Optional\n\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nLONG_DESCRIPTION = \"\"\"\nRun inference on a keypoint detection model hosted on or uploaded to Roboflow.\n\nYou can query any model that is private to your account, or any public model available \non [Roboflow Universe](https://universe.roboflow.com).\n\nYou will need to set your Roboflow API key in your Inference environment to use this \nblock. To learn more about setting your Roboflow API key, [refer to the Inference \ndocumentation](https://inference.roboflow.com/quickstart/configure_api_key/).\n\"\"\"\n\n\n\n# Module-level constant for the compatible task types. Use a single allocated list\n# and return a shallow copy on each call to preserve original semantics (fresh list).\n_COMPATIBLE_TASK_TYPES: List[str] = [\"keypoint-detection\"]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_compatible_task_types(cls) -> Optional[List[str]]:\n        return _COMPATIBLE_TASK_TYPES.copy()",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/models/roboflow/keypoint_detection/v2.py\nfrom typing import List, Optional\n\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nLONG_DESCRIPTION = \"\"\"\nRun inference on a keypoint detection model hosted on or uploaded to Roboflow.\n\nYou can query any model that is private to your account, or any public model available \non [Roboflow Universe](https://universe.roboflow.com).\n\nYou will need to set your Roboflow API key in your Inference environment to use this \nblock. To learn more about setting your Roboflow API key, [refer to the Inference \ndocumentation](https://inference.roboflow.com/quickstart/configure_api_key/).\n\"\"\"\n\n\n\n# Module-level constant for the compatible task types. Use a single allocated list\n# and return a shallow copy on each call to preserve original semantics (fresh list).\n_COMPATIBLE_TASK_TYPES: List[str] = [\"keypoint-detection\"]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_compatible_task_types(cls) -> Optional[List[str]]:\n        return _COMPATIBLE_TASK_TYPES.copy()\n```",
    "optimized_function_only": "    def get_compatible_task_types(cls) -> Optional[List[str]]:\n        return _COMPATIBLE_TASK_TYPES.copy()",
    "original_file_content": "from typing import List, Literal, Optional, Type, Union\n\nfrom pydantic import ConfigDict, Field, PositiveInt\n\nfrom inference.core.entities.requests.inference import (\n    KeypointsDetectionInferenceRequest,\n)\nfrom inference.core.env import (\n    HOSTED_DETECT_URL,\n    LOCAL_INFERENCE_API_URL,\n    WORKFLOWS_REMOTE_API_TARGET,\n    WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_BATCH_SIZE,\n    WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS,\n)\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.entities import StepExecutionMode\nfrom inference.core.workflows.core_steps.common.utils import (\n    add_inference_keypoints_to_sv_detections,\n    attach_parents_coordinates_to_batch_of_sv_detections,\n    attach_prediction_type_info_to_sv_detections_batch,\n    convert_inference_detections_batch_to_sv_detections,\n    filter_out_unwanted_classes_from_sv_detections_batch,\n)\nfrom inference.core.workflows.execution_engine.constants import INFERENCE_ID_KEY\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    BOOLEAN_KIND,\n    FLOAT_ZERO_TO_ONE_KIND,\n    IMAGE_KIND,\n    INFERENCE_ID_KIND,\n    INTEGER_KIND,\n    KEYPOINT_DETECTION_PREDICTION_KIND,\n    LIST_OF_VALUES_KIND,\n    ROBOFLOW_MODEL_ID_KIND,\n    ROBOFLOW_PROJECT_KIND,\n    FloatZeroToOne,\n    ImageInputField,\n    RoboflowModelField,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\nfrom inference_sdk import InferenceConfiguration, InferenceHTTPClient\n\nLONG_DESCRIPTION = \"\"\"\nRun inference on a keypoint detection model hosted on or uploaded to Roboflow.\n\nYou can query any model that is private to your account, or any public model available \non [Roboflow Universe](https://universe.roboflow.com).\n\nYou will need to set your Roboflow API key in your Inference environment to use this \nblock. To learn more about setting your Roboflow API key, [refer to the Inference \ndocumentation](https://inference.roboflow.com/quickstart/configure_api_key/).\n\"\"\"\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Keypoint Detection Model\",\n            \"version\": \"v2\",\n            \"short_description\": \"Predict skeletons on objects.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"model\",\n            \"search_keywords\": [\"yolo\"],\n            \"ui_manifest\": {\n                \"section\": \"model\",\n                \"icon\": \"far fa-chart-network\",\n                \"blockPriority\": 4,\n                \"inference\": True,\n            },\n        },\n        protected_namespaces=(),\n    )\n    type: Literal[\"roboflow_core/roboflow_keypoint_detection_model@v2\"]\n    images: Selector(kind=[IMAGE_KIND]) = ImageInputField\n    model_id: Union[Selector(kind=[ROBOFLOW_MODEL_ID_KIND]), str] = RoboflowModelField\n    confidence: Union[\n        FloatZeroToOne,\n        Selector(kind=[FLOAT_ZERO_TO_ONE_KIND]),\n    ] = Field(\n        default=0.4,\n        description=\"Confidence threshold for predictions.\",\n        examples=[0.3, \"$inputs.confidence_threshold\"],\n    )\n    keypoint_confidence: Union[\n        FloatZeroToOne,\n        Selector(kind=[FLOAT_ZERO_TO_ONE_KIND]),\n    ] = Field(\n        default=0.0,\n        description=\"Confidence threshold to predict a keypoint as visible.\",\n        examples=[0.3, \"$inputs.keypoint_confidence\"],\n    )\n    class_filter: Union[Optional[List[str]], Selector(kind=[LIST_OF_VALUES_KIND])] = (\n        Field(\n            default=None,\n            description=\"List of accepted classes. Classes must exist in the model's training set.\",\n            examples=[[\"a\", \"b\", \"c\"], \"$inputs.class_filter\"],\n        )\n    )\n    iou_threshold: Union[\n        FloatZeroToOne,\n        Selector(kind=[FLOAT_ZERO_TO_ONE_KIND]),\n    ] = Field(\n        default=0.3,\n        description=\"Minimum overlap threshold between boxes to combine them into a single detection, used in NMS. [Learn more](https://blog.roboflow.com/how-to-code-non-maximum-suppression-nms-in-plain-numpy/).\",\n        examples=[0.4, \"$inputs.iou_threshold\"],\n    )\n    max_detections: Union[PositiveInt, Selector(kind=[INTEGER_KIND])] = Field(\n        default=300,\n        description=\"Maximum number of detections to return.\",\n        examples=[300, \"$inputs.max_detections\"],\n    )\n    class_agnostic_nms: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=False,\n        description=\"Boolean flag to specify if NMS is to be used in class-agnostic mode.\",\n        examples=[True, \"$inputs.class_agnostic_nms\"],\n    )\n    max_candidates: Union[PositiveInt, Selector(kind=[INTEGER_KIND])] = Field(\n        default=3000,\n        description=\"Maximum number of candidates as NMS input to be taken into account.\",\n        examples=[3000, \"$inputs.max_candidates\"],\n    )\n    disable_active_learning: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=True,\n        description=\"Boolean flag to disable project-level active learning for this block.\",\n        examples=[True, \"$inputs.disable_active_learning\"],\n    )\n    active_learning_target_dataset: Union[\n        Selector(kind=[ROBOFLOW_PROJECT_KIND]), Optional[str]\n    ] = Field(\n        default=None,\n        description=\"Target dataset for active learning, if enabled.\",\n        examples=[\"my_project\", \"$inputs.al_target_project\"],\n    )\n\n    @classmethod\n    def get_compatible_task_types(cls) -> Optional[List[str]]:\n        return [\"keypoint-detection\"]\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return [\"images\"]\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=INFERENCE_ID_KEY, kind=[INFERENCE_ID_KIND]),\n            OutputDefinition(\n                name=\"predictions\", kind=[KEYPOINT_DETECTION_PREDICTION_KIND]\n            ),\n            OutputDefinition(name=\"model_id\", kind=[ROBOFLOW_MODEL_ID_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass RoboflowKeypointDetectionModelBlockV2(WorkflowBlock):\n\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"model_manager\", \"api_key\", \"step_execution_mode\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        model_id: str,\n        class_agnostic_nms: Optional[bool],\n        class_filter: Optional[List[str]],\n        confidence: Optional[float],\n        iou_threshold: Optional[float],\n        max_detections: Optional[int],\n        max_candidates: Optional[int],\n        keypoint_confidence: Optional[float],\n        disable_active_learning: Optional[bool],\n        active_learning_target_dataset: Optional[str],\n    ) -> BlockResult:\n        if self._step_execution_mode is StepExecutionMode.LOCAL:\n            return self.run_locally(\n                images=images,\n                model_id=model_id,\n                class_agnostic_nms=class_agnostic_nms,\n                class_filter=class_filter,\n                confidence=confidence,\n                iou_threshold=iou_threshold,\n                max_detections=max_detections,\n                max_candidates=max_candidates,\n                keypoint_confidence=keypoint_confidence,\n                disable_active_learning=disable_active_learning,\n                active_learning_target_dataset=active_learning_target_dataset,\n            )\n        elif self._step_execution_mode is StepExecutionMode.REMOTE:\n            return self.run_remotely(\n                images=images,\n                model_id=model_id,\n                class_agnostic_nms=class_agnostic_nms,\n                class_filter=class_filter,\n                confidence=confidence,\n                iou_threshold=iou_threshold,\n                max_detections=max_detections,\n                max_candidates=max_candidates,\n                keypoint_confidence=keypoint_confidence,\n                disable_active_learning=disable_active_learning,\n                active_learning_target_dataset=active_learning_target_dataset,\n            )\n        else:\n            raise ValueError(\n                f\"Unknown step execution mode: {self._step_execution_mode}\"\n            )\n\n    def run_locally(\n        self,\n        images: Batch[WorkflowImageData],\n        model_id: str,\n        class_agnostic_nms: Optional[bool],\n        class_filter: Optional[List[str]],\n        confidence: Optional[float],\n        iou_threshold: Optional[float],\n        max_detections: Optional[int],\n        max_candidates: Optional[int],\n        keypoint_confidence: Optional[float],\n        disable_active_learning: Optional[bool],\n        active_learning_target_dataset: Optional[str],\n    ) -> BlockResult:\n        inference_images = [i.to_inference_format(numpy_preferred=True) for i in images]\n        request = KeypointsDetectionInferenceRequest(\n            api_key=self._api_key,\n            model_id=model_id,\n            image=inference_images,\n            disable_active_learning=disable_active_learning,\n            active_learning_target_dataset=active_learning_target_dataset,\n            class_agnostic_nms=class_agnostic_nms,\n            class_filter=class_filter,\n            confidence=confidence,\n            iou_threshold=iou_threshold,\n            max_detections=max_detections,\n            max_candidates=max_candidates,\n            keypoint_confidence=keypoint_confidence,\n            source=\"workflow-execution\",\n        )\n        self._model_manager.add_model(\n            model_id=model_id,\n            api_key=self._api_key,\n        )\n        predictions = self._model_manager.infer_from_request_sync(\n            model_id=model_id, request=request\n        )\n        if not isinstance(predictions, list):\n            predictions = [predictions]\n        predictions = [\n            e.model_dump(by_alias=True, exclude_none=True) for e in predictions\n        ]\n        return self._post_process_result(\n            images=images,\n            predictions=predictions,\n            class_filter=class_filter,\n            model_id=model_id,\n        )\n\n    def run_remotely(\n        self,\n        images: Batch[Optional[WorkflowImageData]],\n        model_id: str,\n        class_agnostic_nms: Optional[bool],\n        class_filter: Optional[List[str]],\n        confidence: Optional[float],\n        iou_threshold: Optional[float],\n        max_detections: Optional[int],\n        max_candidates: Optional[int],\n        keypoint_confidence: Optional[float],\n        disable_active_learning: Optional[bool],\n        active_learning_target_dataset: Optional[str],\n    ) -> BlockResult:\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_DETECT_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        if WORKFLOWS_REMOTE_API_TARGET == \"hosted\":\n            client.select_api_v0()\n        client_config = InferenceConfiguration(\n            disable_active_learning=disable_active_learning,\n            active_learning_target_dataset=active_learning_target_dataset,\n            class_agnostic_nms=class_agnostic_nms,\n            class_filter=class_filter,\n            confidence_threshold=confidence,\n            iou_threshold=iou_threshold,\n            max_detections=max_detections,\n            max_candidates=max_candidates,\n            keypoint_confidence_threshold=keypoint_confidence,\n            max_batch_size=WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_BATCH_SIZE,\n            max_concurrent_requests=WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS,\n            source=\"workflow-execution\",\n        )\n        client.configure(inference_configuration=client_config)\n        inference_images = [i.base64_image for i in images]\n        predictions = client.infer(\n            inference_input=inference_images,\n            model_id=model_id,\n        )\n        if not isinstance(predictions, list):\n            predictions = [predictions]\n        return self._post_process_result(\n            images=images,\n            predictions=predictions,\n            class_filter=class_filter,\n            model_id=model_id,\n        )\n\n    def _post_process_result(\n        self,\n        images: Batch[WorkflowImageData],\n        predictions: List[dict],\n        class_filter: Optional[List[str]],\n        model_id: str,\n    ) -> BlockResult:\n        inference_ids = [p.get(INFERENCE_ID_KEY, None) for p in predictions]\n        detections = convert_inference_detections_batch_to_sv_detections(predictions)\n        for prediction, image_detections in zip(predictions, detections):\n            add_inference_keypoints_to_sv_detections(\n                inference_prediction=prediction[\"predictions\"],\n                detections=image_detections,\n            )\n        detections = attach_prediction_type_info_to_sv_detections_batch(\n            predictions=detections,\n            prediction_type=\"keypoint-detection\",\n        )\n        detections = filter_out_unwanted_classes_from_sv_detections_batch(\n            predictions=detections,\n            classes_to_accept=class_filter,\n        )\n        detections = attach_parents_coordinates_to_batch_of_sv_detections(\n            images=images,\n            predictions=detections,\n        )\n        return [\n            {\n                \"inference_id\": inference_id,\n                \"predictions\": image_detections,\n                \"model_id\": model_id,\n            }\n            for inference_id, image_detections in zip(inference_ids, detections)\n        ]\n",
    "patch": null
  },
  {
    "trace_id": "3e9e68c3-582f-41e8-9ac0-b20eb7a50da8",
    "function_name": "BlockManifest.get_compatible_task_types",
    "file_path": "inference/core/workflows/core_steps/models/roboflow/instance_segmentation/v2.py",
    "speedup_x": 0.1465493945850439,
    "review_quality": "medium",
    "pre_optimization_commit": "c20359386c628a08bde69f5f3f780cedd782c50c",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def get_compatible_task_types(cls) -> Optional[List[str]]:\n        return [\"instance-segmentation\"]\n",
    "optimized_function_code": "from typing import List, Optional\n\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nLONG_DESCRIPTION = \"\"\"\nRun inference on an instance segmentation model hosted on or uploaded to Roboflow.\n\nYou can query any model that is private to your account, or any public model available \non [Roboflow Universe](https://universe.roboflow.com).\n\nYou will need to set your Roboflow API key in your Inference environment to use this \nblock. To learn more about setting your Roboflow API key, [refer to the Inference \ndocumentation](https://inference.roboflow.com/quickstart/configure_api_key/).\n\"\"\"\n\n\n\n# Module-level constant to avoid reallocating the list literal on every call.\n_COMPATIBLE_TASK_TYPES: List[str] = [\"instance-segmentation\"]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_compatible_task_types(cls) -> Optional[List[str]]:\n        return _COMPATIBLE_TASK_TYPES.copy()",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/models/roboflow/instance_segmentation/v2.py\nfrom typing import List, Optional\n\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nLONG_DESCRIPTION = \"\"\"\nRun inference on an instance segmentation model hosted on or uploaded to Roboflow.\n\nYou can query any model that is private to your account, or any public model available \non [Roboflow Universe](https://universe.roboflow.com).\n\nYou will need to set your Roboflow API key in your Inference environment to use this \nblock. To learn more about setting your Roboflow API key, [refer to the Inference \ndocumentation](https://inference.roboflow.com/quickstart/configure_api_key/).\n\"\"\"\n\n\n\n# Module-level constant to avoid reallocating the list literal on every call.\n_COMPATIBLE_TASK_TYPES: List[str] = [\"instance-segmentation\"]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_compatible_task_types(cls) -> Optional[List[str]]:\n        return _COMPATIBLE_TASK_TYPES.copy()\n```",
    "optimized_function_only": "    def get_compatible_task_types(cls) -> Optional[List[str]]:\n        return _COMPATIBLE_TASK_TYPES.copy()",
    "original_file_content": "from typing import List, Literal, Optional, Type, Union\n\nfrom pydantic import ConfigDict, Field, PositiveInt\n\nfrom inference.core.entities.requests.inference import (\n    InstanceSegmentationInferenceRequest,\n)\nfrom inference.core.env import (\n    HOSTED_INSTANCE_SEGMENTATION_URL,\n    LOCAL_INFERENCE_API_URL,\n    WORKFLOWS_REMOTE_API_TARGET,\n    WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_BATCH_SIZE,\n    WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS,\n)\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.entities import StepExecutionMode\nfrom inference.core.workflows.core_steps.common.utils import (\n    attach_parents_coordinates_to_batch_of_sv_detections,\n    attach_prediction_type_info_to_sv_detections_batch,\n    convert_inference_detections_batch_to_sv_detections,\n    filter_out_unwanted_classes_from_sv_detections_batch,\n)\nfrom inference.core.workflows.execution_engine.constants import INFERENCE_ID_KEY\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    BOOLEAN_KIND,\n    FLOAT_ZERO_TO_ONE_KIND,\n    IMAGE_KIND,\n    INFERENCE_ID_KIND,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    INTEGER_KIND,\n    LIST_OF_VALUES_KIND,\n    ROBOFLOW_MODEL_ID_KIND,\n    ROBOFLOW_PROJECT_KIND,\n    STRING_KIND,\n    FloatZeroToOne,\n    ImageInputField,\n    RoboflowModelField,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\nfrom inference_sdk import InferenceConfiguration, InferenceHTTPClient\n\nLONG_DESCRIPTION = \"\"\"\nRun inference on an instance segmentation model hosted on or uploaded to Roboflow.\n\nYou can query any model that is private to your account, or any public model available \non [Roboflow Universe](https://universe.roboflow.com).\n\nYou will need to set your Roboflow API key in your Inference environment to use this \nblock. To learn more about setting your Roboflow API key, [refer to the Inference \ndocumentation](https://inference.roboflow.com/quickstart/configure_api_key/).\n\"\"\"\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Instance Segmentation Model\",\n            \"version\": \"v2\",\n            \"short_description\": \"Predict the shape, size, and location of objects.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"model\",\n            \"search_keywords\": [\"yolo\", \"rfdetr\", \"rf-detr\"],\n            \"ui_manifest\": {\n                \"section\": \"model\",\n                \"icon\": \"far fa-chart-network\",\n                \"blockPriority\": 1,\n                \"inference\": True,\n                \"popular\": True,\n            },\n        },\n        protected_namespaces=(),\n    )\n    type: Literal[\"roboflow_core/roboflow_instance_segmentation_model@v2\"]\n    images: Selector(kind=[IMAGE_KIND]) = ImageInputField\n    model_id: Union[Selector(kind=[ROBOFLOW_MODEL_ID_KIND]), str] = RoboflowModelField\n    confidence: Union[\n        FloatZeroToOne,\n        Selector(kind=[FLOAT_ZERO_TO_ONE_KIND]),\n    ] = Field(\n        default=0.4,\n        description=\"Confidence threshold for predictions.\",\n        examples=[0.3, \"$inputs.confidence_threshold\"],\n    )\n    class_filter: Union[Optional[List[str]], Selector(kind=[LIST_OF_VALUES_KIND])] = (\n        Field(\n            default=None,\n            description=\"List of accepted classes. Classes must exist in the model's training set.\",\n            examples=[[\"a\", \"b\", \"c\"], \"$inputs.class_filter\"],\n        )\n    )\n    iou_threshold: Union[\n        FloatZeroToOne,\n        Selector(kind=[FLOAT_ZERO_TO_ONE_KIND]),\n    ] = Field(\n        default=0.3,\n        description=\"Minimum overlap threshold between boxes to combine them into a single detection, used in NMS. [Learn more](https://blog.roboflow.com/how-to-code-non-maximum-suppression-nms-in-plain-numpy/).\",\n        examples=[0.4, \"$inputs.iou_threshold\"],\n    )\n    max_detections: Union[PositiveInt, Selector(kind=[INTEGER_KIND])] = Field(\n        default=300,\n        description=\"Maximum number of detections to return.\",\n        examples=[300, \"$inputs.max_detections\"],\n    )\n    class_agnostic_nms: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=False,\n        description=\"Boolean flag to specify if NMS is to be used in class-agnostic mode.\",\n        examples=[True, \"$inputs.class_agnostic_nms\"],\n    )\n    max_candidates: Union[PositiveInt, Selector(kind=[INTEGER_KIND])] = Field(\n        default=3000,\n        description=\"Maximum number of candidates as NMS input to be taken into account.\",\n        examples=[3000, \"$inputs.max_candidates\"],\n    )\n    mask_decode_mode: Union[\n        Literal[\"accurate\", \"tradeoff\", \"fast\"],\n        Selector(kind=[STRING_KIND]),\n    ] = Field(\n        default=\"accurate\",\n        description=\"Parameter of mask decoding in prediction post-processing.\",\n        examples=[\"accurate\", \"$inputs.mask_decode_mode\"],\n    )\n    tradeoff_factor: Union[\n        FloatZeroToOne,\n        Selector(kind=[FLOAT_ZERO_TO_ONE_KIND]),\n    ] = Field(\n        default=0.0,\n        description=\"Post-processing parameter to dictate tradeoff between fast and accurate.\",\n        examples=[0.3, \"$inputs.tradeoff_factor\"],\n    )\n    disable_active_learning: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=True,\n        description=\"Boolean flag to disable project-level active learning for this block.\",\n        examples=[True, \"$inputs.disable_active_learning\"],\n    )\n    active_learning_target_dataset: Union[\n        Selector(kind=[ROBOFLOW_PROJECT_KIND]), Optional[str]\n    ] = Field(\n        default=None,\n        description=\"Target dataset for active learning, if enabled.\",\n        examples=[\"my_project\", \"$inputs.al_target_project\"],\n    )\n\n    @classmethod\n    def get_compatible_task_types(cls) -> Optional[List[str]]:\n        return [\"instance-segmentation\"]\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return [\"images\"]\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=INFERENCE_ID_KEY, kind=[INFERENCE_ID_KIND]),\n            OutputDefinition(\n                name=\"predictions\",\n                kind=[INSTANCE_SEGMENTATION_PREDICTION_KIND],\n            ),\n            OutputDefinition(name=\"model_id\", kind=[ROBOFLOW_MODEL_ID_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass RoboflowInstanceSegmentationModelBlockV2(WorkflowBlock):\n\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"model_manager\", \"api_key\", \"step_execution_mode\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        model_id: str,\n        class_agnostic_nms: Optional[bool],\n        class_filter: Optional[List[str]],\n        confidence: Optional[float],\n        iou_threshold: Optional[float],\n        max_detections: Optional[int],\n        max_candidates: Optional[int],\n        mask_decode_mode: Literal[\"accurate\", \"tradeoff\", \"fast\"],\n        tradeoff_factor: Optional[float],\n        disable_active_learning: Optional[bool],\n        active_learning_target_dataset: Optional[str],\n    ) -> BlockResult:\n        if self._step_execution_mode is StepExecutionMode.LOCAL:\n            return self.run_locally(\n                images=images,\n                model_id=model_id,\n                class_agnostic_nms=class_agnostic_nms,\n                class_filter=class_filter,\n                confidence=confidence,\n                iou_threshold=iou_threshold,\n                max_detections=max_detections,\n                max_candidates=max_candidates,\n                mask_decode_mode=mask_decode_mode,\n                tradeoff_factor=tradeoff_factor,\n                disable_active_learning=disable_active_learning,\n                active_learning_target_dataset=active_learning_target_dataset,\n            )\n        elif self._step_execution_mode is StepExecutionMode.REMOTE:\n            return self.run_remotely(\n                images=images,\n                model_id=model_id,\n                class_agnostic_nms=class_agnostic_nms,\n                class_filter=class_filter,\n                confidence=confidence,\n                iou_threshold=iou_threshold,\n                max_detections=max_detections,\n                max_candidates=max_candidates,\n                mask_decode_mode=mask_decode_mode,\n                tradeoff_factor=tradeoff_factor,\n                disable_active_learning=disable_active_learning,\n                active_learning_target_dataset=active_learning_target_dataset,\n            )\n        else:\n            raise ValueError(\n                f\"Unknown step execution mode: {self._step_execution_mode}\"\n            )\n\n    def run_locally(\n        self,\n        images: Batch[WorkflowImageData],\n        model_id: str,\n        class_agnostic_nms: Optional[bool],\n        class_filter: Optional[List[str]],\n        confidence: Optional[float],\n        iou_threshold: Optional[float],\n        max_detections: Optional[int],\n        max_candidates: Optional[int],\n        mask_decode_mode: Literal[\"accurate\", \"tradeoff\", \"fast\"],\n        tradeoff_factor: Optional[float],\n        disable_active_learning: Optional[bool],\n        active_learning_target_dataset: Optional[str],\n    ) -> BlockResult:\n        inference_images = [i.to_inference_format(numpy_preferred=True) for i in images]\n        request = InstanceSegmentationInferenceRequest(\n            api_key=self._api_key,\n            model_id=model_id,\n            image=inference_images,\n            disable_active_learning=disable_active_learning,\n            active_learning_target_dataset=active_learning_target_dataset,\n            class_agnostic_nms=class_agnostic_nms,\n            class_filter=class_filter,\n            confidence=confidence,\n            iou_threshold=iou_threshold,\n            max_detections=max_detections,\n            max_candidates=max_candidates,\n            mask_decode_mode=mask_decode_mode,\n            tradeoff_factor=tradeoff_factor,\n            source=\"workflow-execution\",\n        )\n        self._model_manager.add_model(\n            model_id=model_id,\n            api_key=self._api_key,\n        )\n        predictions = self._model_manager.infer_from_request_sync(\n            model_id=model_id, request=request\n        )\n        if not isinstance(predictions, list):\n            predictions = [predictions]\n        predictions = [\n            e.model_dump(by_alias=True, exclude_none=True) for e in predictions\n        ]\n        return self._post_process_result(\n            images=images,\n            predictions=predictions,\n            class_filter=class_filter,\n            model_id=model_id,\n        )\n\n    def run_remotely(\n        self,\n        images: Batch[WorkflowImageData],\n        model_id: str,\n        class_agnostic_nms: Optional[bool],\n        class_filter: Optional[List[str]],\n        confidence: Optional[float],\n        iou_threshold: Optional[float],\n        max_detections: Optional[int],\n        max_candidates: Optional[int],\n        mask_decode_mode: Literal[\"accurate\", \"tradeoff\", \"fast\"],\n        tradeoff_factor: Optional[float],\n        disable_active_learning: Optional[bool],\n        active_learning_target_dataset: Optional[str],\n    ) -> BlockResult:\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_INSTANCE_SEGMENTATION_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        if WORKFLOWS_REMOTE_API_TARGET == \"hosted\":\n            client.select_api_v0()\n        client_config = InferenceConfiguration(\n            disable_active_learning=disable_active_learning,\n            active_learning_target_dataset=active_learning_target_dataset,\n            class_agnostic_nms=class_agnostic_nms,\n            class_filter=class_filter,\n            confidence_threshold=confidence,\n            iou_threshold=iou_threshold,\n            max_detections=max_detections,\n            max_candidates=max_candidates,\n            mask_decode_mode=mask_decode_mode,\n            tradeoff_factor=tradeoff_factor,\n            max_batch_size=WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_BATCH_SIZE,\n            max_concurrent_requests=WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS,\n            source=\"workflow-execution\",\n        )\n        client.configure(inference_configuration=client_config)\n        inference_images = [i.base64_image for i in images]\n        predictions = client.infer(\n            inference_input=inference_images,\n            model_id=model_id,\n        )\n        if not isinstance(predictions, list):\n            predictions = [predictions]\n        return self._post_process_result(\n            images=images,\n            predictions=predictions,\n            class_filter=class_filter,\n            model_id=model_id,\n        )\n\n    def _post_process_result(\n        self,\n        images: Batch[WorkflowImageData],\n        predictions: List[dict],\n        class_filter: Optional[List[str]],\n        model_id: str,\n    ) -> BlockResult:\n        inference_ids = [p.get(INFERENCE_ID_KEY, None) for p in predictions]\n        predictions = convert_inference_detections_batch_to_sv_detections(predictions)\n        predictions = attach_prediction_type_info_to_sv_detections_batch(\n            predictions=predictions,\n            prediction_type=\"instance-segmentation\",\n        )\n        predictions = filter_out_unwanted_classes_from_sv_detections_batch(\n            predictions=predictions,\n            classes_to_accept=class_filter,\n        )\n        predictions = attach_parents_coordinates_to_batch_of_sv_detections(\n            images=images,\n            predictions=predictions,\n        )\n        return [\n            {\n                \"inference_id\": inference_id,\n                \"predictions\": prediction,\n                \"model_id\": model_id,\n            }\n            for inference_id, prediction in zip(inference_ids, predictions)\n        ]\n",
    "patch": null
  },
  {
    "trace_id": "3ea04ac1-9a5a-4ae7-86e3-f9757fb85f78",
    "function_name": "BlockManifest.get_supported_model_variants",
    "file_path": "inference/core/workflows/core_steps/models/foundation/yolo_world/v1.py",
    "speedup_x": 0.28634958900618085,
    "review_quality": "medium",
    "pre_optimization_commit": "c20359386c628a08bde69f5f3f780cedd782c50c",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        return [\n            \"yolo_world/v2-s\",\n            \"yolo_world/v2-m\",\n            \"yolo_world/v2-l\",\n            \"yolo_world/v2-x\",\n            \"yolo_world/s\",\n            \"yolo_world/m\",\n            \"yolo_world/l\",\n            \"yolo_world/x\",\n        ]\n",
    "optimized_function_code": "from inference.core.workflows.prototypes.block import WorkflowBlockManifest\nfrom typing import List, Optional\n\nLONG_DESCRIPTION = \"\"\"\nRun YOLO-World, a zero-shot object detection model, on an image.\n\nYOLO-World accepts one or more text classes you want to identify in an image. The model \nreturns the location of objects that meet the specified class, if YOLO-World is able to \nidentify objects of that class.\n\nWe recommend experimenting with YOLO-World to evaluate the model on your use case \nbefore using this block in production. For example on how to effectively prompt \nYOLO-World, refer to the [Roboflow YOLO-World prompting \nguide](https://blog.roboflow.com/yolo-world-prompting-tips/).\n\"\"\"\n\n_SUPPORTED_MODEL_VARIANTS = [\n    \"yolo_world/v2-s\",\n    \"yolo_world/v2-m\",\n    \"yolo_world/v2-l\",\n    \"yolo_world/v2-x\",\n    \"yolo_world/s\",\n    \"yolo_world/m\",\n    \"yolo_world/l\",\n    \"yolo_world/x\",\n]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        return _SUPPORTED_MODEL_VARIANTS",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/models/foundation/yolo_world/v1.py\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\nfrom typing import List, Optional\n\nLONG_DESCRIPTION = \"\"\"\nRun YOLO-World, a zero-shot object detection model, on an image.\n\nYOLO-World accepts one or more text classes you want to identify in an image. The model \nreturns the location of objects that meet the specified class, if YOLO-World is able to \nidentify objects of that class.\n\nWe recommend experimenting with YOLO-World to evaluate the model on your use case \nbefore using this block in production. For example on how to effectively prompt \nYOLO-World, refer to the [Roboflow YOLO-World prompting \nguide](https://blog.roboflow.com/yolo-world-prompting-tips/).\n\"\"\"\n\n_SUPPORTED_MODEL_VARIANTS = [\n    \"yolo_world/v2-s\",\n    \"yolo_world/v2-m\",\n    \"yolo_world/v2-l\",\n    \"yolo_world/v2-x\",\n    \"yolo_world/s\",\n    \"yolo_world/m\",\n    \"yolo_world/l\",\n    \"yolo_world/x\",\n]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        return _SUPPORTED_MODEL_VARIANTS\n```",
    "optimized_function_only": "    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        return _SUPPORTED_MODEL_VARIANTS",
    "original_file_content": "from typing import List, Literal, Optional, Type, Union\n\nfrom pydantic import ConfigDict, Field\n\nfrom inference.core.entities.requests.yolo_world import YOLOWorldInferenceRequest\nfrom inference.core.env import (\n    HOSTED_CORE_MODEL_URL,\n    LOCAL_INFERENCE_API_URL,\n    WORKFLOWS_REMOTE_API_TARGET,\n    WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS,\n)\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.entities import StepExecutionMode\nfrom inference.core.workflows.core_steps.common.utils import (\n    attach_parents_coordinates_to_batch_of_sv_detections,\n    attach_prediction_type_info_to_sv_detections_batch,\n    convert_inference_detections_batch_to_sv_detections,\n    load_core_model,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    FLOAT_ZERO_TO_ONE_KIND,\n    IMAGE_KIND,\n    LIST_OF_VALUES_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    STRING_KIND,\n    FloatZeroToOne,\n    ImageInputField,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\nfrom inference_sdk import InferenceConfiguration, InferenceHTTPClient\nfrom inference_sdk.http.utils.iterables import make_batches\n\nLONG_DESCRIPTION = \"\"\"\nRun YOLO-World, a zero-shot object detection model, on an image.\n\nYOLO-World accepts one or more text classes you want to identify in an image. The model \nreturns the location of objects that meet the specified class, if YOLO-World is able to \nidentify objects of that class.\n\nWe recommend experimenting with YOLO-World to evaluate the model on your use case \nbefore using this block in production. For example on how to effectively prompt \nYOLO-World, refer to the [Roboflow YOLO-World prompting \nguide](https://blog.roboflow.com/yolo-world-prompting-tips/).\n\"\"\"\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"YOLO-World Model\",\n            \"version\": \"v1\",\n            \"short_description\": \"Run a zero-shot object detection model.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"model\",\n            \"ui_manifest\": {\n                \"section\": \"model\",\n                \"icon\": \"fal fa-atom\",\n                \"blockPriority\": 8,\n                \"inference\": True,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/yolo_world_model@v1\", \"YoloWorldModel\", \"YoloWorld\"]\n    images: Selector(kind=[IMAGE_KIND]) = ImageInputField\n    class_names: Union[Selector(kind=[LIST_OF_VALUES_KIND]), List[str]] = Field(\n        description=\"One or more classes that you want YOLO-World to detect. The model accepts any string as an input, though does best with short descriptions of common objects.\",\n        examples=[[\"person\", \"car\", \"license plate\"], \"$inputs.class_names\"],\n    )\n    version: Union[\n        Literal[\n            \"v2-s\",\n            \"v2-m\",\n            \"v2-l\",\n            \"v2-x\",\n            \"s\",\n            \"m\",\n            \"l\",\n            \"x\",\n        ],\n        Selector(kind=[STRING_KIND]),\n    ] = Field(\n        default=\"v2-s\",\n        description=\"Variant of YoloWorld model\",\n        examples=[\"v2-s\", \"$inputs.variant\"],\n    )\n    confidence: Union[\n        Optional[FloatZeroToOne],\n        Selector(kind=[FLOAT_ZERO_TO_ONE_KIND]),\n    ] = Field(\n        default=0.005,\n        description=\"Confidence threshold for detections\",\n        examples=[0.005, \"$inputs.confidence\"],\n    )\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return [\"images\"]\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(\n                name=\"predictions\", kind=[OBJECT_DETECTION_PREDICTION_KIND]\n            ),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n    @classmethod\n    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        return [\n            \"yolo_world/v2-s\",\n            \"yolo_world/v2-m\",\n            \"yolo_world/v2-l\",\n            \"yolo_world/v2-x\",\n            \"yolo_world/s\",\n            \"yolo_world/m\",\n            \"yolo_world/l\",\n            \"yolo_world/x\",\n        ]\n\n\nclass YoloWorldModelBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"model_manager\", \"api_key\", \"step_execution_mode\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        class_names: List[str],\n        version: str,\n        confidence: Optional[float],\n    ) -> BlockResult:\n        if self._step_execution_mode is StepExecutionMode.LOCAL:\n            return self.run_locally(\n                images=images,\n                class_names=class_names,\n                version=version,\n                confidence=confidence,\n            )\n        elif self._step_execution_mode is StepExecutionMode.REMOTE:\n            return self.run_remotely(\n                images=images,\n                class_names=class_names,\n                version=version,\n                confidence=confidence,\n            )\n        else:\n            raise ValueError(\n                f\"Unknown step execution mode: {self._step_execution_mode}\"\n            )\n\n    def run_locally(\n        self,\n        images: Batch[WorkflowImageData],\n        class_names: List[str],\n        version: str,\n        confidence: Optional[float],\n    ) -> BlockResult:\n        predictions = []\n        for single_image in images:\n            inference_request = YOLOWorldInferenceRequest(\n                image=single_image.to_inference_format(numpy_preferred=True),\n                yolo_world_version_id=version,\n                confidence=confidence,\n                text=class_names,\n                api_key=self._api_key,\n            )\n            yolo_world_model_id = load_core_model(\n                model_manager=self._model_manager,\n                inference_request=inference_request,\n                core_model=\"yolo_world\",\n            )\n            prediction = self._model_manager.infer_from_request_sync(\n                yolo_world_model_id, inference_request\n            )\n            predictions.append(prediction.model_dump(by_alias=True, exclude_none=True))\n        return self._post_process_result(\n            images=images,\n            predictions=predictions,\n        )\n\n    def run_remotely(\n        self,\n        images: Batch[WorkflowImageData],\n        class_names: List[str],\n        version: str,\n        confidence: Optional[float],\n    ) -> BlockResult:\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_CORE_MODEL_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        if WORKFLOWS_REMOTE_API_TARGET == \"hosted\":\n            client.select_api_v0()\n        configuration = InferenceConfiguration(\n            max_concurrent_requests=WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS,\n        )\n        client.configure(inference_configuration=configuration)\n        if WORKFLOWS_REMOTE_API_TARGET == \"hosted\":\n            client.select_api_v0()\n        inference_images = [i.to_inference_format() for i in images]\n        image_sub_batches = list(\n            make_batches(\n                iterable=inference_images,\n                batch_size=WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS,\n            )\n        )\n        predictions = []\n        for sub_batch in image_sub_batches:\n            sub_batch_predictions = client.infer_from_yolo_world(\n                inference_input=[i[\"value\"] for i in sub_batch],\n                class_names=class_names,\n                model_version=version,\n                confidence=confidence,\n            )\n            predictions.extend(sub_batch_predictions)\n        return self._post_process_result(images=images, predictions=predictions)\n\n    def _post_process_result(\n        self,\n        images: Batch[WorkflowImageData],\n        predictions: List[dict],\n    ) -> BlockResult:\n        predictions = convert_inference_detections_batch_to_sv_detections(predictions)\n        predictions = attach_prediction_type_info_to_sv_detections_batch(\n            predictions=predictions,\n            prediction_type=\"object-detection\",\n        )\n        predictions = attach_parents_coordinates_to_batch_of_sv_detections(\n            images=images,\n            predictions=predictions,\n        )\n        return [{\"predictions\": prediction} for prediction in predictions]\n",
    "patch": null
  },
  {
    "trace_id": "85d35d22-806c-4bbc-ad6f-913d3d160e67",
    "function_name": "BlockManifest.get_supported_model_variants",
    "file_path": "inference/core/workflows/core_steps/models/foundation/segment_anything3/v3.py",
    "speedup_x": 0.12582793991335078,
    "review_quality": "medium",
    "pre_optimization_commit": "c20359386c628a08bde69f5f3f780cedd782c50c",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        return [\"sam3/sam3_final\"]\n",
    "optimized_function_code": "from typing import List, Optional\n\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nSHORT_DESCRIPTION = \"Run SAM3 with text prompts for zero-shot segmentation.\"\n\nLONG_DESCRIPTION = \"\"\"\nRun Segment Anything 3 (SAM3), a zero-shot instance segmentation model, on an image.\n\nYou can use text prompts for open-vocabulary segmentation - just specify class names and SAM3 will\nsegment those objects in the image.\n\nThis block supports two output formats:\n- **rle** (default): Returns masks in RLE (Run-Length Encoding) format, which is more memory-efficient\n- **polygons**: Returns polygon coordinates for each mask\n\nRLE format is recommended for high-resolution images or workflows with many detections.\n\"\"\"\n\n\n\n# Module-level constant to avoid reconstructing the list literal on each call.\n_SUPPORTED_MODEL_VARIANTS: List[str] = [\"sam3/sam3_final\"]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        return _SUPPORTED_MODEL_VARIANTS.copy()",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/models/foundation/segment_anything3/v3.py\nfrom typing import List, Optional\n\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nSHORT_DESCRIPTION = \"Run SAM3 with text prompts for zero-shot segmentation.\"\n\nLONG_DESCRIPTION = \"\"\"\nRun Segment Anything 3 (SAM3), a zero-shot instance segmentation model, on an image.\n\nYou can use text prompts for open-vocabulary segmentation - just specify class names and SAM3 will\nsegment those objects in the image.\n\nThis block supports two output formats:\n- **rle** (default): Returns masks in RLE (Run-Length Encoding) format, which is more memory-efficient\n- **polygons**: Returns polygon coordinates for each mask\n\nRLE format is recommended for high-resolution images or workflows with many detections.\n\"\"\"\n\n\n\n# Module-level constant to avoid reconstructing the list literal on each call.\n_SUPPORTED_MODEL_VARIANTS: List[str] = [\"sam3/sam3_final\"]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        return _SUPPORTED_MODEL_VARIANTS.copy()\n```",
    "optimized_function_only": "    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        return _SUPPORTED_MODEL_VARIANTS.copy()",
    "original_file_content": "from typing import List, Literal, Optional, Type, Union\n\nimport numpy as np\nimport requests\nimport supervision as sv\nfrom pycocotools import mask as mask_utils\nfrom pydantic import ConfigDict, Field, model_validator, validator\n\nfrom inference.core import logger\nfrom inference.core.entities.requests.sam3 import Sam3Prompt, Sam3SegmentationRequest\nfrom inference.core.entities.responses.inference import (\n    InferenceResponseImage,\n    InstanceSegmentationInferenceResponse,\n    InstanceSegmentationPrediction,\n    InstanceSegmentationRLEPrediction,\n    Point,\n)\nfrom inference.core.env import (\n    API_BASE_URL,\n    HOSTED_CORE_MODEL_URL,\n    LOCAL_INFERENCE_API_URL,\n    ROBOFLOW_INTERNAL_SERVICE_NAME,\n    ROBOFLOW_INTERNAL_SERVICE_SECRET,\n    SAM3_EXEC_MODE,\n    WORKFLOWS_REMOTE_API_TARGET,\n)\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.roboflow_api import build_roboflow_api_headers\nfrom inference.core.workflows.core_steps.common.entities import StepExecutionMode\nfrom inference.core.workflows.core_steps.common.utils import (\n    attach_parents_coordinates_to_batch_of_sv_detections,\n    attach_prediction_type_info_to_sv_detections_batch,\n)\nfrom inference.core.workflows.execution_engine.constants import (\n    DETECTION_ID_KEY,\n    IMAGE_DIMENSIONS_KEY,\n    PARENT_ID_KEY,\n    RLE_MASK_KEY_IN_SV_DETECTIONS,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    BOOLEAN_KIND,\n    FLOAT_KIND,\n    IMAGE_KIND,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    LIST_OF_VALUES_KIND,\n    RLE_INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    ROBOFLOW_MODEL_ID_KIND,\n    STRING_KIND,\n    ImageInputField,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\nfrom inference_sdk import InferenceHTTPClient\n\nSHORT_DESCRIPTION = \"Run SAM3 with text prompts for zero-shot segmentation.\"\n\nLONG_DESCRIPTION = \"\"\"\nRun Segment Anything 3 (SAM3), a zero-shot instance segmentation model, on an image.\n\nYou can use text prompts for open-vocabulary segmentation - just specify class names and SAM3 will\nsegment those objects in the image.\n\nThis block supports two output formats:\n- **rle** (default): Returns masks in RLE (Run-Length Encoding) format, which is more memory-efficient\n- **polygons**: Returns polygon coordinates for each mask\n\nRLE format is recommended for high-resolution images or workflows with many detections.\n\"\"\"\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"SAM 3\",\n            \"version\": \"v3\",\n            \"short_description\": SHORT_DESCRIPTION,\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"model\",\n            \"search_keywords\": [\n                \"Sam\",\n                \"SAM3\",\n                \"segment anything\",\n                \"segment anything 3\",\n            ],\n            \"ui_manifest\": {\n                \"section\": \"model\",\n                \"icon\": \"fa-solid fa-eye\",\n                \"blockPriority\": 9.48,\n                \"needsGPU\": True,\n                \"inference\": True,\n            },\n        },\n        protected_namespaces=(),\n    )\n\n    type: Literal[\"roboflow_core/sam3@v3\"]\n    images: Selector(kind=[IMAGE_KIND]) = ImageInputField\n\n    model_id: Union[Selector(kind=[ROBOFLOW_MODEL_ID_KIND]), Optional[str]] = Field(\n        default=\"sam3/sam3_final\",\n        description=\"model version. You only need to change this for fine tuned sam3 models.\",\n        examples=[\n            \"sam3/sam3_final\",\n            \"$inputs.model_variant\",\n        ],\n    )\n\n    class_names: Optional[\n        Union[List[str], str, Selector(kind=[LIST_OF_VALUES_KIND, STRING_KIND])]\n    ] = Field(\n        title=\"Class Names\",\n        default=None,\n        description=\"List of classes to recognise\",\n        examples=[[\"car\", \"person\"], \"$inputs.classes\"],\n    )\n    confidence: Union[Selector(kind=[FLOAT_KIND]), float] = Field(\n        default=0.5,\n        title=\"Confidence Threshold\",\n        description=\"Minimum confidence threshold for predicted masks\",\n        examples=[0.3],\n    )\n\n    per_class_confidence: Optional[\n        Union[List[float], Selector(kind=[LIST_OF_VALUES_KIND])]\n    ] = Field(\n        default=None,\n        title=\"Per-Class Confidence\",\n        description=\"List of confidence thresholds per class (must match class_names length)\",\n        examples=[[0.3, 0.5, 0.7]],\n    )\n\n    apply_nms: Union[Selector(kind=[BOOLEAN_KIND]), bool] = Field(\n        default=True,\n        title=\"Apply NMS\",\n        description=\"Whether to apply Non-Maximum Suppression across prompts\",\n    )\n\n    nms_iou_threshold: Union[Selector(kind=[FLOAT_KIND]), float] = Field(\n        default=0.9,\n        title=\"NMS IoU Threshold\",\n        description=\"IoU threshold for cross-prompt NMS. Must be in [0.0, 1.0]\",\n        examples=[0.5, 0.9],\n    )\n\n    output_format: Literal[\"rle\", \"polygons\"] = Field(\n        default=\"rle\",\n        title=\"Output Format\",\n        description=\"'rle' returns efficient RLE encoding (recommended), 'polygons' returns polygon coordinates\",\n        examples=[\"rle\", \"polygons\"],\n    )\n\n    @validator(\"nms_iou_threshold\")\n    def _validate_nms_iou_threshold(cls, v):\n        if isinstance(v, (int, float)) and (v < 0.0 or v > 1.0):\n            raise ValueError(\"nms_iou_threshold must be between 0.0 and 1.0\")\n        return v\n\n    @model_validator(mode=\"after\")\n    def _validate_per_class_confidence_length(self) -> \"BlockManifest\":\n        if not isinstance(self.per_class_confidence, list):\n            return self\n\n        # Determine class_names length, handling both list and comma-separated string\n        if isinstance(self.class_names, list):\n            class_names_length = len(self.class_names)\n        elif isinstance(self.class_names, str):\n            class_names_length = len(self.class_names.split(\",\"))\n        else:\n            return self\n\n        if len(self.per_class_confidence) != class_names_length:\n            raise ValueError(\n                f\"per_class_confidence length ({len(self.per_class_confidence)}) \"\n                f\"must match class_names length ({class_names_length})\"\n            )\n        return self\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return [\"images\", \"boxes\"]\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(\n                name=\"predictions\",\n                kind=[\n                    # RLE first since it's the default and more efficient\n                    RLE_INSTANCE_SEGMENTATION_PREDICTION_KIND,\n                    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n                ],\n            ),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n    @classmethod\n    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        return [\"sam3/sam3_final\"]\n\n\nclass SegmentAnything3BlockV3(WorkflowBlock):\n\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"model_manager\", \"api_key\", \"step_execution_mode\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        model_id: str,\n        class_names: Optional[Union[List[str], str]],\n        confidence: float,\n        per_class_confidence: Optional[List[float]] = None,\n        apply_nms: bool = True,\n        nms_iou_threshold: float = 0.9,\n        output_format: Literal[\"rle\", \"polygons\"] = \"rle\",\n    ) -> BlockResult:\n\n        if isinstance(class_names, str):\n            class_names = class_names.split(\",\")\n        elif isinstance(class_names, list):\n            class_names = class_names\n        else:\n            raise ValueError(f\"Invalid class names type: {type(class_names)}\")\n\n        if SAM3_EXEC_MODE == \"remote\":\n            logger.debug(\"Running SAM3 v3 via inference proxy (SAM3_EXEC_MODE=remote)\")\n            return self.run_via_request(\n                images=images,\n                class_names=class_names,\n                confidence=confidence,\n                per_class_confidence=per_class_confidence,\n                apply_nms=apply_nms,\n                nms_iou_threshold=nms_iou_threshold,\n                output_format=output_format,\n            )\n        elif self._step_execution_mode is StepExecutionMode.LOCAL:\n            logger.debug(f\"Running SAM3 v3 locally with output_format={output_format}\")\n            return self.run_locally(\n                images=images,\n                model_id=model_id,\n                class_names=class_names,\n                confidence=confidence,\n                per_class_confidence=per_class_confidence,\n                apply_nms=apply_nms,\n                nms_iou_threshold=nms_iou_threshold,\n                output_format=output_format,\n            )\n        elif self._step_execution_mode is StepExecutionMode.REMOTE:\n            logger.debug(\"Running SAM3 v3 remotely via SDK\")\n            return self.run_remotely(\n                images=images,\n                model_id=model_id,\n                class_names=class_names,\n                confidence=confidence,\n                per_class_confidence=per_class_confidence,\n                apply_nms=apply_nms,\n                nms_iou_threshold=nms_iou_threshold,\n                output_format=output_format,\n            )\n        else:\n            raise ValueError(\n                f\"Unknown step execution mode: {self._step_execution_mode}\"\n            )\n\n    def run_locally(\n        self,\n        images: Batch[WorkflowImageData],\n        model_id: str,\n        class_names: Optional[List[str]],\n        confidence: float,\n        per_class_confidence: Optional[List[float]] = None,\n        apply_nms: bool = True,\n        nms_iou_threshold: float = 0.9,\n        output_format: Literal[\"rle\", \"polygons\"] = \"rle\",\n    ) -> BlockResult:\n        if class_names is None:\n            class_names = []\n        if len(class_names) == 0:\n            class_names.append(None)\n\n        self._model_manager.add_model(\n            model_id=model_id,\n            api_key=self._api_key,\n        )\n\n        # Determine format to request from model\n        model_format = \"rle\" if output_format == \"rle\" else \"polygon\"\n\n        all_detections = []\n        for single_image in images:\n            # Build unified prompt list: one per class name\n            unified_prompts: List[Sam3Prompt] = []\n            for idx, class_name in enumerate(class_names):\n                prompt_thresh = (\n                    per_class_confidence[idx] if per_class_confidence else None\n                )\n                unified_prompts.append(\n                    Sam3Prompt(\n                        type=\"text\", text=class_name, output_prob_thresh=prompt_thresh\n                    )\n                )\n\n            # Single batched request with all prompts\n            inference_request = Sam3SegmentationRequest(\n                image=single_image.to_inference_format(numpy_preferred=True),\n                model_id=model_id,\n                api_key=self._api_key,\n                prompts=unified_prompts,\n                output_prob_thresh=confidence,\n                nms_iou_threshold=nms_iou_threshold if apply_nms else None,\n                format=model_format,\n            )\n\n            sam3_response = self._model_manager.infer_from_request_sync(\n                model_id, inference_request\n            )\n\n            image_width = single_image.numpy_image.shape[1]\n            image_height = single_image.numpy_image.shape[0]\n\n            if output_format == \"rle\":\n                # RLE output: build sv.Detections with RLE in data\n                detections = self._convert_rle_response_to_sv_detections(\n                    sam3_response=sam3_response,\n                    class_names=class_names,\n                    confidence=confidence,\n                    image_height=image_height,\n                    image_width=image_width,\n                )\n            else:\n                # Polygon output: use existing conversion\n                inference_response = self._convert_polygon_response_to_inference_format(\n                    sam3_response=sam3_response,\n                    class_names=class_names,\n                    confidence=confidence,\n                    image_height=image_height,\n                    image_width=image_width,\n                )\n                detections = sv.Detections.from_inference(inference_response)\n                detections[DETECTION_ID_KEY] = np.array(\n                    [p.detection_id for p in inference_response.predictions]\n                )\n                detections[PARENT_ID_KEY] = np.array([\"\"] * len(detections))\n                detections[IMAGE_DIMENSIONS_KEY] = np.array(\n                    [[image_height, image_width]] * len(detections)\n                )\n\n            all_detections.append(detections)\n\n        return self._post_process_result(\n            images=images,\n            predictions=all_detections,\n            output_format=output_format,\n        )\n\n    def run_remotely(\n        self,\n        images: Batch[WorkflowImageData],\n        model_id: str,\n        class_names: Optional[List[str]],\n        confidence: float,\n        per_class_confidence: Optional[List[float]] = None,\n        apply_nms: bool = True,\n        nms_iou_threshold: float = 0.9,\n        output_format: Literal[\"rle\", \"polygons\"] = \"rle\",\n    ) -> BlockResult:\n        if class_names is None:\n            class_names = []\n        if len(class_names) == 0:\n            class_names.append(None)\n\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_CORE_MODEL_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        if WORKFLOWS_REMOTE_API_TARGET == \"hosted\":\n            client.select_api_v0()\n\n        model_format = \"rle\" if output_format == \"rle\" else \"polygon\"\n\n        all_detections = []\n        for single_image in images:\n            http_prompts: List[dict] = []\n            for idx, class_name in enumerate(class_names):\n                prompt_data = {\"type\": \"text\", \"text\": class_name}\n                if per_class_confidence is not None:\n                    prompt_data[\"output_prob_thresh\"] = per_class_confidence[idx]\n                http_prompts.append(prompt_data)\n\n            resp_json = client.sam3_concept_segment(\n                inference_input=single_image.base64_image,\n                prompts=http_prompts,\n                model_id=model_id,\n                output_prob_thresh=confidence,\n                nms_iou_threshold=nms_iou_threshold if apply_nms else None,\n                format=model_format,\n            )\n\n            image_width = single_image.numpy_image.shape[1]\n            image_height = single_image.numpy_image.shape[0]\n\n            if output_format == \"rle\":\n                detections = self._convert_rle_json_response_to_sv_detections(\n                    resp_json=resp_json,\n                    class_names=class_names,\n                    confidence=confidence,\n                    image_height=image_height,\n                    image_width=image_width,\n                )\n            else:\n                inference_response = (\n                    self._convert_polygon_json_response_to_inference_format(\n                        resp_json=resp_json,\n                        class_names=class_names,\n                        confidence=confidence,\n                        image_height=image_height,\n                        image_width=image_width,\n                    )\n                )\n                detections = sv.Detections.from_inference(inference_response)\n                detections[DETECTION_ID_KEY] = np.array(\n                    [p.detection_id for p in inference_response.predictions]\n                )\n                detections[PARENT_ID_KEY] = np.array([\"\"] * len(detections))\n                detections[IMAGE_DIMENSIONS_KEY] = np.array(\n                    [[image_height, image_width]] * len(detections)\n                )\n\n            all_detections.append(detections)\n\n        return self._post_process_result(\n            images=images,\n            predictions=all_detections,\n            output_format=output_format,\n        )\n\n    def run_via_request(\n        self,\n        images: Batch[WorkflowImageData],\n        class_names: Optional[List[str]],\n        confidence: float,\n        per_class_confidence: Optional[List[float]] = None,\n        apply_nms: bool = True,\n        nms_iou_threshold: float = 0.9,\n        output_format: Literal[\"rle\", \"polygons\"] = \"rle\",\n    ) -> BlockResult:\n        if class_names is None:\n            class_names = []\n        if len(class_names) == 0:\n            class_names.append(None)\n\n        endpoint = f\"{API_BASE_URL}/inferenceproxy/seg-preview\"\n        api_key = self._api_key\n        model_format = \"rle\" if output_format == \"rle\" else \"polygon\"\n\n        all_detections = []\n        for single_image in images:\n            # Build unified prompt list payloads for HTTP\n            http_prompts: List[dict] = []\n            for idx, class_name in enumerate(class_names):\n                prompt_data = {\"type\": \"text\", \"text\": class_name}\n                if per_class_confidence is not None:\n                    prompt_data[\"output_prob_thresh\"] = per_class_confidence[idx]\n                http_prompts.append(prompt_data)\n\n            # Prepare image for remote API (base64)\n            http_image = {\"type\": \"base64\", \"value\": single_image.base64_image}\n\n            payload = {\n                \"image\": http_image,\n                \"prompts\": http_prompts,\n                \"output_prob_thresh\": confidence,\n                \"nms_iou_threshold\": nms_iou_threshold if apply_nms else None,\n                \"format\": model_format,\n            }\n\n            try:\n                headers = {\"Content-Type\": \"application/json\"}\n                if ROBOFLOW_INTERNAL_SERVICE_NAME:\n                    headers[\"X-Roboflow-Internal-Service-Name\"] = (\n                        ROBOFLOW_INTERNAL_SERVICE_NAME\n                    )\n                if ROBOFLOW_INTERNAL_SERVICE_SECRET:\n                    headers[\"X-Roboflow-Internal-Service-Secret\"] = (\n                        ROBOFLOW_INTERNAL_SERVICE_SECRET\n                    )\n\n                headers = build_roboflow_api_headers(explicit_headers=headers)\n\n                response = requests.post(\n                    f\"{endpoint}?api_key={api_key}\",\n                    json=payload,\n                    headers=headers,\n                    timeout=60,\n                )\n                response.raise_for_status()\n                resp_json = response.json()\n            except Exception as e:\n                raise Exception(f\"SAM3 request failed: {e}\")\n\n            image_width = single_image.numpy_image.shape[1]\n            image_height = single_image.numpy_image.shape[0]\n\n            if output_format == \"rle\":\n                # RLE output\n                detections = self._convert_rle_json_response_to_sv_detections(\n                    resp_json=resp_json,\n                    class_names=class_names,\n                    confidence=confidence,\n                    image_height=image_height,\n                    image_width=image_width,\n                )\n            else:\n                # Polygon output\n                inference_response = (\n                    self._convert_polygon_json_response_to_inference_format(\n                        resp_json=resp_json,\n                        class_names=class_names,\n                        confidence=confidence,\n                        image_height=image_height,\n                        image_width=image_width,\n                    )\n                )\n                detections = sv.Detections.from_inference(inference_response)\n                detections[DETECTION_ID_KEY] = np.array(\n                    [p.detection_id for p in inference_response.predictions]\n                )\n                detections[PARENT_ID_KEY] = np.array([\"\"] * len(detections))\n                detections[IMAGE_DIMENSIONS_KEY] = np.array(\n                    [[image_height, image_width]] * len(detections)\n                )\n\n            all_detections.append(detections)\n\n        return self._post_process_result(\n            images=images,\n            predictions=all_detections,\n            output_format=output_format,\n        )\n\n    @staticmethod\n    def build_rle_prediction(\n        rle: dict,\n        bbox: List[float],\n        pred_confidence: float,\n        class_name: str,\n        class_id: int,\n    ) -> InstanceSegmentationRLEPrediction:\n        x, y, w, h = bbox\n        return InstanceSegmentationRLEPrediction(\n            **{\n                \"x\": x + w / 2,\n                \"y\": y + h / 2,\n                \"width\": w,\n                \"height\": h,\n                \"confidence\": pred_confidence,\n                \"class\": class_name,\n                \"class_id\": class_id,\n                \"rle\": rle,\n            }\n        )\n\n    @staticmethod\n    def build_rle_detections(\n        predictions: List[InstanceSegmentationRLEPrediction],\n        image_height: int,\n        image_width: int,\n    ) -> sv.Detections:\n        if len(predictions) == 0:\n            return sv.Detections.empty()\n\n        xyxy_list = []\n        for p in predictions:\n            x1 = p.x - p.width / 2\n            y1 = p.y - p.height / 2\n            x2 = p.x + p.width / 2\n            y2 = p.y + p.height / 2\n            xyxy_list.append([x1, y1, x2, y2])\n\n        detections = sv.Detections(\n            xyxy=np.array(xyxy_list, dtype=np.float32),\n            confidence=np.array([p.confidence for p in predictions], dtype=np.float32),\n            class_id=np.array([p.class_id for p in predictions], dtype=int),\n        )\n        detections[\"class_name\"] = np.array([p.class_name for p in predictions])\n        detections[DETECTION_ID_KEY] = np.array([p.detection_id for p in predictions])\n        detections[PARENT_ID_KEY] = np.array([p.parent_id or \"\" for p in predictions])\n        detections[IMAGE_DIMENSIONS_KEY] = np.array(\n            [[image_height, image_width]] * len(detections)\n        )\n        detections[RLE_MASK_KEY_IN_SV_DETECTIONS] = np.array(\n            [p.rle for p in predictions], dtype=object\n        )\n\n        return detections\n\n    def _convert_rle_response_to_sv_detections(\n        self,\n        sam3_response,\n        class_names: List[Optional[str]],\n        confidence: float,\n        image_height: int,\n        image_width: int,\n    ) -> sv.Detections:\n        predictions: List[InstanceSegmentationRLEPrediction] = []\n\n        for prompt_result in sam3_response.prompt_results:\n            idx = prompt_result.prompt_index\n            class_name = class_names[idx] if idx < len(class_names) else \"foreground\"\n            if class_name is None:\n                class_name = \"foreground\"\n\n            for prediction in prompt_result.predictions:\n                if prediction.confidence < confidence:\n                    continue\n\n                rle = prediction.masks\n                if not isinstance(rle, dict) or \"counts\" not in rle:\n                    continue\n\n                bbox = mask_utils.toBbox(rle)\n                pred = self.build_rle_prediction(\n                    rle=rle,\n                    bbox=bbox,\n                    pred_confidence=prediction.confidence,\n                    class_name=class_name,\n                    class_id=idx,\n                )\n                predictions.append(pred)\n\n        return self.build_rle_detections(predictions, image_height, image_width)\n\n    def _convert_rle_json_response_to_sv_detections(\n        self,\n        resp_json: dict,\n        class_names: List[Optional[str]],\n        confidence: float,\n        image_height: int,\n        image_width: int,\n    ) -> sv.Detections:\n        predictions: List[InstanceSegmentationRLEPrediction] = []\n\n        for prompt_result in resp_json.get(\"prompt_results\", []):\n            idx = prompt_result.get(\"prompt_index\", 0)\n            class_name = class_names[idx] if idx < len(class_names) else \"foreground\"\n            if class_name is None:\n                class_name = \"foreground\"\n\n            for prediction in prompt_result.get(\"predictions\", []):\n                pred_confidence = prediction.get(\"confidence\", 0.0)\n                if pred_confidence < confidence:\n                    continue\n\n                rle = prediction.get(\"masks\")\n                if not isinstance(rle, dict) or \"counts\" not in rle:\n                    continue\n\n                bbox = mask_utils.toBbox(rle)\n                pred = self.build_rle_prediction(\n                    rle=rle,\n                    bbox=bbox,\n                    pred_confidence=pred_confidence,\n                    class_name=class_name,\n                    class_id=idx,\n                )\n                predictions.append(pred)\n\n        return self.build_rle_detections(predictions, image_height, image_width)\n\n    @staticmethod\n    def build_polygon_prediction(\n        mask: List[List[float]],\n        pred_confidence: float,\n        class_name: str,\n        class_id: int,\n    ) -> Optional[InstanceSegmentationPrediction]:\n        if len(mask) < 3:\n            return None\n\n        x_coords = [coord[0] for coord in mask]\n        y_coords = [coord[1] for coord in mask]\n        min_x, max_x = np.min(x_coords), np.max(x_coords)\n        min_y, max_y = np.min(y_coords), np.max(y_coords)\n\n        return InstanceSegmentationPrediction(\n            **{\n                \"x\": (min_x + max_x) / 2,\n                \"y\": (min_y + max_y) / 2,\n                \"width\": max_x - min_x,\n                \"height\": max_y - min_y,\n                \"points\": [Point(x=p[0], y=p[1]) for p in mask],\n                \"confidence\": pred_confidence,\n                \"class\": class_name,\n                \"class_id\": class_id,\n            }\n        )\n\n    def _convert_polygon_response_to_inference_format(\n        self,\n        sam3_response,\n        class_names: List[Optional[str]],\n        confidence: float,\n        image_height: int,\n        image_width: int,\n    ) -> InstanceSegmentationInferenceResponse:\n        predictions: List[InstanceSegmentationPrediction] = []\n\n        for prompt_result in sam3_response.prompt_results:\n            idx = prompt_result.prompt_index\n            class_name = class_names[idx] if idx < len(class_names) else \"foreground\"\n            if class_name is None:\n                class_name = \"foreground\"\n\n            for prediction in prompt_result.predictions:\n                if prediction.confidence < confidence:\n                    continue\n\n                for mask in prediction.masks:\n                    pred = self.build_polygon_prediction(\n                        mask, prediction.confidence, class_name, idx\n                    )\n                    if pred:\n                        predictions.append(pred)\n\n        return InstanceSegmentationInferenceResponse(\n            predictions=predictions,\n            image=InferenceResponseImage(width=image_width, height=image_height),\n        )\n\n    def _convert_polygon_json_response_to_inference_format(\n        self,\n        resp_json: dict,\n        class_names: List[Optional[str]],\n        confidence: float,\n        image_height: int,\n        image_width: int,\n    ) -> InstanceSegmentationInferenceResponse:\n        predictions: List[InstanceSegmentationPrediction] = []\n\n        for prompt_result in resp_json.get(\"prompt_results\", []):\n            idx = prompt_result.get(\"prompt_index\", 0)\n            class_name = class_names[idx] if idx < len(class_names) else \"foreground\"\n            if class_name is None:\n                class_name = \"foreground\"\n\n            for prediction in prompt_result.get(\"predictions\", []):\n                pred_confidence = prediction.get(\"confidence\", 0.0)\n                if pred_confidence < confidence:\n                    continue\n\n                for mask in prediction.get(\"masks\", []):\n                    pred = self.build_polygon_prediction(\n                        mask, pred_confidence, class_name, idx\n                    )\n                    if pred:\n                        predictions.append(pred)\n\n        return InstanceSegmentationInferenceResponse(\n            predictions=predictions,\n            image=InferenceResponseImage(width=image_width, height=image_height),\n        )\n\n    @staticmethod\n    def decode_rle_masks(rle_list: np.ndarray) -> np.ndarray:\n        masks = [mask_utils.decode(rle).astype(bool) for rle in rle_list]\n        return np.array(masks)\n\n    def _decode_and_cache_rle_masks(\n        self,\n        predictions: List[sv.Detections],\n    ) -> List[sv.Detections]:\n        for detection in predictions:\n            if (\n                detection.mask is None\n                and RLE_MASK_KEY_IN_SV_DETECTIONS in detection.data\n            ):\n                rle_masks = detection.data[RLE_MASK_KEY_IN_SV_DETECTIONS]\n                detection.mask = self.decode_rle_masks(rle_masks)\n        return predictions\n\n    def _post_process_result(\n        self,\n        images: Batch[WorkflowImageData],\n        predictions: List[sv.Detections],\n        output_format: Literal[\"rle\", \"polygons\"],\n    ) -> BlockResult:\n        prediction_type = (\n            \"rle-instance-segmentation\"\n            if output_format == \"rle\"\n            else \"instance-segmentation\"\n        )\n        predictions = attach_prediction_type_info_to_sv_detections_batch(\n            predictions=predictions,\n            prediction_type=prediction_type,\n        )\n        predictions = attach_parents_coordinates_to_batch_of_sv_detections(\n            images=images,\n            predictions=predictions,\n        )\n        if output_format == \"rle\":\n            predictions = self._decode_and_cache_rle_masks(predictions)\n        return [{\"predictions\": prediction} for prediction in predictions]\n",
    "patch": null
  },
  {
    "trace_id": "ec5f6a3f-19cb-45c9-9eb8-5b261e8fc24b",
    "function_name": "BlockManifest.get_supported_model_variants",
    "file_path": "inference/core/workflows/core_steps/models/foundation/moondream2/v1.py",
    "speedup_x": 0.14974510264785262,
    "review_quality": "medium",
    "pre_optimization_commit": "c20359386c628a08bde69f5f3f780cedd782c50c",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        return [\"moondream2/moondream2_2b_jul24\"]\n",
    "optimized_function_code": "from typing import List, Optional\n\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\n_SUPPORTED_MODEL_VARIANTS: List[str] = [\"moondream2/moondream2_2b_jul24\"]\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        return _SUPPORTED_MODEL_VARIANTS.copy()",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/models/foundation/moondream2/v1.py\nfrom typing import List, Optional\n\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\n_SUPPORTED_MODEL_VARIANTS: List[str] = [\"moondream2/moondream2_2b_jul24\"]\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        return _SUPPORTED_MODEL_VARIANTS.copy()\n```",
    "optimized_function_only": "    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        return _SUPPORTED_MODEL_VARIANTS.copy()",
    "original_file_content": "import json\nfrom typing import List, Literal, Optional, Type, Union\n\nfrom pydantic import ConfigDict, Field\n\nfrom inference.core.entities.requests.moondream2 import Moondream2InferenceRequest\nfrom inference.core.env import (\n    HOSTED_CORE_MODEL_URL,\n    LOCAL_INFERENCE_API_URL,\n    WORKFLOWS_REMOTE_API_TARGET,\n)\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.entities import StepExecutionMode\nfrom inference.core.workflows.core_steps.common.utils import (\n    attach_parents_coordinates_to_batch_of_sv_detections,\n    attach_prediction_type_info_to_sv_detections_batch,\n    convert_inference_detections_batch_to_sv_detections,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    DICTIONARY_KIND,\n    FLOAT_ZERO_TO_ONE_KIND,\n    IMAGE_KIND,\n    LIST_OF_VALUES_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    ROBOFLOW_MODEL_ID_KIND,\n    STRING_KIND,\n    FloatZeroToOne,\n    ImageInputField,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\nfrom inference_sdk import InferenceHTTPClient\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    # SmolVLM needs an image and a text prompt.\n    images: Selector(kind=[IMAGE_KIND]) = ImageInputField\n    prompt: Union[\n        Selector(kind=[STRING_KIND]),\n        str,\n    ] = Field(\n        description=\"Optional text prompt to provide additional context to Moondream2.\",\n        examples=[\"my prompt\", \"$inputs.prompt\"],\n        default=None,\n    )\n\n    # Standard model configuration for UI, schema, etc.\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Moondream2\",\n            \"version\": \"v1\",\n            \"short_description\": \"Run Moondream2 on an image.\",\n            \"long_description\": \"This workflow block runs Moondream2, a multimodal vision-language model. You can use this block to run zero-shot object detection.\",\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"model\",\n            \"search_keywords\": [\n                \"Moondream2\",\n                \"moondream\",\n                \"vision language model\",\n                \"VLM\",\n                \"object detection\",\n            ],\n            \"ui_manifest\": {\n                \"section\": \"model\",\n                \"icon\": \"fal fa-atom\",\n                \"blockPriority\": 5.5,\n            },\n        },\n        protected_namespaces=(),\n    )\n    type: Literal[\"roboflow_core/moondream2@v1\"]\n\n    model_version: Union[Selector(kind=[ROBOFLOW_MODEL_ID_KIND]), str] = Field(\n        default=\"moondream2/moondream2_2b_jul24\",\n        description=\"The Moondream2 model to be used for inference.\",\n        examples=[\"moondream2/moondream2_2b_jul24\", \"moondream2/moondream2-2b\"],\n    )\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return [\"images\"]\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(\n                name=\"predictions\", kind=[OBJECT_DETECTION_PREDICTION_KIND]\n            ),\n        ]\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        # Only images can be passed in as a list/batch\n        return [\"images\"]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n    @classmethod\n    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        return [\"moondream2/moondream2_2b_jul24\"]\n\n\nclass Moondream2BlockV1(WorkflowBlock):\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"model_manager\", \"api_key\", \"step_execution_mode\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n    ) -> BlockResult:\n        if self._step_execution_mode == StepExecutionMode.LOCAL:\n            return self.run_locally(\n                images=images,\n                model_version=model_version,\n                prompt=prompt,\n            )\n        elif self._step_execution_mode == StepExecutionMode.REMOTE:\n            return self.run_remotely(\n                images=images,\n                model_version=model_version,\n                prompt=prompt,\n            )\n        else:\n            raise ValueError(\n                f\"Unknown step execution mode: {self._step_execution_mode}\"\n            )\n\n    def run_remotely(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n    ) -> BlockResult:\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_CORE_MODEL_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        if WORKFLOWS_REMOTE_API_TARGET == \"hosted\":\n            client.select_api_v0()\n\n        prompt = prompt or \"\"\n        predictions = []\n        for image in images:\n            result = client.infer_lmm(\n                inference_input=image.base64_image,\n                model_id=model_version,\n                prompt=prompt,\n                model_id_in_path=True,\n            )\n            predictions.append(result)\n\n        return self._post_process_result(images=images, predictions=predictions)\n\n    def run_locally(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n    ) -> BlockResult:\n        # Convert each image to the format required by the model.\n        inference_images = [\n            i.to_inference_format(numpy_preferred=False) for i in images\n        ]\n\n        # Use the provided prompt (or an empty string if None) for every image.\n        prompt = prompt or \"\"\n\n        prompts = [prompt] * len(inference_images)\n\n        # Register Moondream2 with the model manager.\n        self._model_manager.add_model(model_id=model_version, api_key=self._api_key)\n\n        predictions = []\n        for image, single_prompt in zip(inference_images, prompts):\n            request = Moondream2InferenceRequest(\n                api_key=self._api_key,\n                model_id=model_version,\n                image=image,\n                text=[],\n                prompt=single_prompt,\n            )\n            # Run inference.\n            prediction = self._model_manager.infer_from_request_sync(\n                model_id=model_version, request=request\n            )\n            predictions.append(prediction.model_dump(by_alias=True, exclude_none=True))\n\n        return self._post_process_result(images=images, predictions=predictions)\n\n    def _post_process_result(\n        self,\n        images: Batch[WorkflowImageData],\n        predictions: List[dict],\n    ) -> BlockResult:\n        predictions = convert_inference_detections_batch_to_sv_detections(predictions)\n        predictions = attach_prediction_type_info_to_sv_detections_batch(\n            predictions=predictions,\n            prediction_type=\"object-detection\",\n        )\n        predictions = attach_parents_coordinates_to_batch_of_sv_detections(\n            images=images,\n            predictions=predictions,\n        )\n        return [{\"predictions\": prediction} for prediction in predictions]\n",
    "patch": null
  },
  {
    "trace_id": "6df4e97b-b43f-4cd0-8381-480aeddf13c0",
    "function_name": "BlockManifest.get_supported_model_variants",
    "file_path": "inference/core/workflows/core_steps/models/foundation/gaze/v1.py",
    "speedup_x": 0.21482246171298922,
    "review_quality": "high",
    "pre_optimization_commit": "c20359386c628a08bde69f5f3f780cedd782c50c",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        return [\"gaze/L2CS\"]\n",
    "optimized_function_code": "from typing import List, Optional\n\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nLONG_DESCRIPTION = \"\"\"\nRun L2CS Gaze detection model on faces in images.\n\nThis block can:\n1. Detect faces in images and estimate their gaze direction\n2. Estimate gaze direction on pre-cropped face images\n\nThe gaze direction is represented by yaw and pitch angles in degrees.\n\"\"\"\n\n\n\n# Module-level cached list to avoid reallocating the literal on every call.\n# We return a shallow copy so callers receive a new list instance (behavior preserved).\n_SUPPORTED_MODEL_VARIANTS: List[str] = [\"gaze/L2CS\"]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        return _SUPPORTED_MODEL_VARIANTS.copy()",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/models/foundation/gaze/v1.py\nfrom typing import List, Optional\n\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nLONG_DESCRIPTION = \"\"\"\nRun L2CS Gaze detection model on faces in images.\n\nThis block can:\n1. Detect faces in images and estimate their gaze direction\n2. Estimate gaze direction on pre-cropped face images\n\nThe gaze direction is represented by yaw and pitch angles in degrees.\n\"\"\"\n\n\n\n# Module-level cached list to avoid reallocating the literal on every call.\n# We return a shallow copy so callers receive a new list instance (behavior preserved).\n_SUPPORTED_MODEL_VARIANTS: List[str] = [\"gaze/L2CS\"]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        return _SUPPORTED_MODEL_VARIANTS.copy()\n```",
    "optimized_function_only": "    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        return _SUPPORTED_MODEL_VARIANTS.copy()",
    "original_file_content": "from typing import List, Literal, Optional, Tuple, Type, Union\n\nimport numpy as np\nimport supervision as sv\nfrom pydantic import ConfigDict, Field\n\nfrom inference.core.entities.requests.gaze import GazeDetectionInferenceRequest\nfrom inference.core.env import (\n    HOSTED_CORE_MODEL_URL,\n    LOCAL_INFERENCE_API_URL,\n    WORKFLOWS_REMOTE_API_TARGET,\n)\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.entities import StepExecutionMode\nfrom inference.core.workflows.core_steps.common.utils import (\n    add_inference_keypoints_to_sv_detections,\n    attach_parents_coordinates_to_batch_of_sv_detections,\n    attach_prediction_type_info_to_sv_detections_batch,\n    convert_inference_detections_batch_to_sv_detections,\n    load_core_model,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    BOOLEAN_KIND,\n    FLOAT_KIND,\n    IMAGE_KIND,\n    KEYPOINT_DETECTION_PREDICTION_KIND,\n    ImageInputField,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\nfrom inference_sdk import InferenceHTTPClient\n\nLONG_DESCRIPTION = \"\"\"\nRun L2CS Gaze detection model on faces in images.\n\nThis block can:\n1. Detect faces in images and estimate their gaze direction\n2. Estimate gaze direction on pre-cropped face images\n\nThe gaze direction is represented by yaw and pitch angles in degrees.\n\"\"\"\n\n\ndef convert_gaze_detections_to_sv_detections_and_angles(\n    images: Batch[WorkflowImageData],\n    gaze_predictions: List[dict],\n) -> Tuple[List[sv.Detections], List[List[float]], List[List[float]]]:\n    \"\"\"Convert gaze detection results to supervision detections and angle lists.\"\"\"\n    face_predictions = []\n    yaw_degrees = []\n    pitch_degrees = []\n\n    for single_image, predictions in zip(images, gaze_predictions):\n        height, width = single_image.numpy_image.shape[:2]\n\n        # Format predictions for this image\n        image_face_preds = {\n            \"predictions\": [],\n            \"image\": {\"width\": width, \"height\": height},\n        }\n        batch_yaw = []\n        batch_pitch = []\n\n        for p in predictions:  # predictions is already a list\n            p_dict = p.model_dump(by_alias=True, exclude_none=True)\n            for pred in p_dict[\"predictions\"]:\n                face = pred[\"face\"]\n\n                # Face detection with landmarks\n                face_pred = {\n                    \"x\": face[\"x\"],\n                    \"y\": face[\"y\"],\n                    \"width\": face[\"width\"],\n                    \"height\": face[\"height\"],\n                    \"confidence\": face[\"confidence\"],\n                    \"class\": \"face\",\n                    \"class_id\": 0,\n                    \"keypoints\": [\n                        {\n                            \"x\": l[\"x\"],\n                            \"y\": l[\"y\"],\n                            \"confidence\": face[\"confidence\"],\n                            \"class\": str(i),\n                            \"class_id\": i,\n                        }\n                        for i, l in enumerate(face[\"landmarks\"])\n                    ],\n                }\n\n                image_face_preds[\"predictions\"].append(face_pred)\n\n                # Store angles in degrees\n                batch_yaw.append(pred[\"yaw\"] * 180 / np.pi)\n                batch_pitch.append(pred[\"pitch\"] * 180 / np.pi)\n\n        face_predictions.append(image_face_preds)\n        yaw_degrees.append(batch_yaw)\n        pitch_degrees.append(batch_pitch)\n\n    # Process predictions\n    face_preds = convert_inference_detections_batch_to_sv_detections(face_predictions)\n\n    # Add keypoints to supervision detections\n    for prediction, detections in zip(face_predictions, face_preds):\n        add_inference_keypoints_to_sv_detections(\n            inference_prediction=prediction[\"predictions\"],\n            detections=detections,\n        )\n\n    face_preds = attach_prediction_type_info_to_sv_detections_batch(\n        predictions=face_preds,\n        prediction_type=\"facial-landmark\",\n    )\n    face_preds = attach_parents_coordinates_to_batch_of_sv_detections(\n        images=images,\n        predictions=face_preds,\n    )\n\n    return face_preds, yaw_degrees, pitch_degrees\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Gaze Detection\",\n            \"version\": \"v1\",\n            \"short_description\": \"Detect faces and estimate gaze direction\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"model\",\n            \"search_keywords\": [\"gaze\", \"face\"],\n            \"ui_manifest\": {\n                \"section\": \"model\",\n                \"icon\": \"far fa-eyes\",\n                \"blockPriority\": 13.5,\n            },\n        },\n        protected_namespaces=(),\n    )\n\n    type: Literal[\"roboflow_core/gaze@v1\"]\n    images: Selector(kind=[IMAGE_KIND]) = ImageInputField\n    do_run_face_detection: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=True,\n        description=\"Whether to run face detection. Set to False if input images are pre-cropped face images.\",\n    )\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return [\"images\"]\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(\n                name=\"face_predictions\",\n                kind=[KEYPOINT_DETECTION_PREDICTION_KIND],\n                description=\"Facial landmark predictions\",\n            ),\n            OutputDefinition(\n                name=\"yaw_degrees\",\n                kind=[FLOAT_KIND],\n                description=\"Yaw angle in degrees (-180 to 180, negative is left)\",\n            ),\n            OutputDefinition(\n                name=\"pitch_degrees\",\n                kind=[FLOAT_KIND],\n                description=\"Pitch angle in degrees (-90 to 90, negative is down)\",\n            ),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n    @classmethod\n    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        return [\"gaze/L2CS\"]\n\n\nclass GazeBlockV1(WorkflowBlock):\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"model_manager\", \"api_key\", \"step_execution_mode\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        do_run_face_detection: bool,\n    ) -> BlockResult:\n        if self._step_execution_mode is StepExecutionMode.LOCAL:\n            return self.run_locally(\n                images=images,\n                do_run_face_detection=do_run_face_detection,\n            )\n        elif self._step_execution_mode is StepExecutionMode.REMOTE:\n            return self.run_remotely(\n                images=images,\n                do_run_face_detection=do_run_face_detection,\n            )\n        else:\n            raise ValueError(\n                f\"Unsupported step execution mode: {self._step_execution_mode}\"\n            )\n\n    def run_remotely(\n        self,\n        images: Batch[WorkflowImageData],\n        do_run_face_detection: bool,\n    ) -> BlockResult:\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_CORE_MODEL_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        if WORKFLOWS_REMOTE_API_TARGET == \"hosted\":\n            client.select_api_v0()\n        else:\n            client.select_api_v1()\n\n        inference_images = [i.base64_image for i in images]\n        predictions = client.detect_gazes(inference_input=inference_images)\n\n        if not isinstance(predictions, list):\n            predictions = [predictions]\n\n        # Process remote predictions into the expected format\n        return self._process_remote_predictions(\n            images=images,\n            predictions=predictions,\n        )\n\n    def _process_remote_predictions(\n        self,\n        images: Batch[WorkflowImageData],\n        predictions: List[dict],\n    ) -> BlockResult:\n        \"\"\"Process predictions from remote execution into the expected format.\"\"\"\n        face_predictions = []\n        yaw_degrees = []\n        pitch_degrees = []\n\n        for single_image, prediction in zip(images, predictions):\n            height, width = single_image.numpy_image.shape[:2]\n\n            image_face_preds = {\n                \"predictions\": [],\n                \"image\": {\"width\": width, \"height\": height},\n            }\n            batch_yaw = []\n            batch_pitch = []\n\n            for pred in prediction.get(\"predictions\", []):\n                face = pred.get(\"face\", {})\n\n                face_pred = {\n                    \"x\": face.get(\"x\", 0),\n                    \"y\": face.get(\"y\", 0),\n                    \"width\": face.get(\"width\", 0),\n                    \"height\": face.get(\"height\", 0),\n                    \"confidence\": face.get(\"confidence\", 0),\n                    \"class\": \"face\",\n                    \"class_id\": 0,\n                    \"keypoints\": [\n                        {\n                            \"x\": l.get(\"x\", 0),\n                            \"y\": l.get(\"y\", 0),\n                            \"confidence\": face.get(\"confidence\", 0),\n                            \"class\": str(i),\n                            \"class_id\": i,\n                        }\n                        for i, l in enumerate(face.get(\"landmarks\", []))\n                    ],\n                }\n\n                image_face_preds[\"predictions\"].append(face_pred)\n\n                # Store angles in degrees (remote already returns radians)\n                batch_yaw.append(pred.get(\"yaw\", 0) * 180 / np.pi)\n                batch_pitch.append(pred.get(\"pitch\", 0) * 180 / np.pi)\n\n            face_predictions.append(image_face_preds)\n            yaw_degrees.append(batch_yaw)\n            pitch_degrees.append(batch_pitch)\n\n        # Process predictions\n        face_preds = convert_inference_detections_batch_to_sv_detections(\n            face_predictions\n        )\n\n        # Add keypoints to supervision detections\n        for prediction, detections in zip(face_predictions, face_preds):\n            add_inference_keypoints_to_sv_detections(\n                inference_prediction=prediction[\"predictions\"],\n                detections=detections,\n            )\n\n        face_preds = attach_prediction_type_info_to_sv_detections_batch(\n            predictions=face_preds,\n            prediction_type=\"facial-landmark\",\n        )\n        face_preds = attach_parents_coordinates_to_batch_of_sv_detections(\n            images=images,\n            predictions=face_preds,\n        )\n\n        return [\n            {\n                \"face_predictions\": face_pred,\n                \"yaw_degrees\": yaw,\n                \"pitch_degrees\": pitch,\n            }\n            for face_pred, yaw, pitch in zip(face_preds, yaw_degrees, pitch_degrees)\n        ]\n\n    def run_locally(\n        self,\n        images: Batch[WorkflowImageData],\n        do_run_face_detection: bool,\n    ) -> BlockResult:\n        predictions = []\n\n        for single_image in images:\n            inference_request = GazeDetectionInferenceRequest(\n                image=single_image.to_inference_format(numpy_preferred=True),\n                do_run_face_detection=do_run_face_detection,\n                api_key=self._api_key,\n            )\n            gaze_model_id = load_core_model(\n                model_manager=self._model_manager,\n                inference_request=inference_request,\n                core_model=\"gaze\",\n            )\n            prediction = self._model_manager.infer_from_request_sync(\n                gaze_model_id, inference_request\n            )\n            predictions.append(prediction)\n\n        # Convert predictions to supervision format and get angles\n        face_preds, yaw_degrees, pitch_degrees = (\n            convert_gaze_detections_to_sv_detections_and_angles(\n                images=images,\n                gaze_predictions=predictions,\n            )\n        )\n\n        return [\n            {\n                \"face_predictions\": face_pred,\n                \"yaw_degrees\": yaw,\n                \"pitch_degrees\": pitch,\n            }\n            for face_pred, yaw, pitch in zip(face_preds, yaw_degrees, pitch_degrees)\n        ]\n",
    "patch": null
  },
  {
    "trace_id": "2e5f8ffc-2db7-46bf-981b-fdba5bcf81f8",
    "function_name": "BlockManifest.get_supported_model_variants",
    "file_path": "inference/core/workflows/core_steps/models/foundation/easy_ocr/v1.py",
    "speedup_x": 0.3066705454545455,
    "review_quality": "high",
    "pre_optimization_commit": "c20359386c628a08bde69f5f3f780cedd782c50c",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        return [\n            \"easy_ocr/english_g2\",\n            \"easy_ocr/japanese_g2\",\n            \"easy_ocr/kannada_g2\",\n            \"easy_ocr/korean_g2\",\n            \"easy_ocr/latin_g2\",\n            \"easy_ocr/telugu_g2\",\n            \"easy_ocr/zh_sim_g2\",\n        ]\n",
    "optimized_function_code": "# These are the displayed languages in the UI dropdown\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\nfrom typing import List, Literal, Optional\n\nLANGUAGES = Literal[\n    \"English\",\n    \"Japanese\",\n    \"Kannada\",\n    \"Korean\",\n    \"Latin\",\n    \"Telugu\",\n    \"Simplified Chinese\",\n]\n\nLONG_DESCRIPTION = \"\"\"\n Retrieve the characters in an image using EasyOCR Optical Character Recognition (OCR).\n\nThis block returns the text within an image.\n\nYou may want to use this block in combination with a detections-based block (i.e.\nObjectDetectionBlock). An object detection model could isolate specific regions from an\nimage (i.e. a shipping container ID in a logistics use case) for further processing.\nYou can then use a DynamicCropBlock to crop the region of interest before running OCR.\n\nUsing a detections model then cropping detections allows you to isolate your analysis\non particular regions of an image.\n\nNote that EasyOCR has limitations running within containers on Apple Silicon.\n\"\"\"\n\n_SUPPORTED_MODEL_VARIANTS = [\n    \"easy_ocr/english_g2\",\n    \"easy_ocr/japanese_g2\",\n    \"easy_ocr/kannada_g2\",\n    \"easy_ocr/korean_g2\",\n    \"easy_ocr/latin_g2\",\n    \"easy_ocr/telugu_g2\",\n    \"easy_ocr/zh_sim_g2\",\n]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        return _SUPPORTED_MODEL_VARIANTS",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/models/foundation/easy_ocr/v1.py\n# These are the displayed languages in the UI dropdown\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\nfrom typing import List, Literal, Optional\n\nLANGUAGES = Literal[\n    \"English\",\n    \"Japanese\",\n    \"Kannada\",\n    \"Korean\",\n    \"Latin\",\n    \"Telugu\",\n    \"Simplified Chinese\",\n]\n\nLONG_DESCRIPTION = \"\"\"\n Retrieve the characters in an image using EasyOCR Optical Character Recognition (OCR).\n\nThis block returns the text within an image.\n\nYou may want to use this block in combination with a detections-based block (i.e.\nObjectDetectionBlock). An object detection model could isolate specific regions from an\nimage (i.e. a shipping container ID in a logistics use case) for further processing.\nYou can then use a DynamicCropBlock to crop the region of interest before running OCR.\n\nUsing a detections model then cropping detections allows you to isolate your analysis\non particular regions of an image.\n\nNote that EasyOCR has limitations running within containers on Apple Silicon.\n\"\"\"\n\n_SUPPORTED_MODEL_VARIANTS = [\n    \"easy_ocr/english_g2\",\n    \"easy_ocr/japanese_g2\",\n    \"easy_ocr/kannada_g2\",\n    \"easy_ocr/korean_g2\",\n    \"easy_ocr/latin_g2\",\n    \"easy_ocr/telugu_g2\",\n    \"easy_ocr/zh_sim_g2\",\n]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        return _SUPPORTED_MODEL_VARIANTS\n```",
    "optimized_function_only": "    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        return _SUPPORTED_MODEL_VARIANTS",
    "original_file_content": "import hashlib\nfrom typing import Dict, List, Literal, Optional, Tuple, Type, Union\nfrom uuid import uuid4\n\nimport numpy as np\nimport supervision as sv\nfrom pydantic import ConfigDict, Field\n\nfrom inference.core.cache.lru_cache import LRUCache\nfrom inference.core.entities.requests.easy_ocr import EasyOCRInferenceRequest\nfrom inference.core.env import (\n    HOSTED_CORE_MODEL_URL,\n    LOCAL_INFERENCE_API_URL,\n    WORKFLOWS_REMOTE_API_TARGET,\n    WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_BATCH_SIZE,\n    WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS,\n)\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.entities import StepExecutionMode\nfrom inference.core.workflows.core_steps.common.utils import (\n    load_core_model,\n    post_process_ocr_result,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    IMAGE_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    PARENT_ID_KIND,\n    PREDICTION_TYPE_KIND,\n    STRING_KIND,\n    ImageInputField,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\nfrom inference_sdk import InferenceHTTPClient\nfrom inference_sdk.http.entities import InferenceConfiguration\n\n# These are the displayed languages in the UI dropdown\nLANGUAGES = Literal[\n    \"English\",\n    \"Japanese\",\n    \"Kannada\",\n    \"Korean\",\n    \"Latin\",\n    \"Telugu\",\n    \"Simplified Chinese\",\n]\n\n# Dictionary of displayed_language: (model, language_code)\n# This is not an extensive list of supported languages, more codes can be added\nMODELS: Dict[str, Tuple[str, List[str]]] = {\n    \"English\": (\"english_g2\", [\"en\"]),\n    \"Japanese\": (\"japanese_g2\", [\"en\", \"ja\"]),\n    \"Kannada\": (\"kannada_g2\", [\"en\", \"kn\"]),\n    \"Korean\": (\"korean_g2\", [\"en\", \"ko\"]),\n    \"Latin\": (\"latin_g2\", [\"en\", \"la\", \"es\", \"fr\", \"it\", \"pt\", \"de\", \"pl\", \"nl\"]),\n    \"Telugu\": (\"telugu_g2\", [\"en\", \"te\"]),\n    \"Simplified Chinese\": (\"zh_sim_g2\", [\"en\", \"ch_sim\"]),\n}\n\nLONG_DESCRIPTION = \"\"\"\n Retrieve the characters in an image using EasyOCR Optical Character Recognition (OCR).\n\nThis block returns the text within an image.\n\nYou may want to use this block in combination with a detections-based block (i.e.\nObjectDetectionBlock). An object detection model could isolate specific regions from an\nimage (i.e. a shipping container ID in a logistics use case) for further processing.\nYou can then use a DynamicCropBlock to crop the region of interest before running OCR.\n\nUsing a detections model then cropping detections allows you to isolate your analysis\non particular regions of an image.\n\nNote that EasyOCR has limitations running within containers on Apple Silicon.\n\"\"\"\n\nEXPECTED_OUTPUT_KEYS = {\n    \"result\",\n    \"parent_id\",\n    \"root_parent_id\",\n    \"prediction_type\",\n    \"predictions\",\n}\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"EasyOCR\",\n            \"version\": \"v1\",\n            \"short_description\": \"Extract text from an image using EasyOCR optical character recognition.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"model\",\n            \"ui_manifest\": {\n                \"section\": \"model\",\n                \"icon\": \"far fa-text\",\n                \"blockPriority\": 11,\n                \"inDevelopment\": False,\n                \"inference\": True,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/easy_ocr@v1\", \"EasyOCR\"]\n    name: str = Field(description=\"Unique name of step in workflows\")\n    images: Selector(kind=[IMAGE_KIND]) = ImageInputField\n    language: LANGUAGES = Field(\n        title=\"Language\",\n        description=\"Language model to use for OCR\",\n        default=\"English\",\n    )\n    quantize: bool = Field(\n        title=\"Use Quantized Model\",\n        description=\"Quantized models are smaller and faster, but may be less accurate and won't work correctly on all hardware.\",\n        default=False,\n    )\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return [\"images\"]\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"result\", kind=[STRING_KIND]),\n            OutputDefinition(\n                name=\"predictions\", kind=[OBJECT_DETECTION_PREDICTION_KIND]\n            ),\n            OutputDefinition(name=\"parent_id\", kind=[PARENT_ID_KIND]),\n            OutputDefinition(name=\"root_parent_id\", kind=[PARENT_ID_KIND]),\n            OutputDefinition(name=\"prediction_type\", kind=[PREDICTION_TYPE_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n    @classmethod\n    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        return [\n            \"easy_ocr/english_g2\",\n            \"easy_ocr/japanese_g2\",\n            \"easy_ocr/kannada_g2\",\n            \"easy_ocr/korean_g2\",\n            \"easy_ocr/latin_g2\",\n            \"easy_ocr/telugu_g2\",\n            \"easy_ocr/zh_sim_g2\",\n        ]\n\n\nclass EasyOCRBlockV1(WorkflowBlock):\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"model_manager\", \"api_key\", \"step_execution_mode\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        language: LANGUAGES = \"English\",\n        quantize: bool = False,\n    ) -> BlockResult:\n\n        if language not in MODELS:\n            raise ValueError(f\"Unsupported language: {language}\")\n\n        version, language_codes = MODELS.get(language, \"english_g2\")\n        if self._step_execution_mode is StepExecutionMode.LOCAL:\n            return self.run_locally(\n                images=images,\n                language_codes=language_codes,\n                version=version,\n                quantize=quantize,\n            )\n        elif self._step_execution_mode is StepExecutionMode.REMOTE:\n            return self.run_remotely(\n                images=images,\n                language_codes=language_codes,\n                version=version,\n                quantize=quantize,\n            )\n        else:\n            raise ValueError(\n                f\"Unknown step execution mode: {self._step_execution_mode}\"\n            )\n\n    def run_locally(\n        self,\n        images: Batch[WorkflowImageData],\n        language_codes: List[str],\n        version: str = \"english_g2\",\n        quantize: bool = False,\n    ) -> BlockResult:\n\n        predictions = []\n        for single_image in images:\n\n            inference_request = EasyOCRInferenceRequest(\n                easy_ocr_version_id=version,\n                image=single_image.to_inference_format(numpy_preferred=True),\n                api_key=self._api_key,\n                language_codes=language_codes,\n                quantize=quantize,\n            )\n            model_id = load_core_model(\n                model_manager=self._model_manager,\n                inference_request=inference_request,\n                core_model=\"easy_ocr\",\n            )\n            result = self._model_manager.infer_from_request_sync(\n                model_id, inference_request\n            )\n\n            predictions.append(result.model_dump(by_alias=True, exclude_none=True))\n\n        return post_process_ocr_result(\n            predictions=predictions,\n            images=images,\n            expected_output_keys=EXPECTED_OUTPUT_KEYS,\n        )\n\n    def run_remotely(\n        self,\n        images: Batch[WorkflowImageData],\n        language_codes: List[str],\n        version: str = \"english_g2\",\n        quantize: bool = False,\n    ) -> BlockResult:\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_CORE_MODEL_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        if WORKFLOWS_REMOTE_API_TARGET == \"hosted\":\n            client.select_api_v0()\n        configuration = InferenceConfiguration(\n            max_batch_size=WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_BATCH_SIZE,\n            max_concurrent_requests=WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS,\n        )\n        client.configure(configuration)\n        non_empty_inference_images = [i.base64_image for i in images]\n        predictions = client.ocr_image(\n            inference_input=non_empty_inference_images,\n            model=\"easy_ocr\",\n            version=version,\n            quantize=quantize,\n            language_codes=language_codes,\n        )\n        if len(images) == 1:\n            predictions = [predictions]\n        return post_process_ocr_result(\n            predictions=predictions,\n            images=images,\n            expected_output_keys=EXPECTED_OUTPUT_KEYS,\n        )\n",
    "patch": null
  },
  {
    "trace_id": "c4643598-a7f5-408f-995d-4798efd44b3e",
    "function_name": "BlockManifest.get_supported_model_variants",
    "file_path": "inference/core/workflows/core_steps/models/foundation/clip_comparison/v2.py",
    "speedup_x": 0.2193915663123621,
    "review_quality": "medium",
    "pre_optimization_commit": "c20359386c628a08bde69f5f3f780cedd782c50c",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        from inference.core.workflows.core_steps.models.foundation.clip.v1 import (\n            CLIP_CACHE_MODEL_IDS,\n        )\n\n        return list(CLIP_CACHE_MODEL_IDS)\n",
    "optimized_function_code": "from inference.core.workflows.prototypes.block import WorkflowBlockManifest\nfrom typing import List, Optional\nfrom functools import lru_cache\nfrom importlib import import_module\n\nLONG_DESCRIPTION = \"\"\"\nUse the OpenAI CLIP zero-shot classification model to classify images.\n\nThis block accepts an image and a list of text prompts. The block then returns the \nsimilarity of each text label to the provided image.\n\nThis block is useful for classifying images without having to train a fine-tuned \nclassification model. For example, you could use CLIP to classify the type of vehicle \nin an image, or if an image contains NSFW material.\n\"\"\"\n\n\n\n# Cache the imported module object to avoid repeated import overhead while keeping\n# attribute reads fresh (we still build a new list on each call to preserve behavior).\n@lru_cache(maxsize=1)\ndef _cached_clip_module():\n    return import_module(\"inference.core.workflows.core_steps.models.foundation.clip.v1\")\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        module = _cached_clip_module()\n        # Build a new list from the module attribute each call to preserve original semantics.\n        return list(module.CLIP_CACHE_MODEL_IDS)",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/models/foundation/clip_comparison/v2.py\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\nfrom typing import List, Optional\nfrom functools import lru_cache\nfrom importlib import import_module\n\nLONG_DESCRIPTION = \"\"\"\nUse the OpenAI CLIP zero-shot classification model to classify images.\n\nThis block accepts an image and a list of text prompts. The block then returns the \nsimilarity of each text label to the provided image.\n\nThis block is useful for classifying images without having to train a fine-tuned \nclassification model. For example, you could use CLIP to classify the type of vehicle \nin an image, or if an image contains NSFW material.\n\"\"\"\n\n\n\n# Cache the imported module object to avoid repeated import overhead while keeping\n# attribute reads fresh (we still build a new list on each call to preserve behavior).\n@lru_cache(maxsize=1)\ndef _cached_clip_module():\n    return import_module(\"inference.core.workflows.core_steps.models.foundation.clip.v1\")\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        module = _cached_clip_module()\n        # Build a new list from the module attribute each call to preserve original semantics.\n        return list(module.CLIP_CACHE_MODEL_IDS)\n```",
    "optimized_function_only": "    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        module = _cached_clip_module()\n        # Build a new list from the module attribute each call to preserve original semantics.\n        return list(module.CLIP_CACHE_MODEL_IDS)",
    "original_file_content": "from functools import partial\nfrom typing import List, Literal, Optional, Type, Union\n\nimport numpy as np\nfrom pydantic import ConfigDict, Field\n\nfrom inference.core.entities.requests.clip import ClipCompareRequest\nfrom inference.core.env import (\n    HOSTED_CORE_MODEL_URL,\n    LOCAL_INFERENCE_API_URL,\n    WORKFLOWS_REMOTE_API_TARGET,\n    WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS,\n)\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.entities import StepExecutionMode\nfrom inference.core.workflows.core_steps.common.utils import (\n    load_core_model,\n    run_in_parallel,\n)\nfrom inference.core.workflows.execution_engine.constants import (\n    PARENT_ID_KEY,\n    ROOT_PARENT_ID_KEY,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    CLASSIFICATION_PREDICTION_KIND,\n    FLOAT_ZERO_TO_ONE_KIND,\n    IMAGE_KIND,\n    LIST_OF_VALUES_KIND,\n    PARENT_ID_KIND,\n    STRING_KIND,\n    ImageInputField,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\nfrom inference_sdk import InferenceHTTPClient\n\nLONG_DESCRIPTION = \"\"\"\nUse the OpenAI CLIP zero-shot classification model to classify images.\n\nThis block accepts an image and a list of text prompts. The block then returns the \nsimilarity of each text label to the provided image.\n\nThis block is useful for classifying images without having to train a fine-tuned \nclassification model. For example, you could use CLIP to classify the type of vehicle \nin an image, or if an image contains NSFW material.\n\"\"\"\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Clip Comparison\",\n            \"version\": \"v2\",\n            \"short_description\": \"Compare CLIP image and text embeddings.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"model\",\n            \"ui_manifest\": {\n                \"section\": \"model\",\n                \"icon\": \"fak fa-message-image\",\n                \"blockPriority\": 10,\n                \"inference\": True,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/clip_comparison@v2\"]\n    name: str = Field(description=\"Unique name of step in workflows\")\n    images: Selector(kind=[IMAGE_KIND]) = ImageInputField\n    classes: Union[Selector(kind=[LIST_OF_VALUES_KIND]), List[str]] = Field(\n        description=\"List of classes to calculate similarity against each input image\",\n        examples=[[\"a\", \"b\", \"c\"], \"$inputs.texts\"],\n        min_items=1,\n    )\n    version: Union[\n        Literal[\n            \"RN101\",\n            \"RN50\",\n            \"RN50x16\",\n            \"RN50x4\",\n            \"RN50x64\",\n            \"ViT-B-16\",\n            \"ViT-B-32\",\n            \"ViT-L-14-336px\",\n            \"ViT-L-14\",\n        ],\n        Selector(kind=[STRING_KIND]),\n    ] = Field(\n        default=\"ViT-B-16\",\n        description=\"Variant of CLIP model\",\n        examples=[\"ViT-B-16\", \"$inputs.variant\"],\n    )\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return [\"images\"]\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"similarities\", kind=[LIST_OF_VALUES_KIND]),\n            OutputDefinition(name=\"max_similarity\", kind=[FLOAT_ZERO_TO_ONE_KIND]),\n            OutputDefinition(name=\"most_similar_class\", kind=[STRING_KIND]),\n            OutputDefinition(name=\"min_similarity\", kind=[FLOAT_ZERO_TO_ONE_KIND]),\n            OutputDefinition(name=\"least_similar_class\", kind=[STRING_KIND]),\n            OutputDefinition(\n                name=\"classification_predictions\",\n                kind=[CLASSIFICATION_PREDICTION_KIND],\n            ),\n            OutputDefinition(name=\"parent_id\", kind=[PARENT_ID_KIND]),\n            OutputDefinition(name=\"root_parent_id\", kind=[PARENT_ID_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n    @classmethod\n    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        from inference.core.workflows.core_steps.models.foundation.clip.v1 import (\n            CLIP_CACHE_MODEL_IDS,\n        )\n\n        return list(CLIP_CACHE_MODEL_IDS)\n\n\nclass ClipComparisonBlockV2(WorkflowBlock):\n\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"model_manager\", \"api_key\", \"step_execution_mode\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        classes: List[str],\n        version: str,\n    ) -> BlockResult:\n        if self._step_execution_mode is StepExecutionMode.LOCAL:\n            return self.run_locally(images=images, classes=classes, version=version)\n        elif self._step_execution_mode is StepExecutionMode.REMOTE:\n            return self.run_remotely(images=images, classes=classes, version=version)\n        else:\n            raise ValueError(\n                f\"Unknown step execution mode: {self._step_execution_mode}\"\n            )\n\n    def run_locally(\n        self,\n        images: Batch[WorkflowImageData],\n        classes: List[str],\n        version: str,\n    ) -> BlockResult:\n        predictions = []\n        for single_image in images:\n            inference_request = ClipCompareRequest(\n                clip_version_id=version,\n                subject=single_image.to_inference_format(numpy_preferred=True),\n                subject_type=\"image\",\n                prompt=classes,\n                prompt_type=\"text\",\n                api_key=self._api_key,\n            )\n            clip_model_id = load_core_model(\n                model_manager=self._model_manager,\n                inference_request=inference_request,\n                core_model=\"clip\",\n            )\n            prediction = self._model_manager.infer_from_request_sync(\n                clip_model_id, inference_request\n            )\n            predictions.append(prediction.model_dump())\n        return self._post_process_result(\n            images=images,\n            predictions=predictions,\n            classes=classes,\n        )\n\n    def run_remotely(\n        self,\n        images: Batch[WorkflowImageData],\n        classes: List[str],\n        version: str,\n    ) -> BlockResult:\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_CORE_MODEL_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        if WORKFLOWS_REMOTE_API_TARGET == \"hosted\":\n            client.select_api_v0()\n        tasks = [\n            partial(\n                client.clip_compare,\n                subject=single_image.base64_image,\n                prompt=classes,\n                clip_version=version,\n            )\n            for single_image in images\n        ]\n        predictions = run_in_parallel(\n            tasks=tasks,\n            max_workers=WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS,\n        )\n        return self._post_process_result(\n            images=images,\n            predictions=predictions,\n            classes=classes,\n        )\n\n    def _post_process_result(\n        self,\n        images: Batch[WorkflowImageData],\n        predictions: List[dict],\n        classes: List[str],\n    ) -> List[dict]:\n        results = []\n        for prediction, image in zip(predictions, images):\n            similarities = prediction[\"similarity\"]\n            max_similarity = np.max(similarities)\n            max_similarity_id = np.argmax(similarities)\n            min_similarity = np.min(similarities)\n            min_similarity_id = np.argmin(similarities)\n            most_similar_class_name = classes[max_similarity_id]\n            least_similar_class_name = classes[min_similarity_id]\n            prediction[PARENT_ID_KEY] = image.parent_metadata.parent_id\n            prediction[ROOT_PARENT_ID_KEY] = (\n                image.workflow_root_ancestor_metadata.parent_id\n            )\n            classification_predictions = {\n                \"predictions\": [\n                    {\n                        \"class\": class_name,\n                        \"class_id\": class_id,\n                        \"confidence\": confidence,\n                    }\n                    for class_id, (class_name, confidence) in enumerate(\n                        zip(classes, similarities)\n                    )\n                ],\n                \"top\": most_similar_class_name,\n                \"confidence\": max_similarity,\n                \"parent_id\": image.parent_metadata.parent_id,\n            }\n            result = {\n                PARENT_ID_KEY: image.parent_metadata.parent_id,\n                ROOT_PARENT_ID_KEY: image.workflow_root_ancestor_metadata.parent_id,\n                \"similarities\": similarities,\n                \"max_similarity\": max_similarity,\n                \"most_similar_class\": most_similar_class_name,\n                \"min_similarity\": min_similarity,\n                \"least_similar_class\": least_similar_class_name,\n                \"classification_predictions\": classification_predictions,\n            }\n            results.append(result)\n        return results\n",
    "patch": null
  },
  {
    "trace_id": "49c73cf2-76fa-420f-a02a-2778ec6804fb",
    "function_name": "BlockManifest.get_supported_model_variants",
    "file_path": "inference/core/workflows/core_steps/models/foundation/clip_comparison/v1.py",
    "speedup_x": 0.283659805326534,
    "review_quality": "medium",
    "pre_optimization_commit": "c20359386c628a08bde69f5f3f780cedd782c50c",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        from inference.core.workflows.core_steps.models.foundation.clip.v1 import (\n            CLIP_CACHE_MODEL_IDS,\n        )\n\n        return list(CLIP_CACHE_MODEL_IDS)\n",
    "optimized_function_code": "import importlib\nfrom typing import List, Optional\n\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nLONG_DESCRIPTION = \"\"\"\nUse the OpenAI CLIP zero-shot classification model to classify images.\n\nThis block accepts an image and a list of text prompts. The block then returns the \nsimilarity of each text label to the provided image.\n\nThis block is useful for classifying images without having to train a fine-tuned \nclassification model. For example, you could use CLIP to classify the type of vehicle \nin an image, or if an image contains NSFW material.\n\"\"\"\n\n\n\n# Cache for the lazily imported module to avoid repeated import overhead.\n_clip_v1_module: Optional[object] = None\n\n\ndef _get_clip_v1_module() -> object:\n    \"\"\"\n    Lazily import and cache the clip.v1 module. This preserves the original lazy\n    import semantics while avoiding the cost of re-importing on every call.\n    \"\"\"\n    global _clip_v1_module\n    if _clip_v1_module is None:\n        # Import lazily to preserve original behavior (imports only when needed).\n        _clip_v1_module = importlib.import_module(\n            \"inference.core.workflows.core_steps.models.foundation.clip.v1\"\n        )\n    return _clip_v1_module\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        module = _get_clip_v1_module()\n        return list(module.CLIP_CACHE_MODEL_IDS)",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/models/foundation/clip_comparison/v1.py\nimport importlib\nfrom typing import List, Optional\n\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nLONG_DESCRIPTION = \"\"\"\nUse the OpenAI CLIP zero-shot classification model to classify images.\n\nThis block accepts an image and a list of text prompts. The block then returns the \nsimilarity of each text label to the provided image.\n\nThis block is useful for classifying images without having to train a fine-tuned \nclassification model. For example, you could use CLIP to classify the type of vehicle \nin an image, or if an image contains NSFW material.\n\"\"\"\n\n\n\n# Cache for the lazily imported module to avoid repeated import overhead.\n_clip_v1_module: Optional[object] = None\n\n\ndef _get_clip_v1_module() -> object:\n    \"\"\"\n    Lazily import and cache the clip.v1 module. This preserves the original lazy\n    import semantics while avoiding the cost of re-importing on every call.\n    \"\"\"\n    global _clip_v1_module\n    if _clip_v1_module is None:\n        # Import lazily to preserve original behavior (imports only when needed).\n        _clip_v1_module = importlib.import_module(\n            \"inference.core.workflows.core_steps.models.foundation.clip.v1\"\n        )\n    return _clip_v1_module\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        module = _get_clip_v1_module()\n        return list(module.CLIP_CACHE_MODEL_IDS)\n```",
    "optimized_function_only": "    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        module = _get_clip_v1_module()\n        return list(module.CLIP_CACHE_MODEL_IDS)",
    "original_file_content": "from functools import partial\nfrom typing import List, Literal, Optional, Type, Union\n\nfrom pydantic import AliasChoices, ConfigDict, Field\n\nfrom inference.core.entities.requests.clip import ClipCompareRequest\nfrom inference.core.env import (\n    HOSTED_CORE_MODEL_URL,\n    LOCAL_INFERENCE_API_URL,\n    WORKFLOWS_REMOTE_API_TARGET,\n    WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS,\n)\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.entities import StepExecutionMode\nfrom inference.core.workflows.core_steps.common.utils import (\n    load_core_model,\n    remove_unexpected_keys_from_dictionary,\n    run_in_parallel,\n)\nfrom inference.core.workflows.execution_engine.constants import (\n    PARENT_ID_KEY,\n    PREDICTION_TYPE_KEY,\n    ROOT_PARENT_ID_KEY,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    IMAGE_KIND,\n    LIST_OF_VALUES_KIND,\n    PARENT_ID_KIND,\n    PREDICTION_TYPE_KIND,\n    ImageInputField,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\nfrom inference_sdk import InferenceHTTPClient\n\nLONG_DESCRIPTION = \"\"\"\nUse the OpenAI CLIP zero-shot classification model to classify images.\n\nThis block accepts an image and a list of text prompts. The block then returns the \nsimilarity of each text label to the provided image.\n\nThis block is useful for classifying images without having to train a fine-tuned \nclassification model. For example, you could use CLIP to classify the type of vehicle \nin an image, or if an image contains NSFW material.\n\"\"\"\n\nEXPECTED_OUTPUT_KEYS = {\"similarity\", \"parent_id\", \"root_parent_id\", \"prediction_type\"}\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Clip Comparison\",\n            \"version\": \"v1\",\n            \"short_description\": \"Compare CLIP image and text embeddings.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"model\",\n            \"ui_manifest\": {\n                \"section\": \"model\",\n                \"icon\": \"fak fa-message-image\",\n                \"blockPriority\": 10,\n                \"inference\": True,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/clip_comparison@v1\", \"ClipComparison\"]\n    name: str = Field(description=\"Unique name of step in workflows\")\n    images: Selector(kind=[IMAGE_KIND]) = ImageInputField\n    texts: Union[Selector(kind=[LIST_OF_VALUES_KIND]), List[str]] = Field(\n        description=\"List of texts to calculate similarity against each input image\",\n        examples=[[\"a\", \"b\", \"c\"], \"$inputs.texts\"],\n        validation_alias=AliasChoices(\"texts\", \"text\"),\n    )\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return [\"images\"]\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"similarity\", kind=[LIST_OF_VALUES_KIND]),\n            OutputDefinition(name=\"parent_id\", kind=[PARENT_ID_KIND]),\n            OutputDefinition(name=\"root_parent_id\", kind=[PARENT_ID_KIND]),\n            OutputDefinition(name=\"prediction_type\", kind=[PREDICTION_TYPE_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n    @classmethod\n    def get_supported_model_variants(cls) -> Optional[List[str]]:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        from inference.core.workflows.core_steps.models.foundation.clip.v1 import (\n            CLIP_CACHE_MODEL_IDS,\n        )\n\n        return list(CLIP_CACHE_MODEL_IDS)\n\n\nclass ClipComparisonBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"model_manager\", \"api_key\", \"step_execution_mode\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        texts: List[str],\n    ) -> BlockResult:\n        if self._step_execution_mode is StepExecutionMode.LOCAL:\n            return self.run_locally(images=images, texts=texts)\n        elif self._step_execution_mode is StepExecutionMode.REMOTE:\n            return self.run_remotely(images=images, texts=texts)\n        else:\n            raise ValueError(\n                f\"Unknown step execution mode: {self._step_execution_mode}\"\n            )\n\n    def run_locally(\n        self,\n        images: Batch[WorkflowImageData],\n        texts: List[str],\n    ) -> BlockResult:\n        predictions = []\n        for single_image in images:\n            inference_request = ClipCompareRequest(\n                subject=single_image.to_inference_format(numpy_preferred=True),\n                subject_type=\"image\",\n                prompt=texts,\n                prompt_type=\"text\",\n                api_key=self._api_key,\n            )\n            clip_model_id = load_core_model(\n                model_manager=self._model_manager,\n                inference_request=inference_request,\n                core_model=\"clip\",\n            )\n            prediction = self._model_manager.infer_from_request_sync(\n                clip_model_id, inference_request\n            )\n            predictions.append(prediction.model_dump())\n        return self._post_process_result(\n            images=images,\n            predictions=predictions,\n        )\n\n    def run_remotely(\n        self,\n        images: Batch[WorkflowImageData],\n        texts: List[str],\n    ) -> BlockResult:\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_CORE_MODEL_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        if WORKFLOWS_REMOTE_API_TARGET == \"hosted\":\n            client.select_api_v0()\n        tasks = [\n            partial(\n                client.clip_compare,\n                subject=single_image.numpy_image,\n                prompt=texts,\n            )\n            for single_image in images\n        ]\n        predictions = run_in_parallel(\n            tasks=tasks,\n            max_workers=WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS,\n        )\n        return self._post_process_result(images=images, predictions=predictions)\n\n    def _post_process_result(\n        self,\n        images: Batch[WorkflowImageData],\n        predictions: List[dict],\n    ) -> List[dict]:\n        for prediction, image in zip(predictions, images):\n            prediction[PREDICTION_TYPE_KEY] = \"classification\"\n            prediction[PARENT_ID_KEY] = image.parent_metadata.parent_id\n            prediction[ROOT_PARENT_ID_KEY] = (\n                image.workflow_root_ancestor_metadata.parent_id\n            )\n            # removing fields from `inference` response model\n            # that are not registered as outputs\n            _ = remove_unexpected_keys_from_dictionary(\n                dictionary=prediction,\n                expected_keys=EXPECTED_OUTPUT_KEYS,\n            )\n        return predictions\n",
    "patch": null
  },
  {
    "trace_id": "219b5d07-9d54-49a7-bc3d-f7bf8a5c5629",
    "function_name": "handle_describe_workflows_blocks_request",
    "file_path": "inference/core/interfaces/http/handlers/workflows.py",
    "speedup_x": 1.4969531997905343,
    "review_quality": "high",
    "pre_optimization_commit": "41e35e60c37b6e8ad32cd3cf3a0b472af8b5baa7",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def handle_describe_workflows_blocks_request(\n    dynamic_blocks_definitions: Optional[List[DynamicBlockDefinition]] = None,\n    requested_execution_engine_version: Optional[str] = None,\n    api_key: Optional[str] = None,\n    air_gapped: bool = False,\n) -> WorkflowsBlocksDescription:\n    if dynamic_blocks_definitions is None:\n        dynamic_blocks_definitions = []\n    dynamic_blocks = compile_dynamic_blocks(\n        dynamic_blocks_definitions=dynamic_blocks_definitions,\n        api_key=api_key,\n    )\n    blocks_description = describe_available_blocks(\n        dynamic_blocks=dynamic_blocks,\n        execution_engine_version=requested_execution_engine_version,\n    )\n    blocks_connections = discover_blocks_connections(\n        blocks_description=blocks_description,\n    )\n    kinds_connections = {\n        kind_name: [\n            ExternalWorkflowsBlockSelectorDefinition(\n                manifest_type_identifier=c.manifest_type_identifier,\n                property_name=c.property_name,\n                property_description=c.property_description,\n                compatible_element=c.compatible_element,\n                is_list_element=c.is_list_element,\n                is_dict_element=c.is_dict_element,\n            )\n            for c in connections\n        ]\n        for kind_name, connections in blocks_connections.kinds_connections.items()\n    }\n    primitives_connections = [\n        ExternalBlockPropertyPrimitiveDefinition(\n            manifest_type_identifier=primitives_connection.manifest_type_identifier,\n            property_name=primitives_connection.property_name,\n            property_description=primitives_connection.property_description,\n            type_annotation=primitives_connection.type_annotation,\n        )\n        for primitives_connection in blocks_connections.primitives_connections\n    ]\n    uql_operations_descriptions = prepare_operations_descriptions()\n    uql_operators_descriptions = prepare_operators_descriptions()\n    universal_query_language_description = (\n        UniversalQueryLanguageDescription.from_internal_entities(\n            operations_descriptions=uql_operations_descriptions,\n            operators_descriptions=uql_operators_descriptions,\n        )\n    )\n    result = WorkflowsBlocksDescription(\n        blocks=blocks_description.blocks,\n        declared_kinds=blocks_description.declared_kinds,\n        kinds_connections=kinds_connections,\n        primitives_connections=primitives_connections,\n        universal_query_language_description=universal_query_language_description,\n        dynamic_block_definition_schema=DynamicBlockDefinition.schema(),\n    )\n    if air_gapped and ENABLE_BUILDER:\n        result = enrich_with_air_gapped_info(result)\n    return result\n",
    "optimized_function_code": "from functools import lru_cache\nfrom typing import Any, List, Optional\n\nfrom inference.core.workflows.execution_engine.introspection.blocks_loader import \\\n    load_all_defined_kinds\nfrom inference.core.workflows.execution_engine.profiling.core import (\n    WorkflowsProfiler, execution_phase)\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import \\\n    BlockSpecification\nfrom inference.core.workflows.execution_engine.v1.dynamic_blocks.entities import (\n    DynamicBlockDefinition, ValueType)\n\n\n@execution_phase(\n    name=\"dynamic_blocks_compilation\",\n    categories=[\"execution_engine_operation\"],\n)\ndef compile_dynamic_blocks(\n    dynamic_blocks_definitions: List[dict],\n    profiler: Optional[WorkflowsProfiler] = None,\n    api_key: Optional[str] = None,\n    skip_class_eval: Optional[bool] = False,\n) -> List[BlockSpecification]:\n    if not dynamic_blocks_definitions:\n        return []\n    ensure_dynamic_blocks_allowed(dynamic_blocks_definitions=dynamic_blocks_definitions)\n    all_defined_kinds = load_all_defined_kinds()\n    kinds_lookup = {kind.name: kind for kind in all_defined_kinds}\n    dynamic_blocks = [\n        DynamicBlockDefinition.model_validate(dynamic_block)\n        for dynamic_block in dynamic_blocks_definitions\n    ]\n    compiled_blocks = []\n    for dynamic_block in dynamic_blocks:\n        block_specification = create_dynamic_block_specification(\n            dynamic_block_definition=dynamic_block,\n            kinds_lookup=kinds_lookup,\n            api_key=api_key,\n            skip_class_eval=skip_class_eval,\n        )\n        compiled_blocks.append(block_specification)\n    return compiled_blocks\n\n\nPYTHON_TYPES_MAPPING = {\n    ValueType.ANY: Any,\n    ValueType.INTEGER: int,\n    ValueType.FLOAT: float,\n    ValueType.BOOLEAN: bool,\n    ValueType.DICT: dict,\n    ValueType.LIST: list,\n    ValueType.STRING: str,\n}",
    "optimized_raw_markdown": "```python:inference/core/workflows/execution_engine/v1/dynamic_blocks/block_assembler.py\nfrom functools import lru_cache\nfrom typing import Any, List, Optional\n\nfrom inference.core.workflows.execution_engine.introspection.blocks_loader import \\\n    load_all_defined_kinds\nfrom inference.core.workflows.execution_engine.profiling.core import (\n    WorkflowsProfiler, execution_phase)\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import \\\n    BlockSpecification\nfrom inference.core.workflows.execution_engine.v1.dynamic_blocks.entities import (\n    DynamicBlockDefinition, ValueType)\n\n\n@execution_phase(\n    name=\"dynamic_blocks_compilation\",\n    categories=[\"execution_engine_operation\"],\n)\ndef compile_dynamic_blocks(\n    dynamic_blocks_definitions: List[dict],\n    profiler: Optional[WorkflowsProfiler] = None,\n    api_key: Optional[str] = None,\n    skip_class_eval: Optional[bool] = False,\n) -> List[BlockSpecification]:\n    if not dynamic_blocks_definitions:\n        return []\n    ensure_dynamic_blocks_allowed(dynamic_blocks_definitions=dynamic_blocks_definitions)\n    all_defined_kinds = load_all_defined_kinds()\n    kinds_lookup = {kind.name: kind for kind in all_defined_kinds}\n    dynamic_blocks = [\n        DynamicBlockDefinition.model_validate(dynamic_block)\n        for dynamic_block in dynamic_blocks_definitions\n    ]\n    compiled_blocks = []\n    for dynamic_block in dynamic_blocks:\n        block_specification = create_dynamic_block_specification(\n            dynamic_block_definition=dynamic_block,\n            kinds_lookup=kinds_lookup,\n            api_key=api_key,\n            skip_class_eval=skip_class_eval,\n        )\n        compiled_blocks.append(block_specification)\n    return compiled_blocks\n\n\nPYTHON_TYPES_MAPPING = {\n    ValueType.ANY: Any,\n    ValueType.INTEGER: int,\n    ValueType.FLOAT: float,\n    ValueType.BOOLEAN: bool,\n    ValueType.DICT: dict,\n    ValueType.LIST: list,\n    ValueType.STRING: str,\n}\n```\n```python:inference/core/entities/responses/workflows.py\nfrom typing import Dict, List, Optional\n\nfrom inference.core.workflows.core_steps.common.query_language.entities.introspection import (\n    OperationDescription, OperatorDescription)\nfrom inference.core.workflows.execution_engine.entities.types import Kind\nfrom inference.core.workflows.execution_engine.introspection.entities import \\\n    BlockDescription\nfrom pydantic import BaseModel, Field\n\n\nclass ExternalWorkflowsBlockSelectorDefinition(BaseModel):\n    manifest_type_identifier: str = Field(description=\"Identifier of block\")\n    property_name: str = Field(description=\"Name of specific property\")\n    property_description: str = Field(description=\"Description for specific property\")\n    compatible_element: str = Field(\n        description=\"Defines to what type of object (step_output, parameter, etc) reference may be pointing\"\n    )\n    is_list_element: bool = Field(\n        description=\"Boolean flag defining if list of references will be accepted\"\n    )\n    is_dict_element: bool = Field(\n        description=\"Boolean flag defining if dict of references will be accepted\"\n    )\n\n\nclass ExternalBlockPropertyPrimitiveDefinition(BaseModel):\n    manifest_type_identifier: str = Field(description=\"Identifier of block\")\n    property_name: str = Field(description=\"Name of specific property\")\n    property_description: str = Field(description=\"Description for specific property\")\n    type_annotation: str = Field(\n        description=\"Pythonic type annotation for property\",\n        examples=[\"Union[str, int]\"],\n    )\n\n\nclass ExternalOperationDescription(BaseModel):\n    operation_type: str\n    compound: bool\n    input_kind: List[str]\n    output_kind: List[str]\n    nested_operation_input_kind: Optional[List[str]] = None\n    nested_operation_output_kind: Optional[List[str]] = None\n    description: Optional[str] = None\n\n    property_name_options: Optional[List[str]] = Field(\n        default=None,\n        description=(\n            \"List of possible property names. \\\n            Optional parameter for operations extracting property values from data. \"\n        ),\n        examples=[\n            \"size\",\n            \"height\",\n            \"width\",\n            \"aspect_ratio\",\n        ],\n    )\n\n    @classmethod\n    def from_internal_entity(\n        cls, operation_description: OperationDescription\n    ) -> \"ExternalOperationDescription\":\n        nested_operation_input_kind, nested_operation_output_kind = None, None\n        if operation_description.nested_operation_input_kind:\n            nested_operation_input_kind = [\n                k.name for k in operation_description.nested_operation_input_kind\n            ]\n        if operation_description.nested_operation_output_kind:\n            nested_operation_output_kind = [\n                k.name for k in operation_description.nested_operation_output_kind\n            ]\n        return cls(\n            operation_type=operation_description.operation_type,\n            compound=operation_description.compound,\n            input_kind=[k.name for k in operation_description.input_kind],\n            output_kind=[k.name for k in operation_description.output_kind],\n            nested_operation_input_kind=nested_operation_input_kind,\n            nested_operation_output_kind=nested_operation_output_kind,\n            description=operation_description.description,\n            property_name_options=operation_description.property_name_options,\n        )\n\n\nclass ExternalOperatorDescription(BaseModel):\n    operator_type: str\n    operands_number: int\n    operands_kinds: List[List[str]]\n    description: Optional[str] = None\n\n    @classmethod\n    def from_internal_entity(\n        cls, operator_description: OperatorDescription\n    ) -> \"ExternalOperatorDescription\":\n        operands_kinds = [\n            [k.name for k in kind] for kind in operator_description.operands_kinds\n        ]\n        return cls(\n            operator_type=operator_description.operator_type,\n            operands_number=operator_description.operands_number,\n            operands_kinds=operands_kinds,\n            description=operator_description.description,\n        )\n\n\nclass UniversalQueryLanguageDescription(BaseModel):\n\n    operations_description: List[ExternalOperationDescription]\n    operators_descriptions: List[ExternalOperatorDescription]\n\n    @classmethod\n    def from_internal_entities(\n        cls,\n        operations_descriptions: List[OperationDescription],\n        operators_descriptions: List[OperatorDescription],\n    ) -> \"UniversalQueryLanguageDescription\":\n        return cls(\n            operations_description=[\n                ExternalOperationDescription.from_internal_entity(\n                    operation_description=op\n                )\n                for op in operations_descriptions\n            ],\n            operators_descriptions=[\n                ExternalOperatorDescription.from_internal_entity(\n                    operator_description=op\n                )\n                for op in operators_descriptions\n            ],\n        )\n\n\nclass WorkflowsBlocksDescription(BaseModel):\n    blocks: List[BlockDescription] = Field(\n        description=\"List of loaded blocks descriptions\"\n    )\n    declared_kinds: List[Kind] = Field(description=\"List of kinds defined for blocks\")\n    kinds_connections: Dict[str, List[ExternalWorkflowsBlockSelectorDefinition]] = (\n        Field(\n            description=\"Mapping from kind name into list of blocks properties accepting references of that kind\"\n        )\n    )\n    primitives_connections: List[ExternalBlockPropertyPrimitiveDefinition] = Field(\n        description=\"List defining all properties for all blocks that can be filled \"\n        \"with primitive values in workflow definition.\"\n    )\n    universal_query_language_description: UniversalQueryLanguageDescription = Field(\n        description=\"Definitions of Universal Query Language operations and operators\"\n    )\n    dynamic_block_definition_schema: dict = Field(\n        description=\"Schema for dynamic block definition\"\n    )\n```\n```python:inference/core/workflows/core_steps/common/query_language/introspection/core.py\nfrom functools import lru_cache\nfrom typing import List, Optional\n\nfrom inference.core.workflows.core_steps.common.query_language.entities.introspection import (\n    OperationDescription, OperatorDescription)\nfrom inference.core.workflows.core_steps.common.query_language.entities.operations import (\n    DoesNotExist, Equals, Exists, In, IsEmpty, IsFalse, IsNotEmpty, IsTrue,\n    NotEquals, NumberGreater, NumberGreaterEqual, NumberLower,\n    NumberLowerEqual, OperationsChain, StringContains, StringEndsWith,\n    StringStartsWith)\n\n\ndef _ref_to_def_name(\n    schema: dict,\n    ref_key: str = \"$ref\",\n) -> Optional[str]:\n    \"\"\"Extract definition name from a JSON Schema object's $ref (e.g. {'$ref': '#/$defs/Foo'} -> 'Foo').\"\"\"\n    ref = schema.get(ref_key)\n    if ref is None:\n        return None\n\n    return ref.split(\"/\")[-1]\n\n\ndef _get_property_name_options(\n    type_definition: dict,\n    defs: dict,\n) -> Optional[List[str]]:\n    \"\"\"Resolve property_name enum from operation schema when present (e.g. DetectionsProperty).\"\"\"\n    properties = type_definition.get(\"properties\") or {}\n    property_name_schema = properties.get(\"property_name\")\n\n    if not property_name_schema:\n        return None\n\n    ref_name = _ref_to_def_name(property_name_schema)\n    if ref_name is not None:\n        resolved = defs.get(ref_name)\n        if resolved and \"enum\" in resolved:\n            return list(resolved[\"enum\"])\n\n    if \"enum\" in property_name_schema:\n        return list(property_name_schema[\"enum\"])\n\n    return None\n\n\n@lru_cache(maxsize=1)\ndef _get_operations_chain_schema():\n    \"\"\"Cache the OperationsChain schema since it's static and expensive to compute.\"\"\"\n    return OperationsChain.model_json_schema()\n\n\n\ndef prepare_operations_descriptions() -> List[OperationDescription]:\n    operations_chain_schema = _get_operations_chain_schema()\n    defs = operations_chain_schema.get(\"$defs\", {})\n    operation_type_definitions = operations_chain_schema[\"properties\"][\"operations\"][\"items\"][\"oneOf\"]  # fmt: skip\n\n    operation_types = [\n        name\n        for type_definition in operation_type_definitions\n        if (name := _ref_to_def_name(type_definition)) is not None\n    ]\n    type_definitions = [defs[operation_type] for operation_type in operation_types]\n\n    result = []\n    for type_definition in type_definitions:\n        property_name_options = _get_property_name_options(type_definition, defs)\n\n        result.append(\n            OperationDescription(\n                operation_type=type_definition[\"properties\"][\"type\"][\"const\"],\n                compound=type_definition.get(\"compound\", False),\n                input_kind=type_definition[\"input_kind\"],\n                output_kind=type_definition[\"output_kind\"],\n                nested_operation_input_kind=type_definition.get(\n                    \"nested_operation_input_kind\"\n                ),\n                nested_operation_output_kind=type_definition.get(\n                    \"nested_operation_output_kind\"\n                ),\n                property_name_options=property_name_options,\n            )\n        )\n    return result\n\n\n\n\n@lru_cache(maxsize=256)\ndef _get_operator_schema(operator_type):\n    \"\"\"Cache individual operator schemas.\"\"\"\n    return operator_type.model_json_schema()\n\n\ndef prepare_operators_descriptions() -> List[OperatorDescription]:\n    operator_types = [\n        In,\n        StringContains,\n        StringEndsWith,\n        StringStartsWith,\n        NumberLowerEqual,\n        NumberLower,\n        NumberGreaterEqual,\n        NumberGreater,\n        NotEquals,\n        Equals,\n        Exists,\n        DoesNotExist,\n        IsTrue,\n        IsFalse,\n        IsEmpty,\n        IsNotEmpty,\n    ]\n    results = []\n    for operator_type in operator_types:\n        operator_schema = _get_operator_schema(operator_type)\n        for alias in operator_schema[\"properties\"][\"type\"].get(\"enum\", []):\n            results.append(\n                OperatorDescription(\n                    operator_type=alias,\n                    operands_number=operator_schema[\"operands_number\"],\n                    operands_kinds=operator_schema[\"operands_kinds\"],\n                    description=operator_schema.get(\"description\"),\n                )\n            )\n    return results\n```",
    "optimized_function_only": null,
    "original_file_content": "# TODO - for everyone: start migrating other handlers to bring relief to http_api.py\nimport copy\nfrom typing import Any, Dict, List, Optional, Set, Union\n\nfrom packaging.specifiers import SpecifierSet\n\nfrom inference.core.cache.air_gapped import has_cached_model_variant\nfrom inference.core.entities.responses.workflows import (\n    DescribeInterfaceResponse,\n    ExternalBlockPropertyPrimitiveDefinition,\n    ExternalWorkflowsBlockSelectorDefinition,\n    UniversalQueryLanguageDescription,\n    WorkflowsBlocksDescription,\n)\nfrom inference.core.env import ENABLE_BUILDER\nfrom inference.core.workflows.core_steps.common.query_language.introspection.core import (\n    prepare_operations_descriptions,\n    prepare_operators_descriptions,\n)\nfrom inference.core.workflows.errors import WorkflowExecutionEngineVersionError\nfrom inference.core.workflows.execution_engine.core import (\n    retrieve_requested_execution_engine_version,\n)\nfrom inference.core.workflows.execution_engine.introspection.blocks_loader import (\n    describe_available_blocks,\n)\nfrom inference.core.workflows.execution_engine.introspection.connections_discovery import (\n    discover_blocks_connections,\n)\nfrom inference.core.workflows.execution_engine.v1.dynamic_blocks.block_assembler import (\n    compile_dynamic_blocks,\n)\nfrom inference.core.workflows.execution_engine.v1.dynamic_blocks.entities import (\n    DynamicBlockDefinition,\n)\nfrom inference.core.workflows.execution_engine.v1.introspection.inputs_discovery import (\n    describe_workflow_inputs,\n)\nfrom inference.core.workflows.execution_engine.v1.introspection.outputs_discovery import (\n    describe_workflow_outputs,\n)\nfrom inference.core.workflows.execution_engine.v1.introspection.types_discovery import (\n    discover_kinds_schemas,\n    discover_kinds_typing_hints,\n)\nfrom inference.core.workflows.prototypes.block import BlockAirGappedInfo\n\n\ndef handle_describe_workflows_blocks_request(\n    dynamic_blocks_definitions: Optional[List[DynamicBlockDefinition]] = None,\n    requested_execution_engine_version: Optional[str] = None,\n    api_key: Optional[str] = None,\n    air_gapped: bool = False,\n) -> WorkflowsBlocksDescription:\n    if dynamic_blocks_definitions is None:\n        dynamic_blocks_definitions = []\n    dynamic_blocks = compile_dynamic_blocks(\n        dynamic_blocks_definitions=dynamic_blocks_definitions,\n        api_key=api_key,\n    )\n    blocks_description = describe_available_blocks(\n        dynamic_blocks=dynamic_blocks,\n        execution_engine_version=requested_execution_engine_version,\n    )\n    blocks_connections = discover_blocks_connections(\n        blocks_description=blocks_description,\n    )\n    kinds_connections = {\n        kind_name: [\n            ExternalWorkflowsBlockSelectorDefinition(\n                manifest_type_identifier=c.manifest_type_identifier,\n                property_name=c.property_name,\n                property_description=c.property_description,\n                compatible_element=c.compatible_element,\n                is_list_element=c.is_list_element,\n                is_dict_element=c.is_dict_element,\n            )\n            for c in connections\n        ]\n        for kind_name, connections in blocks_connections.kinds_connections.items()\n    }\n    primitives_connections = [\n        ExternalBlockPropertyPrimitiveDefinition(\n            manifest_type_identifier=primitives_connection.manifest_type_identifier,\n            property_name=primitives_connection.property_name,\n            property_description=primitives_connection.property_description,\n            type_annotation=primitives_connection.type_annotation,\n        )\n        for primitives_connection in blocks_connections.primitives_connections\n    ]\n    uql_operations_descriptions = prepare_operations_descriptions()\n    uql_operators_descriptions = prepare_operators_descriptions()\n    universal_query_language_description = (\n        UniversalQueryLanguageDescription.from_internal_entities(\n            operations_descriptions=uql_operations_descriptions,\n            operators_descriptions=uql_operators_descriptions,\n        )\n    )\n    result = WorkflowsBlocksDescription(\n        blocks=blocks_description.blocks,\n        declared_kinds=blocks_description.declared_kinds,\n        kinds_connections=kinds_connections,\n        primitives_connections=primitives_connections,\n        universal_query_language_description=universal_query_language_description,\n        dynamic_block_definition_schema=DynamicBlockDefinition.schema(),\n    )\n    if air_gapped and ENABLE_BUILDER:\n        result = enrich_with_air_gapped_info(result)\n    return result\n\n\ndef enrich_with_air_gapped_info(\n    result: WorkflowsBlocksDescription,\n) -> WorkflowsBlocksDescription:\n    \"\"\"Post-process block descriptions to include air-gapped availability info.\n\n    Deep-copies block schemas before mutating so the LRU-cached objects are\n    not modified.\n    \"\"\"\n    enriched_blocks = []\n    for block in result.blocks:\n        manifest_cls = block.manifest_class\n        air_gapped_info = _get_air_gapped_info_for_block(manifest_cls)\n        enriched_schema = copy.deepcopy(block.block_schema)\n        if \"json_schema_extra\" not in enriched_schema:\n            enriched_schema[\"json_schema_extra\"] = {}\n        enriched_schema[\"json_schema_extra\"][\n            \"air_gapped_info\"\n        ] = air_gapped_info.to_dict()\n        enriched_blocks.append(\n            block.model_copy(update={\"block_schema\": enriched_schema})\n        )\n    return result.model_copy(update={\"blocks\": enriched_blocks})\n\n\ndef _get_air_gapped_info_for_block(\n    manifest_cls: Any,\n) -> BlockAirGappedInfo:\n    \"\"\"Determine air-gapped availability for a single block manifest class.\n\n    Resolution order:\n\n    1. **Cloud-only blocks** \u2014 ``get_air_gapped_availability()`` returns\n       ``available=False`` (e.g. blocks wrapping OpenAI / Anthropic APIs).\n    2. **Foundation-model blocks** \u2014 ``get_supported_model_variants()``\n       returns a non-None list; availability depends on whether any\n       variant has cached weights.\n    3. **Default** \u2014 the block is available (pure logic, local-network, etc.).\n\n    Compatible task types from ``get_compatible_task_types()`` are always\n    attached when present.\n    \"\"\"\n    task_types = manifest_cls.get_compatible_task_types()\n\n    # 1. Explicit cloud/internet declaration\n    availability = manifest_cls.get_air_gapped_availability()\n    if not availability.available:\n        return BlockAirGappedInfo(\n            available=False,\n            reason=availability.reason,\n            compatible_task_types=task_types,\n        )\n\n    # 2. Foundation models with locally-cacheable weights\n    model_variants = manifest_cls.get_supported_model_variants()\n    if model_variants is not None:\n        cached = has_cached_model_variant(model_variants)\n        # Use the first variant as a representative identifier for the UI.\n        # The list is ordered by convention (default/primary variant first),\n        # and individual variant selection happens at workflow-execution time.\n        representative_id = model_variants[0] if model_variants else None\n        return BlockAirGappedInfo(\n            available=cached,\n            reason=None if cached else \"missing_cache_artifacts\",\n            model_id=representative_id,\n            compatible_task_types=task_types,\n        )\n\n    # 3. Default: block is available (pure logic blocks, local-network blocks, etc.)\n    return BlockAirGappedInfo(\n        available=True,\n        compatible_task_types=task_types,\n    )\n\n\ndef handle_describe_workflows_interface(\n    definition: dict,\n) -> DescribeInterfaceResponse:\n    requested_execution_engine_version = retrieve_requested_execution_engine_version(\n        workflow_definition=definition\n    )\n    if not SpecifierSet(f\">=1.0.0,<2.0.0\").contains(requested_execution_engine_version):\n        raise WorkflowExecutionEngineVersionError(\n            public_message=\"Describing workflow outputs is only supported for Execution Engine v1.\",\n            context=\"describing_workflow_outputs\",\n        )\n    inputs = describe_workflow_inputs(definition=definition)\n    outputs = describe_workflow_outputs(definition=definition)\n    unique_kinds = get_unique_kinds(inputs=inputs, outputs=outputs)\n    typing_hints = discover_kinds_typing_hints(kinds_names=unique_kinds)\n    kinds_schemas = discover_kinds_schemas(kinds_names=unique_kinds)\n    return DescribeInterfaceResponse(\n        inputs=inputs,\n        outputs=outputs,\n        typing_hints=typing_hints,\n        kinds_schemas=kinds_schemas,\n    )\n\n\ndef get_unique_kinds(\n    inputs: Dict[str, List[str]],\n    outputs: Dict[str, Union[List[str], Dict[str, List[str]]]],\n) -> Set[str]:\n    all_kinds = set()\n    for input_element_kinds in inputs.values():\n        all_kinds.update(input_element_kinds)\n    for output_definition in outputs.values():\n        if isinstance(output_definition, list):\n            all_kinds.update(output_definition)\n        if isinstance(output_definition, dict):\n            for output_field_kinds in output_definition.values():\n                all_kinds.update(output_field_kinds)\n    return all_kinds\n\n\ndef filter_out_unwanted_workflow_outputs(\n    workflow_results: List[dict],\n    excluded_fields: Optional[List[str]],\n) -> List[dict]:\n    if not excluded_fields:\n        return workflow_results\n    excluded_fields = set(excluded_fields)\n    filtered_results = []\n    for result_element in workflow_results:\n        filtered_result = {}\n        for key, value in result_element.items():\n            if key in excluded_fields:\n                continue\n            filtered_result[key] = value\n        filtered_results.append(filtered_result)\n    return filtered_results\n",
    "patch": null
  },
  {
    "trace_id": "ad81c7fe-d1a7-4a63-8fd1-b0a8657d9230",
    "function_name": "get_task_type_to_block_mapping",
    "file_path": "inference/core/cache/air_gapped.py",
    "speedup_x": 0.3883569922374179,
    "review_quality": "high",
    "pre_optimization_commit": "f297c436b732f5012a51f7b04c135db9133c2370",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def get_task_type_to_block_mapping(\n    blocks: Optional[list] = None,\n) -> Dict[str, List[str]]:\n    \"\"\"Build a reverse mapping from task_type to compatible block type identifiers.\n\n    Uses ``get_compatible_task_types()`` on block manifests.  Blocks whose\n    method returns *None* (the base-class default) are skipped.\n\n    Args:\n        blocks: Optional pre-loaded list of block specifications.  When\n            *None* (the default) the blocks are loaded via the engine's\n            block loader.\n    \"\"\"\n    mapping: Dict[str, List[str]] = {}\n    if blocks is None:\n        try:\n            blocks = _load_blocks()\n        except Exception:\n            logger.debug(\n                \"Could not load workflow blocks for task-type mapping\",\n                exc_info=True,\n            )\n            return mapping\n\n    for block in blocks:\n        manifest_cls = block.manifest_class\n        task_types = manifest_cls.get_compatible_task_types()\n        if task_types is None:\n            continue\n\n        block_type_id = _get_block_type_identifier(block)\n        for tt in task_types:\n            mapping.setdefault(tt, []).append(block_type_id)\n\n    return mapping\n",
    "optimized_function_code": "import functools\nimport logging\nfrom typing import Dict, List, Optional\n\nlogger = logging.getLogger(__name__)\n\n\n\n\n@functools.cache\ndef _load_blocks() -> list:\n    \"\"\"Load workflow blocks, isolating the heavy import for testability.\"\"\"\n    from inference.core.workflows.execution_engine.introspection.blocks_loader import \\\n        load_workflow_blocks\n\n    return load_workflow_blocks()\n\n\n\n\n# Cache mapping from block.identifier -> resolved type identifier\n_BLOCK_TYPE_ID_CACHE: Dict[str, str] = {}\n\n\ndef get_task_type_to_block_mapping(\n    blocks: Optional[list] = None,\n) -> Dict[str, List[str]]:\n    \"\"\"Build a reverse mapping from task_type to compatible block type identifiers.\n\n    Uses ``get_compatible_task_types()`` on block manifests.  Blocks whose\n    method returns *None* (the base-class default) are skipped.\n\n    Args:\n        blocks: Optional pre-loaded list of block specifications.  When\n            *None* (the default) the blocks are loaded via the engine's\n            block loader.\n    \"\"\"\n    mapping: Dict[str, List[str]] = {}\n    if blocks is None:\n        try:\n            blocks = _load_blocks()\n        except Exception:\n            logger.debug(\n                \"Could not load workflow blocks for task-type mapping\",\n                exc_info=True,\n            )\n            return mapping\n\n    for block in blocks:\n        manifest_cls = block.manifest_class\n        task_types = manifest_cls.get_compatible_task_types()\n        if task_types is None:\n            continue\n\n        block_type_id = _get_block_type_identifier(block)\n        for tt in task_types:\n            mapping.setdefault(tt, []).append(block_type_id)\n\n    return mapping\n\n\ndef _get_block_type_identifier(block) -> str:\n    \"\"\"Extract the canonical ``type`` identifier from a block specification.\"\"\"\n    # Use a simple identifier-keyed cache to avoid reparsing schema for the same block type.\n    # This preserves behavior while improving repeated-call performance.\n    key = getattr(block, \"identifier\", None)\n    if key is not None:\n        cached = _BLOCK_TYPE_ID_CACHE.get(key)\n        if cached is not None:\n            return cached\n\n    try:\n        schema = block.manifest_class.model_json_schema()\n        type_prop = schema.get(\"properties\", {}).get(\"type\", {})\n        # The type field is typically a const or enum with one value.\n        if \"const\" in type_prop:\n            result = type_prop[\"const\"]\n            if key is not None:\n                _BLOCK_TYPE_ID_CACHE[key] = result\n            return result\n        if \"enum\" in type_prop and type_prop[\"enum\"]:\n            result = type_prop[\"enum\"][0]\n            if key is not None:\n                _BLOCK_TYPE_ID_CACHE[key] = result\n            return result\n    except Exception:\n        pass\n    # Fallback: use the block's identifier; cache if possible\n    fallback = block.identifier\n    if key is not None:\n        _BLOCK_TYPE_ID_CACHE[key] = fallback\n    return fallback",
    "optimized_raw_markdown": "```python:inference/core/cache/air_gapped.py\nimport functools\nimport logging\nfrom typing import Dict, List, Optional\n\nlogger = logging.getLogger(__name__)\n\n\n\n\n@functools.cache\ndef _load_blocks() -> list:\n    \"\"\"Load workflow blocks, isolating the heavy import for testability.\"\"\"\n    from inference.core.workflows.execution_engine.introspection.blocks_loader import \\\n        load_workflow_blocks\n\n    return load_workflow_blocks()\n\n\n\n\n# Cache mapping from block.identifier -> resolved type identifier\n_BLOCK_TYPE_ID_CACHE: Dict[str, str] = {}\n\n\ndef get_task_type_to_block_mapping(\n    blocks: Optional[list] = None,\n) -> Dict[str, List[str]]:\n    \"\"\"Build a reverse mapping from task_type to compatible block type identifiers.\n\n    Uses ``get_compatible_task_types()`` on block manifests.  Blocks whose\n    method returns *None* (the base-class default) are skipped.\n\n    Args:\n        blocks: Optional pre-loaded list of block specifications.  When\n            *None* (the default) the blocks are loaded via the engine's\n            block loader.\n    \"\"\"\n    mapping: Dict[str, List[str]] = {}\n    if blocks is None:\n        try:\n            blocks = _load_blocks()\n        except Exception:\n            logger.debug(\n                \"Could not load workflow blocks for task-type mapping\",\n                exc_info=True,\n            )\n            return mapping\n\n    for block in blocks:\n        manifest_cls = block.manifest_class\n        task_types = manifest_cls.get_compatible_task_types()\n        if task_types is None:\n            continue\n\n        block_type_id = _get_block_type_identifier(block)\n        for tt in task_types:\n            mapping.setdefault(tt, []).append(block_type_id)\n\n    return mapping\n\n\ndef _get_block_type_identifier(block) -> str:\n    \"\"\"Extract the canonical ``type`` identifier from a block specification.\"\"\"\n    # Use a simple identifier-keyed cache to avoid reparsing schema for the same block type.\n    # This preserves behavior while improving repeated-call performance.\n    key = getattr(block, \"identifier\", None)\n    if key is not None:\n        cached = _BLOCK_TYPE_ID_CACHE.get(key)\n        if cached is not None:\n            return cached\n\n    try:\n        schema = block.manifest_class.model_json_schema()\n        type_prop = schema.get(\"properties\", {}).get(\"type\", {})\n        # The type field is typically a const or enum with one value.\n        if \"const\" in type_prop:\n            result = type_prop[\"const\"]\n            if key is not None:\n                _BLOCK_TYPE_ID_CACHE[key] = result\n            return result\n        if \"enum\" in type_prop and type_prop[\"enum\"]:\n            result = type_prop[\"enum\"][0]\n            if key is not None:\n                _BLOCK_TYPE_ID_CACHE[key] = result\n            return result\n    except Exception:\n        pass\n    # Fallback: use the block's identifier; cache if possible\n    fallback = block.identifier\n    if key is not None:\n        _BLOCK_TYPE_ID_CACHE[key] = fallback\n    return fallback\n```",
    "optimized_function_only": "def get_task_type_to_block_mapping(\n    blocks: Optional[list] = None,\n) -> Dict[str, List[str]]:\n    \"\"\"Build a reverse mapping from task_type to compatible block type identifiers.\n\n    Uses ``get_compatible_task_types()`` on block manifests.  Blocks whose\n    method returns *None* (the base-class default) are skipped.\n\n    Args:\n        blocks: Optional pre-loaded list of block specifications.  When\n            *None* (the default) the blocks are loaded via the engine's\n            block loader.\n    \"\"\"\n    mapping: Dict[str, List[str]] = {}\n    if blocks is None:\n        try:\n            blocks = _load_blocks()\n        except Exception:\n            logger.debug(\n                \"Could not load workflow blocks for task-type mapping\",\n                exc_info=True,\n            )\n            return mapping\n\n    for block in blocks:\n        manifest_cls = block.manifest_class\n        task_types = manifest_cls.get_compatible_task_types()\n        if task_types is None:\n            continue\n\n        block_type_id = _get_block_type_identifier(block)\n        for tt in task_types:\n            mapping.setdefault(tt, []).append(block_type_id)\n\n    return mapping\n",
    "original_file_content": "\"\"\"Utilities for discovering models and foundation-model weights in the local cache.\n\nUsed by the air-gapped workflow builder to enumerate what is available for\noffline workflow construction.\n\"\"\"\n\nimport hashlib\nimport json\nimport logging\nimport os\nimport re\nfrom typing import Any, Dict, List, Optional\n\nfrom inference.core.env import MODEL_CACHE_DIR, USE_INFERENCE_MODELS\nfrom inference.core.roboflow_api import MODEL_TYPE_KEY, PROJECT_TASK_TYPE_KEY\n\nlogger = logging.getLogger(__name__)\n\n# Directories directly under MODEL_CACHE_DIR that are not model trees.\n_SKIP_TOP_LEVEL = {\"workflow\", \"_file_locks\"}\n\n\ndef _slugify_model_id(model_id: str) -> str:\n    \"\"\"Reproduce the slug used by inference-models for cache directory names.\n\n    Must stay in sync with\n    ``inference_models.models.auto_loaders.core.slugify_model_id_to_os_safe_format``.\n    \"\"\"\n    slug = re.sub(r\"[^A-Za-z0-9_-]+\", \"-\", model_id)\n    slug = re.sub(r\"[_-]{2,}\", \"-\", slug)\n    if not slug:\n        slug = \"special-char-only-model-id\"\n    if len(slug) > 48:\n        slug = slug[:48]\n    digest = hashlib.blake2s(model_id.encode(\"utf-8\"), digest_size=4).hexdigest()\n    return f\"{slug}-{digest}\"\n\n\ndef _has_non_hidden_children(path: str) -> bool:\n    \"\"\"Return True if *path* contains at least one non-hidden entry.\n\n    Hidden files (names starting with ``\".\"``) are excluded because they may be\n    stale lock-file leftovers that do not represent usable model artifacts.\n    \"\"\"\n    try:\n        return any(not f.startswith(\".\") for f in os.listdir(path))\n    except OSError:\n        return False\n\n\ndef is_model_cached(model_id: str) -> bool:\n    \"\"\"Best-effort check whether *model_id* has cached artifacts.\n\n    Checks both the traditional and ``inference-models`` cache layouts,\n    respecting the ``USE_INFERENCE_MODELS`` flag to avoid false positives\n    from one layout when the runtime uses the other.\n\n    .. note::\n\n       This is intentionally optimistic \u2014 a directory with non-hidden files\n       is assumed to contain a usable model.  Full integrity verification\n       (hash checks, registry validation) happens at model-load time inside\n       ``inference-models``.  Treat the result as *\"there is a chance the\n       model is cached\"* rather than a guarantee.\n    \"\"\"\n    if not USE_INFERENCE_MODELS:\n        # Only check the traditional layout when inference-models is disabled.\n        traditional_path = os.path.join(MODEL_CACHE_DIR, model_id)\n        return os.path.isdir(traditional_path) and _has_non_hidden_children(\n            traditional_path\n        )\n\n    # When inference-models is enabled, check both layouts \u2014 models cached\n    # before the migration still sit in the traditional tree.\n    traditional_path = os.path.join(MODEL_CACHE_DIR, model_id)\n    if os.path.isdir(traditional_path) and _has_non_hidden_children(traditional_path):\n        return True\n\n    slug = _slugify_model_id(model_id)\n    models_cache_path = os.path.join(MODEL_CACHE_DIR, \"models-cache\", slug)\n    if os.path.isdir(models_cache_path) and _has_non_hidden_children(models_cache_path):\n        return True\n\n    return False\n\n\ndef has_cached_model_variant(model_variants: Optional[List[str]]) -> bool:\n    \"\"\"Return True if **any** of the given model variant IDs has cached artifacts.\n\n    Args:\n        model_variants: List of model IDs as returned by\n            ``WorkflowBlockManifest.get_supported_model_variants()``.\n            Returns ``False`` when *None* or empty.\n    \"\"\"\n    if not model_variants:\n        return False\n    return any(is_model_cached(mid) for mid in model_variants)\n\n\ndef _load_blocks() -> list:\n    \"\"\"Load workflow blocks, isolating the heavy import for testability.\"\"\"\n    from inference.core.workflows.execution_engine.introspection.blocks_loader import (\n        load_workflow_blocks,\n    )\n\n    return load_workflow_blocks()\n\n\ndef scan_cached_models(cache_dir: str) -> List[Dict[str, Any]]:\n    \"\"\"Walk *cache_dir* looking for ``model_type.json`` marker files.\n\n    Each marker is written by the model registry when a model is first\n    downloaded.  The file contains at least ``project_task_type`` and\n    ``model_type`` keys.\n\n    Returns a list of dicts with the following shape::\n\n        {\n            \"model_id\": \"workspace/project/3\",\n            \"name\": \"workspace/project/3\",\n            \"task_type\": \"object-detection\",\n            \"model_architecture\": \"yolov8n\",\n            \"is_foundation\": False,\n        }\n    \"\"\"\n    results: List[Dict[str, Any]] = []\n    if not os.path.isdir(cache_dir):\n        return results\n\n    for root, dirs, files in os.walk(cache_dir):\n        # Prune top-level directories we know are not model trees.\n        rel = os.path.relpath(root, cache_dir)\n        if rel == \".\":\n            dirs[:] = [d for d in dirs if d not in _SKIP_TOP_LEVEL]\n            continue\n\n        if \"model_type.json\" not in files:\n            continue\n\n        model_type_path = os.path.join(root, \"model_type.json\")\n        try:\n            with open(model_type_path, \"r\") as fh:\n                metadata = json.load(fh)\n        except (json.JSONDecodeError, OSError) as exc:\n            logger.warning(\n                \"Skipping unreadable model_type.json at %s: %s\",\n                model_type_path,\n                exc,\n            )\n            continue\n\n        if not isinstance(metadata, dict):\n            continue\n\n        # Support both traditional keys and inference-models metadata keys.\n        task_type = metadata.get(PROJECT_TASK_TYPE_KEY) or metadata.get(\"taskType\", \"\")\n        model_architecture = metadata.get(MODEL_TYPE_KEY) or metadata.get(\n            \"modelArchitecture\", \"\"\n        )\n\n        if not task_type:\n            continue\n\n        model_id = os.path.relpath(root, cache_dir)\n        # Normalise path separators on Windows.\n        model_id = model_id.replace(os.sep, \"/\")\n\n        results.append(\n            {\n                \"model_id\": model_id,\n                \"name\": model_id,\n                \"task_type\": task_type,\n                \"model_architecture\": model_architecture,\n                \"is_foundation\": False,\n            }\n        )\n\n    return results\n\n\ndef get_cached_foundation_models(\n    blocks: Optional[list] = None,\n) -> List[Dict[str, Any]]:\n    \"\"\"Return metadata for workflow blocks whose required weights are cached.\n\n    Each block whose manifest class exposes ``get_supported_model_variants``\n    is inspected.  If any variant it declares is present in the local cache\n    the block is included in the result list.\n\n    Args:\n        blocks: Optional pre-loaded list of block specifications.  When\n            *None* (the default) the blocks are loaded via the engine's\n            block loader.\n    \"\"\"\n    results: List[Dict[str, Any]] = []\n    if blocks is None:\n        try:\n            blocks = _load_blocks()\n        except Exception:\n            logger.debug(\n                \"Could not load workflow blocks for foundation model scan\",\n                exc_info=True,\n            )\n            return results\n\n    for block in blocks:\n        manifest_cls = block.manifest_class\n        model_variants = manifest_cls.get_supported_model_variants()\n        if model_variants is None:\n            continue\n\n        if not has_cached_model_variant(model_variants):\n            continue\n\n        model_id = model_variants[0] if model_variants else \"\"\n\n        block_name = model_id\n        try:\n            schema = manifest_cls.model_json_schema()\n            block_name = schema.get(\"name\", model_id)\n        except Exception:\n            pass\n\n        block_type_id = _get_block_type_identifier(block)\n\n        results.append(\n            {\n                \"model_id\": model_id,\n                \"name\": block_name,\n                \"task_type\": \"\",\n                \"model_architecture\": \"\",\n                \"is_foundation\": True,\n                \"block_type\": block_type_id,\n            }\n        )\n\n    return results\n\n\ndef get_task_type_to_block_mapping(\n    blocks: Optional[list] = None,\n) -> Dict[str, List[str]]:\n    \"\"\"Build a reverse mapping from task_type to compatible block type identifiers.\n\n    Uses ``get_compatible_task_types()`` on block manifests.  Blocks whose\n    method returns *None* (the base-class default) are skipped.\n\n    Args:\n        blocks: Optional pre-loaded list of block specifications.  When\n            *None* (the default) the blocks are loaded via the engine's\n            block loader.\n    \"\"\"\n    mapping: Dict[str, List[str]] = {}\n    if blocks is None:\n        try:\n            blocks = _load_blocks()\n        except Exception:\n            logger.debug(\n                \"Could not load workflow blocks for task-type mapping\",\n                exc_info=True,\n            )\n            return mapping\n\n    for block in blocks:\n        manifest_cls = block.manifest_class\n        task_types = manifest_cls.get_compatible_task_types()\n        if task_types is None:\n            continue\n\n        block_type_id = _get_block_type_identifier(block)\n        for tt in task_types:\n            mapping.setdefault(tt, []).append(block_type_id)\n\n    return mapping\n\n\ndef _get_block_type_identifier(block) -> str:\n    \"\"\"Extract the canonical ``type`` identifier from a block specification.\"\"\"\n    try:\n        schema = block.manifest_class.model_json_schema()\n        type_prop = schema.get(\"properties\", {}).get(\"type\", {})\n        # The type field is typically a const or enum with one value.\n        if \"const\" in type_prop:\n            return type_prop[\"const\"]\n        if \"enum\" in type_prop and type_prop[\"enum\"]:\n            return type_prop[\"enum\"][0]\n    except Exception:\n        pass\n    return block.identifier\n",
    "patch": null
  },
  {
    "trace_id": "50730a43-2c7a-45cf-b582-dcc67c2036a7",
    "function_name": "get_cached_foundation_models",
    "file_path": "inference/core/cache/air_gapped.py",
    "speedup_x": 0.45940313429973345,
    "review_quality": "high",
    "pre_optimization_commit": "f297c436b732f5012a51f7b04c135db9133c2370",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def get_cached_foundation_models(\n    blocks: Optional[list] = None,\n) -> List[Dict[str, Any]]:\n    \"\"\"Return metadata for workflow blocks whose required weights are cached.\n\n    Each block whose manifest class exposes ``get_supported_model_variants``\n    is inspected.  If any variant it declares is present in the local cache\n    the block is included in the result list.\n\n    Args:\n        blocks: Optional pre-loaded list of block specifications.  When\n            *None* (the default) the blocks are loaded via the engine's\n            block loader.\n    \"\"\"\n    results: List[Dict[str, Any]] = []\n    if blocks is None:\n        try:\n            blocks = _load_blocks()\n        except Exception:\n            logger.debug(\n                \"Could not load workflow blocks for foundation model scan\",\n                exc_info=True,\n            )\n            return results\n\n    for block in blocks:\n        manifest_cls = block.manifest_class\n        model_variants = manifest_cls.get_supported_model_variants()\n        if model_variants is None:\n            continue\n\n        if not has_cached_model_variant(model_variants):\n            continue\n\n        model_id = model_variants[0] if model_variants else \"\"\n\n        block_name = model_id\n        try:\n            schema = manifest_cls.model_json_schema()\n            block_name = schema.get(\"name\", model_id)\n        except Exception:\n            pass\n\n        block_type_id = _get_block_type_identifier(block)\n\n        results.append(\n            {\n                \"model_id\": model_id,\n                \"name\": block_name,\n                \"task_type\": \"\",\n                \"model_architecture\": \"\",\n                \"is_foundation\": True,\n                \"block_type\": block_type_id,\n            }\n        )\n\n    return results\n",
    "optimized_function_code": "import logging\nimport weakref\nfrom typing import Any, Dict, List, Optional\n\nfrom inference.core.cache.air_gapped import is_model_cached\n\nlogger = logging.getLogger(__name__)\n\n\n\n# Cache results of is_model_cached to avoid repeated filesystem/IO work\n_IS_MODEL_CACHED_CACHE: Dict[str, bool] = {}\n\n# Cache schema objects per manifest class. Use a weak key dict to avoid\n# holding classes alive indefinitely.\n_SCHEMA_CACHE: \"weakref.WeakKeyDictionary[Any, dict]\" = weakref.WeakKeyDictionary()\n\n\ndef has_cached_model_variant(model_variants: Optional[List[str]]) -> bool:\n    \"\"\"Return True if **any** of the given model variant IDs has cached artifacts.\n\n    Args:\n        model_variants: List of model IDs as returned by\n            ``WorkflowBlockManifest.get_supported_model_variants()``.\n            Returns ``False`` when *None* or empty.\n    \"\"\"\n    if not model_variants:\n        return False\n\n    # Iterate manually to allow caching and to preserve exception propagation\n    for mid in model_variants:\n        if mid in _IS_MODEL_CACHED_CACHE:\n            if _IS_MODEL_CACHED_CACHE[mid]:\n                return True\n            continue\n        # Not cached yet: call the heavy function and cache its result.\n        cached = is_model_cached(mid)\n        _IS_MODEL_CACHED_CACHE[mid] = cached\n        if cached:\n            return True\n    return False\n\n\n\n\ndef _load_blocks() -> list:\n    \"\"\"Load workflow blocks, isolating the heavy import for testability.\"\"\"\n    from inference.core.workflows.execution_engine.introspection.blocks_loader import \\\n        load_workflow_blocks\n\n    return load_workflow_blocks()\n\n\ndef get_cached_foundation_models(\n    blocks: Optional[list] = None,\n) -> List[Dict[str, Any]]:\n    \"\"\"Return metadata for workflow blocks whose required weights are cached.\n\n    Each block whose manifest class exposes ``get_supported_model_variants``\n    is inspected.  If any variant it declares is present in the local cache\n    the block is included in the result list.\n\n    Args:\n        blocks: Optional pre-loaded list of block specifications.  When\n            *None* (the default) the blocks are loaded via the engine's\n            block loader.\n    \"\"\"\n    results: List[Dict[str, Any]] = []\n    if blocks is None:\n        try:\n            blocks = _load_blocks()\n        except Exception:\n            logger.debug(\n                \"Could not load workflow blocks for foundation model scan\",\n                exc_info=True,\n            )\n            return results\n\n    for block in blocks:\n        manifest_cls = block.manifest_class\n        model_variants = manifest_cls.get_supported_model_variants()\n        if model_variants is None:\n            continue\n\n        if not has_cached_model_variant(model_variants):\n            continue\n\n        model_id = model_variants[0] if model_variants else \"\"\n\n        block_name = model_id\n        try:\n            schema = manifest_cls.model_json_schema()\n            # Cache successful schema lookups to avoid calling model_json_schema()\n            # multiple times for the same manifest class.\n            try:\n                _SCHEMA_CACHE[manifest_cls] = schema\n            except Exception:\n                # If caching fails for any reason, proceed without caching.\n                pass\n            block_name = schema.get(\"name\", model_id)\n        except Exception:\n            pass\n\n        block_type_id = _get_block_type_identifier(block)\n\n        results.append(\n            {\n                \"model_id\": model_id,\n                \"name\": block_name,\n                \"task_type\": \"\",\n                \"model_architecture\": \"\",\n                \"is_foundation\": True,\n                \"block_type\": block_type_id,\n            }\n        )\n\n    return results\n\n\ndef _get_block_type_identifier(block) -> str:\n    \"\"\"Extract the canonical ``type`` identifier from a block specification.\"\"\"\n    try:\n        # Try to reuse a previously cached schema for this manifest class.\n        schema = None\n        try:\n            schema = _SCHEMA_CACHE.get(block.manifest_class)  # type: ignore[attr-defined]\n        except Exception:\n            # If cache access fails, fall back to direct call.\n            schema = None\n\n        if schema is None:\n            schema = block.manifest_class.model_json_schema()\n            try:\n                _SCHEMA_CACHE[block.manifest_class] = schema\n            except Exception:\n                # If caching fails for any reason, continue without caching.\n                pass\n\n        type_prop = schema.get(\"properties\", {}).get(\"type\", {})\n        # The type field is typically a const or enum with one value.\n        if \"const\" in type_prop:\n            return type_prop[\"const\"]\n        if \"enum\" in type_prop and type_prop[\"enum\"]:\n            return type_prop[\"enum\"][0]\n    except Exception:\n        pass\n    return block.identifier",
    "optimized_raw_markdown": "```python:inference/core/cache/air_gapped.py\nimport logging\nimport weakref\nfrom typing import Any, Dict, List, Optional\n\nfrom inference.core.cache.air_gapped import is_model_cached\n\nlogger = logging.getLogger(__name__)\n\n\n\n# Cache results of is_model_cached to avoid repeated filesystem/IO work\n_IS_MODEL_CACHED_CACHE: Dict[str, bool] = {}\n\n# Cache schema objects per manifest class. Use a weak key dict to avoid\n# holding classes alive indefinitely.\n_SCHEMA_CACHE: \"weakref.WeakKeyDictionary[Any, dict]\" = weakref.WeakKeyDictionary()\n\n\ndef has_cached_model_variant(model_variants: Optional[List[str]]) -> bool:\n    \"\"\"Return True if **any** of the given model variant IDs has cached artifacts.\n\n    Args:\n        model_variants: List of model IDs as returned by\n            ``WorkflowBlockManifest.get_supported_model_variants()``.\n            Returns ``False`` when *None* or empty.\n    \"\"\"\n    if not model_variants:\n        return False\n\n    # Iterate manually to allow caching and to preserve exception propagation\n    for mid in model_variants:\n        if mid in _IS_MODEL_CACHED_CACHE:\n            if _IS_MODEL_CACHED_CACHE[mid]:\n                return True\n            continue\n        # Not cached yet: call the heavy function and cache its result.\n        cached = is_model_cached(mid)\n        _IS_MODEL_CACHED_CACHE[mid] = cached\n        if cached:\n            return True\n    return False\n\n\n\n\ndef _load_blocks() -> list:\n    \"\"\"Load workflow blocks, isolating the heavy import for testability.\"\"\"\n    from inference.core.workflows.execution_engine.introspection.blocks_loader import \\\n        load_workflow_blocks\n\n    return load_workflow_blocks()\n\n\ndef get_cached_foundation_models(\n    blocks: Optional[list] = None,\n) -> List[Dict[str, Any]]:\n    \"\"\"Return metadata for workflow blocks whose required weights are cached.\n\n    Each block whose manifest class exposes ``get_supported_model_variants``\n    is inspected.  If any variant it declares is present in the local cache\n    the block is included in the result list.\n\n    Args:\n        blocks: Optional pre-loaded list of block specifications.  When\n            *None* (the default) the blocks are loaded via the engine's\n            block loader.\n    \"\"\"\n    results: List[Dict[str, Any]] = []\n    if blocks is None:\n        try:\n            blocks = _load_blocks()\n        except Exception:\n            logger.debug(\n                \"Could not load workflow blocks for foundation model scan\",\n                exc_info=True,\n            )\n            return results\n\n    for block in blocks:\n        manifest_cls = block.manifest_class\n        model_variants = manifest_cls.get_supported_model_variants()\n        if model_variants is None:\n            continue\n\n        if not has_cached_model_variant(model_variants):\n            continue\n\n        model_id = model_variants[0] if model_variants else \"\"\n\n        block_name = model_id\n        try:\n            schema = manifest_cls.model_json_schema()\n            # Cache successful schema lookups to avoid calling model_json_schema()\n            # multiple times for the same manifest class.\n            try:\n                _SCHEMA_CACHE[manifest_cls] = schema\n            except Exception:\n                # If caching fails for any reason, proceed without caching.\n                pass\n            block_name = schema.get(\"name\", model_id)\n        except Exception:\n            pass\n\n        block_type_id = _get_block_type_identifier(block)\n\n        results.append(\n            {\n                \"model_id\": model_id,\n                \"name\": block_name,\n                \"task_type\": \"\",\n                \"model_architecture\": \"\",\n                \"is_foundation\": True,\n                \"block_type\": block_type_id,\n            }\n        )\n\n    return results\n\n\ndef _get_block_type_identifier(block) -> str:\n    \"\"\"Extract the canonical ``type`` identifier from a block specification.\"\"\"\n    try:\n        # Try to reuse a previously cached schema for this manifest class.\n        schema = None\n        try:\n            schema = _SCHEMA_CACHE.get(block.manifest_class)  # type: ignore[attr-defined]\n        except Exception:\n            # If cache access fails, fall back to direct call.\n            schema = None\n\n        if schema is None:\n            schema = block.manifest_class.model_json_schema()\n            try:\n                _SCHEMA_CACHE[block.manifest_class] = schema\n            except Exception:\n                # If caching fails for any reason, continue without caching.\n                pass\n\n        type_prop = schema.get(\"properties\", {}).get(\"type\", {})\n        # The type field is typically a const or enum with one value.\n        if \"const\" in type_prop:\n            return type_prop[\"const\"]\n        if \"enum\" in type_prop and type_prop[\"enum\"]:\n            return type_prop[\"enum\"][0]\n    except Exception:\n        pass\n    return block.identifier\n```",
    "optimized_function_only": "def get_cached_foundation_models(\n    blocks: Optional[list] = None,\n) -> List[Dict[str, Any]]:\n    \"\"\"Return metadata for workflow blocks whose required weights are cached.\n\n    Each block whose manifest class exposes ``get_supported_model_variants``\n    is inspected.  If any variant it declares is present in the local cache\n    the block is included in the result list.\n\n    Args:\n        blocks: Optional pre-loaded list of block specifications.  When\n            *None* (the default) the blocks are loaded via the engine's\n            block loader.\n    \"\"\"\n    results: List[Dict[str, Any]] = []\n    if blocks is None:\n        try:\n            blocks = _load_blocks()\n        except Exception:\n            logger.debug(\n                \"Could not load workflow blocks for foundation model scan\",\n                exc_info=True,\n            )\n            return results\n\n    for block in blocks:\n        manifest_cls = block.manifest_class\n        model_variants = manifest_cls.get_supported_model_variants()\n        if model_variants is None:\n            continue\n\n        if not has_cached_model_variant(model_variants):\n            continue\n\n        model_id = model_variants[0] if model_variants else \"\"\n\n        block_name = model_id\n        try:\n            schema = manifest_cls.model_json_schema()\n            # Cache successful schema lookups to avoid calling model_json_schema()\n            # multiple times for the same manifest class.\n            try:\n                _SCHEMA_CACHE[manifest_cls] = schema\n            except Exception:\n                # If caching fails for any reason, proceed without caching.\n                pass\n            block_name = schema.get(\"name\", model_id)\n        except Exception:\n            pass\n\n        block_type_id = _get_block_type_identifier(block)\n\n        results.append(\n            {\n                \"model_id\": model_id,\n                \"name\": block_name,\n                \"task_type\": \"\",\n                \"model_architecture\": \"\",\n                \"is_foundation\": True,\n                \"block_type\": block_type_id,\n            }\n        )\n\n    return results\n",
    "original_file_content": "\"\"\"Utilities for discovering models and foundation-model weights in the local cache.\n\nUsed by the air-gapped workflow builder to enumerate what is available for\noffline workflow construction.\n\"\"\"\n\nimport hashlib\nimport json\nimport logging\nimport os\nimport re\nfrom typing import Any, Dict, List, Optional\n\nfrom inference.core.env import MODEL_CACHE_DIR, USE_INFERENCE_MODELS\nfrom inference.core.roboflow_api import MODEL_TYPE_KEY, PROJECT_TASK_TYPE_KEY\n\nlogger = logging.getLogger(__name__)\n\n# Directories directly under MODEL_CACHE_DIR that are not model trees.\n_SKIP_TOP_LEVEL = {\"workflow\", \"_file_locks\"}\n\n\ndef _slugify_model_id(model_id: str) -> str:\n    \"\"\"Reproduce the slug used by inference-models for cache directory names.\n\n    Must stay in sync with\n    ``inference_models.models.auto_loaders.core.slugify_model_id_to_os_safe_format``.\n    \"\"\"\n    slug = re.sub(r\"[^A-Za-z0-9_-]+\", \"-\", model_id)\n    slug = re.sub(r\"[_-]{2,}\", \"-\", slug)\n    if not slug:\n        slug = \"special-char-only-model-id\"\n    if len(slug) > 48:\n        slug = slug[:48]\n    digest = hashlib.blake2s(model_id.encode(\"utf-8\"), digest_size=4).hexdigest()\n    return f\"{slug}-{digest}\"\n\n\ndef _has_non_hidden_children(path: str) -> bool:\n    \"\"\"Return True if *path* contains at least one non-hidden entry.\n\n    Hidden files (names starting with ``\".\"``) are excluded because they may be\n    stale lock-file leftovers that do not represent usable model artifacts.\n    \"\"\"\n    try:\n        return any(not f.startswith(\".\") for f in os.listdir(path))\n    except OSError:\n        return False\n\n\ndef is_model_cached(model_id: str) -> bool:\n    \"\"\"Best-effort check whether *model_id* has cached artifacts.\n\n    Checks both the traditional and ``inference-models`` cache layouts,\n    respecting the ``USE_INFERENCE_MODELS`` flag to avoid false positives\n    from one layout when the runtime uses the other.\n\n    .. note::\n\n       This is intentionally optimistic \u2014 a directory with non-hidden files\n       is assumed to contain a usable model.  Full integrity verification\n       (hash checks, registry validation) happens at model-load time inside\n       ``inference-models``.  Treat the result as *\"there is a chance the\n       model is cached\"* rather than a guarantee.\n    \"\"\"\n    if not USE_INFERENCE_MODELS:\n        # Only check the traditional layout when inference-models is disabled.\n        traditional_path = os.path.join(MODEL_CACHE_DIR, model_id)\n        return os.path.isdir(traditional_path) and _has_non_hidden_children(\n            traditional_path\n        )\n\n    # When inference-models is enabled, check both layouts \u2014 models cached\n    # before the migration still sit in the traditional tree.\n    traditional_path = os.path.join(MODEL_CACHE_DIR, model_id)\n    if os.path.isdir(traditional_path) and _has_non_hidden_children(traditional_path):\n        return True\n\n    slug = _slugify_model_id(model_id)\n    models_cache_path = os.path.join(MODEL_CACHE_DIR, \"models-cache\", slug)\n    if os.path.isdir(models_cache_path) and _has_non_hidden_children(models_cache_path):\n        return True\n\n    return False\n\n\ndef has_cached_model_variant(model_variants: Optional[List[str]]) -> bool:\n    \"\"\"Return True if **any** of the given model variant IDs has cached artifacts.\n\n    Args:\n        model_variants: List of model IDs as returned by\n            ``WorkflowBlockManifest.get_supported_model_variants()``.\n            Returns ``False`` when *None* or empty.\n    \"\"\"\n    if not model_variants:\n        return False\n    return any(is_model_cached(mid) for mid in model_variants)\n\n\ndef _load_blocks() -> list:\n    \"\"\"Load workflow blocks, isolating the heavy import for testability.\"\"\"\n    from inference.core.workflows.execution_engine.introspection.blocks_loader import (\n        load_workflow_blocks,\n    )\n\n    return load_workflow_blocks()\n\n\ndef scan_cached_models(cache_dir: str) -> List[Dict[str, Any]]:\n    \"\"\"Walk *cache_dir* looking for ``model_type.json`` marker files.\n\n    Each marker is written by the model registry when a model is first\n    downloaded.  The file contains at least ``project_task_type`` and\n    ``model_type`` keys.\n\n    Returns a list of dicts with the following shape::\n\n        {\n            \"model_id\": \"workspace/project/3\",\n            \"name\": \"workspace/project/3\",\n            \"task_type\": \"object-detection\",\n            \"model_architecture\": \"yolov8n\",\n            \"is_foundation\": False,\n        }\n    \"\"\"\n    results: List[Dict[str, Any]] = []\n    if not os.path.isdir(cache_dir):\n        return results\n\n    for root, dirs, files in os.walk(cache_dir):\n        # Prune top-level directories we know are not model trees.\n        rel = os.path.relpath(root, cache_dir)\n        if rel == \".\":\n            dirs[:] = [d for d in dirs if d not in _SKIP_TOP_LEVEL]\n            continue\n\n        if \"model_type.json\" not in files:\n            continue\n\n        model_type_path = os.path.join(root, \"model_type.json\")\n        try:\n            with open(model_type_path, \"r\") as fh:\n                metadata = json.load(fh)\n        except (json.JSONDecodeError, OSError) as exc:\n            logger.warning(\n                \"Skipping unreadable model_type.json at %s: %s\",\n                model_type_path,\n                exc,\n            )\n            continue\n\n        if not isinstance(metadata, dict):\n            continue\n\n        # Support both traditional keys and inference-models metadata keys.\n        task_type = metadata.get(PROJECT_TASK_TYPE_KEY) or metadata.get(\"taskType\", \"\")\n        model_architecture = metadata.get(MODEL_TYPE_KEY) or metadata.get(\n            \"modelArchitecture\", \"\"\n        )\n\n        if not task_type:\n            continue\n\n        model_id = os.path.relpath(root, cache_dir)\n        # Normalise path separators on Windows.\n        model_id = model_id.replace(os.sep, \"/\")\n\n        results.append(\n            {\n                \"model_id\": model_id,\n                \"name\": model_id,\n                \"task_type\": task_type,\n                \"model_architecture\": model_architecture,\n                \"is_foundation\": False,\n            }\n        )\n\n    return results\n\n\ndef get_cached_foundation_models(\n    blocks: Optional[list] = None,\n) -> List[Dict[str, Any]]:\n    \"\"\"Return metadata for workflow blocks whose required weights are cached.\n\n    Each block whose manifest class exposes ``get_supported_model_variants``\n    is inspected.  If any variant it declares is present in the local cache\n    the block is included in the result list.\n\n    Args:\n        blocks: Optional pre-loaded list of block specifications.  When\n            *None* (the default) the blocks are loaded via the engine's\n            block loader.\n    \"\"\"\n    results: List[Dict[str, Any]] = []\n    if blocks is None:\n        try:\n            blocks = _load_blocks()\n        except Exception:\n            logger.debug(\n                \"Could not load workflow blocks for foundation model scan\",\n                exc_info=True,\n            )\n            return results\n\n    for block in blocks:\n        manifest_cls = block.manifest_class\n        model_variants = manifest_cls.get_supported_model_variants()\n        if model_variants is None:\n            continue\n\n        if not has_cached_model_variant(model_variants):\n            continue\n\n        model_id = model_variants[0] if model_variants else \"\"\n\n        block_name = model_id\n        try:\n            schema = manifest_cls.model_json_schema()\n            block_name = schema.get(\"name\", model_id)\n        except Exception:\n            pass\n\n        block_type_id = _get_block_type_identifier(block)\n\n        results.append(\n            {\n                \"model_id\": model_id,\n                \"name\": block_name,\n                \"task_type\": \"\",\n                \"model_architecture\": \"\",\n                \"is_foundation\": True,\n                \"block_type\": block_type_id,\n            }\n        )\n\n    return results\n\n\ndef get_task_type_to_block_mapping(\n    blocks: Optional[list] = None,\n) -> Dict[str, List[str]]:\n    \"\"\"Build a reverse mapping from task_type to compatible block type identifiers.\n\n    Uses ``get_compatible_task_types()`` on block manifests.  Blocks whose\n    method returns *None* (the base-class default) are skipped.\n\n    Args:\n        blocks: Optional pre-loaded list of block specifications.  When\n            *None* (the default) the blocks are loaded via the engine's\n            block loader.\n    \"\"\"\n    mapping: Dict[str, List[str]] = {}\n    if blocks is None:\n        try:\n            blocks = _load_blocks()\n        except Exception:\n            logger.debug(\n                \"Could not load workflow blocks for task-type mapping\",\n                exc_info=True,\n            )\n            return mapping\n\n    for block in blocks:\n        manifest_cls = block.manifest_class\n        task_types = manifest_cls.get_compatible_task_types()\n        if task_types is None:\n            continue\n\n        block_type_id = _get_block_type_identifier(block)\n        for tt in task_types:\n            mapping.setdefault(tt, []).append(block_type_id)\n\n    return mapping\n\n\ndef _get_block_type_identifier(block) -> str:\n    \"\"\"Extract the canonical ``type`` identifier from a block specification.\"\"\"\n    try:\n        schema = block.manifest_class.model_json_schema()\n        type_prop = schema.get(\"properties\", {}).get(\"type\", {})\n        # The type field is typically a const or enum with one value.\n        if \"const\" in type_prop:\n            return type_prop[\"const\"]\n        if \"enum\" in type_prop and type_prop[\"enum\"]:\n            return type_prop[\"enum\"][0]\n    except Exception:\n        pass\n    return block.identifier\n",
    "patch": null
  },
  {
    "trace_id": "3a26eecd-4ffc-48a9-b42b-aece6eb00038",
    "function_name": "_slugify_model_id",
    "file_path": "inference/core/cache/air_gapped.py",
    "speedup_x": 10.20682848025384,
    "review_quality": "high",
    "pre_optimization_commit": "f297c436b732f5012a51f7b04c135db9133c2370",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def _slugify_model_id(model_id: str) -> str:\n    \"\"\"Reproduce the slug used by inference-models for cache directory names.\n\n    Must stay in sync with\n    ``inference_models.models.auto_loaders.core.slugify_model_id_to_os_safe_format``.\n    \"\"\"\n    slug = re.sub(r\"[^A-Za-z0-9_-]+\", \"-\", model_id)\n    slug = re.sub(r\"[_-]{2,}\", \"-\", slug)\n    if not slug:\n        slug = \"special-char-only-model-id\"\n    if len(slug) > 48:\n        slug = slug[:48]\n    digest = hashlib.blake2s(model_id.encode(\"utf-8\"), digest_size=4).hexdigest()\n    return f\"{slug}-{digest}\"\n",
    "optimized_function_code": "import hashlib\nimport re\nfrom functools import lru_cache\n\n# Precompile regular expressions to avoid recompilation on every call.\n_INVALID_RE = re.compile(r\"[^A-Za-z0-9_-]+\")\n_SEQ_RE = re.compile(r\"[_-]{2,}\")\n\ndef _slugify_model_id(model_id: str) -> str:\n    \"\"\"Reproduce the slug used by inference-models for cache directory names.\n\n    Must stay in sync with\n    ``inference_models.models.auto_loaders.core.slugify_model_id_to_os_safe_format``.\n    \"\"\"\n    # Use a tiny cache to speed up repeated calls with the same model_id.\n    return _cached_slugify_model_id(model_id)\n\n\n# Keep implementation in a separate function so we can cache results without\n# changing the public function signature or behavior.\n@lru_cache(maxsize=4096)\ndef _cached_slugify_model_id(model_id: str) -> str:\n    slug = _INVALID_RE.sub(\"-\", model_id)\n    slug = _SEQ_RE.sub(\"-\", slug)\n    if not slug:\n        slug = \"special-char-only-model-id\"\n    if len(slug) > 48:\n        slug = slug[:48]\n    digest = hashlib.blake2s(model_id.encode(\"utf-8\"), digest_size=4).hexdigest()\n    return f\"{slug}-{digest}\"",
    "optimized_raw_markdown": "```python:inference/core/cache/air_gapped.py\nimport hashlib\nimport re\nfrom functools import lru_cache\n\n# Precompile regular expressions to avoid recompilation on every call.\n_INVALID_RE = re.compile(r\"[^A-Za-z0-9_-]+\")\n_SEQ_RE = re.compile(r\"[_-]{2,}\")\n\ndef _slugify_model_id(model_id: str) -> str:\n    \"\"\"Reproduce the slug used by inference-models for cache directory names.\n\n    Must stay in sync with\n    ``inference_models.models.auto_loaders.core.slugify_model_id_to_os_safe_format``.\n    \"\"\"\n    # Use a tiny cache to speed up repeated calls with the same model_id.\n    return _cached_slugify_model_id(model_id)\n\n\n# Keep implementation in a separate function so we can cache results without\n# changing the public function signature or behavior.\n@lru_cache(maxsize=4096)\ndef _cached_slugify_model_id(model_id: str) -> str:\n    slug = _INVALID_RE.sub(\"-\", model_id)\n    slug = _SEQ_RE.sub(\"-\", slug)\n    if not slug:\n        slug = \"special-char-only-model-id\"\n    if len(slug) > 48:\n        slug = slug[:48]\n    digest = hashlib.blake2s(model_id.encode(\"utf-8\"), digest_size=4).hexdigest()\n    return f\"{slug}-{digest}\"\n```",
    "optimized_function_only": "def _slugify_model_id(model_id: str) -> str:\n    \"\"\"Reproduce the slug used by inference-models for cache directory names.\n\n    Must stay in sync with\n    ``inference_models.models.auto_loaders.core.slugify_model_id_to_os_safe_format``.\n    \"\"\"\n    # Use a tiny cache to speed up repeated calls with the same model_id.\n    return _cached_slugify_model_id(model_id)\n",
    "original_file_content": "\"\"\"Utilities for discovering models and foundation-model weights in the local cache.\n\nUsed by the air-gapped workflow builder to enumerate what is available for\noffline workflow construction.\n\"\"\"\n\nimport hashlib\nimport json\nimport logging\nimport os\nimport re\nfrom typing import Any, Dict, List, Optional\n\nfrom inference.core.env import MODEL_CACHE_DIR, USE_INFERENCE_MODELS\nfrom inference.core.roboflow_api import MODEL_TYPE_KEY, PROJECT_TASK_TYPE_KEY\n\nlogger = logging.getLogger(__name__)\n\n# Directories directly under MODEL_CACHE_DIR that are not model trees.\n_SKIP_TOP_LEVEL = {\"workflow\", \"_file_locks\"}\n\n\ndef _slugify_model_id(model_id: str) -> str:\n    \"\"\"Reproduce the slug used by inference-models for cache directory names.\n\n    Must stay in sync with\n    ``inference_models.models.auto_loaders.core.slugify_model_id_to_os_safe_format``.\n    \"\"\"\n    slug = re.sub(r\"[^A-Za-z0-9_-]+\", \"-\", model_id)\n    slug = re.sub(r\"[_-]{2,}\", \"-\", slug)\n    if not slug:\n        slug = \"special-char-only-model-id\"\n    if len(slug) > 48:\n        slug = slug[:48]\n    digest = hashlib.blake2s(model_id.encode(\"utf-8\"), digest_size=4).hexdigest()\n    return f\"{slug}-{digest}\"\n\n\ndef _has_non_hidden_children(path: str) -> bool:\n    \"\"\"Return True if *path* contains at least one non-hidden entry.\n\n    Hidden files (names starting with ``\".\"``) are excluded because they may be\n    stale lock-file leftovers that do not represent usable model artifacts.\n    \"\"\"\n    try:\n        return any(not f.startswith(\".\") for f in os.listdir(path))\n    except OSError:\n        return False\n\n\ndef is_model_cached(model_id: str) -> bool:\n    \"\"\"Best-effort check whether *model_id* has cached artifacts.\n\n    Checks both the traditional and ``inference-models`` cache layouts,\n    respecting the ``USE_INFERENCE_MODELS`` flag to avoid false positives\n    from one layout when the runtime uses the other.\n\n    .. note::\n\n       This is intentionally optimistic \u2014 a directory with non-hidden files\n       is assumed to contain a usable model.  Full integrity verification\n       (hash checks, registry validation) happens at model-load time inside\n       ``inference-models``.  Treat the result as *\"there is a chance the\n       model is cached\"* rather than a guarantee.\n    \"\"\"\n    if not USE_INFERENCE_MODELS:\n        # Only check the traditional layout when inference-models is disabled.\n        traditional_path = os.path.join(MODEL_CACHE_DIR, model_id)\n        return os.path.isdir(traditional_path) and _has_non_hidden_children(\n            traditional_path\n        )\n\n    # When inference-models is enabled, check both layouts \u2014 models cached\n    # before the migration still sit in the traditional tree.\n    traditional_path = os.path.join(MODEL_CACHE_DIR, model_id)\n    if os.path.isdir(traditional_path) and _has_non_hidden_children(traditional_path):\n        return True\n\n    slug = _slugify_model_id(model_id)\n    models_cache_path = os.path.join(MODEL_CACHE_DIR, \"models-cache\", slug)\n    if os.path.isdir(models_cache_path) and _has_non_hidden_children(models_cache_path):\n        return True\n\n    return False\n\n\ndef has_cached_model_variant(model_variants: Optional[List[str]]) -> bool:\n    \"\"\"Return True if **any** of the given model variant IDs has cached artifacts.\n\n    Args:\n        model_variants: List of model IDs as returned by\n            ``WorkflowBlockManifest.get_supported_model_variants()``.\n            Returns ``False`` when *None* or empty.\n    \"\"\"\n    if not model_variants:\n        return False\n    return any(is_model_cached(mid) for mid in model_variants)\n\n\ndef _load_blocks() -> list:\n    \"\"\"Load workflow blocks, isolating the heavy import for testability.\"\"\"\n    from inference.core.workflows.execution_engine.introspection.blocks_loader import (\n        load_workflow_blocks,\n    )\n\n    return load_workflow_blocks()\n\n\ndef scan_cached_models(cache_dir: str) -> List[Dict[str, Any]]:\n    \"\"\"Walk *cache_dir* looking for ``model_type.json`` marker files.\n\n    Each marker is written by the model registry when a model is first\n    downloaded.  The file contains at least ``project_task_type`` and\n    ``model_type`` keys.\n\n    Returns a list of dicts with the following shape::\n\n        {\n            \"model_id\": \"workspace/project/3\",\n            \"name\": \"workspace/project/3\",\n            \"task_type\": \"object-detection\",\n            \"model_architecture\": \"yolov8n\",\n            \"is_foundation\": False,\n        }\n    \"\"\"\n    results: List[Dict[str, Any]] = []\n    if not os.path.isdir(cache_dir):\n        return results\n\n    for root, dirs, files in os.walk(cache_dir):\n        # Prune top-level directories we know are not model trees.\n        rel = os.path.relpath(root, cache_dir)\n        if rel == \".\":\n            dirs[:] = [d for d in dirs if d not in _SKIP_TOP_LEVEL]\n            continue\n\n        if \"model_type.json\" not in files:\n            continue\n\n        model_type_path = os.path.join(root, \"model_type.json\")\n        try:\n            with open(model_type_path, \"r\") as fh:\n                metadata = json.load(fh)\n        except (json.JSONDecodeError, OSError) as exc:\n            logger.warning(\n                \"Skipping unreadable model_type.json at %s: %s\",\n                model_type_path,\n                exc,\n            )\n            continue\n\n        if not isinstance(metadata, dict):\n            continue\n\n        # Support both traditional keys and inference-models metadata keys.\n        task_type = metadata.get(PROJECT_TASK_TYPE_KEY) or metadata.get(\"taskType\", \"\")\n        model_architecture = metadata.get(MODEL_TYPE_KEY) or metadata.get(\n            \"modelArchitecture\", \"\"\n        )\n\n        if not task_type:\n            continue\n\n        model_id = os.path.relpath(root, cache_dir)\n        # Normalise path separators on Windows.\n        model_id = model_id.replace(os.sep, \"/\")\n\n        results.append(\n            {\n                \"model_id\": model_id,\n                \"name\": model_id,\n                \"task_type\": task_type,\n                \"model_architecture\": model_architecture,\n                \"is_foundation\": False,\n            }\n        )\n\n    return results\n\n\ndef get_cached_foundation_models(\n    blocks: Optional[list] = None,\n) -> List[Dict[str, Any]]:\n    \"\"\"Return metadata for workflow blocks whose required weights are cached.\n\n    Each block whose manifest class exposes ``get_supported_model_variants``\n    is inspected.  If any variant it declares is present in the local cache\n    the block is included in the result list.\n\n    Args:\n        blocks: Optional pre-loaded list of block specifications.  When\n            *None* (the default) the blocks are loaded via the engine's\n            block loader.\n    \"\"\"\n    results: List[Dict[str, Any]] = []\n    if blocks is None:\n        try:\n            blocks = _load_blocks()\n        except Exception:\n            logger.debug(\n                \"Could not load workflow blocks for foundation model scan\",\n                exc_info=True,\n            )\n            return results\n\n    for block in blocks:\n        manifest_cls = block.manifest_class\n        model_variants = manifest_cls.get_supported_model_variants()\n        if model_variants is None:\n            continue\n\n        if not has_cached_model_variant(model_variants):\n            continue\n\n        model_id = model_variants[0] if model_variants else \"\"\n\n        block_name = model_id\n        try:\n            schema = manifest_cls.model_json_schema()\n            block_name = schema.get(\"name\", model_id)\n        except Exception:\n            pass\n\n        block_type_id = _get_block_type_identifier(block)\n\n        results.append(\n            {\n                \"model_id\": model_id,\n                \"name\": block_name,\n                \"task_type\": \"\",\n                \"model_architecture\": \"\",\n                \"is_foundation\": True,\n                \"block_type\": block_type_id,\n            }\n        )\n\n    return results\n\n\ndef get_task_type_to_block_mapping(\n    blocks: Optional[list] = None,\n) -> Dict[str, List[str]]:\n    \"\"\"Build a reverse mapping from task_type to compatible block type identifiers.\n\n    Uses ``get_compatible_task_types()`` on block manifests.  Blocks whose\n    method returns *None* (the base-class default) are skipped.\n\n    Args:\n        blocks: Optional pre-loaded list of block specifications.  When\n            *None* (the default) the blocks are loaded via the engine's\n            block loader.\n    \"\"\"\n    mapping: Dict[str, List[str]] = {}\n    if blocks is None:\n        try:\n            blocks = _load_blocks()\n        except Exception:\n            logger.debug(\n                \"Could not load workflow blocks for task-type mapping\",\n                exc_info=True,\n            )\n            return mapping\n\n    for block in blocks:\n        manifest_cls = block.manifest_class\n        task_types = manifest_cls.get_compatible_task_types()\n        if task_types is None:\n            continue\n\n        block_type_id = _get_block_type_identifier(block)\n        for tt in task_types:\n            mapping.setdefault(tt, []).append(block_type_id)\n\n    return mapping\n\n\ndef _get_block_type_identifier(block) -> str:\n    \"\"\"Extract the canonical ``type`` identifier from a block specification.\"\"\"\n    try:\n        schema = block.manifest_class.model_json_schema()\n        type_prop = schema.get(\"properties\", {}).get(\"type\", {})\n        # The type field is typically a const or enum with one value.\n        if \"const\" in type_prop:\n            return type_prop[\"const\"]\n        if \"enum\" in type_prop and type_prop[\"enum\"]:\n            return type_prop[\"enum\"][0]\n    except Exception:\n        pass\n    return block.identifier\n",
    "patch": null
  },
  {
    "trace_id": "c2f72052-57be-427c-a250-dc05986887de",
    "function_name": "is_model_cached",
    "file_path": "inference/core/cache/air_gapped.py",
    "speedup_x": 0.22290056307897232,
    "review_quality": "high",
    "pre_optimization_commit": "f297c436b732f5012a51f7b04c135db9133c2370",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def is_model_cached(model_id: str) -> bool:\n    \"\"\"Best-effort check whether *model_id* has cached artifacts.\n\n    Checks both the traditional and ``inference-models`` cache layouts,\n    respecting the ``USE_INFERENCE_MODELS`` flag to avoid false positives\n    from one layout when the runtime uses the other.\n\n    .. note::\n\n       This is intentionally optimistic \u2014 a directory with non-hidden files\n       is assumed to contain a usable model.  Full integrity verification\n       (hash checks, registry validation) happens at model-load time inside\n       ``inference-models``.  Treat the result as *\"there is a chance the\n       model is cached\"* rather than a guarantee.\n    \"\"\"\n    if not USE_INFERENCE_MODELS:\n        # Only check the traditional layout when inference-models is disabled.\n        traditional_path = os.path.join(MODEL_CACHE_DIR, model_id)\n        return os.path.isdir(traditional_path) and _has_non_hidden_children(\n            traditional_path\n        )\n\n    # When inference-models is enabled, check both layouts \u2014 models cached\n    # before the migration still sit in the traditional tree.\n    traditional_path = os.path.join(MODEL_CACHE_DIR, model_id)\n    if os.path.isdir(traditional_path) and _has_non_hidden_children(traditional_path):\n        return True\n\n    slug = _slugify_model_id(model_id)\n    models_cache_path = os.path.join(MODEL_CACHE_DIR, \"models-cache\", slug)\n    if os.path.isdir(models_cache_path) and _has_non_hidden_children(models_cache_path):\n        return True\n\n    return False\n",
    "optimized_function_code": "import hashlib\nimport os\nimport re\n\nfrom inference.core.env import MODEL_CACHE_DIR, USE_INFERENCE_MODELS\n\n# Precompile regexes to avoid repeated compilation overhead.\n_NON_ALLOWED_RE = re.compile(r\"[^A-Za-z0-9_-]+\")\n_CONSEC_RE = re.compile(r\"[_-]{2,}\")\n\n\ndef _slugify_model_id(model_id: str) -> str:\n    \"\"\"Reproduce the slug used by inference-models for cache directory names.\n\n    Must stay in sync with\n    ``inference_models.models.auto_loaders.core.slugify_model_id_to_os_safe_format``.\n    \"\"\"\n    slug = _NON_ALLOWED_RE.sub(\"-\", model_id)\n    slug = _CONSEC_RE.sub(\"-\", slug)\n    if not slug:\n        slug = \"special-char-only-model-id\"\n    if len(slug) > 48:\n        slug = slug[:48]\n    digest = hashlib.blake2s(model_id.encode(\"utf-8\"), digest_size=4).hexdigest()\n    return f\"{slug}-{digest}\"\n\n\ndef _has_non_hidden_children(path: str) -> bool:\n    \"\"\"Return True if *path* contains at least one non-hidden entry.\n\n    Hidden files (names starting with ``\".\"``) are excluded because they may be\n    stale lock-file leftovers that do not represent usable model artifacts.\n    \"\"\"\n    try:\n        # Use scandir to avoid building a full list of entries and to reduce\n        # syscall overhead compared to listdir + subsequent stats.\n        with os.scandir(path) as it:\n            for entry in it:\n                if not entry.name.startswith(\".\"):\n                    return True\n        return False\n    except OSError:\n        return False\n\n\ndef is_model_cached(model_id: str) -> bool:\n    \"\"\"Best-effort check whether *model_id* has cached artifacts.\n\n    Checks both the traditional and ``inference-models`` cache layouts,\n    respecting the ``USE_INFERENCE_MODELS`` flag to avoid false positives\n    from one layout when the runtime uses the other.\n\n    .. note::\n\n       This is intentionally optimistic \u2014 a directory with non-hidden files\n       is assumed to contain a usable model.  Full integrity verification\n       (hash checks, registry validation) happens at model-load time inside\n       ``inference-models``.  Treat the result as *\"there is a chance the\n       model is cached\"* rather than a guarantee.\n    \"\"\"\n    if not USE_INFERENCE_MODELS:\n        # Only check the traditional layout when inference-models is disabled.\n        traditional_path = os.path.join(MODEL_CACHE_DIR, model_id)\n        return _has_non_hidden_children(traditional_path)\n\n    # When inference-models is enabled, check both layouts \u2014 models cached\n    # before the migration still sit in the traditional tree.\n\n    # When inference-models is enabled, check both layouts \u2014 models cached\n    # before the migration still sit in the traditional tree.\n    traditional_path = os.path.join(MODEL_CACHE_DIR, model_id)\n    if _has_non_hidden_children(traditional_path):\n        return True\n\n    slug = _slugify_model_id(model_id)\n    models_cache_path = os.path.join(MODEL_CACHE_DIR, \"models-cache\", slug)\n    if _has_non_hidden_children(models_cache_path):\n        return True\n\n    return False",
    "optimized_raw_markdown": "```python:inference/core/cache/air_gapped.py\nimport hashlib\nimport os\nimport re\n\nfrom inference.core.env import MODEL_CACHE_DIR, USE_INFERENCE_MODELS\n\n# Precompile regexes to avoid repeated compilation overhead.\n_NON_ALLOWED_RE = re.compile(r\"[^A-Za-z0-9_-]+\")\n_CONSEC_RE = re.compile(r\"[_-]{2,}\")\n\n\ndef _slugify_model_id(model_id: str) -> str:\n    \"\"\"Reproduce the slug used by inference-models for cache directory names.\n\n    Must stay in sync with\n    ``inference_models.models.auto_loaders.core.slugify_model_id_to_os_safe_format``.\n    \"\"\"\n    slug = _NON_ALLOWED_RE.sub(\"-\", model_id)\n    slug = _CONSEC_RE.sub(\"-\", slug)\n    if not slug:\n        slug = \"special-char-only-model-id\"\n    if len(slug) > 48:\n        slug = slug[:48]\n    digest = hashlib.blake2s(model_id.encode(\"utf-8\"), digest_size=4).hexdigest()\n    return f\"{slug}-{digest}\"\n\n\ndef _has_non_hidden_children(path: str) -> bool:\n    \"\"\"Return True if *path* contains at least one non-hidden entry.\n\n    Hidden files (names starting with ``\".\"``) are excluded because they may be\n    stale lock-file leftovers that do not represent usable model artifacts.\n    \"\"\"\n    try:\n        # Use scandir to avoid building a full list of entries and to reduce\n        # syscall overhead compared to listdir + subsequent stats.\n        with os.scandir(path) as it:\n            for entry in it:\n                if not entry.name.startswith(\".\"):\n                    return True\n        return False\n    except OSError:\n        return False\n\n\ndef is_model_cached(model_id: str) -> bool:\n    \"\"\"Best-effort check whether *model_id* has cached artifacts.\n\n    Checks both the traditional and ``inference-models`` cache layouts,\n    respecting the ``USE_INFERENCE_MODELS`` flag to avoid false positives\n    from one layout when the runtime uses the other.\n\n    .. note::\n\n       This is intentionally optimistic \u2014 a directory with non-hidden files\n       is assumed to contain a usable model.  Full integrity verification\n       (hash checks, registry validation) happens at model-load time inside\n       ``inference-models``.  Treat the result as *\"there is a chance the\n       model is cached\"* rather than a guarantee.\n    \"\"\"\n    if not USE_INFERENCE_MODELS:\n        # Only check the traditional layout when inference-models is disabled.\n        traditional_path = os.path.join(MODEL_CACHE_DIR, model_id)\n        return _has_non_hidden_children(traditional_path)\n\n    # When inference-models is enabled, check both layouts \u2014 models cached\n    # before the migration still sit in the traditional tree.\n\n    # When inference-models is enabled, check both layouts \u2014 models cached\n    # before the migration still sit in the traditional tree.\n    traditional_path = os.path.join(MODEL_CACHE_DIR, model_id)\n    if _has_non_hidden_children(traditional_path):\n        return True\n\n    slug = _slugify_model_id(model_id)\n    models_cache_path = os.path.join(MODEL_CACHE_DIR, \"models-cache\", slug)\n    if _has_non_hidden_children(models_cache_path):\n        return True\n\n    return False\n```",
    "optimized_function_only": "def is_model_cached(model_id: str) -> bool:\n    \"\"\"Best-effort check whether *model_id* has cached artifacts.\n\n    Checks both the traditional and ``inference-models`` cache layouts,\n    respecting the ``USE_INFERENCE_MODELS`` flag to avoid false positives\n    from one layout when the runtime uses the other.\n\n    .. note::\n\n       This is intentionally optimistic \u2014 a directory with non-hidden files\n       is assumed to contain a usable model.  Full integrity verification\n       (hash checks, registry validation) happens at model-load time inside\n       ``inference-models``.  Treat the result as *\"there is a chance the\n       model is cached\"* rather than a guarantee.\n    \"\"\"\n    if not USE_INFERENCE_MODELS:\n        # Only check the traditional layout when inference-models is disabled.\n        traditional_path = os.path.join(MODEL_CACHE_DIR, model_id)\n        return _has_non_hidden_children(traditional_path)\n\n    # When inference-models is enabled, check both layouts \u2014 models cached\n    # before the migration still sit in the traditional tree.\n\n    # When inference-models is enabled, check both layouts \u2014 models cached\n    # before the migration still sit in the traditional tree.\n    traditional_path = os.path.join(MODEL_CACHE_DIR, model_id)\n    if _has_non_hidden_children(traditional_path):\n        return True\n\n    slug = _slugify_model_id(model_id)\n    models_cache_path = os.path.join(MODEL_CACHE_DIR, \"models-cache\", slug)\n    if _has_non_hidden_children(models_cache_path):\n        return True\n\n    return False",
    "original_file_content": "\"\"\"Utilities for discovering models and foundation-model weights in the local cache.\n\nUsed by the air-gapped workflow builder to enumerate what is available for\noffline workflow construction.\n\"\"\"\n\nimport hashlib\nimport json\nimport logging\nimport os\nimport re\nfrom typing import Any, Dict, List, Optional\n\nfrom inference.core.env import MODEL_CACHE_DIR, USE_INFERENCE_MODELS\nfrom inference.core.roboflow_api import MODEL_TYPE_KEY, PROJECT_TASK_TYPE_KEY\n\nlogger = logging.getLogger(__name__)\n\n# Directories directly under MODEL_CACHE_DIR that are not model trees.\n_SKIP_TOP_LEVEL = {\"workflow\", \"_file_locks\"}\n\n\ndef _slugify_model_id(model_id: str) -> str:\n    \"\"\"Reproduce the slug used by inference-models for cache directory names.\n\n    Must stay in sync with\n    ``inference_models.models.auto_loaders.core.slugify_model_id_to_os_safe_format``.\n    \"\"\"\n    slug = re.sub(r\"[^A-Za-z0-9_-]+\", \"-\", model_id)\n    slug = re.sub(r\"[_-]{2,}\", \"-\", slug)\n    if not slug:\n        slug = \"special-char-only-model-id\"\n    if len(slug) > 48:\n        slug = slug[:48]\n    digest = hashlib.blake2s(model_id.encode(\"utf-8\"), digest_size=4).hexdigest()\n    return f\"{slug}-{digest}\"\n\n\ndef _has_non_hidden_children(path: str) -> bool:\n    \"\"\"Return True if *path* contains at least one non-hidden entry.\n\n    Hidden files (names starting with ``\".\"``) are excluded because they may be\n    stale lock-file leftovers that do not represent usable model artifacts.\n    \"\"\"\n    try:\n        return any(not f.startswith(\".\") for f in os.listdir(path))\n    except OSError:\n        return False\n\n\ndef is_model_cached(model_id: str) -> bool:\n    \"\"\"Best-effort check whether *model_id* has cached artifacts.\n\n    Checks both the traditional and ``inference-models`` cache layouts,\n    respecting the ``USE_INFERENCE_MODELS`` flag to avoid false positives\n    from one layout when the runtime uses the other.\n\n    .. note::\n\n       This is intentionally optimistic \u2014 a directory with non-hidden files\n       is assumed to contain a usable model.  Full integrity verification\n       (hash checks, registry validation) happens at model-load time inside\n       ``inference-models``.  Treat the result as *\"there is a chance the\n       model is cached\"* rather than a guarantee.\n    \"\"\"\n    if not USE_INFERENCE_MODELS:\n        # Only check the traditional layout when inference-models is disabled.\n        traditional_path = os.path.join(MODEL_CACHE_DIR, model_id)\n        return os.path.isdir(traditional_path) and _has_non_hidden_children(\n            traditional_path\n        )\n\n    # When inference-models is enabled, check both layouts \u2014 models cached\n    # before the migration still sit in the traditional tree.\n    traditional_path = os.path.join(MODEL_CACHE_DIR, model_id)\n    if os.path.isdir(traditional_path) and _has_non_hidden_children(traditional_path):\n        return True\n\n    slug = _slugify_model_id(model_id)\n    models_cache_path = os.path.join(MODEL_CACHE_DIR, \"models-cache\", slug)\n    if os.path.isdir(models_cache_path) and _has_non_hidden_children(models_cache_path):\n        return True\n\n    return False\n\n\ndef has_cached_model_variant(model_variants: Optional[List[str]]) -> bool:\n    \"\"\"Return True if **any** of the given model variant IDs has cached artifacts.\n\n    Args:\n        model_variants: List of model IDs as returned by\n            ``WorkflowBlockManifest.get_supported_model_variants()``.\n            Returns ``False`` when *None* or empty.\n    \"\"\"\n    if not model_variants:\n        return False\n    return any(is_model_cached(mid) for mid in model_variants)\n\n\ndef _load_blocks() -> list:\n    \"\"\"Load workflow blocks, isolating the heavy import for testability.\"\"\"\n    from inference.core.workflows.execution_engine.introspection.blocks_loader import (\n        load_workflow_blocks,\n    )\n\n    return load_workflow_blocks()\n\n\ndef scan_cached_models(cache_dir: str) -> List[Dict[str, Any]]:\n    \"\"\"Walk *cache_dir* looking for ``model_type.json`` marker files.\n\n    Each marker is written by the model registry when a model is first\n    downloaded.  The file contains at least ``project_task_type`` and\n    ``model_type`` keys.\n\n    Returns a list of dicts with the following shape::\n\n        {\n            \"model_id\": \"workspace/project/3\",\n            \"name\": \"workspace/project/3\",\n            \"task_type\": \"object-detection\",\n            \"model_architecture\": \"yolov8n\",\n            \"is_foundation\": False,\n        }\n    \"\"\"\n    results: List[Dict[str, Any]] = []\n    if not os.path.isdir(cache_dir):\n        return results\n\n    for root, dirs, files in os.walk(cache_dir):\n        # Prune top-level directories we know are not model trees.\n        rel = os.path.relpath(root, cache_dir)\n        if rel == \".\":\n            dirs[:] = [d for d in dirs if d not in _SKIP_TOP_LEVEL]\n            continue\n\n        if \"model_type.json\" not in files:\n            continue\n\n        model_type_path = os.path.join(root, \"model_type.json\")\n        try:\n            with open(model_type_path, \"r\") as fh:\n                metadata = json.load(fh)\n        except (json.JSONDecodeError, OSError) as exc:\n            logger.warning(\n                \"Skipping unreadable model_type.json at %s: %s\",\n                model_type_path,\n                exc,\n            )\n            continue\n\n        if not isinstance(metadata, dict):\n            continue\n\n        # Support both traditional keys and inference-models metadata keys.\n        task_type = metadata.get(PROJECT_TASK_TYPE_KEY) or metadata.get(\"taskType\", \"\")\n        model_architecture = metadata.get(MODEL_TYPE_KEY) or metadata.get(\n            \"modelArchitecture\", \"\"\n        )\n\n        if not task_type:\n            continue\n\n        model_id = os.path.relpath(root, cache_dir)\n        # Normalise path separators on Windows.\n        model_id = model_id.replace(os.sep, \"/\")\n\n        results.append(\n            {\n                \"model_id\": model_id,\n                \"name\": model_id,\n                \"task_type\": task_type,\n                \"model_architecture\": model_architecture,\n                \"is_foundation\": False,\n            }\n        )\n\n    return results\n\n\ndef get_cached_foundation_models(\n    blocks: Optional[list] = None,\n) -> List[Dict[str, Any]]:\n    \"\"\"Return metadata for workflow blocks whose required weights are cached.\n\n    Each block whose manifest class exposes ``get_supported_model_variants``\n    is inspected.  If any variant it declares is present in the local cache\n    the block is included in the result list.\n\n    Args:\n        blocks: Optional pre-loaded list of block specifications.  When\n            *None* (the default) the blocks are loaded via the engine's\n            block loader.\n    \"\"\"\n    results: List[Dict[str, Any]] = []\n    if blocks is None:\n        try:\n            blocks = _load_blocks()\n        except Exception:\n            logger.debug(\n                \"Could not load workflow blocks for foundation model scan\",\n                exc_info=True,\n            )\n            return results\n\n    for block in blocks:\n        manifest_cls = block.manifest_class\n        model_variants = manifest_cls.get_supported_model_variants()\n        if model_variants is None:\n            continue\n\n        if not has_cached_model_variant(model_variants):\n            continue\n\n        model_id = model_variants[0] if model_variants else \"\"\n\n        block_name = model_id\n        try:\n            schema = manifest_cls.model_json_schema()\n            block_name = schema.get(\"name\", model_id)\n        except Exception:\n            pass\n\n        block_type_id = _get_block_type_identifier(block)\n\n        results.append(\n            {\n                \"model_id\": model_id,\n                \"name\": block_name,\n                \"task_type\": \"\",\n                \"model_architecture\": \"\",\n                \"is_foundation\": True,\n                \"block_type\": block_type_id,\n            }\n        )\n\n    return results\n\n\ndef get_task_type_to_block_mapping(\n    blocks: Optional[list] = None,\n) -> Dict[str, List[str]]:\n    \"\"\"Build a reverse mapping from task_type to compatible block type identifiers.\n\n    Uses ``get_compatible_task_types()`` on block manifests.  Blocks whose\n    method returns *None* (the base-class default) are skipped.\n\n    Args:\n        blocks: Optional pre-loaded list of block specifications.  When\n            *None* (the default) the blocks are loaded via the engine's\n            block loader.\n    \"\"\"\n    mapping: Dict[str, List[str]] = {}\n    if blocks is None:\n        try:\n            blocks = _load_blocks()\n        except Exception:\n            logger.debug(\n                \"Could not load workflow blocks for task-type mapping\",\n                exc_info=True,\n            )\n            return mapping\n\n    for block in blocks:\n        manifest_cls = block.manifest_class\n        task_types = manifest_cls.get_compatible_task_types()\n        if task_types is None:\n            continue\n\n        block_type_id = _get_block_type_identifier(block)\n        for tt in task_types:\n            mapping.setdefault(tt, []).append(block_type_id)\n\n    return mapping\n\n\ndef _get_block_type_identifier(block) -> str:\n    \"\"\"Extract the canonical ``type`` identifier from a block specification.\"\"\"\n    try:\n        schema = block.manifest_class.model_json_schema()\n        type_prop = schema.get(\"properties\", {}).get(\"type\", {})\n        # The type field is typically a const or enum with one value.\n        if \"const\" in type_prop:\n            return type_prop[\"const\"]\n        if \"enum\" in type_prop and type_prop[\"enum\"]:\n            return type_prop[\"enum\"][0]\n    except Exception:\n        pass\n    return block.identifier\n",
    "patch": null
  },
  {
    "trace_id": "09350212-8ca2-4603-8c4f-dae2bc715c05",
    "function_name": "_build_image_entry",
    "file_path": "inference/enterprise/workflows/enterprise_blocks/sinks/event_writer/v1.py",
    "speedup_x": 0.103020961008418,
    "review_quality": "high",
    "pre_optimization_commit": "ad7d91d0150bee8f45dc26ae83f7c499503c8a4d",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def _build_image_entry(\n    output_image: WorkflowImageData,\n    input_image: Optional[WorkflowImageData] = None,\n    image_label: Optional[str] = None,\n    object_detections: Optional[Any] = None,\n    classifications: Optional[Any] = None,\n    instance_segmentations: Optional[Any] = None,\n    keypoint_detections: Optional[Any] = None,\n) -> Dict[str, Any]:\n    \"\"\"Build the single image object for the v2 API payload.\"\"\"\n    entry: Dict[str, Any] = {\n        \"base64Image\": output_image.base64_image,\n    }\n    if input_image is not None:\n        entry[\"inputBase64Image\"] = input_image.base64_image\n    if image_label is not None:\n        entry[\"label\"] = image_label\n\n    od = _detections_to_v2_object_detections(object_detections)\n    if od:\n        entry[\"objectDetections\"] = od\n\n    cl = _classifications_to_v2(classifications)\n    if cl:\n        entry[\"classifications\"] = cl\n\n    seg = _detections_to_v2_instance_segmentations(instance_segmentations)\n    if seg:\n        entry[\"instanceSegmentations\"] = seg\n\n    kp = _keypoints_to_v2(keypoint_detections)\n    if kp:\n        entry[\"keypoints\"] = kp\n\n    return entry\n",
    "optimized_function_code": "import logging\nfrom typing import Any, Dict, List, Optional\n\nimport cv2\nimport numpy as np\nfrom inference.core.workflows.execution_engine.entities.base import \\\n    WorkflowImageData\n\n\ndef _detections_to_v2_object_detections(detections: Any) -> List[Dict[str, Any]]:\n    \"\"\"Convert Supervision Detections to v2 objectDetections format.\n\n    Uses center-based absolute pixel coordinates to match the main Roboflow\n    annotation format: x,y = center of box, width,height = full dimensions.\n    \"\"\"\n    if detections is None or not hasattr(detections, 'xyxy'):\n        return []\n    try:\n        xyxy = detections.xyxy\n        num_detections = len(xyxy)\n        if num_detections == 0:\n            return []\n        \n        confidence = detections.confidence\n        data = detections.data\n        class_names = data.get(\"class_name\", []) if data else []\n        \n        results = []\n        for i in range(num_detections):\n            x1, y1, x2, y2 = xyxy[i]\n            w = float(x2 - x1)\n            h = float(y2 - y1)\n            results.append(\n                {\n                    \"class\": class_names[i] if i < len(class_names) else \"unknown\",\n                    \"x\": float((x1 + x2) / 2),\n                    \"y\": float((y1 + y2) / 2),\n                    \"width\": w,\n                    \"height\": h,\n                    \"confidence\": (\n                        float(confidence[i]) if confidence is not None else 0.0\n                    ),\n                }\n            )\n        return results\n    except Exception as e:\n        logging.warning(f\"Failed to convert object detections: {e}\")\n        return []\n\n\n\n\ndef _detections_to_v2_instance_segmentations(detections: Any) -> List[Dict[str, Any]]:\n    \"\"\"Convert Supervision Detections with masks to v2 instanceSegmentations format.\"\"\"\n    if detections is None or not hasattr(detections, 'xyxy'):\n        return []\n    try:\n        xyxy = detections.xyxy\n        num_detections = len(xyxy)\n        if num_detections == 0:\n            return []\n        \n        confidence = detections.confidence\n        data = detections.data\n        class_names = data.get(\"class_name\", []) if data else []\n        masks = detections.mask\n        \n        results = []\n        for i in range(num_detections):\n            x1, y1, x2, y2 = xyxy[i]\n            w = float(x2 - x1)\n            h = float(y2 - y1)\n            entry = {\n                \"class\": class_names[i] if i < len(class_names) else \"unknown\",\n                \"x\": float((x1 + x2) / 2),\n                \"y\": float((y1 + y2) / 2),\n                \"width\": w,\n                \"height\": h,\n                \"confidence\": float(confidence[i]) if confidence is not None else 0.0,\n                \"points\": [],\n            }\n            if masks is not None and i < len(masks):\n                mask = masks[i].astype(np.uint8)\n                contours, _ = cv2.findContours(\n                    mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE\n                )\n                if contours:\n                    largest = max(contours, key=cv2.contourArea)\n                    entry[\"points\"] = [\n                        [float(pt[0][0]), float(pt[0][1])] for pt in largest\n                    ]\n            if len(entry[\"points\"]) >= 3:\n                results.append(entry)\n        return results\n    except Exception as e:\n        logging.warning(f\"Failed to convert instance segmentations: {e}\")\n        return []\n\n\n\n\ndef _classifications_to_v2(predictions: Any) -> List[Dict[str, Any]]:\n    \"\"\"Convert classification predictions to v2 classifications format.\"\"\"\n    if predictions is None:\n        return []\n    try:\n        if isinstance(predictions, dict):\n            class_names = predictions.get(\"class_name\", [])\n            num_classes = len(class_names)\n            if num_classes == 0:\n                return []\n            confidences = predictions.get(\"confidence\", [])\n            return [\n                {\n                    \"class\": class_names[i],\n                    \"confidence\": float(confidences[i]) if i < len(confidences) else 0.0,\n                }\n                for i in range(num_classes)\n            ]\n        elif hasattr(predictions, \"data\"):\n            data = predictions.data\n            class_names = data.get(\"class_name\", []) if data else []\n            num_classes = len(class_names)\n            if num_classes == 0:\n                return []\n            confidences = predictions.confidence\n            return [\n                {\n                    \"class\": class_names[i],\n                    \"confidence\": (\n                        float(confidences[i])\n                        if confidences is not None and i < len(confidences)\n                        else 0.0\n                    ),\n                }\n                for i in range(num_classes)\n            ]\n        return []\n    except Exception as e:\n        logging.warning(f\"Failed to convert classifications: {e}\")\n        return []\n\n\n\n\ndef _keypoints_to_v2(detections: Any) -> List[Dict[str, Any]]:\n    \"\"\"Convert keypoint detection predictions to v2 keypoints format.\"\"\"\n    if detections is None or not hasattr(detections, 'xyxy'):\n        return []\n    try:\n        xyxy = detections.xyxy\n        num_detections = len(xyxy)\n        if num_detections == 0:\n            return []\n        \n        confidence = detections.confidence\n        data = detections.data\n        class_names = data.get(\"class_name\", []) if data else []\n        keypoints_xy = data.get(\"keypoints_xy\") if data else None\n        \n        results = []\n        for i in range(num_detections):\n            x1, y1, x2, y2 = xyxy[i]\n            w = float(x2 - x1)\n            h = float(y2 - y1)\n            entry = {\n                \"class\": class_names[i] if i < len(class_names) else \"unknown\",\n                \"x\": float((x1 + x2) / 2),\n                \"y\": float((y1 + y2) / 2),\n                \"width\": w,\n                \"height\": h,\n                \"confidence\": float(confidence[i]) if confidence is not None else 0.0,\n                \"keypoints\": [],\n            }\n            if keypoints_xy is not None and i < len(keypoints_xy):\n                kps = keypoints_xy[i]\n                entry[\"keypoints\"] = [\n                    {\n                        \"id\": j,\n                        \"x\": float(kp[0]),\n                        \"y\": float(kp[1]),\n                    }\n                    for j, kp in enumerate(kps)\n                ]\n            if entry[\"keypoints\"]:\n                results.append(entry)\n        return results\n    except Exception as e:\n        logging.warning(f\"Failed to convert keypoint detections: {e}\")\n        return []\n\n\n\n\ndef _build_image_entry(\n    output_image: WorkflowImageData,\n    input_image: Optional[WorkflowImageData] = None,\n    image_label: Optional[str] = None,\n    object_detections: Optional[Any] = None,\n    classifications: Optional[Any] = None,\n    instance_segmentations: Optional[Any] = None,\n    keypoint_detections: Optional[Any] = None,\n) -> Dict[str, Any]:\n    \"\"\"Build the single image object for the v2 API payload.\"\"\"\n    entry: Dict[str, Any] = {\n        \"base64Image\": output_image.base64_image,\n    }\n    if input_image is not None:\n        entry[\"inputBase64Image\"] = input_image.base64_image\n    if image_label is not None:\n        entry[\"label\"] = image_label\n\n    od = _detections_to_v2_object_detections(object_detections)\n    if od:\n        entry[\"objectDetections\"] = od\n\n    cl = _classifications_to_v2(classifications)\n    if cl:\n        entry[\"classifications\"] = cl\n\n    seg = _detections_to_v2_instance_segmentations(instance_segmentations)\n    if seg:\n        entry[\"instanceSegmentations\"] = seg\n\n    kp = _keypoints_to_v2(keypoint_detections)\n    if kp:\n        entry[\"keypoints\"] = kp\n\n    return entry",
    "optimized_raw_markdown": "```python:inference/enterprise/workflows/enterprise_blocks/sinks/event_writer/v1.py\nimport logging\nfrom typing import Any, Dict, List, Optional\n\nimport cv2\nimport numpy as np\nfrom inference.core.workflows.execution_engine.entities.base import \\\n    WorkflowImageData\n\n\ndef _detections_to_v2_object_detections(detections: Any) -> List[Dict[str, Any]]:\n    \"\"\"Convert Supervision Detections to v2 objectDetections format.\n\n    Uses center-based absolute pixel coordinates to match the main Roboflow\n    annotation format: x,y = center of box, width,height = full dimensions.\n    \"\"\"\n    if detections is None or not hasattr(detections, 'xyxy'):\n        return []\n    try:\n        xyxy = detections.xyxy\n        num_detections = len(xyxy)\n        if num_detections == 0:\n            return []\n        \n        confidence = detections.confidence\n        data = detections.data\n        class_names = data.get(\"class_name\", []) if data else []\n        \n        results = []\n        for i in range(num_detections):\n            x1, y1, x2, y2 = xyxy[i]\n            w = float(x2 - x1)\n            h = float(y2 - y1)\n            results.append(\n                {\n                    \"class\": class_names[i] if i < len(class_names) else \"unknown\",\n                    \"x\": float((x1 + x2) / 2),\n                    \"y\": float((y1 + y2) / 2),\n                    \"width\": w,\n                    \"height\": h,\n                    \"confidence\": (\n                        float(confidence[i]) if confidence is not None else 0.0\n                    ),\n                }\n            )\n        return results\n    except Exception as e:\n        logging.warning(f\"Failed to convert object detections: {e}\")\n        return []\n\n\n\n\ndef _detections_to_v2_instance_segmentations(detections: Any) -> List[Dict[str, Any]]:\n    \"\"\"Convert Supervision Detections with masks to v2 instanceSegmentations format.\"\"\"\n    if detections is None or not hasattr(detections, 'xyxy'):\n        return []\n    try:\n        xyxy = detections.xyxy\n        num_detections = len(xyxy)\n        if num_detections == 0:\n            return []\n        \n        confidence = detections.confidence\n        data = detections.data\n        class_names = data.get(\"class_name\", []) if data else []\n        masks = detections.mask\n        \n        results = []\n        for i in range(num_detections):\n            x1, y1, x2, y2 = xyxy[i]\n            w = float(x2 - x1)\n            h = float(y2 - y1)\n            entry = {\n                \"class\": class_names[i] if i < len(class_names) else \"unknown\",\n                \"x\": float((x1 + x2) / 2),\n                \"y\": float((y1 + y2) / 2),\n                \"width\": w,\n                \"height\": h,\n                \"confidence\": float(confidence[i]) if confidence is not None else 0.0,\n                \"points\": [],\n            }\n            if masks is not None and i < len(masks):\n                mask = masks[i].astype(np.uint8)\n                contours, _ = cv2.findContours(\n                    mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE\n                )\n                if contours:\n                    largest = max(contours, key=cv2.contourArea)\n                    entry[\"points\"] = [\n                        [float(pt[0][0]), float(pt[0][1])] for pt in largest\n                    ]\n            if len(entry[\"points\"]) >= 3:\n                results.append(entry)\n        return results\n    except Exception as e:\n        logging.warning(f\"Failed to convert instance segmentations: {e}\")\n        return []\n\n\n\n\ndef _classifications_to_v2(predictions: Any) -> List[Dict[str, Any]]:\n    \"\"\"Convert classification predictions to v2 classifications format.\"\"\"\n    if predictions is None:\n        return []\n    try:\n        if isinstance(predictions, dict):\n            class_names = predictions.get(\"class_name\", [])\n            num_classes = len(class_names)\n            if num_classes == 0:\n                return []\n            confidences = predictions.get(\"confidence\", [])\n            return [\n                {\n                    \"class\": class_names[i],\n                    \"confidence\": float(confidences[i]) if i < len(confidences) else 0.0,\n                }\n                for i in range(num_classes)\n            ]\n        elif hasattr(predictions, \"data\"):\n            data = predictions.data\n            class_names = data.get(\"class_name\", []) if data else []\n            num_classes = len(class_names)\n            if num_classes == 0:\n                return []\n            confidences = predictions.confidence\n            return [\n                {\n                    \"class\": class_names[i],\n                    \"confidence\": (\n                        float(confidences[i])\n                        if confidences is not None and i < len(confidences)\n                        else 0.0\n                    ),\n                }\n                for i in range(num_classes)\n            ]\n        return []\n    except Exception as e:\n        logging.warning(f\"Failed to convert classifications: {e}\")\n        return []\n\n\n\n\ndef _keypoints_to_v2(detections: Any) -> List[Dict[str, Any]]:\n    \"\"\"Convert keypoint detection predictions to v2 keypoints format.\"\"\"\n    if detections is None or not hasattr(detections, 'xyxy'):\n        return []\n    try:\n        xyxy = detections.xyxy\n        num_detections = len(xyxy)\n        if num_detections == 0:\n            return []\n        \n        confidence = detections.confidence\n        data = detections.data\n        class_names = data.get(\"class_name\", []) if data else []\n        keypoints_xy = data.get(\"keypoints_xy\") if data else None\n        \n        results = []\n        for i in range(num_detections):\n            x1, y1, x2, y2 = xyxy[i]\n            w = float(x2 - x1)\n            h = float(y2 - y1)\n            entry = {\n                \"class\": class_names[i] if i < len(class_names) else \"unknown\",\n                \"x\": float((x1 + x2) / 2),\n                \"y\": float((y1 + y2) / 2),\n                \"width\": w,\n                \"height\": h,\n                \"confidence\": float(confidence[i]) if confidence is not None else 0.0,\n                \"keypoints\": [],\n            }\n            if keypoints_xy is not None and i < len(keypoints_xy):\n                kps = keypoints_xy[i]\n                entry[\"keypoints\"] = [\n                    {\n                        \"id\": j,\n                        \"x\": float(kp[0]),\n                        \"y\": float(kp[1]),\n                    }\n                    for j, kp in enumerate(kps)\n                ]\n            if entry[\"keypoints\"]:\n                results.append(entry)\n        return results\n    except Exception as e:\n        logging.warning(f\"Failed to convert keypoint detections: {e}\")\n        return []\n\n\n\n\ndef _build_image_entry(\n    output_image: WorkflowImageData,\n    input_image: Optional[WorkflowImageData] = None,\n    image_label: Optional[str] = None,\n    object_detections: Optional[Any] = None,\n    classifications: Optional[Any] = None,\n    instance_segmentations: Optional[Any] = None,\n    keypoint_detections: Optional[Any] = None,\n) -> Dict[str, Any]:\n    \"\"\"Build the single image object for the v2 API payload.\"\"\"\n    entry: Dict[str, Any] = {\n        \"base64Image\": output_image.base64_image,\n    }\n    if input_image is not None:\n        entry[\"inputBase64Image\"] = input_image.base64_image\n    if image_label is not None:\n        entry[\"label\"] = image_label\n\n    od = _detections_to_v2_object_detections(object_detections)\n    if od:\n        entry[\"objectDetections\"] = od\n\n    cl = _classifications_to_v2(classifications)\n    if cl:\n        entry[\"classifications\"] = cl\n\n    seg = _detections_to_v2_instance_segmentations(instance_segmentations)\n    if seg:\n        entry[\"instanceSegmentations\"] = seg\n\n    kp = _keypoints_to_v2(keypoint_detections)\n    if kp:\n        entry[\"keypoints\"] = kp\n\n    return entry\n```",
    "optimized_function_only": "def _build_image_entry(\n    output_image: WorkflowImageData,\n    input_image: Optional[WorkflowImageData] = None,\n    image_label: Optional[str] = None,\n    object_detections: Optional[Any] = None,\n    classifications: Optional[Any] = None,\n    instance_segmentations: Optional[Any] = None,\n    keypoint_detections: Optional[Any] = None,\n) -> Dict[str, Any]:\n    \"\"\"Build the single image object for the v2 API payload.\"\"\"\n    entry: Dict[str, Any] = {\n        \"base64Image\": output_image.base64_image,\n    }\n    if input_image is not None:\n        entry[\"inputBase64Image\"] = input_image.base64_image\n    if image_label is not None:\n        entry[\"label\"] = image_label\n\n    od = _detections_to_v2_object_detections(object_detections)\n    if od:\n        entry[\"objectDetections\"] = od\n\n    cl = _classifications_to_v2(classifications)\n    if cl:\n        entry[\"classifications\"] = cl\n\n    seg = _detections_to_v2_instance_segmentations(instance_segmentations)\n    if seg:\n        entry[\"instanceSegmentations\"] = seg\n\n    kp = _keypoints_to_v2(keypoint_detections)\n    if kp:\n        entry[\"keypoints\"] = kp\n\n    return entry",
    "original_file_content": "import logging\nimport os\nfrom concurrent.futures import ThreadPoolExecutor\nfrom datetime import datetime, timezone\nfrom functools import partial\nfrom typing import Any, Dict, List, Literal, Optional, Tuple, Type, Union\nfrom urllib.parse import urljoin\n\nimport cv2\nimport numpy as np\nimport requests\nfrom fastapi import BackgroundTasks\nfrom pydantic import ConfigDict, Field\n\nfrom inference.core.workflows.execution_engine.entities.base import (\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    BOOLEAN_KIND,\n    CLASSIFICATION_PREDICTION_KIND,\n    IMAGE_KIND,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    INTEGER_KIND,\n    KEYPOINT_DETECTION_PREDICTION_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    STRING_KIND,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nLONG_DESCRIPTION = \"\"\"\nThe **Event Writer** block sends structured events to the Event Ingestion Service\nusing the v2 API.\n\n## Supported Event Schemas\n\n* **Quality Check** \u2014 pass/fail inspection results\n* **Inventory Count** \u2014 item counts at a location\n* **Safety Alert** \u2014 safety incidents with severity levels\n* **Custom** \u2014 free-form events with an arbitrary value field\n\n## Images\n\nEach event includes one image entry. You must provide an **output image** (the\nprimary display image, typically a visualization). You can optionally attach an\n**input image** (the original frame before any annotation).\n\n## Annotations\n\nYou can optionally pass object detection, classification, instance segmentation,\nor keypoint predictions from upstream model blocks. These are stored as\nstructured annotations on the image within the event.\n\n## Execution Modes\n\n* **Fire-and-forget** (`fire_and_forget=True`, default) \u2014 the HTTP request is\n  dispatched in the background so the workflow continues immediately. The\n  `event_id` output will be empty.\n* **Synchronous** (`fire_and_forget=False`) \u2014 the block waits for the response\n  and returns the created `event_id`.\n\n## Rate Limiting\n\nUse the **Rate Limiter** workflow block upstream of this block to control how\noften events are sent.\n\n## Authentication\n\nIf the Event Ingestion Service requires an API key, set the\n`EVENT_INGESTION_API_KEY` environment variable on the inference server.\nRequests are sent unauthenticated when the variable is not set.\n\"\"\"\n\nQUALITY_CHECK_RELEVANT = {\n    \"event_schema\": {\"values\": [\"quality_check\"], \"required\": True},\n}\nINVENTORY_COUNT_RELEVANT = {\n    \"event_schema\": {\"values\": [\"inventory_count\"], \"required\": True},\n}\nSAFETY_ALERT_RELEVANT = {\n    \"event_schema\": {\"values\": [\"safety_alert\"], \"required\": True},\n}\nCUSTOM_RELEVANT = {\n    \"event_schema\": {\"values\": [\"custom\"], \"required\": True},\n}\nALL_DATA_SCHEMAS_RELEVANT = {\n    \"event_schema\": {\n        \"values\": [\"quality_check\", \"inventory_count\", \"safety_alert\", \"custom\"],\n    },\n}\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Event Writer\",\n            \"version\": \"v1\",\n            \"short_description\": \"Write structured events to the Event Ingestion Service.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Roboflow Enterprise License\",\n            \"block_type\": \"sink\",\n            \"ui_manifest\": {\n                \"section\": \"industrial\",\n                \"icon\": \"fal fa-calendar-check\",\n                \"blockPriority\": 5,\n                \"enterprise_only\": True,\n                \"local_only\": True,\n            },\n        }\n    )\n    type: Literal[\"roboflow_enterprise/event_writer_sink@v1\"]\n\n    # --- Connection ---\n    event_ingestion_url: Union[Selector(kind=[STRING_KIND]), str] = Field(\n        default=\"http://localhost:8001\",\n        description=\"Base URL of the Event Ingestion Service.\",\n        examples=[\"http://localhost:8001\", \"$inputs.event_ingestion_url\"],\n    )\n\n    # --- Schema selector ---\n    event_schema: Literal[\n        \"quality_check\", \"inventory_count\", \"safety_alert\", \"custom\"\n    ] = Field(\n        description=\"The event schema to use.\",\n        json_schema_extra={\"always_visible\": True},\n    )\n\n    # --- Images ---\n    output_image: Selector(kind=[IMAGE_KIND]) = Field(\n        description=\"The output/visualization image. Sent as the primary display image.\",\n        json_schema_extra={\"always_visible\": True},\n    )\n    input_image: Optional[Selector(kind=[IMAGE_KIND])] = Field(\n        default=None,\n        description=\"The original input image (optional). Sent as the source image.\",\n    )\n    image_label: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Label for the image entry.\",\n        examples=[\"defect-analysis\", \"$inputs.image_label\"],\n    )\n\n    # --- Custom metadata ---\n    custom_metadata: Dict[\n        str,\n        Union[\n            Selector(),\n            str,\n            float,\n            bool,\n            int,\n        ],\n    ] = Field(\n        default_factory=dict,\n        description=\"Flat key-value metadata (max 100 keys, values must be str/int/float/bool).\",\n        examples=[{\"line\": \"A1\", \"shift\": \"morning\"}],\n        json_schema_extra={\"always_visible\": True},\n    )\n\n    # --- Quality Check fields ---\n    qc_result: Optional[\n        Union[Selector(kind=[STRING_KIND]), Literal[\"pass\", \"fail\"]]\n    ] = Field(\n        default=None,\n        description=\"Quality check result: pass or fail.\",\n        examples=[\"pass\", \"fail\", \"$steps.qc_logic.result\"],\n        json_schema_extra={\n            \"relevant_for\": QUALITY_CHECK_RELEVANT,\n            \"always_visible\": True,\n        },\n    )\n\n    # --- External ID (shared across schemas) ---\n    external_id: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"External identifier for correlation with other systems (max 1000 chars).\",\n        examples=[\"batch-2025-001\", \"$inputs.external_id\"],\n        json_schema_extra={\n            \"relevant_for\": ALL_DATA_SCHEMAS_RELEVANT,\n        },\n    )\n\n    # --- Inventory Count fields ---\n    location: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Location identifier for inventory count.\",\n        examples=[\"warehouse-A\", \"$inputs.location\"],\n        json_schema_extra={\"relevant_for\": INVENTORY_COUNT_RELEVANT},\n    )\n    item_count: Optional[Union[Selector(kind=[INTEGER_KIND]), int]] = Field(\n        default=None,\n        description=\"Number of items counted.\",\n        examples=[42, \"$steps.counter.count\"],\n        json_schema_extra={\"relevant_for\": INVENTORY_COUNT_RELEVANT},\n    )\n    item_type: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Type of item being counted.\",\n        examples=[\"widget\", \"$inputs.item_type\"],\n        json_schema_extra={\"relevant_for\": INVENTORY_COUNT_RELEVANT},\n    )\n\n    # --- Safety Alert fields ---\n    alert_type: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Alert type identifier (alphanumeric, underscores, hyphens).\",\n        examples=[\"no_hardhat\", \"$steps.classifier.top_class\"],\n        json_schema_extra={\"relevant_for\": SAFETY_ALERT_RELEVANT},\n    )\n    severity: Optional[\n        Union[Selector(kind=[STRING_KIND]), Literal[\"low\", \"medium\", \"high\"]]\n    ] = Field(\n        default=None,\n        description=\"Severity level for the safety alert.\",\n        examples=[\"high\", \"$inputs.severity\"],\n        json_schema_extra={\"relevant_for\": SAFETY_ALERT_RELEVANT},\n    )\n    alert_description: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Description of the safety alert (max 10000 chars).\",\n        examples=[\"Worker detected without hardhat in zone B\"],\n        json_schema_extra={\"relevant_for\": SAFETY_ALERT_RELEVANT},\n    )\n\n    # --- Custom Event fields ---\n    custom_value: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Arbitrary value for custom events (max 10000 chars).\",\n        examples=[\"anomaly detected at 14:32\"],\n        json_schema_extra={\"relevant_for\": CUSTOM_RELEVANT},\n    )\n\n    # --- Annotation pass-through ---\n    object_detections: Optional[Selector(kind=[OBJECT_DETECTION_PREDICTION_KIND])] = (\n        Field(\n            default=None,\n            description=\"Object detection predictions to attach to the image.\",\n            json_schema_extra={\"additional_section\": True},\n        )\n    )\n    classifications: Optional[Selector(kind=[CLASSIFICATION_PREDICTION_KIND])] = Field(\n        default=None,\n        description=\"Classification predictions to attach to the image.\",\n        json_schema_extra={\"additional_section\": True},\n    )\n    instance_segmentations: Optional[\n        Selector(kind=[INSTANCE_SEGMENTATION_PREDICTION_KIND])\n    ] = Field(\n        default=None,\n        description=\"Instance segmentation predictions to attach to the image.\",\n        json_schema_extra={\"additional_section\": True},\n    )\n    keypoint_detections: Optional[\n        Selector(kind=[KEYPOINT_DETECTION_PREDICTION_KIND])\n    ] = Field(\n        default=None,\n        description=\"Keypoint detection predictions to attach to the image.\",\n        json_schema_extra={\"additional_section\": True},\n    )\n\n    # --- Execution control ---\n    fire_and_forget: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=True,\n        description=\"If True, send the event asynchronously (no event_id returned). \"\n        \"If False, wait for the response and return the event_id.\",\n        examples=[True, False, \"$inputs.fire_and_forget\"],\n    )\n    disable_sink: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=False,\n        description=\"If True, skip sending the event entirely.\",\n        examples=[False, \"$inputs.disable_event_writer\"],\n    )\n    request_timeout: Union[int, Selector(kind=[INTEGER_KIND])] = Field(\n        default=5,\n        description=\"HTTP request timeout in seconds.\",\n        examples=[5, 10],\n    )\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"error_status\", kind=[BOOLEAN_KIND]),\n            OutputDefinition(name=\"event_id\", kind=[STRING_KIND]),\n            OutputDefinition(name=\"message\", kind=[STRING_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass EventWriterSinkBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        background_tasks: Optional[BackgroundTasks],\n        thread_pool_executor: Optional[ThreadPoolExecutor],\n    ):\n        self._background_tasks = background_tasks\n        self._thread_pool_executor = thread_pool_executor\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"background_tasks\", \"thread_pool_executor\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        event_ingestion_url: str,\n        event_schema: str,\n        output_image: WorkflowImageData,\n        fire_and_forget: bool,\n        disable_sink: bool,\n        request_timeout: int,\n        input_image: Optional[WorkflowImageData] = None,\n        image_label: Optional[str] = None,\n        custom_metadata: Optional[Dict[str, Any]] = None,\n        qc_result: Optional[str] = None,\n        external_id: Optional[str] = None,\n        location: Optional[str] = None,\n        item_count: Optional[int] = None,\n        item_type: Optional[str] = None,\n        alert_type: Optional[str] = None,\n        severity: Optional[str] = None,\n        alert_description: Optional[str] = None,\n        custom_value: Optional[str] = None,\n        object_detections: Optional[Any] = None,\n        classifications: Optional[Any] = None,\n        instance_segmentations: Optional[Any] = None,\n        keypoint_detections: Optional[Any] = None,\n    ) -> BlockResult:\n        if disable_sink:\n            return {\n                \"error_status\": False,\n                \"event_id\": \"\",\n                \"message\": \"Sink was disabled by parameter `disable_sink`\",\n            }\n\n        event_data = _build_event_data(\n            event_schema=event_schema,\n            qc_result=qc_result,\n            external_id=external_id,\n            location=location,\n            item_count=item_count,\n            item_type=item_type,\n            alert_type=alert_type,\n            severity=severity,\n            alert_description=alert_description,\n            custom_value=custom_value,\n        )\n\n        image_entry = _build_image_entry(\n            output_image=output_image,\n            input_image=input_image,\n            image_label=image_label,\n            object_detections=object_detections,\n            classifications=classifications,\n            instance_segmentations=instance_segmentations,\n            keypoint_detections=keypoint_detections,\n        )\n\n        payload: Dict[str, Any] = {\n            \"inference_timestamp\": datetime.now(timezone.utc).isoformat(),\n            \"event_schema\": event_schema,\n            \"event_data\": event_data,\n            \"images\": [image_entry],\n            \"displayImagePosition\": 0,\n        }\n        if custom_metadata:\n            payload[\"custom_metadata\"] = custom_metadata\n\n        request_handler = partial(\n            _execute_event_request,\n            url=urljoin(event_ingestion_url, \"/v2/events\"),\n            payload=payload,\n            api_key=os.environ.get(\"EVENT_INGESTION_API_KEY\"),\n            timeout=request_timeout,\n        )\n\n        if fire_and_forget and self._background_tasks:\n            self._background_tasks.add_task(request_handler)\n            return {\n                \"error_status\": False,\n                \"event_id\": \"\",\n                \"message\": \"Event sent in background task\",\n            }\n        if fire_and_forget and self._thread_pool_executor:\n            self._thread_pool_executor.submit(request_handler)\n            return {\n                \"error_status\": False,\n                \"event_id\": \"\",\n                \"message\": \"Event sent in background task\",\n            }\n\n        error_status, message, event_id = request_handler()\n        return {\n            \"error_status\": error_status,\n            \"event_id\": event_id,\n            \"message\": message,\n        }\n\n\ndef _build_event_data(\n    event_schema: str,\n    qc_result: Optional[str] = None,\n    external_id: Optional[str] = None,\n    location: Optional[str] = None,\n    item_count: Optional[int] = None,\n    item_type: Optional[str] = None,\n    alert_type: Optional[str] = None,\n    severity: Optional[str] = None,\n    alert_description: Optional[str] = None,\n    custom_value: Optional[str] = None,\n) -> Dict[str, Any]:\n    \"\"\"Build schema-specific event_data dict with camelCase keys, stripping None values.\"\"\"\n    if event_schema == \"quality_check\":\n        data = {\"result\": qc_result, \"externalId\": external_id}\n    elif event_schema == \"inventory_count\":\n        data = {\n            \"location\": location,\n            \"itemCount\": item_count,\n            \"itemType\": item_type,\n            \"externalId\": external_id,\n        }\n    elif event_schema == \"safety_alert\":\n        data = {\n            \"alertType\": alert_type,\n            \"severity\": severity,\n            \"description\": alert_description,\n            \"externalId\": external_id,\n        }\n    elif event_schema == \"custom\":\n        data = {\"externalId\": external_id, \"value\": custom_value}\n    else:\n        data = {}\n    # Strip None values \u2014 event_data schemas use extra=\"forbid\"\n    return {k: v for k, v in data.items() if v is not None}\n\n\ndef _detections_to_v2_object_detections(detections: Any) -> List[Dict[str, Any]]:\n    \"\"\"Convert Supervision Detections to v2 objectDetections format.\n\n    Uses center-based absolute pixel coordinates to match the main Roboflow\n    annotation format: x,y = center of box, width,height = full dimensions.\n    \"\"\"\n    if detections is None:\n        return []\n    results = []\n    try:\n        xyxy = detections.xyxy\n        confidence = detections.confidence\n        class_names = detections.data.get(\"class_name\", [])\n        for i in range(len(xyxy)):\n            x1, y1, x2, y2 = xyxy[i]\n            w = float(x2 - x1)\n            h = float(y2 - y1)\n            results.append(\n                {\n                    \"class\": class_names[i] if i < len(class_names) else \"unknown\",\n                    \"x\": float((x1 + x2) / 2),\n                    \"y\": float((y1 + y2) / 2),\n                    \"width\": w,\n                    \"height\": h,\n                    \"confidence\": (\n                        float(confidence[i]) if confidence is not None else 0.0\n                    ),\n                }\n            )\n    except Exception as e:\n        logging.warning(f\"Failed to convert object detections: {e}\")\n    return results\n\n\ndef _detections_to_v2_instance_segmentations(detections: Any) -> List[Dict[str, Any]]:\n    \"\"\"Convert Supervision Detections with masks to v2 instanceSegmentations format.\"\"\"\n    if detections is None:\n        return []\n    results = []\n    try:\n        xyxy = detections.xyxy\n        confidence = detections.confidence\n        class_names = detections.data.get(\"class_name\", [])\n        masks = detections.mask\n        for i in range(len(xyxy)):\n            x1, y1, x2, y2 = xyxy[i]\n            w = float(x2 - x1)\n            h = float(y2 - y1)\n            entry = {\n                \"class\": class_names[i] if i < len(class_names) else \"unknown\",\n                \"x\": float((x1 + x2) / 2),\n                \"y\": float((y1 + y2) / 2),\n                \"width\": w,\n                \"height\": h,\n                \"confidence\": float(confidence[i]) if confidence is not None else 0.0,\n                \"points\": [],\n            }\n            if masks is not None and i < len(masks):\n                mask = masks[i].astype(np.uint8)\n                contours, _ = cv2.findContours(\n                    mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE\n                )\n                if contours:\n                    largest = max(contours, key=cv2.contourArea)\n                    entry[\"points\"] = [\n                        [float(pt[0][0]), float(pt[0][1])] for pt in largest\n                    ]\n            if len(entry[\"points\"]) >= 3:\n                results.append(entry)\n    except Exception as e:\n        logging.warning(f\"Failed to convert instance segmentations: {e}\")\n    return results\n\n\ndef _classifications_to_v2(predictions: Any) -> List[Dict[str, Any]]:\n    \"\"\"Convert classification predictions to v2 classifications format.\"\"\"\n    if predictions is None:\n        return []\n    results = []\n    try:\n        if isinstance(predictions, dict):\n            class_names = predictions.get(\"class_name\", [])\n            confidences = predictions.get(\"confidence\", [])\n            for i in range(len(class_names)):\n                results.append(\n                    {\n                        \"class\": class_names[i],\n                        \"confidence\": (\n                            float(confidences[i]) if i < len(confidences) else 0.0\n                        ),\n                    }\n                )\n        elif hasattr(predictions, \"data\"):\n            class_names = predictions.data.get(\"class_name\", [])\n            confidences = predictions.confidence\n            for i in range(len(class_names)):\n                results.append(\n                    {\n                        \"class\": class_names[i],\n                        \"confidence\": (\n                            float(confidences[i])\n                            if confidences is not None and i < len(confidences)\n                            else 0.0\n                        ),\n                    }\n                )\n    except Exception as e:\n        logging.warning(f\"Failed to convert classifications: {e}\")\n    return results\n\n\ndef _keypoints_to_v2(detections: Any) -> List[Dict[str, Any]]:\n    \"\"\"Convert keypoint detection predictions to v2 keypoints format.\"\"\"\n    if detections is None:\n        return []\n    results = []\n    try:\n        xyxy = detections.xyxy\n        confidence = detections.confidence\n        class_names = detections.data.get(\"class_name\", [])\n        keypoints_xy = detections.data.get(\"keypoints_xy\")\n        for i in range(len(xyxy)):\n            x1, y1, x2, y2 = xyxy[i]\n            w = float(x2 - x1)\n            h = float(y2 - y1)\n            entry = {\n                \"class\": class_names[i] if i < len(class_names) else \"unknown\",\n                \"x\": float((x1 + x2) / 2),\n                \"y\": float((y1 + y2) / 2),\n                \"width\": w,\n                \"height\": h,\n                \"confidence\": float(confidence[i]) if confidence is not None else 0.0,\n                \"keypoints\": [],\n            }\n            if keypoints_xy is not None and i < len(keypoints_xy):\n                kps = keypoints_xy[i]\n                for j, kp in enumerate(kps):\n                    entry[\"keypoints\"].append(\n                        {\n                            \"id\": j,\n                            \"x\": float(kp[0]),\n                            \"y\": float(kp[1]),\n                        }\n                    )\n            if entry[\"keypoints\"]:\n                results.append(entry)\n    except Exception as e:\n        logging.warning(f\"Failed to convert keypoint detections: {e}\")\n    return results\n\n\ndef _build_image_entry(\n    output_image: WorkflowImageData,\n    input_image: Optional[WorkflowImageData] = None,\n    image_label: Optional[str] = None,\n    object_detections: Optional[Any] = None,\n    classifications: Optional[Any] = None,\n    instance_segmentations: Optional[Any] = None,\n    keypoint_detections: Optional[Any] = None,\n) -> Dict[str, Any]:\n    \"\"\"Build the single image object for the v2 API payload.\"\"\"\n    entry: Dict[str, Any] = {\n        \"base64Image\": output_image.base64_image,\n    }\n    if input_image is not None:\n        entry[\"inputBase64Image\"] = input_image.base64_image\n    if image_label is not None:\n        entry[\"label\"] = image_label\n\n    od = _detections_to_v2_object_detections(object_detections)\n    if od:\n        entry[\"objectDetections\"] = od\n\n    cl = _classifications_to_v2(classifications)\n    if cl:\n        entry[\"classifications\"] = cl\n\n    seg = _detections_to_v2_instance_segmentations(instance_segmentations)\n    if seg:\n        entry[\"instanceSegmentations\"] = seg\n\n    kp = _keypoints_to_v2(keypoint_detections)\n    if kp:\n        entry[\"keypoints\"] = kp\n\n    return entry\n\n\ndef _execute_event_request(\n    url: str,\n    payload: Dict[str, Any],\n    api_key: Optional[str],\n    timeout: int,\n) -> Tuple[bool, str, str]:\n    \"\"\"POST the event to the ingestion service.\n\n    Returns:\n        (error_status, message, event_id)\n    \"\"\"\n    try:\n        headers: Dict[str, str] = {\"Content-Type\": \"application/json\"}\n        if api_key:\n            headers[\"X-API-Key\"] = api_key\n\n        response = requests.post(url, json=payload, headers=headers, timeout=timeout)\n\n        if response.status_code == 201:\n            data = response.json()\n            event_id = str(data.get(\"id\", \"\"))\n            return False, \"Event created successfully\", event_id\n\n        if response.status_code == 529:\n            detail = _extract_detail(response)\n            return (\n                True,\n                f\"Event Ingestion Service at capacity (529). \"\n                f\"The device is experiencing backpressure. Detail: {detail}\",\n                \"\",\n            )\n\n        detail = _extract_detail(response)\n        return True, f\"HTTP {response.status_code}: {detail}\", \"\"\n    except requests.exceptions.Timeout:\n        return True, f\"Request timed out after {timeout}s\", \"\"\n    except Exception as e:\n        logging.warning(f\"Event writer request failed: {e}\")\n        return True, f\"Request failed: {e}\", \"\"\n\n\ndef _extract_detail(response: requests.Response) -> str:\n    \"\"\"Try to extract 'detail' from a JSON error response.\"\"\"\n    try:\n        return str(response.json().get(\"detail\", response.text))\n    except Exception:\n        return response.text\n",
    "patch": null
  },
  {
    "trace_id": "d7f98495-d3fc-4892-9c87-e67a39b02bc7",
    "function_name": "_detections_to_v2_instance_segmentations",
    "file_path": "inference/enterprise/workflows/enterprise_blocks/sinks/event_writer/v1.py",
    "speedup_x": 1.1844541446213097,
    "review_quality": "high",
    "pre_optimization_commit": "ad7d91d0150bee8f45dc26ae83f7c499503c8a4d",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def _detections_to_v2_instance_segmentations(detections: Any) -> List[Dict[str, Any]]:\n    \"\"\"Convert Supervision Detections with masks to v2 instanceSegmentations format.\"\"\"\n    if detections is None:\n        return []\n    results = []\n    try:\n        xyxy = detections.xyxy\n        confidence = detections.confidence\n        class_names = detections.data.get(\"class_name\", [])\n        masks = detections.mask\n        for i in range(len(xyxy)):\n            x1, y1, x2, y2 = xyxy[i]\n            w = float(x2 - x1)\n            h = float(y2 - y1)\n            entry = {\n                \"class\": class_names[i] if i < len(class_names) else \"unknown\",\n                \"x\": float((x1 + x2) / 2),\n                \"y\": float((y1 + y2) / 2),\n                \"width\": w,\n                \"height\": h,\n                \"confidence\": float(confidence[i]) if confidence is not None else 0.0,\n                \"points\": [],\n            }\n            if masks is not None and i < len(masks):\n                mask = masks[i].astype(np.uint8)\n                contours, _ = cv2.findContours(\n                    mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE\n                )\n                if contours:\n                    largest = max(contours, key=cv2.contourArea)\n                    entry[\"points\"] = [\n                        [float(pt[0][0]), float(pt[0][1])] for pt in largest\n                    ]\n            if len(entry[\"points\"]) >= 3:\n                results.append(entry)\n    except Exception as e:\n        logging.warning(f\"Failed to convert instance segmentations: {e}\")\n    return results\n",
    "optimized_function_code": "import cv2\nimport logging\nimport numpy as np\nfrom typing import Any, Dict, List\n\n\ndef _detections_to_v2_instance_segmentations(detections: Any) -> List[Dict[str, Any]]:\n    \"\"\"Convert Supervision Detections with masks to v2 instanceSegmentations format.\"\"\"\n    if detections is None:\n        return []\n    results = []\n    try:\n        xyxy = detections.xyxy\n        confidence = detections.confidence\n        class_names = detections.data.get(\"class_name\", [])\n        masks = detections.mask\n        if masks is None:\n            return results\n        for i, (box, mask) in enumerate(zip(xyxy, masks)):\n            if mask is None:\n                continue\n            mask = mask.astype(np.uint8)\n            contours, _ = cv2.findContours(\n                mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE\n            )\n            if not contours:\n                continue\n            largest = max(contours, key=cv2.contourArea)\n            pts = np.asarray(largest).reshape(-1, 2)\n            if pts.shape[0] < 3:\n                continue\n            x1, y1, x2, y2 = box\n            w = float(x2 - x1)\n            h = float(y2 - y1)\n            entry = {\n                \"class\": class_names[i] if i < len(class_names) else \"unknown\",\n                \"x\": float((x1 + x2) / 2),\n                \"y\": float((y1 + y2) / 2),\n                \"width\": w,\n                \"height\": h,\n                \"confidence\": float(confidence[i]) if confidence is not None else 0.0,\n                \"points\": pts.astype(float).tolist(),\n            }\n            results.append(entry)\n    except Exception as e:\n        logging.warning(f\"Failed to convert instance segmentations: {e}\")\n    return results",
    "optimized_raw_markdown": "```python:inference/enterprise/workflows/enterprise_blocks/sinks/event_writer/v1.py\nimport cv2\nimport logging\nimport numpy as np\nfrom typing import Any, Dict, List\n\n\ndef _detections_to_v2_instance_segmentations(detections: Any) -> List[Dict[str, Any]]:\n    \"\"\"Convert Supervision Detections with masks to v2 instanceSegmentations format.\"\"\"\n    if detections is None:\n        return []\n    results = []\n    try:\n        xyxy = detections.xyxy\n        confidence = detections.confidence\n        class_names = detections.data.get(\"class_name\", [])\n        masks = detections.mask\n        if masks is None:\n            return results\n        for i, (box, mask) in enumerate(zip(xyxy, masks)):\n            if mask is None:\n                continue\n            mask = mask.astype(np.uint8)\n            contours, _ = cv2.findContours(\n                mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE\n            )\n            if not contours:\n                continue\n            largest = max(contours, key=cv2.contourArea)\n            pts = np.asarray(largest).reshape(-1, 2)\n            if pts.shape[0] < 3:\n                continue\n            x1, y1, x2, y2 = box\n            w = float(x2 - x1)\n            h = float(y2 - y1)\n            entry = {\n                \"class\": class_names[i] if i < len(class_names) else \"unknown\",\n                \"x\": float((x1 + x2) / 2),\n                \"y\": float((y1 + y2) / 2),\n                \"width\": w,\n                \"height\": h,\n                \"confidence\": float(confidence[i]) if confidence is not None else 0.0,\n                \"points\": pts.astype(float).tolist(),\n            }\n            results.append(entry)\n    except Exception as e:\n        logging.warning(f\"Failed to convert instance segmentations: {e}\")\n    return results\n```",
    "optimized_function_only": "def _detections_to_v2_instance_segmentations(detections: Any) -> List[Dict[str, Any]]:\n    \"\"\"Convert Supervision Detections with masks to v2 instanceSegmentations format.\"\"\"\n    if detections is None:\n        return []\n    results = []\n    try:\n        xyxy = detections.xyxy\n        confidence = detections.confidence\n        class_names = detections.data.get(\"class_name\", [])\n        masks = detections.mask\n        if masks is None:\n            return results\n        for i, (box, mask) in enumerate(zip(xyxy, masks)):\n            if mask is None:\n                continue\n            mask = mask.astype(np.uint8)\n            contours, _ = cv2.findContours(\n                mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE\n            )\n            if not contours:\n                continue\n            largest = max(contours, key=cv2.contourArea)\n            pts = np.asarray(largest).reshape(-1, 2)\n            if pts.shape[0] < 3:\n                continue\n            x1, y1, x2, y2 = box\n            w = float(x2 - x1)\n            h = float(y2 - y1)\n            entry = {\n                \"class\": class_names[i] if i < len(class_names) else \"unknown\",\n                \"x\": float((x1 + x2) / 2),\n                \"y\": float((y1 + y2) / 2),\n                \"width\": w,\n                \"height\": h,\n                \"confidence\": float(confidence[i]) if confidence is not None else 0.0,\n                \"points\": pts.astype(float).tolist(),\n            }\n            results.append(entry)\n    except Exception as e:\n        logging.warning(f\"Failed to convert instance segmentations: {e}\")\n    return results",
    "original_file_content": "import logging\nimport os\nfrom concurrent.futures import ThreadPoolExecutor\nfrom datetime import datetime, timezone\nfrom functools import partial\nfrom typing import Any, Dict, List, Literal, Optional, Tuple, Type, Union\nfrom urllib.parse import urljoin\n\nimport cv2\nimport numpy as np\nimport requests\nfrom fastapi import BackgroundTasks\nfrom pydantic import ConfigDict, Field\n\nfrom inference.core.workflows.execution_engine.entities.base import (\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    BOOLEAN_KIND,\n    CLASSIFICATION_PREDICTION_KIND,\n    IMAGE_KIND,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    INTEGER_KIND,\n    KEYPOINT_DETECTION_PREDICTION_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    STRING_KIND,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nLONG_DESCRIPTION = \"\"\"\nThe **Event Writer** block sends structured events to the Event Ingestion Service\nusing the v2 API.\n\n## Supported Event Schemas\n\n* **Quality Check** \u2014 pass/fail inspection results\n* **Inventory Count** \u2014 item counts at a location\n* **Safety Alert** \u2014 safety incidents with severity levels\n* **Custom** \u2014 free-form events with an arbitrary value field\n\n## Images\n\nEach event includes one image entry. You must provide an **output image** (the\nprimary display image, typically a visualization). You can optionally attach an\n**input image** (the original frame before any annotation).\n\n## Annotations\n\nYou can optionally pass object detection, classification, instance segmentation,\nor keypoint predictions from upstream model blocks. These are stored as\nstructured annotations on the image within the event.\n\n## Execution Modes\n\n* **Fire-and-forget** (`fire_and_forget=True`, default) \u2014 the HTTP request is\n  dispatched in the background so the workflow continues immediately. The\n  `event_id` output will be empty.\n* **Synchronous** (`fire_and_forget=False`) \u2014 the block waits for the response\n  and returns the created `event_id`.\n\n## Rate Limiting\n\nUse the **Rate Limiter** workflow block upstream of this block to control how\noften events are sent.\n\n## Authentication\n\nIf the Event Ingestion Service requires an API key, set the\n`EVENT_INGESTION_API_KEY` environment variable on the inference server.\nRequests are sent unauthenticated when the variable is not set.\n\"\"\"\n\nQUALITY_CHECK_RELEVANT = {\n    \"event_schema\": {\"values\": [\"quality_check\"], \"required\": True},\n}\nINVENTORY_COUNT_RELEVANT = {\n    \"event_schema\": {\"values\": [\"inventory_count\"], \"required\": True},\n}\nSAFETY_ALERT_RELEVANT = {\n    \"event_schema\": {\"values\": [\"safety_alert\"], \"required\": True},\n}\nCUSTOM_RELEVANT = {\n    \"event_schema\": {\"values\": [\"custom\"], \"required\": True},\n}\nALL_DATA_SCHEMAS_RELEVANT = {\n    \"event_schema\": {\n        \"values\": [\"quality_check\", \"inventory_count\", \"safety_alert\", \"custom\"],\n    },\n}\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Event Writer\",\n            \"version\": \"v1\",\n            \"short_description\": \"Write structured events to the Event Ingestion Service.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Roboflow Enterprise License\",\n            \"block_type\": \"sink\",\n            \"ui_manifest\": {\n                \"section\": \"industrial\",\n                \"icon\": \"fal fa-calendar-check\",\n                \"blockPriority\": 5,\n                \"enterprise_only\": True,\n                \"local_only\": True,\n            },\n        }\n    )\n    type: Literal[\"roboflow_enterprise/event_writer_sink@v1\"]\n\n    # --- Connection ---\n    event_ingestion_url: Union[Selector(kind=[STRING_KIND]), str] = Field(\n        default=\"http://localhost:8001\",\n        description=\"Base URL of the Event Ingestion Service.\",\n        examples=[\"http://localhost:8001\", \"$inputs.event_ingestion_url\"],\n    )\n\n    # --- Schema selector ---\n    event_schema: Literal[\n        \"quality_check\", \"inventory_count\", \"safety_alert\", \"custom\"\n    ] = Field(\n        description=\"The event schema to use.\",\n        json_schema_extra={\"always_visible\": True},\n    )\n\n    # --- Images ---\n    output_image: Selector(kind=[IMAGE_KIND]) = Field(\n        description=\"The output/visualization image. Sent as the primary display image.\",\n        json_schema_extra={\"always_visible\": True},\n    )\n    input_image: Optional[Selector(kind=[IMAGE_KIND])] = Field(\n        default=None,\n        description=\"The original input image (optional). Sent as the source image.\",\n    )\n    image_label: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Label for the image entry.\",\n        examples=[\"defect-analysis\", \"$inputs.image_label\"],\n    )\n\n    # --- Custom metadata ---\n    custom_metadata: Dict[\n        str,\n        Union[\n            Selector(),\n            str,\n            float,\n            bool,\n            int,\n        ],\n    ] = Field(\n        default_factory=dict,\n        description=\"Flat key-value metadata (max 100 keys, values must be str/int/float/bool).\",\n        examples=[{\"line\": \"A1\", \"shift\": \"morning\"}],\n        json_schema_extra={\"always_visible\": True},\n    )\n\n    # --- Quality Check fields ---\n    qc_result: Optional[\n        Union[Selector(kind=[STRING_KIND]), Literal[\"pass\", \"fail\"]]\n    ] = Field(\n        default=None,\n        description=\"Quality check result: pass or fail.\",\n        examples=[\"pass\", \"fail\", \"$steps.qc_logic.result\"],\n        json_schema_extra={\n            \"relevant_for\": QUALITY_CHECK_RELEVANT,\n            \"always_visible\": True,\n        },\n    )\n\n    # --- External ID (shared across schemas) ---\n    external_id: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"External identifier for correlation with other systems (max 1000 chars).\",\n        examples=[\"batch-2025-001\", \"$inputs.external_id\"],\n        json_schema_extra={\n            \"relevant_for\": ALL_DATA_SCHEMAS_RELEVANT,\n        },\n    )\n\n    # --- Inventory Count fields ---\n    location: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Location identifier for inventory count.\",\n        examples=[\"warehouse-A\", \"$inputs.location\"],\n        json_schema_extra={\"relevant_for\": INVENTORY_COUNT_RELEVANT},\n    )\n    item_count: Optional[Union[Selector(kind=[INTEGER_KIND]), int]] = Field(\n        default=None,\n        description=\"Number of items counted.\",\n        examples=[42, \"$steps.counter.count\"],\n        json_schema_extra={\"relevant_for\": INVENTORY_COUNT_RELEVANT},\n    )\n    item_type: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Type of item being counted.\",\n        examples=[\"widget\", \"$inputs.item_type\"],\n        json_schema_extra={\"relevant_for\": INVENTORY_COUNT_RELEVANT},\n    )\n\n    # --- Safety Alert fields ---\n    alert_type: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Alert type identifier (alphanumeric, underscores, hyphens).\",\n        examples=[\"no_hardhat\", \"$steps.classifier.top_class\"],\n        json_schema_extra={\"relevant_for\": SAFETY_ALERT_RELEVANT},\n    )\n    severity: Optional[\n        Union[Selector(kind=[STRING_KIND]), Literal[\"low\", \"medium\", \"high\"]]\n    ] = Field(\n        default=None,\n        description=\"Severity level for the safety alert.\",\n        examples=[\"high\", \"$inputs.severity\"],\n        json_schema_extra={\"relevant_for\": SAFETY_ALERT_RELEVANT},\n    )\n    alert_description: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Description of the safety alert (max 10000 chars).\",\n        examples=[\"Worker detected without hardhat in zone B\"],\n        json_schema_extra={\"relevant_for\": SAFETY_ALERT_RELEVANT},\n    )\n\n    # --- Custom Event fields ---\n    custom_value: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Arbitrary value for custom events (max 10000 chars).\",\n        examples=[\"anomaly detected at 14:32\"],\n        json_schema_extra={\"relevant_for\": CUSTOM_RELEVANT},\n    )\n\n    # --- Annotation pass-through ---\n    object_detections: Optional[Selector(kind=[OBJECT_DETECTION_PREDICTION_KIND])] = (\n        Field(\n            default=None,\n            description=\"Object detection predictions to attach to the image.\",\n            json_schema_extra={\"additional_section\": True},\n        )\n    )\n    classifications: Optional[Selector(kind=[CLASSIFICATION_PREDICTION_KIND])] = Field(\n        default=None,\n        description=\"Classification predictions to attach to the image.\",\n        json_schema_extra={\"additional_section\": True},\n    )\n    instance_segmentations: Optional[\n        Selector(kind=[INSTANCE_SEGMENTATION_PREDICTION_KIND])\n    ] = Field(\n        default=None,\n        description=\"Instance segmentation predictions to attach to the image.\",\n        json_schema_extra={\"additional_section\": True},\n    )\n    keypoint_detections: Optional[\n        Selector(kind=[KEYPOINT_DETECTION_PREDICTION_KIND])\n    ] = Field(\n        default=None,\n        description=\"Keypoint detection predictions to attach to the image.\",\n        json_schema_extra={\"additional_section\": True},\n    )\n\n    # --- Execution control ---\n    fire_and_forget: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=True,\n        description=\"If True, send the event asynchronously (no event_id returned). \"\n        \"If False, wait for the response and return the event_id.\",\n        examples=[True, False, \"$inputs.fire_and_forget\"],\n    )\n    disable_sink: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=False,\n        description=\"If True, skip sending the event entirely.\",\n        examples=[False, \"$inputs.disable_event_writer\"],\n    )\n    request_timeout: Union[int, Selector(kind=[INTEGER_KIND])] = Field(\n        default=5,\n        description=\"HTTP request timeout in seconds.\",\n        examples=[5, 10],\n    )\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"error_status\", kind=[BOOLEAN_KIND]),\n            OutputDefinition(name=\"event_id\", kind=[STRING_KIND]),\n            OutputDefinition(name=\"message\", kind=[STRING_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass EventWriterSinkBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        background_tasks: Optional[BackgroundTasks],\n        thread_pool_executor: Optional[ThreadPoolExecutor],\n    ):\n        self._background_tasks = background_tasks\n        self._thread_pool_executor = thread_pool_executor\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"background_tasks\", \"thread_pool_executor\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        event_ingestion_url: str,\n        event_schema: str,\n        output_image: WorkflowImageData,\n        fire_and_forget: bool,\n        disable_sink: bool,\n        request_timeout: int,\n        input_image: Optional[WorkflowImageData] = None,\n        image_label: Optional[str] = None,\n        custom_metadata: Optional[Dict[str, Any]] = None,\n        qc_result: Optional[str] = None,\n        external_id: Optional[str] = None,\n        location: Optional[str] = None,\n        item_count: Optional[int] = None,\n        item_type: Optional[str] = None,\n        alert_type: Optional[str] = None,\n        severity: Optional[str] = None,\n        alert_description: Optional[str] = None,\n        custom_value: Optional[str] = None,\n        object_detections: Optional[Any] = None,\n        classifications: Optional[Any] = None,\n        instance_segmentations: Optional[Any] = None,\n        keypoint_detections: Optional[Any] = None,\n    ) -> BlockResult:\n        if disable_sink:\n            return {\n                \"error_status\": False,\n                \"event_id\": \"\",\n                \"message\": \"Sink was disabled by parameter `disable_sink`\",\n            }\n\n        event_data = _build_event_data(\n            event_schema=event_schema,\n            qc_result=qc_result,\n            external_id=external_id,\n            location=location,\n            item_count=item_count,\n            item_type=item_type,\n            alert_type=alert_type,\n            severity=severity,\n            alert_description=alert_description,\n            custom_value=custom_value,\n        )\n\n        image_entry = _build_image_entry(\n            output_image=output_image,\n            input_image=input_image,\n            image_label=image_label,\n            object_detections=object_detections,\n            classifications=classifications,\n            instance_segmentations=instance_segmentations,\n            keypoint_detections=keypoint_detections,\n        )\n\n        payload: Dict[str, Any] = {\n            \"inference_timestamp\": datetime.now(timezone.utc).isoformat(),\n            \"event_schema\": event_schema,\n            \"event_data\": event_data,\n            \"images\": [image_entry],\n            \"displayImagePosition\": 0,\n        }\n        if custom_metadata:\n            payload[\"custom_metadata\"] = custom_metadata\n\n        request_handler = partial(\n            _execute_event_request,\n            url=urljoin(event_ingestion_url, \"/v2/events\"),\n            payload=payload,\n            api_key=os.environ.get(\"EVENT_INGESTION_API_KEY\"),\n            timeout=request_timeout,\n        )\n\n        if fire_and_forget and self._background_tasks:\n            self._background_tasks.add_task(request_handler)\n            return {\n                \"error_status\": False,\n                \"event_id\": \"\",\n                \"message\": \"Event sent in background task\",\n            }\n        if fire_and_forget and self._thread_pool_executor:\n            self._thread_pool_executor.submit(request_handler)\n            return {\n                \"error_status\": False,\n                \"event_id\": \"\",\n                \"message\": \"Event sent in background task\",\n            }\n\n        error_status, message, event_id = request_handler()\n        return {\n            \"error_status\": error_status,\n            \"event_id\": event_id,\n            \"message\": message,\n        }\n\n\ndef _build_event_data(\n    event_schema: str,\n    qc_result: Optional[str] = None,\n    external_id: Optional[str] = None,\n    location: Optional[str] = None,\n    item_count: Optional[int] = None,\n    item_type: Optional[str] = None,\n    alert_type: Optional[str] = None,\n    severity: Optional[str] = None,\n    alert_description: Optional[str] = None,\n    custom_value: Optional[str] = None,\n) -> Dict[str, Any]:\n    \"\"\"Build schema-specific event_data dict with camelCase keys, stripping None values.\"\"\"\n    if event_schema == \"quality_check\":\n        data = {\"result\": qc_result, \"externalId\": external_id}\n    elif event_schema == \"inventory_count\":\n        data = {\n            \"location\": location,\n            \"itemCount\": item_count,\n            \"itemType\": item_type,\n            \"externalId\": external_id,\n        }\n    elif event_schema == \"safety_alert\":\n        data = {\n            \"alertType\": alert_type,\n            \"severity\": severity,\n            \"description\": alert_description,\n            \"externalId\": external_id,\n        }\n    elif event_schema == \"custom\":\n        data = {\"externalId\": external_id, \"value\": custom_value}\n    else:\n        data = {}\n    # Strip None values \u2014 event_data schemas use extra=\"forbid\"\n    return {k: v for k, v in data.items() if v is not None}\n\n\ndef _detections_to_v2_object_detections(detections: Any) -> List[Dict[str, Any]]:\n    \"\"\"Convert Supervision Detections to v2 objectDetections format.\n\n    Uses center-based absolute pixel coordinates to match the main Roboflow\n    annotation format: x,y = center of box, width,height = full dimensions.\n    \"\"\"\n    if detections is None:\n        return []\n    results = []\n    try:\n        xyxy = detections.xyxy\n        confidence = detections.confidence\n        class_names = detections.data.get(\"class_name\", [])\n        for i in range(len(xyxy)):\n            x1, y1, x2, y2 = xyxy[i]\n            w = float(x2 - x1)\n            h = float(y2 - y1)\n            results.append(\n                {\n                    \"class\": class_names[i] if i < len(class_names) else \"unknown\",\n                    \"x\": float((x1 + x2) / 2),\n                    \"y\": float((y1 + y2) / 2),\n                    \"width\": w,\n                    \"height\": h,\n                    \"confidence\": (\n                        float(confidence[i]) if confidence is not None else 0.0\n                    ),\n                }\n            )\n    except Exception as e:\n        logging.warning(f\"Failed to convert object detections: {e}\")\n    return results\n\n\ndef _detections_to_v2_instance_segmentations(detections: Any) -> List[Dict[str, Any]]:\n    \"\"\"Convert Supervision Detections with masks to v2 instanceSegmentations format.\"\"\"\n    if detections is None:\n        return []\n    results = []\n    try:\n        xyxy = detections.xyxy\n        confidence = detections.confidence\n        class_names = detections.data.get(\"class_name\", [])\n        masks = detections.mask\n        for i in range(len(xyxy)):\n            x1, y1, x2, y2 = xyxy[i]\n            w = float(x2 - x1)\n            h = float(y2 - y1)\n            entry = {\n                \"class\": class_names[i] if i < len(class_names) else \"unknown\",\n                \"x\": float((x1 + x2) / 2),\n                \"y\": float((y1 + y2) / 2),\n                \"width\": w,\n                \"height\": h,\n                \"confidence\": float(confidence[i]) if confidence is not None else 0.0,\n                \"points\": [],\n            }\n            if masks is not None and i < len(masks):\n                mask = masks[i].astype(np.uint8)\n                contours, _ = cv2.findContours(\n                    mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE\n                )\n                if contours:\n                    largest = max(contours, key=cv2.contourArea)\n                    entry[\"points\"] = [\n                        [float(pt[0][0]), float(pt[0][1])] for pt in largest\n                    ]\n            if len(entry[\"points\"]) >= 3:\n                results.append(entry)\n    except Exception as e:\n        logging.warning(f\"Failed to convert instance segmentations: {e}\")\n    return results\n\n\ndef _classifications_to_v2(predictions: Any) -> List[Dict[str, Any]]:\n    \"\"\"Convert classification predictions to v2 classifications format.\"\"\"\n    if predictions is None:\n        return []\n    results = []\n    try:\n        if isinstance(predictions, dict):\n            class_names = predictions.get(\"class_name\", [])\n            confidences = predictions.get(\"confidence\", [])\n            for i in range(len(class_names)):\n                results.append(\n                    {\n                        \"class\": class_names[i],\n                        \"confidence\": (\n                            float(confidences[i]) if i < len(confidences) else 0.0\n                        ),\n                    }\n                )\n        elif hasattr(predictions, \"data\"):\n            class_names = predictions.data.get(\"class_name\", [])\n            confidences = predictions.confidence\n            for i in range(len(class_names)):\n                results.append(\n                    {\n                        \"class\": class_names[i],\n                        \"confidence\": (\n                            float(confidences[i])\n                            if confidences is not None and i < len(confidences)\n                            else 0.0\n                        ),\n                    }\n                )\n    except Exception as e:\n        logging.warning(f\"Failed to convert classifications: {e}\")\n    return results\n\n\ndef _keypoints_to_v2(detections: Any) -> List[Dict[str, Any]]:\n    \"\"\"Convert keypoint detection predictions to v2 keypoints format.\"\"\"\n    if detections is None:\n        return []\n    results = []\n    try:\n        xyxy = detections.xyxy\n        confidence = detections.confidence\n        class_names = detections.data.get(\"class_name\", [])\n        keypoints_xy = detections.data.get(\"keypoints_xy\")\n        for i in range(len(xyxy)):\n            x1, y1, x2, y2 = xyxy[i]\n            w = float(x2 - x1)\n            h = float(y2 - y1)\n            entry = {\n                \"class\": class_names[i] if i < len(class_names) else \"unknown\",\n                \"x\": float((x1 + x2) / 2),\n                \"y\": float((y1 + y2) / 2),\n                \"width\": w,\n                \"height\": h,\n                \"confidence\": float(confidence[i]) if confidence is not None else 0.0,\n                \"keypoints\": [],\n            }\n            if keypoints_xy is not None and i < len(keypoints_xy):\n                kps = keypoints_xy[i]\n                for j, kp in enumerate(kps):\n                    entry[\"keypoints\"].append(\n                        {\n                            \"id\": j,\n                            \"x\": float(kp[0]),\n                            \"y\": float(kp[1]),\n                        }\n                    )\n            if entry[\"keypoints\"]:\n                results.append(entry)\n    except Exception as e:\n        logging.warning(f\"Failed to convert keypoint detections: {e}\")\n    return results\n\n\ndef _build_image_entry(\n    output_image: WorkflowImageData,\n    input_image: Optional[WorkflowImageData] = None,\n    image_label: Optional[str] = None,\n    object_detections: Optional[Any] = None,\n    classifications: Optional[Any] = None,\n    instance_segmentations: Optional[Any] = None,\n    keypoint_detections: Optional[Any] = None,\n) -> Dict[str, Any]:\n    \"\"\"Build the single image object for the v2 API payload.\"\"\"\n    entry: Dict[str, Any] = {\n        \"base64Image\": output_image.base64_image,\n    }\n    if input_image is not None:\n        entry[\"inputBase64Image\"] = input_image.base64_image\n    if image_label is not None:\n        entry[\"label\"] = image_label\n\n    od = _detections_to_v2_object_detections(object_detections)\n    if od:\n        entry[\"objectDetections\"] = od\n\n    cl = _classifications_to_v2(classifications)\n    if cl:\n        entry[\"classifications\"] = cl\n\n    seg = _detections_to_v2_instance_segmentations(instance_segmentations)\n    if seg:\n        entry[\"instanceSegmentations\"] = seg\n\n    kp = _keypoints_to_v2(keypoint_detections)\n    if kp:\n        entry[\"keypoints\"] = kp\n\n    return entry\n\n\ndef _execute_event_request(\n    url: str,\n    payload: Dict[str, Any],\n    api_key: Optional[str],\n    timeout: int,\n) -> Tuple[bool, str, str]:\n    \"\"\"POST the event to the ingestion service.\n\n    Returns:\n        (error_status, message, event_id)\n    \"\"\"\n    try:\n        headers: Dict[str, str] = {\"Content-Type\": \"application/json\"}\n        if api_key:\n            headers[\"X-API-Key\"] = api_key\n\n        response = requests.post(url, json=payload, headers=headers, timeout=timeout)\n\n        if response.status_code == 201:\n            data = response.json()\n            event_id = str(data.get(\"id\", \"\"))\n            return False, \"Event created successfully\", event_id\n\n        if response.status_code == 529:\n            detail = _extract_detail(response)\n            return (\n                True,\n                f\"Event Ingestion Service at capacity (529). \"\n                f\"The device is experiencing backpressure. Detail: {detail}\",\n                \"\",\n            )\n\n        detail = _extract_detail(response)\n        return True, f\"HTTP {response.status_code}: {detail}\", \"\"\n    except requests.exceptions.Timeout:\n        return True, f\"Request timed out after {timeout}s\", \"\"\n    except Exception as e:\n        logging.warning(f\"Event writer request failed: {e}\")\n        return True, f\"Request failed: {e}\", \"\"\n\n\ndef _extract_detail(response: requests.Response) -> str:\n    \"\"\"Try to extract 'detail' from a JSON error response.\"\"\"\n    try:\n        return str(response.json().get(\"detail\", response.text))\n    except Exception:\n        return response.text\n",
    "patch": null
  },
  {
    "trace_id": "e784aca3-8eff-401b-a5c1-8878e6e9f109",
    "function_name": "_build_event_data",
    "file_path": "inference/enterprise/workflows/enterprise_blocks/sinks/event_writer/v1.py",
    "speedup_x": 0.7396972469911406,
    "review_quality": "high",
    "pre_optimization_commit": "ad7d91d0150bee8f45dc26ae83f7c499503c8a4d",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def _build_event_data(\n    event_schema: str,\n    qc_result: Optional[str] = None,\n    external_id: Optional[str] = None,\n    location: Optional[str] = None,\n    item_count: Optional[int] = None,\n    item_type: Optional[str] = None,\n    alert_type: Optional[str] = None,\n    severity: Optional[str] = None,\n    alert_description: Optional[str] = None,\n    custom_value: Optional[str] = None,\n) -> Dict[str, Any]:\n    \"\"\"Build schema-specific event_data dict with camelCase keys, stripping None values.\"\"\"\n    if event_schema == \"quality_check\":\n        data = {\"result\": qc_result, \"externalId\": external_id}\n    elif event_schema == \"inventory_count\":\n        data = {\n            \"location\": location,\n            \"itemCount\": item_count,\n            \"itemType\": item_type,\n            \"externalId\": external_id,\n        }\n    elif event_schema == \"safety_alert\":\n        data = {\n            \"alertType\": alert_type,\n            \"severity\": severity,\n            \"description\": alert_description,\n            \"externalId\": external_id,\n        }\n    elif event_schema == \"custom\":\n        data = {\"externalId\": external_id, \"value\": custom_value}\n    else:\n        data = {}\n    # Strip None values \u2014 event_data schemas use extra=\"forbid\"\n    return {k: v for k, v in data.items() if v is not None}\n",
    "optimized_function_code": "from typing import Any, Dict, Optional\n\n\ndef _build_event_data(\n    event_schema: str,\n    qc_result: Optional[str] = None,\n    external_id: Optional[str] = None,\n    location: Optional[str] = None,\n    item_count: Optional[int] = None,\n    item_type: Optional[str] = None,\n    alert_type: Optional[str] = None,\n    severity: Optional[str] = None,\n    alert_description: Optional[str] = None,\n    custom_value: Optional[str] = None,\n) -> Dict[str, Any]:\n    \"\"\"Build schema-specific event_data dict with camelCase keys, stripping None values.\"\"\"\n    if event_schema == \"quality_check\":\n        data = {}\n        if qc_result is not None:\n            data[\"result\"] = qc_result\n        if external_id is not None:\n            data[\"externalId\"] = external_id\n    elif event_schema == \"inventory_count\":\n        data = {}\n        if location is not None:\n            data[\"location\"] = location\n        if item_count is not None:\n            data[\"itemCount\"] = item_count\n        if item_type is not None:\n            data[\"itemType\"] = item_type\n        if external_id is not None:\n            data[\"externalId\"] = external_id\n    elif event_schema == \"safety_alert\":\n        data = {}\n        if alert_type is not None:\n            data[\"alertType\"] = alert_type\n        if severity is not None:\n            data[\"severity\"] = severity\n        if alert_description is not None:\n            data[\"description\"] = alert_description\n        if external_id is not None:\n            data[\"externalId\"] = external_id\n    elif event_schema == \"custom\":\n        data = {}\n        if external_id is not None:\n            data[\"externalId\"] = external_id\n        if custom_value is not None:\n            data[\"value\"] = custom_value\n    else:\n        data = {}\n    # Strip None values \u2014 event_data schemas use extra=\"forbid\"\n    return data",
    "optimized_raw_markdown": "```python:inference/enterprise/workflows/enterprise_blocks/sinks/event_writer/v1.py\nfrom typing import Any, Dict, Optional\n\n\ndef _build_event_data(\n    event_schema: str,\n    qc_result: Optional[str] = None,\n    external_id: Optional[str] = None,\n    location: Optional[str] = None,\n    item_count: Optional[int] = None,\n    item_type: Optional[str] = None,\n    alert_type: Optional[str] = None,\n    severity: Optional[str] = None,\n    alert_description: Optional[str] = None,\n    custom_value: Optional[str] = None,\n) -> Dict[str, Any]:\n    \"\"\"Build schema-specific event_data dict with camelCase keys, stripping None values.\"\"\"\n    if event_schema == \"quality_check\":\n        data = {}\n        if qc_result is not None:\n            data[\"result\"] = qc_result\n        if external_id is not None:\n            data[\"externalId\"] = external_id\n    elif event_schema == \"inventory_count\":\n        data = {}\n        if location is not None:\n            data[\"location\"] = location\n        if item_count is not None:\n            data[\"itemCount\"] = item_count\n        if item_type is not None:\n            data[\"itemType\"] = item_type\n        if external_id is not None:\n            data[\"externalId\"] = external_id\n    elif event_schema == \"safety_alert\":\n        data = {}\n        if alert_type is not None:\n            data[\"alertType\"] = alert_type\n        if severity is not None:\n            data[\"severity\"] = severity\n        if alert_description is not None:\n            data[\"description\"] = alert_description\n        if external_id is not None:\n            data[\"externalId\"] = external_id\n    elif event_schema == \"custom\":\n        data = {}\n        if external_id is not None:\n            data[\"externalId\"] = external_id\n        if custom_value is not None:\n            data[\"value\"] = custom_value\n    else:\n        data = {}\n    # Strip None values \u2014 event_data schemas use extra=\"forbid\"\n    return data\n```",
    "optimized_function_only": "def _build_event_data(\n    event_schema: str,\n    qc_result: Optional[str] = None,\n    external_id: Optional[str] = None,\n    location: Optional[str] = None,\n    item_count: Optional[int] = None,\n    item_type: Optional[str] = None,\n    alert_type: Optional[str] = None,\n    severity: Optional[str] = None,\n    alert_description: Optional[str] = None,\n    custom_value: Optional[str] = None,\n) -> Dict[str, Any]:\n    \"\"\"Build schema-specific event_data dict with camelCase keys, stripping None values.\"\"\"\n    if event_schema == \"quality_check\":\n        data = {}\n        if qc_result is not None:\n            data[\"result\"] = qc_result\n        if external_id is not None:\n            data[\"externalId\"] = external_id\n    elif event_schema == \"inventory_count\":\n        data = {}\n        if location is not None:\n            data[\"location\"] = location\n        if item_count is not None:\n            data[\"itemCount\"] = item_count\n        if item_type is not None:\n            data[\"itemType\"] = item_type\n        if external_id is not None:\n            data[\"externalId\"] = external_id\n    elif event_schema == \"safety_alert\":\n        data = {}\n        if alert_type is not None:\n            data[\"alertType\"] = alert_type\n        if severity is not None:\n            data[\"severity\"] = severity\n        if alert_description is not None:\n            data[\"description\"] = alert_description\n        if external_id is not None:\n            data[\"externalId\"] = external_id\n    elif event_schema == \"custom\":\n        data = {}\n        if external_id is not None:\n            data[\"externalId\"] = external_id\n        if custom_value is not None:\n            data[\"value\"] = custom_value\n    else:\n        data = {}\n    # Strip None values \u2014 event_data schemas use extra=\"forbid\"\n    return data",
    "original_file_content": "import logging\nimport os\nfrom concurrent.futures import ThreadPoolExecutor\nfrom datetime import datetime, timezone\nfrom functools import partial\nfrom typing import Any, Dict, List, Literal, Optional, Tuple, Type, Union\nfrom urllib.parse import urljoin\n\nimport cv2\nimport numpy as np\nimport requests\nfrom fastapi import BackgroundTasks\nfrom pydantic import ConfigDict, Field\n\nfrom inference.core.workflows.execution_engine.entities.base import (\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    BOOLEAN_KIND,\n    CLASSIFICATION_PREDICTION_KIND,\n    IMAGE_KIND,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    INTEGER_KIND,\n    KEYPOINT_DETECTION_PREDICTION_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    STRING_KIND,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nLONG_DESCRIPTION = \"\"\"\nThe **Event Writer** block sends structured events to the Event Ingestion Service\nusing the v2 API.\n\n## Supported Event Schemas\n\n* **Quality Check** \u2014 pass/fail inspection results\n* **Inventory Count** \u2014 item counts at a location\n* **Safety Alert** \u2014 safety incidents with severity levels\n* **Custom** \u2014 free-form events with an arbitrary value field\n\n## Images\n\nEach event includes one image entry. You must provide an **output image** (the\nprimary display image, typically a visualization). You can optionally attach an\n**input image** (the original frame before any annotation).\n\n## Annotations\n\nYou can optionally pass object detection, classification, instance segmentation,\nor keypoint predictions from upstream model blocks. These are stored as\nstructured annotations on the image within the event.\n\n## Execution Modes\n\n* **Fire-and-forget** (`fire_and_forget=True`, default) \u2014 the HTTP request is\n  dispatched in the background so the workflow continues immediately. The\n  `event_id` output will be empty.\n* **Synchronous** (`fire_and_forget=False`) \u2014 the block waits for the response\n  and returns the created `event_id`.\n\n## Rate Limiting\n\nUse the **Rate Limiter** workflow block upstream of this block to control how\noften events are sent.\n\n## Authentication\n\nIf the Event Ingestion Service requires an API key, set the\n`EVENT_INGESTION_API_KEY` environment variable on the inference server.\nRequests are sent unauthenticated when the variable is not set.\n\"\"\"\n\nQUALITY_CHECK_RELEVANT = {\n    \"event_schema\": {\"values\": [\"quality_check\"], \"required\": True},\n}\nINVENTORY_COUNT_RELEVANT = {\n    \"event_schema\": {\"values\": [\"inventory_count\"], \"required\": True},\n}\nSAFETY_ALERT_RELEVANT = {\n    \"event_schema\": {\"values\": [\"safety_alert\"], \"required\": True},\n}\nCUSTOM_RELEVANT = {\n    \"event_schema\": {\"values\": [\"custom\"], \"required\": True},\n}\nALL_DATA_SCHEMAS_RELEVANT = {\n    \"event_schema\": {\n        \"values\": [\"quality_check\", \"inventory_count\", \"safety_alert\", \"custom\"],\n    },\n}\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Event Writer\",\n            \"version\": \"v1\",\n            \"short_description\": \"Write structured events to the Event Ingestion Service.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Roboflow Enterprise License\",\n            \"block_type\": \"sink\",\n            \"ui_manifest\": {\n                \"section\": \"industrial\",\n                \"icon\": \"fal fa-calendar-check\",\n                \"blockPriority\": 5,\n                \"enterprise_only\": True,\n                \"local_only\": True,\n            },\n        }\n    )\n    type: Literal[\"roboflow_enterprise/event_writer_sink@v1\"]\n\n    # --- Connection ---\n    event_ingestion_url: Union[Selector(kind=[STRING_KIND]), str] = Field(\n        default=\"http://localhost:8001\",\n        description=\"Base URL of the Event Ingestion Service.\",\n        examples=[\"http://localhost:8001\", \"$inputs.event_ingestion_url\"],\n    )\n\n    # --- Schema selector ---\n    event_schema: Literal[\n        \"quality_check\", \"inventory_count\", \"safety_alert\", \"custom\"\n    ] = Field(\n        description=\"The event schema to use.\",\n        json_schema_extra={\"always_visible\": True},\n    )\n\n    # --- Images ---\n    output_image: Selector(kind=[IMAGE_KIND]) = Field(\n        description=\"The output/visualization image. Sent as the primary display image.\",\n        json_schema_extra={\"always_visible\": True},\n    )\n    input_image: Optional[Selector(kind=[IMAGE_KIND])] = Field(\n        default=None,\n        description=\"The original input image (optional). Sent as the source image.\",\n    )\n    image_label: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Label for the image entry.\",\n        examples=[\"defect-analysis\", \"$inputs.image_label\"],\n    )\n\n    # --- Custom metadata ---\n    custom_metadata: Dict[\n        str,\n        Union[\n            Selector(),\n            str,\n            float,\n            bool,\n            int,\n        ],\n    ] = Field(\n        default_factory=dict,\n        description=\"Flat key-value metadata (max 100 keys, values must be str/int/float/bool).\",\n        examples=[{\"line\": \"A1\", \"shift\": \"morning\"}],\n        json_schema_extra={\"always_visible\": True},\n    )\n\n    # --- Quality Check fields ---\n    qc_result: Optional[\n        Union[Selector(kind=[STRING_KIND]), Literal[\"pass\", \"fail\"]]\n    ] = Field(\n        default=None,\n        description=\"Quality check result: pass or fail.\",\n        examples=[\"pass\", \"fail\", \"$steps.qc_logic.result\"],\n        json_schema_extra={\n            \"relevant_for\": QUALITY_CHECK_RELEVANT,\n            \"always_visible\": True,\n        },\n    )\n\n    # --- External ID (shared across schemas) ---\n    external_id: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"External identifier for correlation with other systems (max 1000 chars).\",\n        examples=[\"batch-2025-001\", \"$inputs.external_id\"],\n        json_schema_extra={\n            \"relevant_for\": ALL_DATA_SCHEMAS_RELEVANT,\n        },\n    )\n\n    # --- Inventory Count fields ---\n    location: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Location identifier for inventory count.\",\n        examples=[\"warehouse-A\", \"$inputs.location\"],\n        json_schema_extra={\"relevant_for\": INVENTORY_COUNT_RELEVANT},\n    )\n    item_count: Optional[Union[Selector(kind=[INTEGER_KIND]), int]] = Field(\n        default=None,\n        description=\"Number of items counted.\",\n        examples=[42, \"$steps.counter.count\"],\n        json_schema_extra={\"relevant_for\": INVENTORY_COUNT_RELEVANT},\n    )\n    item_type: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Type of item being counted.\",\n        examples=[\"widget\", \"$inputs.item_type\"],\n        json_schema_extra={\"relevant_for\": INVENTORY_COUNT_RELEVANT},\n    )\n\n    # --- Safety Alert fields ---\n    alert_type: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Alert type identifier (alphanumeric, underscores, hyphens).\",\n        examples=[\"no_hardhat\", \"$steps.classifier.top_class\"],\n        json_schema_extra={\"relevant_for\": SAFETY_ALERT_RELEVANT},\n    )\n    severity: Optional[\n        Union[Selector(kind=[STRING_KIND]), Literal[\"low\", \"medium\", \"high\"]]\n    ] = Field(\n        default=None,\n        description=\"Severity level for the safety alert.\",\n        examples=[\"high\", \"$inputs.severity\"],\n        json_schema_extra={\"relevant_for\": SAFETY_ALERT_RELEVANT},\n    )\n    alert_description: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Description of the safety alert (max 10000 chars).\",\n        examples=[\"Worker detected without hardhat in zone B\"],\n        json_schema_extra={\"relevant_for\": SAFETY_ALERT_RELEVANT},\n    )\n\n    # --- Custom Event fields ---\n    custom_value: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Arbitrary value for custom events (max 10000 chars).\",\n        examples=[\"anomaly detected at 14:32\"],\n        json_schema_extra={\"relevant_for\": CUSTOM_RELEVANT},\n    )\n\n    # --- Annotation pass-through ---\n    object_detections: Optional[Selector(kind=[OBJECT_DETECTION_PREDICTION_KIND])] = (\n        Field(\n            default=None,\n            description=\"Object detection predictions to attach to the image.\",\n            json_schema_extra={\"additional_section\": True},\n        )\n    )\n    classifications: Optional[Selector(kind=[CLASSIFICATION_PREDICTION_KIND])] = Field(\n        default=None,\n        description=\"Classification predictions to attach to the image.\",\n        json_schema_extra={\"additional_section\": True},\n    )\n    instance_segmentations: Optional[\n        Selector(kind=[INSTANCE_SEGMENTATION_PREDICTION_KIND])\n    ] = Field(\n        default=None,\n        description=\"Instance segmentation predictions to attach to the image.\",\n        json_schema_extra={\"additional_section\": True},\n    )\n    keypoint_detections: Optional[\n        Selector(kind=[KEYPOINT_DETECTION_PREDICTION_KIND])\n    ] = Field(\n        default=None,\n        description=\"Keypoint detection predictions to attach to the image.\",\n        json_schema_extra={\"additional_section\": True},\n    )\n\n    # --- Execution control ---\n    fire_and_forget: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=True,\n        description=\"If True, send the event asynchronously (no event_id returned). \"\n        \"If False, wait for the response and return the event_id.\",\n        examples=[True, False, \"$inputs.fire_and_forget\"],\n    )\n    disable_sink: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=False,\n        description=\"If True, skip sending the event entirely.\",\n        examples=[False, \"$inputs.disable_event_writer\"],\n    )\n    request_timeout: Union[int, Selector(kind=[INTEGER_KIND])] = Field(\n        default=5,\n        description=\"HTTP request timeout in seconds.\",\n        examples=[5, 10],\n    )\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"error_status\", kind=[BOOLEAN_KIND]),\n            OutputDefinition(name=\"event_id\", kind=[STRING_KIND]),\n            OutputDefinition(name=\"message\", kind=[STRING_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass EventWriterSinkBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        background_tasks: Optional[BackgroundTasks],\n        thread_pool_executor: Optional[ThreadPoolExecutor],\n    ):\n        self._background_tasks = background_tasks\n        self._thread_pool_executor = thread_pool_executor\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"background_tasks\", \"thread_pool_executor\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        event_ingestion_url: str,\n        event_schema: str,\n        output_image: WorkflowImageData,\n        fire_and_forget: bool,\n        disable_sink: bool,\n        request_timeout: int,\n        input_image: Optional[WorkflowImageData] = None,\n        image_label: Optional[str] = None,\n        custom_metadata: Optional[Dict[str, Any]] = None,\n        qc_result: Optional[str] = None,\n        external_id: Optional[str] = None,\n        location: Optional[str] = None,\n        item_count: Optional[int] = None,\n        item_type: Optional[str] = None,\n        alert_type: Optional[str] = None,\n        severity: Optional[str] = None,\n        alert_description: Optional[str] = None,\n        custom_value: Optional[str] = None,\n        object_detections: Optional[Any] = None,\n        classifications: Optional[Any] = None,\n        instance_segmentations: Optional[Any] = None,\n        keypoint_detections: Optional[Any] = None,\n    ) -> BlockResult:\n        if disable_sink:\n            return {\n                \"error_status\": False,\n                \"event_id\": \"\",\n                \"message\": \"Sink was disabled by parameter `disable_sink`\",\n            }\n\n        event_data = _build_event_data(\n            event_schema=event_schema,\n            qc_result=qc_result,\n            external_id=external_id,\n            location=location,\n            item_count=item_count,\n            item_type=item_type,\n            alert_type=alert_type,\n            severity=severity,\n            alert_description=alert_description,\n            custom_value=custom_value,\n        )\n\n        image_entry = _build_image_entry(\n            output_image=output_image,\n            input_image=input_image,\n            image_label=image_label,\n            object_detections=object_detections,\n            classifications=classifications,\n            instance_segmentations=instance_segmentations,\n            keypoint_detections=keypoint_detections,\n        )\n\n        payload: Dict[str, Any] = {\n            \"inference_timestamp\": datetime.now(timezone.utc).isoformat(),\n            \"event_schema\": event_schema,\n            \"event_data\": event_data,\n            \"images\": [image_entry],\n            \"displayImagePosition\": 0,\n        }\n        if custom_metadata:\n            payload[\"custom_metadata\"] = custom_metadata\n\n        request_handler = partial(\n            _execute_event_request,\n            url=urljoin(event_ingestion_url, \"/v2/events\"),\n            payload=payload,\n            api_key=os.environ.get(\"EVENT_INGESTION_API_KEY\"),\n            timeout=request_timeout,\n        )\n\n        if fire_and_forget and self._background_tasks:\n            self._background_tasks.add_task(request_handler)\n            return {\n                \"error_status\": False,\n                \"event_id\": \"\",\n                \"message\": \"Event sent in background task\",\n            }\n        if fire_and_forget and self._thread_pool_executor:\n            self._thread_pool_executor.submit(request_handler)\n            return {\n                \"error_status\": False,\n                \"event_id\": \"\",\n                \"message\": \"Event sent in background task\",\n            }\n\n        error_status, message, event_id = request_handler()\n        return {\n            \"error_status\": error_status,\n            \"event_id\": event_id,\n            \"message\": message,\n        }\n\n\ndef _build_event_data(\n    event_schema: str,\n    qc_result: Optional[str] = None,\n    external_id: Optional[str] = None,\n    location: Optional[str] = None,\n    item_count: Optional[int] = None,\n    item_type: Optional[str] = None,\n    alert_type: Optional[str] = None,\n    severity: Optional[str] = None,\n    alert_description: Optional[str] = None,\n    custom_value: Optional[str] = None,\n) -> Dict[str, Any]:\n    \"\"\"Build schema-specific event_data dict with camelCase keys, stripping None values.\"\"\"\n    if event_schema == \"quality_check\":\n        data = {\"result\": qc_result, \"externalId\": external_id}\n    elif event_schema == \"inventory_count\":\n        data = {\n            \"location\": location,\n            \"itemCount\": item_count,\n            \"itemType\": item_type,\n            \"externalId\": external_id,\n        }\n    elif event_schema == \"safety_alert\":\n        data = {\n            \"alertType\": alert_type,\n            \"severity\": severity,\n            \"description\": alert_description,\n            \"externalId\": external_id,\n        }\n    elif event_schema == \"custom\":\n        data = {\"externalId\": external_id, \"value\": custom_value}\n    else:\n        data = {}\n    # Strip None values \u2014 event_data schemas use extra=\"forbid\"\n    return {k: v for k, v in data.items() if v is not None}\n\n\ndef _detections_to_v2_object_detections(detections: Any) -> List[Dict[str, Any]]:\n    \"\"\"Convert Supervision Detections to v2 objectDetections format.\n\n    Uses center-based absolute pixel coordinates to match the main Roboflow\n    annotation format: x,y = center of box, width,height = full dimensions.\n    \"\"\"\n    if detections is None:\n        return []\n    results = []\n    try:\n        xyxy = detections.xyxy\n        confidence = detections.confidence\n        class_names = detections.data.get(\"class_name\", [])\n        for i in range(len(xyxy)):\n            x1, y1, x2, y2 = xyxy[i]\n            w = float(x2 - x1)\n            h = float(y2 - y1)\n            results.append(\n                {\n                    \"class\": class_names[i] if i < len(class_names) else \"unknown\",\n                    \"x\": float((x1 + x2) / 2),\n                    \"y\": float((y1 + y2) / 2),\n                    \"width\": w,\n                    \"height\": h,\n                    \"confidence\": (\n                        float(confidence[i]) if confidence is not None else 0.0\n                    ),\n                }\n            )\n    except Exception as e:\n        logging.warning(f\"Failed to convert object detections: {e}\")\n    return results\n\n\ndef _detections_to_v2_instance_segmentations(detections: Any) -> List[Dict[str, Any]]:\n    \"\"\"Convert Supervision Detections with masks to v2 instanceSegmentations format.\"\"\"\n    if detections is None:\n        return []\n    results = []\n    try:\n        xyxy = detections.xyxy\n        confidence = detections.confidence\n        class_names = detections.data.get(\"class_name\", [])\n        masks = detections.mask\n        for i in range(len(xyxy)):\n            x1, y1, x2, y2 = xyxy[i]\n            w = float(x2 - x1)\n            h = float(y2 - y1)\n            entry = {\n                \"class\": class_names[i] if i < len(class_names) else \"unknown\",\n                \"x\": float((x1 + x2) / 2),\n                \"y\": float((y1 + y2) / 2),\n                \"width\": w,\n                \"height\": h,\n                \"confidence\": float(confidence[i]) if confidence is not None else 0.0,\n                \"points\": [],\n            }\n            if masks is not None and i < len(masks):\n                mask = masks[i].astype(np.uint8)\n                contours, _ = cv2.findContours(\n                    mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE\n                )\n                if contours:\n                    largest = max(contours, key=cv2.contourArea)\n                    entry[\"points\"] = [\n                        [float(pt[0][0]), float(pt[0][1])] for pt in largest\n                    ]\n            if len(entry[\"points\"]) >= 3:\n                results.append(entry)\n    except Exception as e:\n        logging.warning(f\"Failed to convert instance segmentations: {e}\")\n    return results\n\n\ndef _classifications_to_v2(predictions: Any) -> List[Dict[str, Any]]:\n    \"\"\"Convert classification predictions to v2 classifications format.\"\"\"\n    if predictions is None:\n        return []\n    results = []\n    try:\n        if isinstance(predictions, dict):\n            class_names = predictions.get(\"class_name\", [])\n            confidences = predictions.get(\"confidence\", [])\n            for i in range(len(class_names)):\n                results.append(\n                    {\n                        \"class\": class_names[i],\n                        \"confidence\": (\n                            float(confidences[i]) if i < len(confidences) else 0.0\n                        ),\n                    }\n                )\n        elif hasattr(predictions, \"data\"):\n            class_names = predictions.data.get(\"class_name\", [])\n            confidences = predictions.confidence\n            for i in range(len(class_names)):\n                results.append(\n                    {\n                        \"class\": class_names[i],\n                        \"confidence\": (\n                            float(confidences[i])\n                            if confidences is not None and i < len(confidences)\n                            else 0.0\n                        ),\n                    }\n                )\n    except Exception as e:\n        logging.warning(f\"Failed to convert classifications: {e}\")\n    return results\n\n\ndef _keypoints_to_v2(detections: Any) -> List[Dict[str, Any]]:\n    \"\"\"Convert keypoint detection predictions to v2 keypoints format.\"\"\"\n    if detections is None:\n        return []\n    results = []\n    try:\n        xyxy = detections.xyxy\n        confidence = detections.confidence\n        class_names = detections.data.get(\"class_name\", [])\n        keypoints_xy = detections.data.get(\"keypoints_xy\")\n        for i in range(len(xyxy)):\n            x1, y1, x2, y2 = xyxy[i]\n            w = float(x2 - x1)\n            h = float(y2 - y1)\n            entry = {\n                \"class\": class_names[i] if i < len(class_names) else \"unknown\",\n                \"x\": float((x1 + x2) / 2),\n                \"y\": float((y1 + y2) / 2),\n                \"width\": w,\n                \"height\": h,\n                \"confidence\": float(confidence[i]) if confidence is not None else 0.0,\n                \"keypoints\": [],\n            }\n            if keypoints_xy is not None and i < len(keypoints_xy):\n                kps = keypoints_xy[i]\n                for j, kp in enumerate(kps):\n                    entry[\"keypoints\"].append(\n                        {\n                            \"id\": j,\n                            \"x\": float(kp[0]),\n                            \"y\": float(kp[1]),\n                        }\n                    )\n            if entry[\"keypoints\"]:\n                results.append(entry)\n    except Exception as e:\n        logging.warning(f\"Failed to convert keypoint detections: {e}\")\n    return results\n\n\ndef _build_image_entry(\n    output_image: WorkflowImageData,\n    input_image: Optional[WorkflowImageData] = None,\n    image_label: Optional[str] = None,\n    object_detections: Optional[Any] = None,\n    classifications: Optional[Any] = None,\n    instance_segmentations: Optional[Any] = None,\n    keypoint_detections: Optional[Any] = None,\n) -> Dict[str, Any]:\n    \"\"\"Build the single image object for the v2 API payload.\"\"\"\n    entry: Dict[str, Any] = {\n        \"base64Image\": output_image.base64_image,\n    }\n    if input_image is not None:\n        entry[\"inputBase64Image\"] = input_image.base64_image\n    if image_label is not None:\n        entry[\"label\"] = image_label\n\n    od = _detections_to_v2_object_detections(object_detections)\n    if od:\n        entry[\"objectDetections\"] = od\n\n    cl = _classifications_to_v2(classifications)\n    if cl:\n        entry[\"classifications\"] = cl\n\n    seg = _detections_to_v2_instance_segmentations(instance_segmentations)\n    if seg:\n        entry[\"instanceSegmentations\"] = seg\n\n    kp = _keypoints_to_v2(keypoint_detections)\n    if kp:\n        entry[\"keypoints\"] = kp\n\n    return entry\n\n\ndef _execute_event_request(\n    url: str,\n    payload: Dict[str, Any],\n    api_key: Optional[str],\n    timeout: int,\n) -> Tuple[bool, str, str]:\n    \"\"\"POST the event to the ingestion service.\n\n    Returns:\n        (error_status, message, event_id)\n    \"\"\"\n    try:\n        headers: Dict[str, str] = {\"Content-Type\": \"application/json\"}\n        if api_key:\n            headers[\"X-API-Key\"] = api_key\n\n        response = requests.post(url, json=payload, headers=headers, timeout=timeout)\n\n        if response.status_code == 201:\n            data = response.json()\n            event_id = str(data.get(\"id\", \"\"))\n            return False, \"Event created successfully\", event_id\n\n        if response.status_code == 529:\n            detail = _extract_detail(response)\n            return (\n                True,\n                f\"Event Ingestion Service at capacity (529). \"\n                f\"The device is experiencing backpressure. Detail: {detail}\",\n                \"\",\n            )\n\n        detail = _extract_detail(response)\n        return True, f\"HTTP {response.status_code}: {detail}\", \"\"\n    except requests.exceptions.Timeout:\n        return True, f\"Request timed out after {timeout}s\", \"\"\n    except Exception as e:\n        logging.warning(f\"Event writer request failed: {e}\")\n        return True, f\"Request failed: {e}\", \"\"\n\n\ndef _extract_detail(response: requests.Response) -> str:\n    \"\"\"Try to extract 'detail' from a JSON error response.\"\"\"\n    try:\n        return str(response.json().get(\"detail\", response.text))\n    except Exception:\n        return response.text\n",
    "patch": null
  },
  {
    "trace_id": "779a22ea-59c7-4c1e-aac8-61e6a9a843ff",
    "function_name": "load_enterprise_blocks",
    "file_path": "inference/enterprise/workflows/enterprise_blocks/loader.py",
    "speedup_x": 0.451824164253751,
    "review_quality": "high",
    "pre_optimization_commit": "8c3b3b05c065ea3aa960eba47a584d80331fe7ed",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def load_enterprise_blocks() -> List[Type[WorkflowBlock]]:\n    return [\n        OPCWriterSinkBlockV1,\n        MQTTWriterSinkBlockV1,\n        PLCBlockV1,\n        ModbusTCPBlockV1,\n        MicrosoftSQLServerSinkBlockV1,\n        EventWriterSinkBlockV1,\n    ]\n",
    "optimized_function_code": "from typing import List, Type\n\nfrom inference.core.workflows.prototypes.block import WorkflowBlock\nfrom inference.enterprise.workflows.enterprise_blocks.sinks.event_writer.v1 import \\\n    EventWriterSinkBlockV1\nfrom inference.enterprise.workflows.enterprise_blocks.sinks.microsoft_sql_server.v1 import \\\n    MicrosoftSQLServerSinkBlockV1\nfrom inference.enterprise.workflows.enterprise_blocks.sinks.mqtt_writer.v1 import \\\n    MQTTWriterSinkBlockV1\nfrom inference.enterprise.workflows.enterprise_blocks.sinks.opc_writer.v1 import \\\n    OPCWriterSinkBlockV1\nfrom inference.enterprise.workflows.enterprise_blocks.sinks.PLC_modbus.v1 import \\\n    ModbusTCPBlockV1\nfrom inference.enterprise.workflows.enterprise_blocks.sinks.PLCethernetIP.v1 import \\\n    PLCBlockV1\n\n_ENTERPRISE_BLOCKS = [\n    OPCWriterSinkBlockV1,\n    MQTTWriterSinkBlockV1,\n    PLCBlockV1,\n    ModbusTCPBlockV1,\n    MicrosoftSQLServerSinkBlockV1,\n    EventWriterSinkBlockV1,\n]\n\ndef load_enterprise_blocks() -> List[Type[WorkflowBlock]]:\n    return _ENTERPRISE_BLOCKS",
    "optimized_raw_markdown": "```python:inference/enterprise/workflows/enterprise_blocks/loader.py\nfrom typing import List, Type\n\nfrom inference.core.workflows.prototypes.block import WorkflowBlock\nfrom inference.enterprise.workflows.enterprise_blocks.sinks.event_writer.v1 import \\\n    EventWriterSinkBlockV1\nfrom inference.enterprise.workflows.enterprise_blocks.sinks.microsoft_sql_server.v1 import \\\n    MicrosoftSQLServerSinkBlockV1\nfrom inference.enterprise.workflows.enterprise_blocks.sinks.mqtt_writer.v1 import \\\n    MQTTWriterSinkBlockV1\nfrom inference.enterprise.workflows.enterprise_blocks.sinks.opc_writer.v1 import \\\n    OPCWriterSinkBlockV1\nfrom inference.enterprise.workflows.enterprise_blocks.sinks.PLC_modbus.v1 import \\\n    ModbusTCPBlockV1\nfrom inference.enterprise.workflows.enterprise_blocks.sinks.PLCethernetIP.v1 import \\\n    PLCBlockV1\n\n_ENTERPRISE_BLOCKS = [\n    OPCWriterSinkBlockV1,\n    MQTTWriterSinkBlockV1,\n    PLCBlockV1,\n    ModbusTCPBlockV1,\n    MicrosoftSQLServerSinkBlockV1,\n    EventWriterSinkBlockV1,\n]\n\ndef load_enterprise_blocks() -> List[Type[WorkflowBlock]]:\n    return _ENTERPRISE_BLOCKS\n```\n```python:inference/enterprise/workflows/enterprise_blocks/sinks/mqtt_writer/v1.py\nimport threading\nfrom typing import Optional\n\nimport paho.mqtt.client as mqtt\nfrom inference.core.workflows.prototypes.block import WorkflowBlock\n\n\nclass MQTTWriterSinkBlockV1(WorkflowBlock):\n    def __init__(self):\n        self.mqtt_client: Optional[mqtt.Client] = None\n        self._connected: Optional[threading.Event] = None\n```\n```python:inference/enterprise/workflows/enterprise_blocks/sinks/PLC_modbus/v1.py\nfrom typing import Optional\n\nfrom inference.core.workflows.prototypes.block import WorkflowBlock\nfrom pymodbus.client import ModbusTcpClient as ModbusClient\n\n\nclass ModbusTCPBlockV1(WorkflowBlock):\n\n    def __init__(self):\n        self.client = None\n```",
    "optimized_function_only": "def load_enterprise_blocks() -> List[Type[WorkflowBlock]]:\n    return _ENTERPRISE_BLOCKS",
    "original_file_content": "from typing import List, Type\n\nfrom inference.core.workflows.prototypes.block import WorkflowBlock\nfrom inference.enterprise.workflows.enterprise_blocks.sinks.event_writer.v1 import (\n    EventWriterSinkBlockV1,\n)\nfrom inference.enterprise.workflows.enterprise_blocks.sinks.microsoft_sql_server.v1 import (\n    MicrosoftSQLServerSinkBlockV1,\n)\nfrom inference.enterprise.workflows.enterprise_blocks.sinks.mqtt_writer.v1 import (\n    MQTTWriterSinkBlockV1,\n)\nfrom inference.enterprise.workflows.enterprise_blocks.sinks.opc_writer.v1 import (\n    OPCWriterSinkBlockV1,\n)\nfrom inference.enterprise.workflows.enterprise_blocks.sinks.PLC_modbus.v1 import (\n    ModbusTCPBlockV1,\n)\nfrom inference.enterprise.workflows.enterprise_blocks.sinks.PLCethernetIP.v1 import (\n    PLCBlockV1,\n)\n\n\ndef load_enterprise_blocks() -> List[Type[WorkflowBlock]]:\n    return [\n        OPCWriterSinkBlockV1,\n        MQTTWriterSinkBlockV1,\n        PLCBlockV1,\n        ModbusTCPBlockV1,\n        MicrosoftSQLServerSinkBlockV1,\n        EventWriterSinkBlockV1,\n    ]\n",
    "patch": null
  },
  {
    "trace_id": "72402a01-b9c2-4c25-8b26-8fcd2c4254fb",
    "function_name": "BlockManifest.get_air_gapped_availability",
    "file_path": "inference/core/workflows/core_steps/sinks/twilio/sms/v1.py",
    "speedup_x": 0.14331850873840382,
    "review_quality": "medium",
    "pre_optimization_commit": "94c9904bdcf3ee22d330da1e19f81e3463f2ed07",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def get_air_gapped_availability(cls) -> dict:\n        return {\"available\": False, \"reason\": \"requires_internet\"}\n",
    "optimized_function_code": "from inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nLONG_DESCRIPTION = \"\"\"\nSend SMS text message notifications via Twilio SMS service with customizable message content featuring dynamic workflow data parameters, automatic message truncation for SMS length limits, cooldown throttling using cache-based session tracking, and optional async background execution for mobile alerts, urgent notifications, and real-time communication workflows.\n\n## How This Block Works\n\nThis block sends SMS text messages to phone numbers using the Twilio SMS API, integrating workflow execution results into message content. The block:\n\n1. Checks if the sink is disabled via `disable_sink` flag (if disabled, returns immediately without sending)\n2. Generates a cache key for cooldown tracking using a hash of Twilio credentials (Account SID and Auth Token) and `cooldown_session_key` (unique per workflow step)\n3. Validates cooldown period by checking cache for the last notification timestamp (if enabled, throttles notifications within `cooldown_seconds` of the last sent SMS, returning throttling status)\n4. Creates or retrieves a Twilio Client instance for the provided credentials (caches clients by credential hash for efficiency)\n5. Formats the message by processing dynamic parameters (replaces placeholders like `{{ $parameters.parameter_name }}` with actual workflow data from `message_parameters`)\n6. Applies optional UQL operations to transform parameter values before insertion (e.g., extract class names from detections, calculate metrics, filter data) using `message_parameters_operations`\n7. Truncates the message if it exceeds `length_limit` characters (appends truncation marker `[...]` to indicate truncation)\n8. Sends the SMS message to the receiver phone number from the sender number using Twilio's `messages.create` API\n9. Updates the cache with the current notification timestamp (expires after 15 minutes)\n10. Executes synchronously or asynchronously based on `fire_and_forget` setting:\n    - **Synchronous mode** (`fire_and_forget=False`): Waits for Twilio API call completion, returns actual error status for debugging\n    - **Asynchronous mode** (`fire_and_forget=True`): Sends SMS in background task, workflow continues immediately, error status always False\n11. Returns status outputs indicating success, throttling, or errors (includes Twilio API error details when available)\n\nThe block supports dynamic message content through parameter placeholders that are replaced with workflow data at runtime. Message parameters can be raw workflow outputs or transformed using UQL operations (e.g., extract properties, calculate counts, filter values). SMS messages are automatically truncated if they exceed the character limit to comply with SMS standards and prevent message delivery issues. Cooldown prevents SMS spam by enforcing minimum time between sends using cache-based tracking with session keys, enabling per-step throttling in distributed or multi-instance environments.\n\n## Requirements\n\n**Twilio Account Configuration**: Requires a Twilio account with SMS capabilities:\n- `twilio_account_sid`: Twilio Account SID (found in [Twilio Console](https://twilio.com/console))\n- `twilio_auth_token`: Twilio Auth Token (found in Twilio Console, marked as private for security)\n- Credentials can be provided via workflow inputs (recommended for security) using SECRET_KIND selectors rather than storing in workflow definitions\n- View [Twilio SMS tutorial](https://www.twilio.com/docs/messaging/tutorials/how-to-send-sms-messages/python) for setup instructions\n\n**Phone Number Configuration**: Requires valid phone numbers in E.164 format (e.g., `+1234567890`):\n- `sender_number`: Twilio phone number to send SMS messages from. Must be a Twilio-purchased number or a verified number in your Twilio account\n- `receiver_number`: Destination phone number to receive the SMS\n\n**Cooldown Session Key**: The `cooldown_session_key` must be unique for each Twilio SMS Notification step in your workflow to enable proper per-step cooldown tracking. The cooldown mechanism uses cache-based storage with a 15-minute expiration time, and cooldown seconds must be between 0 and 900 (15 minutes).\n\n**Message Length Limit**: SMS messages have a default length limit of 160 characters. Messages exceeding `length_limit` are automatically truncated with a truncation marker (`[...]`). Adjust `length_limit` based on your needs, but note that SMS standards typically support 160 characters for single-part messages or 153 characters per segment for multi-part messages.\n\n## Common Use Cases\n\n- **Urgent Alert Notifications**: Send SMS alerts to mobile devices when critical conditions are detected (e.g., alert security personnel when unauthorized objects detected, notify operators when system anomalies occur, send alerts when detection counts exceed critical thresholds), enabling immediate mobile notification for time-sensitive incidents\n- **Mobile Workflow Updates**: Send SMS notifications about workflow execution status and critical results (e.g., notify operators when batch processing completes, send urgent failure alerts, alert about system health issues), enabling mobile visibility into automated processes\n- **Detection Summaries**: Send SMS messages with detection results and key statistics (e.g., share counts of detected objects, send classification summaries, include critical detection alerts), enabling stakeholders to receive important workflow outputs on their mobile devices\n- **Emergency Notifications**: Send urgent SMS alerts for emergency situations and critical events (e.g., alert emergency responders, notify maintenance teams about critical issues, send immediate system failure notifications), enabling rapid mobile communication for emergency response\n- **Real-Time Mobile Monitoring**: Send continuous SMS updates for real-time monitoring and status notifications (e.g., notify about system health issues, send periodic performance alerts, alert about processing milestones), enabling mobile visibility for operational monitoring\n- **On-Call Alerts**: Send SMS notifications to on-call personnel for after-hours or critical issues (e.g., alert on-call engineers about system problems, notify on-call security about detected threats, send after-hours incident notifications), enabling mobile communication for on-call staff\n\n## Connecting to Other Blocks\n\nThis block receives data from workflow steps and sends SMS notifications:\n\n- **After detection or analysis blocks** (e.g., Object Detection, Instance Segmentation, Classification) to send urgent mobile alerts or summaries when objects are detected, classifications are made, or thresholds are exceeded, enabling real-time mobile notifications for critical events\n- **After data processing blocks** (e.g., Expression, Property Definition, Detections Filter) to include computed metrics, transformed data, or filtered results in SMS notifications, enabling customized mobile reporting with processed data\n- **In conditional workflows** (e.g., Continue If) to send SMS notifications only when specific conditions are met, enabling event-driven mobile alerting and urgent notifications\n- **After aggregation blocks** (e.g., Data Aggregator) to send periodic analytics summaries and statistical reports via SMS, enabling scheduled mobile updates and trend analysis\n- **In monitoring workflows** to send status updates, error notifications, or health check reports to mobile devices, enabling automated system monitoring and incident management via SMS\n- **For emergency workflows** where immediate mobile notification is critical (e.g., security alerts, system failures, critical detections), enabling rapid mobile communication for time-sensitive situations\n\"\"\"\n\n\n\n# Cache the constant mapping once at module import to avoid reconstructing it repeatedly.\n_AIR_GAPPED_AVAILABILITY = {\"available\": False, \"reason\": \"requires_internet\"}\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_air_gapped_availability(cls) -> dict:\n        return _AIR_GAPPED_AVAILABILITY.copy()",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/sinks/twilio/sms/v1.py\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nLONG_DESCRIPTION = \"\"\"\nSend SMS text message notifications via Twilio SMS service with customizable message content featuring dynamic workflow data parameters, automatic message truncation for SMS length limits, cooldown throttling using cache-based session tracking, and optional async background execution for mobile alerts, urgent notifications, and real-time communication workflows.\n\n## How This Block Works\n\nThis block sends SMS text messages to phone numbers using the Twilio SMS API, integrating workflow execution results into message content. The block:\n\n1. Checks if the sink is disabled via `disable_sink` flag (if disabled, returns immediately without sending)\n2. Generates a cache key for cooldown tracking using a hash of Twilio credentials (Account SID and Auth Token) and `cooldown_session_key` (unique per workflow step)\n3. Validates cooldown period by checking cache for the last notification timestamp (if enabled, throttles notifications within `cooldown_seconds` of the last sent SMS, returning throttling status)\n4. Creates or retrieves a Twilio Client instance for the provided credentials (caches clients by credential hash for efficiency)\n5. Formats the message by processing dynamic parameters (replaces placeholders like `{{ $parameters.parameter_name }}` with actual workflow data from `message_parameters`)\n6. Applies optional UQL operations to transform parameter values before insertion (e.g., extract class names from detections, calculate metrics, filter data) using `message_parameters_operations`\n7. Truncates the message if it exceeds `length_limit` characters (appends truncation marker `[...]` to indicate truncation)\n8. Sends the SMS message to the receiver phone number from the sender number using Twilio's `messages.create` API\n9. Updates the cache with the current notification timestamp (expires after 15 minutes)\n10. Executes synchronously or asynchronously based on `fire_and_forget` setting:\n    - **Synchronous mode** (`fire_and_forget=False`): Waits for Twilio API call completion, returns actual error status for debugging\n    - **Asynchronous mode** (`fire_and_forget=True`): Sends SMS in background task, workflow continues immediately, error status always False\n11. Returns status outputs indicating success, throttling, or errors (includes Twilio API error details when available)\n\nThe block supports dynamic message content through parameter placeholders that are replaced with workflow data at runtime. Message parameters can be raw workflow outputs or transformed using UQL operations (e.g., extract properties, calculate counts, filter values). SMS messages are automatically truncated if they exceed the character limit to comply with SMS standards and prevent message delivery issues. Cooldown prevents SMS spam by enforcing minimum time between sends using cache-based tracking with session keys, enabling per-step throttling in distributed or multi-instance environments.\n\n## Requirements\n\n**Twilio Account Configuration**: Requires a Twilio account with SMS capabilities:\n- `twilio_account_sid`: Twilio Account SID (found in [Twilio Console](https://twilio.com/console))\n- `twilio_auth_token`: Twilio Auth Token (found in Twilio Console, marked as private for security)\n- Credentials can be provided via workflow inputs (recommended for security) using SECRET_KIND selectors rather than storing in workflow definitions\n- View [Twilio SMS tutorial](https://www.twilio.com/docs/messaging/tutorials/how-to-send-sms-messages/python) for setup instructions\n\n**Phone Number Configuration**: Requires valid phone numbers in E.164 format (e.g., `+1234567890`):\n- `sender_number`: Twilio phone number to send SMS messages from. Must be a Twilio-purchased number or a verified number in your Twilio account\n- `receiver_number`: Destination phone number to receive the SMS\n\n**Cooldown Session Key**: The `cooldown_session_key` must be unique for each Twilio SMS Notification step in your workflow to enable proper per-step cooldown tracking. The cooldown mechanism uses cache-based storage with a 15-minute expiration time, and cooldown seconds must be between 0 and 900 (15 minutes).\n\n**Message Length Limit**: SMS messages have a default length limit of 160 characters. Messages exceeding `length_limit` are automatically truncated with a truncation marker (`[...]`). Adjust `length_limit` based on your needs, but note that SMS standards typically support 160 characters for single-part messages or 153 characters per segment for multi-part messages.\n\n## Common Use Cases\n\n- **Urgent Alert Notifications**: Send SMS alerts to mobile devices when critical conditions are detected (e.g., alert security personnel when unauthorized objects detected, notify operators when system anomalies occur, send alerts when detection counts exceed critical thresholds), enabling immediate mobile notification for time-sensitive incidents\n- **Mobile Workflow Updates**: Send SMS notifications about workflow execution status and critical results (e.g., notify operators when batch processing completes, send urgent failure alerts, alert about system health issues), enabling mobile visibility into automated processes\n- **Detection Summaries**: Send SMS messages with detection results and key statistics (e.g., share counts of detected objects, send classification summaries, include critical detection alerts), enabling stakeholders to receive important workflow outputs on their mobile devices\n- **Emergency Notifications**: Send urgent SMS alerts for emergency situations and critical events (e.g., alert emergency responders, notify maintenance teams about critical issues, send immediate system failure notifications), enabling rapid mobile communication for emergency response\n- **Real-Time Mobile Monitoring**: Send continuous SMS updates for real-time monitoring and status notifications (e.g., notify about system health issues, send periodic performance alerts, alert about processing milestones), enabling mobile visibility for operational monitoring\n- **On-Call Alerts**: Send SMS notifications to on-call personnel for after-hours or critical issues (e.g., alert on-call engineers about system problems, notify on-call security about detected threats, send after-hours incident notifications), enabling mobile communication for on-call staff\n\n## Connecting to Other Blocks\n\nThis block receives data from workflow steps and sends SMS notifications:\n\n- **After detection or analysis blocks** (e.g., Object Detection, Instance Segmentation, Classification) to send urgent mobile alerts or summaries when objects are detected, classifications are made, or thresholds are exceeded, enabling real-time mobile notifications for critical events\n- **After data processing blocks** (e.g., Expression, Property Definition, Detections Filter) to include computed metrics, transformed data, or filtered results in SMS notifications, enabling customized mobile reporting with processed data\n- **In conditional workflows** (e.g., Continue If) to send SMS notifications only when specific conditions are met, enabling event-driven mobile alerting and urgent notifications\n- **After aggregation blocks** (e.g., Data Aggregator) to send periodic analytics summaries and statistical reports via SMS, enabling scheduled mobile updates and trend analysis\n- **In monitoring workflows** to send status updates, error notifications, or health check reports to mobile devices, enabling automated system monitoring and incident management via SMS\n- **For emergency workflows** where immediate mobile notification is critical (e.g., security alerts, system failures, critical detections), enabling rapid mobile communication for time-sensitive situations\n\"\"\"\n\n\n\n# Cache the constant mapping once at module import to avoid reconstructing it repeatedly.\n_AIR_GAPPED_AVAILABILITY = {\"available\": False, \"reason\": \"requires_internet\"}\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_air_gapped_availability(cls) -> dict:\n        return _AIR_GAPPED_AVAILABILITY.copy()\n```",
    "optimized_function_only": "    def get_air_gapped_availability(cls) -> dict:\n        return _AIR_GAPPED_AVAILABILITY.copy()",
    "original_file_content": "import hashlib\nimport logging\nimport re\nfrom collections import defaultdict\nfrom concurrent.futures import ThreadPoolExecutor\nfrom datetime import datetime\nfrom functools import partial\nfrom typing import Any, Dict, List, Literal, Optional, Tuple, Type, Union\n\nfrom fastapi import BackgroundTasks\nfrom pydantic import ConfigDict, Field, field_validator\nfrom twilio.rest import Client\n\nfrom inference.core.cache.base import BaseCache\nfrom inference.core.workflows.core_steps.common.query_language.entities.operations import (\n    AllOperationsType,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.core import (\n    build_operations_chain,\n)\nfrom inference.core.workflows.execution_engine.entities.base import OutputDefinition\nfrom inference.core.workflows.execution_engine.entities.types import (\n    BOOLEAN_KIND,\n    INTEGER_KIND,\n    SECRET_KIND,\n    STRING_KIND,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nCACHE_EXPIRE_TIME = 15 * 60\nTRUNCATION_MARKER = \"[...]\"\n\nLONG_DESCRIPTION = \"\"\"\nSend SMS text message notifications via Twilio SMS service with customizable message content featuring dynamic workflow data parameters, automatic message truncation for SMS length limits, cooldown throttling using cache-based session tracking, and optional async background execution for mobile alerts, urgent notifications, and real-time communication workflows.\n\n## How This Block Works\n\nThis block sends SMS text messages to phone numbers using the Twilio SMS API, integrating workflow execution results into message content. The block:\n\n1. Checks if the sink is disabled via `disable_sink` flag (if disabled, returns immediately without sending)\n2. Generates a cache key for cooldown tracking using a hash of Twilio credentials (Account SID and Auth Token) and `cooldown_session_key` (unique per workflow step)\n3. Validates cooldown period by checking cache for the last notification timestamp (if enabled, throttles notifications within `cooldown_seconds` of the last sent SMS, returning throttling status)\n4. Creates or retrieves a Twilio Client instance for the provided credentials (caches clients by credential hash for efficiency)\n5. Formats the message by processing dynamic parameters (replaces placeholders like `{{ $parameters.parameter_name }}` with actual workflow data from `message_parameters`)\n6. Applies optional UQL operations to transform parameter values before insertion (e.g., extract class names from detections, calculate metrics, filter data) using `message_parameters_operations`\n7. Truncates the message if it exceeds `length_limit` characters (appends truncation marker `[...]` to indicate truncation)\n8. Sends the SMS message to the receiver phone number from the sender number using Twilio's `messages.create` API\n9. Updates the cache with the current notification timestamp (expires after 15 minutes)\n10. Executes synchronously or asynchronously based on `fire_and_forget` setting:\n    - **Synchronous mode** (`fire_and_forget=False`): Waits for Twilio API call completion, returns actual error status for debugging\n    - **Asynchronous mode** (`fire_and_forget=True`): Sends SMS in background task, workflow continues immediately, error status always False\n11. Returns status outputs indicating success, throttling, or errors (includes Twilio API error details when available)\n\nThe block supports dynamic message content through parameter placeholders that are replaced with workflow data at runtime. Message parameters can be raw workflow outputs or transformed using UQL operations (e.g., extract properties, calculate counts, filter values). SMS messages are automatically truncated if they exceed the character limit to comply with SMS standards and prevent message delivery issues. Cooldown prevents SMS spam by enforcing minimum time between sends using cache-based tracking with session keys, enabling per-step throttling in distributed or multi-instance environments.\n\n## Requirements\n\n**Twilio Account Configuration**: Requires a Twilio account with SMS capabilities:\n- `twilio_account_sid`: Twilio Account SID (found in [Twilio Console](https://twilio.com/console))\n- `twilio_auth_token`: Twilio Auth Token (found in Twilio Console, marked as private for security)\n- Credentials can be provided via workflow inputs (recommended for security) using SECRET_KIND selectors rather than storing in workflow definitions\n- View [Twilio SMS tutorial](https://www.twilio.com/docs/messaging/tutorials/how-to-send-sms-messages/python) for setup instructions\n\n**Phone Number Configuration**: Requires valid phone numbers in E.164 format (e.g., `+1234567890`):\n- `sender_number`: Twilio phone number to send from (must be a Twilio-purchased number or verified number in your account)\n- `receiver_number`: Destination phone number to receive the SMS\n\n**Cooldown Session Key**: The `cooldown_session_key` must be unique for each Twilio SMS Notification step in your workflow to enable proper per-step cooldown tracking. The cooldown mechanism uses cache-based storage with a 15-minute expiration time, and cooldown seconds must be between 0 and 900 (15 minutes).\n\n**Message Length Limit**: SMS messages have a default length limit of 160 characters. Messages exceeding `length_limit` are automatically truncated with a truncation marker (`[...]`). Adjust `length_limit` based on your needs, but note that SMS standards typically support 160 characters for single-part messages or 153 characters per segment for multi-part messages.\n\n## Common Use Cases\n\n- **Urgent Alert Notifications**: Send SMS alerts to mobile devices when critical conditions are detected (e.g., alert security personnel when unauthorized objects detected, notify operators when system anomalies occur, send alerts when detection counts exceed critical thresholds), enabling immediate mobile notification for time-sensitive incidents\n- **Mobile Workflow Updates**: Send SMS notifications about workflow execution status and critical results (e.g., notify operators when batch processing completes, send urgent failure alerts, alert about system health issues), enabling mobile visibility into automated processes\n- **Detection Summaries**: Send SMS messages with detection results and key statistics (e.g., share counts of detected objects, send classification summaries, include critical detection alerts), enabling stakeholders to receive important workflow outputs on their mobile devices\n- **Emergency Notifications**: Send urgent SMS alerts for emergency situations and critical events (e.g., alert emergency responders, notify maintenance teams about critical issues, send immediate system failure notifications), enabling rapid mobile communication for emergency response\n- **Real-Time Mobile Monitoring**: Send continuous SMS updates for real-time monitoring and status notifications (e.g., notify about system health issues, send periodic performance alerts, alert about processing milestones), enabling mobile visibility for operational monitoring\n- **On-Call Alerts**: Send SMS notifications to on-call personnel for after-hours or critical issues (e.g., alert on-call engineers about system problems, notify on-call security about detected threats, send after-hours incident notifications), enabling mobile communication for on-call staff\n\n## Connecting to Other Blocks\n\nThis block receives data from workflow steps and sends SMS notifications:\n\n- **After detection or analysis blocks** (e.g., Object Detection, Instance Segmentation, Classification) to send urgent mobile alerts or summaries when objects are detected, classifications are made, or thresholds are exceeded, enabling real-time mobile notifications for critical events\n- **After data processing blocks** (e.g., Expression, Property Definition, Detections Filter) to include computed metrics, transformed data, or filtered results in SMS notifications, enabling customized mobile reporting with processed data\n- **In conditional workflows** (e.g., Continue If) to send SMS notifications only when specific conditions are met, enabling event-driven mobile alerting and urgent notifications\n- **After aggregation blocks** (e.g., Data Aggregator) to send periodic analytics summaries and statistical reports via SMS, enabling scheduled mobile updates and trend analysis\n- **In monitoring workflows** to send status updates, error notifications, or health check reports to mobile devices, enabling automated system monitoring and incident management via SMS\n- **For emergency workflows** where immediate mobile notification is critical (e.g., security alerts, system failures, critical detections), enabling rapid mobile communication for time-sensitive situations\n\"\"\"\n\nPARAMETER_REGEX = re.compile(r\"({{\\s*\\$parameters\\.(\\w+)\\s*}})\")\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Twilio SMS Notification\",\n            \"version\": \"v1\",\n            \"short_description\": \"Send notification via Twilio SMS service.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"sink\",\n            \"ui_manifest\": {\n                \"section\": \"notifications\",\n                \"icon\": \"far fa-comment-sms\",\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/twilio_sms_notification@v1\"]\n    twilio_account_sid: Union[str, Selector(kind=[STRING_KIND, SECRET_KIND])] = Field(\n        title=\"Twilio Account SID\",\n        description=\"Twilio Account SID for authenticating with Twilio API. Found in the [Twilio Console](https://twilio.com/console) under Account Info. This field is marked as private for security. Recommended to provide via workflow inputs using SECRET_KIND selectors rather than storing in workflow definitions. Used together with twilio_auth_token to authenticate Twilio API requests for sending SMS messages.\",\n        private=True,\n        examples=[\"$inputs.twilio_account_sid\"],\n    )\n    twilio_auth_token: Union[str, Selector(kind=[STRING_KIND, SECRET_KIND])] = Field(\n        title=\"Twilio Auth Token\",\n        description=\"Twilio Auth Token for authenticating with Twilio API. Found in the [Twilio Console](https://twilio.com/console) under Account Info (click 'show' to reveal). This field is marked as private for security. Recommended to provide via workflow inputs using SECRET_KIND selectors rather than storing in workflow definitions. Used together with twilio_account_sid to authenticate Twilio API requests for sending SMS messages.\",\n        private=True,\n        examples=[\"$inputs.twilio_auth_token\"],\n        json_schema_extra={\n            \"hide_description\": True,\n        },\n    )\n    sender_number: Union[str, Selector(kind=[STRING_KIND])] = Field(\n        description=\"Twilio phone number to send SMS messages from. Must be in E.164 format (e.g., '+1234567890') and must be a Twilio-purchased phone number or a verified number in your Twilio account. This number appears as the sender in SMS messages received by recipients. You can purchase numbers in the Twilio Console or use trial numbers for testing.\",\n        examples=[\"+1234567890\", \"$inputs.sender_number\"],\n        json_schema_extra={\n            \"hide_description\": True,\n        },\n    )\n    receiver_number: Union[str, Selector(kind=[STRING_KIND])] = Field(\n        description=\"Destination phone number to receive the SMS message. Must be in E.164 format (e.g., '+1234567890'). For Twilio trial accounts, receiver numbers must be verified in your Twilio account. For paid accounts, you can send to any valid phone number. This is the mobile number that will receive the notification.\",\n        examples=[\"+1234567890\", \"$inputs.receiver_number\"],\n        json_schema_extra={\n            \"hide_description\": True,\n        },\n    )\n    message: str = Field(\n        description=\"SMS message content (plain text). Supports dynamic parameters using placeholder syntax: {{ $parameters.parameter_name }}. Placeholders are replaced with values from message_parameters at runtime. Message can be multi-line text but will be sent as a single SMS. Messages exceeding length_limit will be automatically truncated with a truncation marker. Example: 'Detected {{ $parameters.num_objects }} objects. Alert: {{ $parameters.classes }}.'\",\n        examples=[\n            \"During last 5 minutes detected {{ $parameters.num_instances }} instances\"\n        ],\n        json_schema_extra={\n            \"multiline\": True,\n        },\n    )\n    message_parameters: Dict[\n        str,\n        Union[Selector(), Selector(), str, int, float, bool],\n    ] = Field(\n        description=\"Dictionary mapping parameter names (used in message placeholders) to workflow data sources. Keys are parameter names referenced in message as {{ $parameters.key }}, values are selectors to workflow step outputs or direct values. These values are substituted into message placeholders at runtime. Can optionally use message_parameters_operations to transform parameter values before substitution.\",\n        examples=[\n            {\n                \"predictions\": \"$steps.model.predictions\",\n                \"reference\": \"$inputs.reference_class_names\",\n            }\n        ],\n        default_factory=dict,\n        json_schema_extra={\n            \"always_visible\": True,\n        },\n    )\n    message_parameters_operations: Dict[str, List[AllOperationsType]] = Field(\n        description=\"Optional dictionary mapping parameter names (from message_parameters) to UQL operation chains that transform parameter values before inserting them into the message. Operations are applied in sequence (e.g., extract class names from detections, calculate counts, filter values). Keys must match parameter names in message_parameters. Leave empty or omit parameters that don't need transformation.\",\n        examples=[\n            {\n                \"predictions\": [\n                    {\"type\": \"DetectionsPropertyExtract\", \"property_name\": \"class_name\"}\n                ]\n            }\n        ],\n        default_factory=dict,\n    )\n    fire_and_forget: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=True,\n        description=\"Execution mode: True for asynchronous background sending (workflow continues immediately, error_status always False, faster execution), False for synchronous sending (waits for Twilio API call completion, returns actual error status for debugging). Set to False during development and debugging to catch Twilio API errors. Set to True in production for faster workflow execution when SMS delivery timing is not critical.\",\n        examples=[\"$inputs.fire_and_forget\", False],\n    )\n    disable_sink: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=False,\n        description=\"Flag to disable SMS notification sending at runtime. When True, the block skips sending SMS and returns a disabled message. Useful for conditional notification control via workflow inputs (e.g., allow callers to disable notifications for testing, enable/disable based on configuration). Set via workflow inputs for runtime control.\",\n        examples=[False, \"$inputs.disable_sms_notifications\"],\n    )\n    cooldown_seconds: Union[int, Selector(kind=[INTEGER_KIND])] = Field(\n        default=5,\n        description=\"Minimum seconds between consecutive SMS notifications to prevent SMS spam. Defaults to 5 seconds. Set to 0 to disable cooldown (no throttling). Must be between 0 and 900 (15 minutes). During cooldown period, the block returns throttling_status=True and skips sending. Cooldown is tracked per step using cooldown_session_key with cache-based storage (15-minute expiration). Each Twilio SMS Notification step in a workflow should have a unique cooldown_session_key for proper per-step tracking.\",\n        examples=[\"$inputs.cooldown_seconds\", 3],\n        json_schema_extra={\n            \"always_visible\": True,\n        },\n    )\n    cooldown_session_key: str = Field(\n        description=\"Unique identifier for this Twilio SMS Notification step's cooldown tracking session. Must be unique for each Twilio SMS Notification step in your workflow to enable proper per-step cooldown isolation. Used with the Twilio credentials hash to create a cache key for tracking the last notification timestamp. In distributed or multi-instance environments, this ensures cooldown works correctly per step. Typically auto-generated or provided as a workflow input.\",\n        examples=[\"session-1v73kdhfse\"],\n        json_schema_extra={\"hidden\": True},\n    )\n    length_limit: Union[int, Selector(kind=[INTEGER_KIND])] = Field(\n        default=160,\n        description=\"Maximum number of characters allowed in the SMS message before truncation. Defaults to 160 characters (standard single-part SMS length). Messages exceeding this limit are automatically truncated, with the last characters replaced by a truncation marker ('[...]'). Must be greater than 0. Note: SMS standards support 160 characters for single-part messages or 153 characters per segment for multi-part messages. Adjust based on your needs, but longer messages may incur additional costs with Twilio.\",\n        examples=[\"$inputs.sms_length_limit\", 160],\n        json_schema_extra={\n            \"always_visible\": True,\n        },\n    )\n\n    @classmethod\n    def get_air_gapped_availability(cls) -> dict:\n        return {\"available\": False, \"reason\": \"requires_internet\"}\n\n    @field_validator(\"cooldown_seconds\")\n    @classmethod\n    def ensure_cooldown_seconds_within_bounds(cls, value: Any) -> dict:\n        if isinstance(value, int) and (value < 0 or value > CACHE_EXPIRE_TIME):\n            raise ValueError(\n                f\"`cooldown_seconds` must be in range [0, {CACHE_EXPIRE_TIME}]\"\n            )\n        return value\n\n    @field_validator(\"length_limit\")\n    @classmethod\n    def ensure_length_limit_within_bounds(cls, value: Any) -> dict:\n        if isinstance(value, int) and value <= 0:\n            raise ValueError(f\"Length limit for SMS must be greater than 0\")\n        return value\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"error_status\", kind=[BOOLEAN_KIND]),\n            OutputDefinition(name=\"throttling_status\", kind=[BOOLEAN_KIND]),\n            OutputDefinition(name=\"message\", kind=[STRING_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.4.0,<2.0.0\"\n\n\nclass TwilioSMSNotificationBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        cache: BaseCache,\n        background_tasks: Optional[BackgroundTasks],\n        thread_pool_executor: Optional[ThreadPoolExecutor],\n    ):\n        self._cache = cache\n        self._background_tasks = background_tasks\n        self._thread_pool_executor = thread_pool_executor\n        self._clients: Dict[str, Client] = {}\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"cache\", \"background_tasks\", \"thread_pool_executor\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        twilio_account_sid: str,\n        twilio_auth_token: str,\n        message: str,\n        sender_number: str,\n        receiver_number: str,\n        message_parameters: Dict[str, Any],\n        message_parameters_operations: Dict[str, List[AllOperationsType]],\n        fire_and_forget: bool,\n        disable_sink: bool,\n        cooldown_seconds: int,\n        cooldown_session_key: str,\n        length_limit: int,\n    ) -> BlockResult:\n        if disable_sink:\n            return {\n                \"error_status\": False,\n                \"throttling_status\": False,\n                \"message\": \"Sink was disabled by parameter `disable_sink`\",\n            }\n        credentials_hash = _hash_credentials(\n            twilio_account_sid=twilio_account_sid,\n            twilio_auth_token=twilio_auth_token,\n        )\n        cache_key = _generate_cache_key_for_cooldown_session(\n            session_key=cooldown_session_key,\n            token_hash=credentials_hash,\n        )\n        last_notification_fired = self._cache.get(cache_key)\n        seconds_since_last_notification = cooldown_seconds\n        if last_notification_fired is not None:\n            last_notification_fired = datetime.fromisoformat(last_notification_fired)\n            seconds_since_last_notification = (\n                datetime.now() - last_notification_fired\n            ).total_seconds()\n        if seconds_since_last_notification < cooldown_seconds:\n            logging.info(\n                f\"Activated `roboflow_core/twilio_sms_notification@v1` cooldown.\"\n            )\n            return {\n                \"error_status\": False,\n                \"throttling_status\": True,\n                \"message\": \"Sink cooldown applies\",\n            }\n        if credentials_hash not in self._clients:\n            self._clients[credentials_hash] = Client(\n                twilio_account_sid,\n                twilio_auth_token,\n            )\n        client = self._clients[credentials_hash]\n        message = format_message(\n            message=message,\n            message_parameters=message_parameters,\n            message_parameters_operations=message_parameters_operations,\n            length_limit=length_limit,\n        )\n        send_notification_handler = partial(\n            send_sms_notification,\n            client=client,\n            message=message,\n            sender_number=sender_number,\n            receiver_number=receiver_number,\n        )\n        last_notification_fired = datetime.now().isoformat()\n        self._cache.set(\n            key=cache_key, value=last_notification_fired, expire=CACHE_EXPIRE_TIME\n        )\n        if fire_and_forget and self._background_tasks:\n            self._background_tasks.add_task(send_notification_handler)\n            return {\n                \"error_status\": False,\n                \"throttling_status\": False,\n                \"message\": \"Notification sent in the background task\",\n            }\n        if fire_and_forget and self._thread_pool_executor:\n            self._thread_pool_executor.submit(send_notification_handler)\n            return {\n                \"error_status\": False,\n                \"throttling_status\": False,\n                \"message\": \"Notification sent in the background task\",\n            }\n        error_status, message = send_notification_handler()\n        return {\n            \"error_status\": error_status,\n            \"throttling_status\": False,\n            \"message\": message,\n        }\n\n\ndef _hash_credentials(twilio_account_sid: str, twilio_auth_token: str) -> str:\n    sid_hash = hashlib.sha256(twilio_account_sid.encode(\"utf-8\")).hexdigest()\n    auth_token_hash = hashlib.sha256(twilio_auth_token.encode(\"utf-8\")).hexdigest()\n    return f\"{sid_hash}:{auth_token_hash}\"\n\n\ndef _generate_cache_key_for_cooldown_session(session_key: str, token_hash: str) -> str:\n    return (\n        f\"workflows:steps_cache:roboflow_core/twilio_sms_notification@v1:\"\n        f\"{token_hash}:{session_key}:last_notification_time\"\n    )\n\n\ndef format_message(\n    message: str,\n    message_parameters: Dict[str, Any],\n    message_parameters_operations: Dict[str, List[AllOperationsType]],\n    length_limit: int,\n) -> str:\n    matching_parameters = PARAMETER_REGEX.findall(message)\n    parameters_to_get_values = {\n        p[1] for p in matching_parameters if p[1] in message_parameters\n    }\n    parameters_values = {}\n    for parameter_name in parameters_to_get_values:\n        parameter_value = message_parameters[parameter_name]\n        operations = message_parameters_operations.get(parameter_name)\n        if not operations:\n            parameters_values[parameter_name] = parameter_value\n            continue\n        operations_chain = build_operations_chain(operations=operations)\n        parameters_values[parameter_name] = operations_chain(\n            parameter_value, global_parameters={}\n        )\n    parameter_to_placeholders = defaultdict(list)\n    for placeholder, parameter_name in matching_parameters:\n        if parameter_name not in parameters_to_get_values:\n            continue\n        parameter_to_placeholders[parameter_name].append(placeholder)\n    for parameter_name, placeholders in parameter_to_placeholders.items():\n        for placeholder in placeholders:\n            message = message.replace(\n                placeholder, str(parameters_values[parameter_name])\n            )\n    if len(message) > length_limit:\n        truncated_message = message[: length_limit - 1 - len(TRUNCATION_MARKER)]\n        message = f\"{truncated_message} {TRUNCATION_MARKER}\"\n    return message\n\n\ndef send_sms_notification(\n    client: Client,\n    message: str,\n    sender_number: str,\n    receiver_number: str,\n) -> Tuple[bool, str]:\n    try:\n        client.messages.create(\n            body=message,\n            from_=sender_number,\n            to=receiver_number,\n        )\n        return False, \"Notification sent successfully\"\n    except Exception as error:\n        logging.warning(f\"Could not send Twilio SMS notification. Error: {str(error)}\")\n        return (\n            True,\n            f\"Failed to send Twilio SMS notification. Internal error details: {error}\",\n        )\n",
    "patch": null
  },
  {
    "trace_id": "da566e59-2f09-4230-afdc-4070ccd21d96",
    "function_name": "BlockManifest.get_air_gapped_availability",
    "file_path": "inference/core/workflows/core_steps/sinks/slack/notification/v1.py",
    "speedup_x": 0.1395832585090208,
    "review_quality": "medium",
    "pre_optimization_commit": "94c9904bdcf3ee22d330da1e19f81e3463f2ed07",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def get_air_gapped_availability(cls) -> dict:\n        return {\"available\": False, \"reason\": \"requires_internet\"}\n",
    "optimized_function_code": "from inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nLONG_DESCRIPTION = \"\"\"\nSend notifications to Slack channels with customizable message content featuring dynamic workflow data parameters, file attachments, cooldown throttling using cache-based session tracking, and optional async background execution for team alerts, monitoring, and real-time communication workflows.\n\n## How This Block Works\n\nThis block sends notifications to Slack channels using the Slack Web API, integrating workflow execution results into message content. The block:\n\n1. Checks if the sink is disabled via `disable_sink` flag (if disabled, returns immediately without sending)\n2. Generates a cache key for cooldown tracking using the Slack token hash and `cooldown_session_key` (unique per workflow step)\n3. Validates cooldown period by checking cache for the last notification timestamp (if enabled, throttles notifications within `cooldown_seconds` of the last sent notification, returning throttling status)\n4. Creates or retrieves a Slack WebClient instance for the provided token (caches clients by token hash for efficiency)\n5. Formats the message by processing dynamic parameters (replaces placeholders like `{{ $parameters.parameter_name }}` with actual workflow data from `message_parameters`)\n6. Applies optional UQL operations to transform parameter values before insertion (e.g., extract class names from detections, calculate metrics, filter data) using `message_parameters_operations`\n7. Sends the notification to the specified Slack channel:\n   - **Without attachments**: Uses `chat_postMessage` API to send text-only messages\n   - **With attachments**: Uses `files_upload_v2` API to upload files with the message as an initial comment\n8. Updates the cache with the current notification timestamp (expires after 15 minutes)\n9. Executes synchronously or asynchronously based on `fire_and_forget` setting:\n   - **Synchronous mode** (`fire_and_forget=False`): Waits for Slack API call completion, returns actual error status for debugging\n   - **Asynchronous mode** (`fire_and_forget=True`): Sends notification in background task, workflow continues immediately, error status always False\n10. Returns status outputs indicating success, throttling, or errors (includes Slack API error details when available)\n\nThe block supports dynamic message content through parameter placeholders that are replaced with workflow data at runtime. Message parameters can be raw workflow outputs or transformed using UQL operations (e.g., extract properties, calculate counts, filter values). Attachments are sourced from other workflow blocks that produce string or binary content (e.g., CSV Formatter for reports, image outputs for visualizations). Cooldown prevents notification spam by enforcing minimum time between sends using cache-based tracking with session keys, enabling per-step throttling in distributed or multi-instance environments.\n\n## Requirements\n\n**Slack API Token**: Requires a Slack API token (Bot Token or User Token) with appropriate permissions:\n- Token must have `chat:write` scope to send messages to channels\n- Token must have `files:write` scope if using attachments\n- Token can be provided via workflow inputs (recommended for security) or stored in workflow definitions\n- View [Slack API documentation](https://api.slack.com/tutorials/tracks/getting-a-token) or [Roboflow Blog guide](https://blog.roboflow.com/slack-notification-workflows/) for token generation instructions\n\n**Channel Configuration**: Requires a valid Slack channel identifier (channel ID or channel name starting with `#`). The bot or user associated with the token must be a member of the channel.\n\n**Cooldown Session Key**: The `cooldown_session_key` must be unique for each Slack Notification step in your workflow to enable proper per-step cooldown tracking. The cooldown mechanism uses cache-based storage with a 15-minute expiration time, and cooldown seconds must be between 0 and 900 (15 minutes).\n\n## Common Use Cases\n\n- **Team Alert Notifications**: Send Slack alerts to team channels when specific conditions are detected (e.g., alert security team when unauthorized objects detected, notify operations when anomaly detected, send alerts when detection counts exceed thresholds), enabling real-time team collaboration and incident response\n- **Workflow Execution Updates**: Send Slack notifications about workflow execution status and results (e.g., notify team when batch processing completes, send daily summary reports, alert about workflow failures), enabling team visibility into automated processes\n- **Detection Summaries**: Send Slack messages with detection results and aggregated statistics (e.g., share lists of detected objects, send counts and classifications, include detection confidence summaries), enabling stakeholders to stay informed about workflow outputs via team communication channels\n- **Report Distribution**: Upload and share generated reports and data exports via Slack (e.g., attach CSV reports from CSV Formatter, share exported detection data, include formatted analytics summaries), enabling automated data distribution through team channels\n- **Real-Time Monitoring**: Send continuous monitoring updates and status notifications (e.g., notify about system health issues, send periodic performance metrics, alert about processing milestones), enabling real-time visibility for operational monitoring\n- **Multi-Channel Broadcasting**: Send notifications to different Slack channels based on workflow conditions or routing logic (e.g., send alerts to different channels per detection type, route notifications by severity level, distribute reports to department-specific channels), enabling targeted communication and notification routing\n\n## Connecting to Other Blocks\n\nThis block receives data from workflow steps and sends Slack notifications:\n\n- **After detection or analysis blocks** (e.g., Object Detection, Instance Segmentation, Classification) to send alerts or summaries when objects are detected, classifications are made, or thresholds are exceeded, enabling real-time team notifications and collaboration\n- **After data processing blocks** (e.g., Expression, Property Definition, Detections Filter) to include computed metrics, transformed data, or filtered results in Slack notifications, enabling customized reporting with processed data in team channels\n- **After formatter blocks** (e.g., CSV Formatter) to attach formatted reports and exports to Slack messages, enabling automated distribution of structured data and analytics through team communication channels\n- **In conditional workflows** (e.g., Continue If) to send notifications only when specific conditions are met, enabling event-driven alerting and team communication\n- **After aggregation blocks** (e.g., Data Aggregator) to send periodic analytics summaries and statistical reports to Slack, enabling scheduled team updates and trend analysis\n- **In monitoring workflows** to send status updates, error notifications, or health check reports, enabling automated system monitoring and incident management through Slack\n\"\"\"\n\n\n\n_AIR_GAPPED_AVAILABILITY: dict = {\"available\": False, \"reason\": \"requires_internet\"}\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_air_gapped_availability(cls) -> dict:\n        return _AIR_GAPPED_AVAILABILITY.copy()",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/sinks/slack/notification/v1.py\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nLONG_DESCRIPTION = \"\"\"\nSend notifications to Slack channels with customizable message content featuring dynamic workflow data parameters, file attachments, cooldown throttling using cache-based session tracking, and optional async background execution for team alerts, monitoring, and real-time communication workflows.\n\n## How This Block Works\n\nThis block sends notifications to Slack channels using the Slack Web API, integrating workflow execution results into message content. The block:\n\n1. Checks if the sink is disabled via `disable_sink` flag (if disabled, returns immediately without sending)\n2. Generates a cache key for cooldown tracking using the Slack token hash and `cooldown_session_key` (unique per workflow step)\n3. Validates cooldown period by checking cache for the last notification timestamp (if enabled, throttles notifications within `cooldown_seconds` of the last sent notification, returning throttling status)\n4. Creates or retrieves a Slack WebClient instance for the provided token (caches clients by token hash for efficiency)\n5. Formats the message by processing dynamic parameters (replaces placeholders like `{{ $parameters.parameter_name }}` with actual workflow data from `message_parameters`)\n6. Applies optional UQL operations to transform parameter values before insertion (e.g., extract class names from detections, calculate metrics, filter data) using `message_parameters_operations`\n7. Sends the notification to the specified Slack channel:\n   - **Without attachments**: Uses `chat_postMessage` API to send text-only messages\n   - **With attachments**: Uses `files_upload_v2` API to upload files with the message as an initial comment\n8. Updates the cache with the current notification timestamp (expires after 15 minutes)\n9. Executes synchronously or asynchronously based on `fire_and_forget` setting:\n   - **Synchronous mode** (`fire_and_forget=False`): Waits for Slack API call completion, returns actual error status for debugging\n   - **Asynchronous mode** (`fire_and_forget=True`): Sends notification in background task, workflow continues immediately, error status always False\n10. Returns status outputs indicating success, throttling, or errors (includes Slack API error details when available)\n\nThe block supports dynamic message content through parameter placeholders that are replaced with workflow data at runtime. Message parameters can be raw workflow outputs or transformed using UQL operations (e.g., extract properties, calculate counts, filter values). Attachments are sourced from other workflow blocks that produce string or binary content (e.g., CSV Formatter for reports, image outputs for visualizations). Cooldown prevents notification spam by enforcing minimum time between sends using cache-based tracking with session keys, enabling per-step throttling in distributed or multi-instance environments.\n\n## Requirements\n\n**Slack API Token**: Requires a Slack API token (Bot Token or User Token) with appropriate permissions:\n- Token must have `chat:write` scope to send messages to channels\n- Token must have `files:write` scope if using attachments\n- Token can be provided via workflow inputs (recommended for security) or stored in workflow definitions\n- View [Slack API documentation](https://api.slack.com/tutorials/tracks/getting-a-token) or [Roboflow Blog guide](https://blog.roboflow.com/slack-notification-workflows/) for token generation instructions\n\n**Channel Configuration**: Requires a valid Slack channel identifier (channel ID or channel name starting with `#`). The bot or user associated with the token must be a member of the channel.\n\n**Cooldown Session Key**: The `cooldown_session_key` must be unique for each Slack Notification step in your workflow to enable proper per-step cooldown tracking. The cooldown mechanism uses cache-based storage with a 15-minute expiration time, and cooldown seconds must be between 0 and 900 (15 minutes).\n\n## Common Use Cases\n\n- **Team Alert Notifications**: Send Slack alerts to team channels when specific conditions are detected (e.g., alert security team when unauthorized objects detected, notify operations when anomaly detected, send alerts when detection counts exceed thresholds), enabling real-time team collaboration and incident response\n- **Workflow Execution Updates**: Send Slack notifications about workflow execution status and results (e.g., notify team when batch processing completes, send daily summary reports, alert about workflow failures), enabling team visibility into automated processes\n- **Detection Summaries**: Send Slack messages with detection results and aggregated statistics (e.g., share lists of detected objects, send counts and classifications, include detection confidence summaries), enabling stakeholders to stay informed about workflow outputs via team communication channels\n- **Report Distribution**: Upload and share generated reports and data exports via Slack (e.g., attach CSV reports from CSV Formatter, share exported detection data, include formatted analytics summaries), enabling automated data distribution through team channels\n- **Real-Time Monitoring**: Send continuous monitoring updates and status notifications (e.g., notify about system health issues, send periodic performance metrics, alert about processing milestones), enabling real-time visibility for operational monitoring\n- **Multi-Channel Broadcasting**: Send notifications to different Slack channels based on workflow conditions or routing logic (e.g., send alerts to different channels per detection type, route notifications by severity level, distribute reports to department-specific channels), enabling targeted communication and notification routing\n\n## Connecting to Other Blocks\n\nThis block receives data from workflow steps and sends Slack notifications:\n\n- **After detection or analysis blocks** (e.g., Object Detection, Instance Segmentation, Classification) to send alerts or summaries when objects are detected, classifications are made, or thresholds are exceeded, enabling real-time team notifications and collaboration\n- **After data processing blocks** (e.g., Expression, Property Definition, Detections Filter) to include computed metrics, transformed data, or filtered results in Slack notifications, enabling customized reporting with processed data in team channels\n- **After formatter blocks** (e.g., CSV Formatter) to attach formatted reports and exports to Slack messages, enabling automated distribution of structured data and analytics through team communication channels\n- **In conditional workflows** (e.g., Continue If) to send notifications only when specific conditions are met, enabling event-driven alerting and team communication\n- **After aggregation blocks** (e.g., Data Aggregator) to send periodic analytics summaries and statistical reports to Slack, enabling scheduled team updates and trend analysis\n- **In monitoring workflows** to send status updates, error notifications, or health check reports, enabling automated system monitoring and incident management through Slack\n\"\"\"\n\n\n\n_AIR_GAPPED_AVAILABILITY: dict = {\"available\": False, \"reason\": \"requires_internet\"}\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_air_gapped_availability(cls) -> dict:\n        return _AIR_GAPPED_AVAILABILITY.copy()\n```",
    "optimized_function_only": "    def get_air_gapped_availability(cls) -> dict:\n        return _AIR_GAPPED_AVAILABILITY.copy()",
    "original_file_content": "import hashlib\nimport logging\nimport re\nfrom collections import defaultdict\nfrom concurrent.futures import ThreadPoolExecutor\nfrom datetime import datetime\nfrom functools import partial\nfrom typing import Any, Dict, List, Literal, Optional, Tuple, Type, Union\n\nfrom fastapi import BackgroundTasks\nfrom pydantic import ConfigDict, Field, field_validator\nfrom slack_sdk import WebClient\nfrom slack_sdk.errors import SlackApiError\n\nfrom inference.core.cache.base import BaseCache\nfrom inference.core.workflows.core_steps.common.query_language.entities.operations import (\n    AllOperationsType,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.core import (\n    build_operations_chain,\n)\nfrom inference.core.workflows.execution_engine.entities.base import OutputDefinition\nfrom inference.core.workflows.execution_engine.entities.types import (\n    BOOLEAN_KIND,\n    BYTES_KIND,\n    INTEGER_KIND,\n    SECRET_KIND,\n    STRING_KIND,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nCACHE_EXPIRE_TIME = 15 * 60\n\nLONG_DESCRIPTION = \"\"\"\nSend notifications to Slack channels with customizable message content featuring dynamic workflow data parameters, file attachments, cooldown throttling using cache-based session tracking, and optional async background execution for team alerts, monitoring, and real-time communication workflows.\n\n## How This Block Works\n\nThis block sends notifications to Slack channels using the Slack Web API, integrating workflow execution results into message content. The block:\n\n1. Checks if the sink is disabled via `disable_sink` flag (if disabled, returns immediately without sending)\n2. Generates a cache key for cooldown tracking using the Slack token hash and `cooldown_session_key` (unique per workflow step)\n3. Validates cooldown period by checking cache for the last notification timestamp (if enabled, throttles notifications within `cooldown_seconds` of the last sent notification, returning throttling status)\n4. Creates or retrieves a Slack WebClient instance for the provided token (caches clients by token hash for efficiency)\n5. Formats the message by processing dynamic parameters (replaces placeholders like `{{ $parameters.parameter_name }}` with actual workflow data from `message_parameters`)\n6. Applies optional UQL operations to transform parameter values before insertion (e.g., extract class names from detections, calculate metrics, filter data) using `message_parameters_operations`\n7. Sends the notification to the specified Slack channel:\n   - **Without attachments**: Uses `chat_postMessage` API to send text-only messages\n   - **With attachments**: Uses `files_upload_v2` API to upload files with the message as an initial comment\n8. Updates the cache with the current notification timestamp (expires after 15 minutes)\n9. Executes synchronously or asynchronously based on `fire_and_forget` setting:\n   - **Synchronous mode** (`fire_and_forget=False`): Waits for Slack API call completion, returns actual error status for debugging\n   - **Asynchronous mode** (`fire_and_forget=True`): Sends notification in background task, workflow continues immediately, error status always False\n10. Returns status outputs indicating success, throttling, or errors (includes Slack API error details when available)\n\nThe block supports dynamic message content through parameter placeholders that are replaced with workflow data at runtime. Message parameters can be raw workflow outputs or transformed using UQL operations (e.g., extract properties, calculate counts, filter values). Attachments are sourced from other workflow blocks that produce string or binary content (e.g., CSV Formatter for reports, image outputs for visualizations). Cooldown prevents notification spam by enforcing minimum time between sends using cache-based tracking with session keys, enabling per-step throttling in distributed or multi-instance environments.\n\n## Requirements\n\n**Slack API Token**: Requires a Slack API token (Bot Token or User Token) with appropriate permissions:\n- Token must have `chat:write` scope to send messages to channels\n- Token must have `files:write` scope if using attachments\n- Token can be provided via workflow inputs (recommended for security) or stored in workflow definitions\n- View [Slack API documentation](https://api.slack.com/tutorials/tracks/getting-a-token) or [Roboflow Blog guide](https://blog.roboflow.com/slack-notification-workflows/) for token generation instructions\n\n**Channel Configuration**: Requires a valid Slack channel identifier (channel ID or channel name starting with `#`). The bot or user associated with the token must be a member of the channel.\n\n**Cooldown Session Key**: The `cooldown_session_key` must be unique for each Slack Notification step in your workflow to enable proper per-step cooldown tracking. The cooldown mechanism uses cache-based storage with a 15-minute expiration time, and cooldown seconds must be between 0 and 900 (15 minutes).\n\n## Common Use Cases\n\n- **Team Alert Notifications**: Send Slack alerts to team channels when specific conditions are detected (e.g., alert security team when unauthorized objects detected, notify operations when anomaly detected, send alerts when detection counts exceed thresholds), enabling real-time team collaboration and incident response\n- **Workflow Execution Updates**: Send Slack notifications about workflow execution status and results (e.g., notify team when batch processing completes, send daily summary reports, alert about workflow failures), enabling team visibility into automated processes\n- **Detection Summaries**: Send Slack messages with detection results and aggregated statistics (e.g., share lists of detected objects, send counts and classifications, include detection confidence summaries), enabling stakeholders to stay informed about workflow outputs via team communication channels\n- **Report Distribution**: Upload and share generated reports and data exports via Slack (e.g., attach CSV reports from CSV Formatter, share exported detection data, include formatted analytics summaries), enabling automated data distribution through team channels\n- **Real-Time Monitoring**: Send continuous monitoring updates and status notifications (e.g., notify about system health issues, send periodic performance metrics, alert about processing milestones), enabling real-time visibility for operational monitoring\n- **Multi-Channel Broadcasting**: Send notifications to different Slack channels based on workflow conditions or routing logic (e.g., send alerts to different channels per detection type, route notifications by severity level, distribute reports to department-specific channels), enabling targeted communication and notification routing\n\n## Connecting to Other Blocks\n\nThis block receives data from workflow steps and sends Slack notifications:\n\n- **After detection or analysis blocks** (e.g., Object Detection, Instance Segmentation, Classification) to send alerts or summaries when objects are detected, classifications are made, or thresholds are exceeded, enabling real-time team notifications and collaboration\n- **After data processing blocks** (e.g., Expression, Property Definition, Detections Filter) to include computed metrics, transformed data, or filtered results in Slack notifications, enabling customized reporting with processed data in team channels\n- **After formatter blocks** (e.g., CSV Formatter) to attach formatted reports and exports to Slack messages, enabling automated distribution of structured data and analytics through team communication channels\n- **In conditional workflows** (e.g., Continue If) to send notifications only when specific conditions are met, enabling event-driven alerting and team communication\n- **After aggregation blocks** (e.g., Data Aggregator) to send periodic analytics summaries and statistical reports to Slack, enabling scheduled team updates and trend analysis\n- **In monitoring workflows** to send status updates, error notifications, or health check reports to team channels, enabling automated system monitoring and incident management through Slack\n\"\"\"\n\nPARAMETER_REGEX = re.compile(r\"({{\\s*\\$parameters\\.(\\w+)\\s*}})\")\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Slack Notification\",\n            \"version\": \"v1\",\n            \"short_description\": \"Send notification via Slack.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"sink\",\n            \"ui_manifest\": {\n                \"section\": \"notifications\",\n                \"icon\": \"far fa-brands fa-slack\",\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/slack_notification@v1\"]\n    slack_token: Union[str, Selector(kind=[STRING_KIND, SECRET_KIND])] = Field(\n        description=\"Slack API token (Bot Token or User Token) for authenticating with Slack API. Token must have 'chat:write' scope to send messages and 'files:write' scope if using attachments. Token is marked as private for security. Recommended to provide via workflow inputs using SECRET_KIND selectors rather than storing in workflow definitions. Generate tokens via Slack API apps or workspace administration. See [Slack API documentation](https://api.slack.com/tutorials/tracks/getting-a-token) or [Roboflow Blog guide](https://blog.roboflow.com/slack-notification-workflows/) for setup instructions.\",\n        private=True,\n        examples=[\"$inputs.slack_token\"],\n    )\n    channel: Union[str, Selector(kind=[STRING_KIND])] = Field(\n        description=\"Slack channel identifier where the notification will be sent. Can be a channel ID (e.g., 'C1234567890') or channel name starting with '#' (e.g., '#alerts', '#general'). The bot or user associated with the Slack token must be a member of the channel. Channel names are automatically converted to channel IDs by the Slack API.\",\n        examples=[\"$inputs.slack_channel_id\"],\n    )\n    message: str = Field(\n        description=\"Message content to send to the Slack channel (plain text). Supports dynamic parameters using placeholder syntax: {{ $parameters.parameter_name }}. Placeholders are replaced with values from message_parameters at runtime. Message can be multi-line text. If attachments are provided, this message becomes the initial comment attached to the file upload. Example: 'Detected {{ $parameters.num_objects }} objects. Classes: {{ $parameters.classes }}.'\",\n        examples=[\n            \"During last 5 minutes detected {{ $parameters.num_instances }} instances\"\n        ],\n        json_schema_extra={\n            \"multiline\": True,\n        },\n    )\n    message_parameters: Dict[\n        str,\n        Union[Selector(), Selector(), str, int, float, bool],\n    ] = Field(\n        description=\"Dictionary mapping parameter names (used in message placeholders) to workflow data sources. Keys are parameter names referenced in message as {{ $parameters.key }}, values are selectors to workflow step outputs or direct values. These values are substituted into message placeholders at runtime. Can optionally use message_parameters_operations to transform parameter values before substitution.\",\n        examples=[\n            {\n                \"predictions\": \"$steps.model.predictions\",\n                \"reference\": \"$inputs.reference_class_names\",\n            }\n        ],\n        default_factory=dict,\n        json_schema_extra={\n            \"always_visible\": True,\n        },\n    )\n    message_parameters_operations: Dict[str, List[AllOperationsType]] = Field(\n        description=\"Optional dictionary mapping parameter names (from message_parameters) to UQL operation chains that transform parameter values before inserting them into the message. Operations are applied in sequence (e.g., extract class names from detections, calculate counts, filter values). Keys must match parameter names in message_parameters. Leave empty or omit parameters that don't need transformation.\",\n        examples=[\n            {\n                \"predictions\": [\n                    {\"type\": \"DetectionsPropertyExtract\", \"property_name\": \"class_name\"}\n                ]\n            }\n        ],\n        default_factory=dict,\n    )\n    attachments: Dict[str, Selector(kind=[STRING_KIND, BYTES_KIND])] = Field(\n        description=\"Optional dictionary mapping attachment filenames to workflow step outputs that provide file content. Keys are the attachment filenames (e.g., 'report.csv', 'image.jpg'), values are selectors to blocks that output string or binary content (e.g., CSV Formatter outputs, image data, generated reports). Files are uploaded to Slack using files_upload_v2 API, and the message becomes the initial comment. Leave empty if no attachments are needed. Requires 'files:write' scope on the Slack token.\",\n        default_factory=dict,\n        examples=[{\"report.csv\": \"$steps.csv_formatter.csv_content\"}],\n    )\n    fire_and_forget: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=True,\n        description=\"Execution mode: True for asynchronous background sending (workflow continues immediately, error_status always False, faster execution), False for synchronous sending (waits for Slack API call completion, returns actual error status for debugging). Set to False during development and debugging to catch Slack API errors. Set to True in production for faster workflow execution when notification delivery timing is not critical.\",\n        examples=[\"$inputs.fire_and_forget\", False],\n    )\n    disable_sink: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=False,\n        description=\"Flag to disable Slack notification sending at runtime. When True, the block skips sending notification and returns a disabled message. Useful for conditional notification control via workflow inputs (e.g., allow callers to disable notifications for testing, enable/disable based on configuration). Set via workflow inputs for runtime control.\",\n        examples=[False, \"$inputs.disable_slack_notifications\"],\n    )\n    cooldown_seconds: Union[int, Selector(kind=[INTEGER_KIND])] = Field(\n        default=5,\n        description=\"Minimum seconds between consecutive Slack notifications to prevent notification spam. Defaults to 5 seconds. Set to 0 to disable cooldown (no throttling). Must be between 0 and 900 (15 minutes). During cooldown period, the block returns throttling_status=True and skips sending. Cooldown is tracked per step using cooldown_session_key with cache-based storage (15-minute expiration). Each Slack Notification step in a workflow should have a unique cooldown_session_key for proper per-step tracking.\",\n        examples=[\"$inputs.cooldown_seconds\", 3],\n        json_schema_extra={\n            \"always_visible\": True,\n        },\n    )\n    cooldown_session_key: str = Field(\n        description=\"Unique identifier for this Slack Notification step's cooldown tracking session. Must be unique for each Slack Notification step in your workflow to enable proper per-step cooldown isolation. Used with the Slack token hash to create a cache key for tracking the last notification timestamp. In distributed or multi-instance environments, this ensures cooldown works correctly per step. Typically auto-generated or provided as a workflow input.\",\n        examples=[\"session-1v73kdhfse\"],\n        json_schema_extra={\"hidden\": True},\n    )\n\n    @classmethod\n    def get_air_gapped_availability(cls) -> dict:\n        return {\"available\": False, \"reason\": \"requires_internet\"}\n\n    @field_validator(\"cooldown_seconds\")\n    @classmethod\n    def ensure_cooldown_seconds_within_bounds(cls, value: Any) -> dict:\n        if isinstance(value, int) and (value < 0 or value > CACHE_EXPIRE_TIME):\n            raise ValueError(\n                f\"`cooldown_seconds` must be in range [0, {CACHE_EXPIRE_TIME}]\"\n            )\n        return value\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"error_status\", kind=[BOOLEAN_KIND]),\n            OutputDefinition(name=\"throttling_status\", kind=[BOOLEAN_KIND]),\n            OutputDefinition(name=\"message\", kind=[STRING_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.4.0,<2.0.0\"\n\n\nclass SlackNotificationBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        cache: BaseCache,\n        background_tasks: Optional[BackgroundTasks],\n        thread_pool_executor: Optional[ThreadPoolExecutor],\n    ):\n        self._cache = cache\n        self._background_tasks = background_tasks\n        self._thread_pool_executor = thread_pool_executor\n        self._clients: Dict[str, WebClient] = {}\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"cache\", \"background_tasks\", \"thread_pool_executor\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        slack_token: str,\n        message: str,\n        channel: str,\n        message_parameters: Dict[str, Any],\n        message_parameters_operations: Dict[str, List[AllOperationsType]],\n        attachments: Dict[str, str],\n        fire_and_forget: bool,\n        disable_sink: bool,\n        cooldown_seconds: int,\n        cooldown_session_key: str,\n    ) -> BlockResult:\n        if disable_sink:\n            return {\n                \"error_status\": False,\n                \"throttling_status\": False,\n                \"message\": \"Sink was disabled by parameter `disable_sink`\",\n            }\n        token_hash = hashlib.sha256(slack_token.encode(\"utf-8\")).hexdigest()\n        cache_key = _generate_cache_key_for_cooldown_session(\n            session_key=cooldown_session_key,\n            token_hash=token_hash,\n        )\n        last_notification_fired = self._cache.get(cache_key)\n        seconds_since_last_notification = cooldown_seconds\n        if last_notification_fired is not None:\n            last_notification_fired = datetime.fromisoformat(last_notification_fired)\n            seconds_since_last_notification = (\n                datetime.now() - last_notification_fired\n            ).total_seconds()\n        if seconds_since_last_notification < cooldown_seconds:\n            logging.info(f\"Activated `roboflow_core/slack_notification@v1` cooldown.\")\n            return {\n                \"error_status\": False,\n                \"throttling_status\": True,\n                \"message\": \"Sink cooldown applies\",\n            }\n        if token_hash not in self._clients:\n            self._clients[token_hash] = WebClient(token=slack_token)\n        client = self._clients[token_hash]\n        message = format_message(\n            message=message,\n            message_parameters=message_parameters,\n            message_parameters_operations=message_parameters_operations,\n        )\n        send_notification_handler = partial(\n            send_slack_notification,\n            client=client,\n            channel=channel,\n            message=message,\n            attachments=attachments,\n        )\n        last_notification_fired = datetime.now().isoformat()\n        self._cache.set(\n            key=cache_key, value=last_notification_fired, expire=CACHE_EXPIRE_TIME\n        )\n        if fire_and_forget and self._background_tasks:\n            self._background_tasks.add_task(send_notification_handler)\n            return {\n                \"error_status\": False,\n                \"throttling_status\": False,\n                \"message\": \"Notification sent in the background task\",\n            }\n        if fire_and_forget and self._thread_pool_executor:\n            self._thread_pool_executor.submit(send_notification_handler)\n            return {\n                \"error_status\": False,\n                \"throttling_status\": False,\n                \"message\": \"Notification sent in the background task\",\n            }\n        error_status, message = send_notification_handler()\n        return {\n            \"error_status\": error_status,\n            \"throttling_status\": False,\n            \"message\": message,\n        }\n\n\ndef _generate_cache_key_for_cooldown_session(session_key: str, token_hash: str) -> str:\n    return (\n        f\"workflows:steps_cache:roboflow_core/slack_notification@v1:\"\n        f\"{token_hash}:{session_key}:last_notification_time\"\n    )\n\n\ndef format_message(\n    message: str,\n    message_parameters: Dict[str, Any],\n    message_parameters_operations: Dict[str, List[AllOperationsType]],\n) -> str:\n    matching_parameters = PARAMETER_REGEX.findall(message)\n    parameters_to_get_values = {\n        p[1] for p in matching_parameters if p[1] in message_parameters\n    }\n    parameters_values = {}\n    for parameter_name in parameters_to_get_values:\n        parameter_value = message_parameters[parameter_name]\n        operations = message_parameters_operations.get(parameter_name)\n        if not operations:\n            parameters_values[parameter_name] = parameter_value\n            continue\n        operations_chain = build_operations_chain(operations=operations)\n        parameters_values[parameter_name] = operations_chain(\n            parameter_value, global_parameters={}\n        )\n    parameter_to_placeholders = defaultdict(list)\n    for placeholder, parameter_name in matching_parameters:\n        if parameter_name not in parameters_to_get_values:\n            continue\n        parameter_to_placeholders[parameter_name].append(placeholder)\n    for parameter_name, placeholders in parameter_to_placeholders.items():\n        for placeholder in placeholders:\n            message = message.replace(\n                placeholder, str(parameters_values[parameter_name])\n            )\n    return message\n\n\ndef send_slack_notification(\n    client: WebClient,\n    channel: str,\n    message: str,\n    attachments: Dict[str, Union[str, bytes]],\n) -> Tuple[bool, str]:\n    try:\n        _send_slack_notification(\n            client=client,\n            channel=channel,\n            message=message,\n            attachments=attachments,\n        )\n        return False, \"Notification sent successfully\"\n    except SlackApiError as error:\n        error_details = error.response.get(\"error\", \"Not Available.\")\n        logging.warning(f\"Could not send Slack notification. Error: {error_details}\")\n        return (\n            True,\n            f\"Failed to send Slack notification. Internal error details: {error_details}\",\n        )\n    except Exception as error:\n        logging.warning(f\"Could not send Slack notification. Error: {str(error)}\")\n        return (\n            True,\n            f\"Failed to send Slack notification. Internal error details: {error}\",\n        )\n\n\ndef _send_slack_notification(\n    client: WebClient,\n    channel: str,\n    message: str,\n    attachments: Dict[str, Union[str, bytes]],\n) -> None:\n    if not attachments:\n        _ = client.chat_postMessage(\n            channel=channel,\n            text=message,\n        )\n    file_uploads = [\n        {\n            \"title\": name,\n            \"content\": value,\n        }\n        for name, value in attachments.items()\n    ]\n    _ = client.files_upload_v2(\n        channel=channel,\n        initial_comment=message,\n        file_uploads=file_uploads,\n    )\n",
    "patch": null
  },
  {
    "trace_id": "4c711a3d-c738-48e9-90d3-69e0a3cc2d98",
    "function_name": "BlockManifest.get_air_gapped_availability",
    "file_path": "inference/core/workflows/core_steps/sinks/roboflow/dataset_upload/v2.py",
    "speedup_x": 0.10752843288721776,
    "review_quality": "medium",
    "pre_optimization_commit": "835af61109f8cab1d2cb51cf93d061ef3a4c5fc7",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def get_air_gapped_availability(cls) -> dict:\n        return {\"available\": False, \"reason\": \"requires_internet\"}\n",
    "optimized_function_code": "from typing import Literal\n\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\nfrom pydantic import Field\nfrom typing_extensions import Annotated\n\nFloatZeroToHundred = Annotated[float, Field(ge=0.0, le=100.0)]\n\nSHORT_DESCRIPTION = \"Save images and predictions to your Roboflow Dataset.\"\n\nLONG_DESCRIPTION = \"\"\"\nUpload images and model predictions to a Roboflow dataset for active learning, model improvement, and data collection, with configurable usage quotas, probabilistic sampling, batch organization, image compression, and optional annotation persistence.\n\n## How This Block Works\n\nThis block uploads workflow images and predictions to your Roboflow dataset for storage, labeling, and model training. The block:\n\n1. Takes images and optional model predictions (object detection, instance segmentation, keypoint detection, or classification) as input\n2. Validates the Roboflow API key is available (required for uploading)\n3. Applies probabilistic sampling based on `data_percentage` setting, randomly selecting a percentage of inputs to upload (e.g., 50% uploads half the data, 100% uploads everything)\n4. Checks usage quotas (minutely, hourly, daily limits) to ensure uploads stay within configured rate limits for active learning strategies\n5. Prepares images by resizing if they exceed maximum size (maintaining aspect ratio) and compressing to specified quality level\n6. Generates labeling batch names based on the prefix and batch creation frequency (never, daily, weekly, or monthly), organizing uploaded data into batches\n7. Optionally persists model predictions as annotations if `persist_predictions` is enabled, allowing predictions to serve as pre-labels for review and correction\n8. Attaches registration tags to images for organization and filtering in the Roboflow platform\n9. Registers the image (and annotations if enabled) to the specified Roboflow project via the Roboflow API\n10. Executes synchronously or asynchronously based on `fire_and_forget` setting, allowing non-blocking uploads for faster workflow execution\n11. Returns error status and messages indicating upload success, failure, or sampling skip\n\nThe block supports active learning workflows by implementing usage quotas that prevent excessive data collection, helping focus on collecting valuable training data within rate limits. The probabilistic sampling feature (new in v2) allows you to randomly sample a percentage of data for upload, enabling cost-effective data collection strategies where you want to collect representative samples rather than all data. Images are organized into labeling batches that can be automatically recreated on a schedule (daily, weekly, monthly), making it easier to manage and review collected data over time. The block can operate in fire-and-forget mode for asynchronous execution, allowing workflows to continue processing without waiting for uploads to complete, or synchronously for debugging and error handling.\n\n## Version Differences (v2 vs v1)\n\n**New Features in v2:**\n\n- **Probabilistic Data Sampling**: Added `data_percentage` parameter (0-100%) that enables random sampling of data for upload. This allows you to upload only a percentage of workflow inputs (e.g., 25% samples one in four images), reducing storage and annotation costs while still collecting representative data. When sampling skips an upload, the block returns a message indicating the skip.\n\n- **Improved Default Settings**: \n  - `max_image_size` default increased from (512, 512) to (1920, 1080) for higher resolution data collection\n  - `compression_level` default increased from 75 to 95 for better image quality preservation\n\n**Behavior Changes:**\n\n- By default, `data_percentage` is set to 100, so v2 behaves identically to v1 unless sampling is explicitly configured\n- The block now uses probabilistic sampling before quota checking and image preparation, allowing efficient filtering before resource-intensive operations\n\n## Requirements\n\n**API Key Required**: This block requires a valid Roboflow API key to upload data. The API key must be configured in your environment or workflow configuration. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve an API key.\n\n## Common Use Cases\n\n- **Active Learning Data Collection**: Collect images and predictions from production environments where models struggle or are uncertain (e.g., low-confidence detections, edge cases), enabling iterative model improvement by gathering challenging examples for retraining\n- **Probabilistic Data Sampling**: Use `data_percentage` to randomly sample a subset of data for upload (e.g., upload 20% of all detections, 50% of low-confidence cases), enabling cost-effective data collection strategies that reduce storage and annotation overhead while maintaining dataset diversity\n- **Production Data Logging**: Continuously upload production inference data to Roboflow datasets for monitoring, analysis, and future model training, creating a growing dataset from real-world deployments\n- **Pre-Labeled Data Collection**: Upload images with model predictions as pre-labels (when `persist_predictions` is enabled), accelerating annotation workflows by providing initial labels that can be reviewed and corrected rather than starting from scratch\n- **Stratified Data Sampling**: Combine probabilistic sampling with rate limiting and quotas to selectively collect data based on specific criteria (e.g., sample 30% of detections that pass filters), ensuring diverse and balanced dataset collection without overwhelming storage or annotation resources\n- **Batch-Based Labeling Workflows**: Organize uploaded data into batches with automatic recreation schedules (daily, weekly, monthly), making it easier to manage labeling tasks, track progress, and organize data collection efforts over time\n\n## Connecting to Other Blocks\n\nThis block receives data from workflow steps and uploads it to Roboflow:\n\n- **After detection or analysis blocks** (e.g., Object Detection Model, Instance Segmentation Model, Classification Model, Keypoint Detection Model) to upload images along with their predictions, enabling active learning by collecting inference data with model outputs for annotation and retraining\n- **After filtering or analytics blocks** (e.g., Detections Filter, Continue If, Overlap Filter) to selectively upload only specific types of data (e.g., low-confidence detections, overlapping objects, specific classes), focusing data collection on valuable edge cases or interesting scenarios\n- **After rate limiter blocks** (e.g., Rate Limiter) to throttle upload frequency and stay within usage quotas, ensuring controlled data collection that respects rate limits and prevents excessive storage usage\n- **Image inputs or preprocessing blocks** to upload raw images or processed images (e.g., crops, transformed images) without predictions, enabling collection of image data for future labeling or analysis\n- **Conditional workflows** using flow control blocks (e.g., Continue If) to upload data only when certain conditions are met (e.g., upload only when detection count exceeds threshold, upload only errors or failures), enabling selective data collection based on workflow state\n- **Batch processing workflows** where multiple images or predictions are generated, allowing bulk upload of workflow outputs to Roboflow datasets with probabilistic sampling for organized and cost-effective data collection\n\"\"\"\nBatchCreationFrequency = Literal[\"never\", \"daily\", \"weekly\", \"monthly\"]\n\n\n\n# Precompute the mapping once so we avoid rebuilding the same literal dict on every call.\n# Return a shallow copy from the classmethod to preserve original behavior of returning a fresh dict.\n_AIR_GAPPED_AVAILABILITY = {\"available\": False, \"reason\": \"requires_internet\"}\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_air_gapped_availability(cls) -> dict:\n        return _AIR_GAPPED_AVAILABILITY.copy()",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/sinks/roboflow/dataset_upload/v2.py\nfrom typing import Literal\n\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\nfrom pydantic import Field\nfrom typing_extensions import Annotated\n\nFloatZeroToHundred = Annotated[float, Field(ge=0.0, le=100.0)]\n\nSHORT_DESCRIPTION = \"Save images and predictions to your Roboflow Dataset.\"\n\nLONG_DESCRIPTION = \"\"\"\nUpload images and model predictions to a Roboflow dataset for active learning, model improvement, and data collection, with configurable usage quotas, probabilistic sampling, batch organization, image compression, and optional annotation persistence.\n\n## How This Block Works\n\nThis block uploads workflow images and predictions to your Roboflow dataset for storage, labeling, and model training. The block:\n\n1. Takes images and optional model predictions (object detection, instance segmentation, keypoint detection, or classification) as input\n2. Validates the Roboflow API key is available (required for uploading)\n3. Applies probabilistic sampling based on `data_percentage` setting, randomly selecting a percentage of inputs to upload (e.g., 50% uploads half the data, 100% uploads everything)\n4. Checks usage quotas (minutely, hourly, daily limits) to ensure uploads stay within configured rate limits for active learning strategies\n5. Prepares images by resizing if they exceed maximum size (maintaining aspect ratio) and compressing to specified quality level\n6. Generates labeling batch names based on the prefix and batch creation frequency (never, daily, weekly, or monthly), organizing uploaded data into batches\n7. Optionally persists model predictions as annotations if `persist_predictions` is enabled, allowing predictions to serve as pre-labels for review and correction\n8. Attaches registration tags to images for organization and filtering in the Roboflow platform\n9. Registers the image (and annotations if enabled) to the specified Roboflow project via the Roboflow API\n10. Executes synchronously or asynchronously based on `fire_and_forget` setting, allowing non-blocking uploads for faster workflow execution\n11. Returns error status and messages indicating upload success, failure, or sampling skip\n\nThe block supports active learning workflows by implementing usage quotas that prevent excessive data collection, helping focus on collecting valuable training data within rate limits. The probabilistic sampling feature (new in v2) allows you to randomly sample a percentage of data for upload, enabling cost-effective data collection strategies where you want to collect representative samples rather than all data. Images are organized into labeling batches that can be automatically recreated on a schedule (daily, weekly, monthly), making it easier to manage and review collected data over time. The block can operate in fire-and-forget mode for asynchronous execution, allowing workflows to continue processing without waiting for uploads to complete, or synchronously for debugging and error handling.\n\n## Version Differences (v2 vs v1)\n\n**New Features in v2:**\n\n- **Probabilistic Data Sampling**: Added `data_percentage` parameter (0-100%) that enables random sampling of data for upload. This allows you to upload only a percentage of workflow inputs (e.g., 25% samples one in four images), reducing storage and annotation costs while still collecting representative data. When sampling skips an upload, the block returns a message indicating the skip.\n\n- **Improved Default Settings**: \n  - `max_image_size` default increased from (512, 512) to (1920, 1080) for higher resolution data collection\n  - `compression_level` default increased from 75 to 95 for better image quality preservation\n\n**Behavior Changes:**\n\n- By default, `data_percentage` is set to 100, so v2 behaves identically to v1 unless sampling is explicitly configured\n- The block now uses probabilistic sampling before quota checking and image preparation, allowing efficient filtering before resource-intensive operations\n\n## Requirements\n\n**API Key Required**: This block requires a valid Roboflow API key to upload data. The API key must be configured in your environment or workflow configuration. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve an API key.\n\n## Common Use Cases\n\n- **Active Learning Data Collection**: Collect images and predictions from production environments where models struggle or are uncertain (e.g., low-confidence detections, edge cases), enabling iterative model improvement by gathering challenging examples for retraining\n- **Probabilistic Data Sampling**: Use `data_percentage` to randomly sample a subset of data for upload (e.g., upload 20% of all detections, 50% of low-confidence cases), enabling cost-effective data collection strategies that reduce storage and annotation overhead while maintaining dataset diversity\n- **Production Data Logging**: Continuously upload production inference data to Roboflow datasets for monitoring, analysis, and future model training, creating a growing dataset from real-world deployments\n- **Pre-Labeled Data Collection**: Upload images with model predictions as pre-labels (when `persist_predictions` is enabled), accelerating annotation workflows by providing initial labels that can be reviewed and corrected rather than starting from scratch\n- **Stratified Data Sampling**: Combine probabilistic sampling with rate limiting and quotas to selectively collect data based on specific criteria (e.g., sample 30% of detections that pass filters), ensuring diverse and balanced dataset collection without overwhelming storage or annotation resources\n- **Batch-Based Labeling Workflows**: Organize uploaded data into batches with automatic recreation schedules (daily, weekly, monthly), making it easier to manage labeling tasks, track progress, and organize data collection efforts over time\n\n## Connecting to Other Blocks\n\nThis block receives data from workflow steps and uploads it to Roboflow:\n\n- **After detection or analysis blocks** (e.g., Object Detection Model, Instance Segmentation Model, Classification Model, Keypoint Detection Model) to upload images along with their predictions, enabling active learning by collecting inference data with model outputs for annotation and retraining\n- **After filtering or analytics blocks** (e.g., Detections Filter, Continue If, Overlap Filter) to selectively upload only specific types of data (e.g., low-confidence detections, overlapping objects, specific classes), focusing data collection on valuable edge cases or interesting scenarios\n- **After rate limiter blocks** (e.g., Rate Limiter) to throttle upload frequency and stay within usage quotas, ensuring controlled data collection that respects rate limits and prevents excessive storage usage\n- **Image inputs or preprocessing blocks** to upload raw images or processed images (e.g., crops, transformed images) without predictions, enabling collection of image data for future labeling or analysis\n- **Conditional workflows** using flow control blocks (e.g., Continue If) to upload data only when certain conditions are met (e.g., upload only when detection count exceeds threshold, upload only errors or failures), enabling selective data collection based on workflow state\n- **Batch processing workflows** where multiple images or predictions are generated, allowing bulk upload of workflow outputs to Roboflow datasets with probabilistic sampling for organized and cost-effective data collection\n\"\"\"\nBatchCreationFrequency = Literal[\"never\", \"daily\", \"weekly\", \"monthly\"]\n\n\n\n# Precompute the mapping once so we avoid rebuilding the same literal dict on every call.\n# Return a shallow copy from the classmethod to preserve original behavior of returning a fresh dict.\n_AIR_GAPPED_AVAILABILITY = {\"available\": False, \"reason\": \"requires_internet\"}\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_air_gapped_availability(cls) -> dict:\n        return _AIR_GAPPED_AVAILABILITY.copy()\n```",
    "optimized_function_only": "    def get_air_gapped_availability(cls) -> dict:\n        return _AIR_GAPPED_AVAILABILITY.copy()",
    "original_file_content": "import random\nfrom concurrent.futures import ThreadPoolExecutor\nfrom typing import Any, Dict, List, Literal, Optional, Tuple, Type, Union\n\nimport supervision as sv\nfrom fastapi import BackgroundTasks\nfrom pydantic import AliasChoices, ConfigDict, Field\nfrom typing_extensions import Annotated\n\nfrom inference.core.cache.base import BaseCache\nfrom inference.core.workflows.core_steps.sinks.roboflow.dataset_upload.v1 import (\n    register_datapoint_at_roboflow,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    BOOLEAN_KIND,\n    CLASSIFICATION_PREDICTION_KIND,\n    FLOAT_KIND,\n    IMAGE_KIND,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    KEYPOINT_DETECTION_PREDICTION_KIND,\n    LIST_OF_VALUES_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    ROBOFLOW_PROJECT_KIND,\n    STRING_KIND,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nFloatZeroToHundred = Annotated[float, Field(ge=0.0, le=100.0)]\n\nSHORT_DESCRIPTION = \"Save images and predictions to your Roboflow Dataset.\"\n\nLONG_DESCRIPTION = \"\"\"\nUpload images and model predictions to a Roboflow dataset for active learning, model improvement, and data collection, with configurable usage quotas, probabilistic sampling, batch organization, image compression, and optional annotation persistence.\n\n## How This Block Works\n\nThis block uploads workflow images and predictions to your Roboflow dataset for storage, labeling, and model training. The block:\n\n1. Takes images and optional model predictions (object detection, instance segmentation, keypoint detection, or classification) as input\n2. Validates the Roboflow API key is available (required for uploading)\n3. Applies probabilistic sampling based on `data_percentage` setting, randomly selecting a percentage of inputs to upload (e.g., 50% uploads half the data, 100% uploads everything)\n4. Checks usage quotas (minutely, hourly, daily limits) to ensure uploads stay within configured rate limits for active learning strategies\n5. Prepares images by resizing if they exceed maximum size (maintaining aspect ratio) and compressing to specified quality level\n6. Generates labeling batch names based on the prefix and batch creation frequency (never, daily, weekly, or monthly), organizing uploaded data into batches\n7. Optionally persists model predictions as annotations if `persist_predictions` is enabled, allowing predictions to serve as pre-labels for review and correction\n8. Attaches registration tags to images for organization and filtering in the Roboflow platform\n9. Registers the image (and annotations if enabled) to the specified Roboflow project via the Roboflow API\n10. Executes synchronously or asynchronously based on `fire_and_forget` setting, allowing non-blocking uploads for faster workflow execution\n11. Returns error status and messages indicating upload success, failure, or sampling skip\n\nThe block supports active learning workflows by implementing usage quotas that prevent excessive data collection, helping focus on collecting valuable training data within rate limits. The probabilistic sampling feature (new in v2) allows you to randomly sample a percentage of data for upload, enabling cost-effective data collection strategies where you want to collect representative samples rather than all data. Images are organized into labeling batches that can be automatically recreated on a schedule (daily, weekly, monthly), making it easier to manage and review collected data over time. The block can operate in fire-and-forget mode for asynchronous execution, allowing workflows to continue processing without waiting for uploads to complete, or synchronously for debugging and error handling.\n\n## Version Differences (v2 vs v1)\n\n**New Features in v2:**\n\n- **Probabilistic Data Sampling**: Added `data_percentage` parameter (0-100%) that enables random sampling of data for upload. This allows you to upload only a percentage of workflow inputs (e.g., 25% samples one in four images), reducing storage and annotation costs while still collecting representative data. When sampling skips an upload, the block returns a message indicating the skip.\n\n- **Improved Default Settings**: \n  - `max_image_size` default increased from (512, 512) to (1920, 1080) for higher resolution data collection\n  - `compression_level` default increased from 75 to 95 for better image quality preservation\n\n**Behavior Changes:**\n\n- By default, `data_percentage` is set to 100, so v2 behaves identically to v1 unless sampling is explicitly configured\n- The block now uses probabilistic sampling before quota checking and image preparation, allowing efficient filtering before resource-intensive operations\n\n## Requirements\n\n**API Key Required**: This block requires a valid Roboflow API key to upload data. The API key must be configured in your environment or workflow configuration. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve an API key.\n\n## Common Use Cases\n\n- **Active Learning Data Collection**: Collect images and predictions from production environments where models struggle or are uncertain (e.g., low-confidence detections, edge cases), enabling iterative model improvement by gathering challenging examples for retraining\n- **Probabilistic Data Sampling**: Use `data_percentage` to randomly sample a subset of data for upload (e.g., upload 20% of all detections, 50% of low-confidence cases), enabling cost-effective data collection strategies that reduce storage and annotation overhead while maintaining dataset diversity\n- **Production Data Logging**: Continuously upload production inference data to Roboflow datasets for monitoring, analysis, and future model training, creating a growing dataset from real-world deployments\n- **Pre-Labeled Data Collection**: Upload images with model predictions as pre-labels (when `persist_predictions` is enabled), accelerating annotation workflows by providing initial labels that can be reviewed and corrected rather than starting from scratch\n- **Stratified Data Sampling**: Combine probabilistic sampling with rate limiting and quotas to selectively collect data based on specific criteria (e.g., sample 30% of detections that pass filters), ensuring diverse and balanced dataset collection without overwhelming storage or annotation resources\n- **Batch-Based Labeling Workflows**: Organize uploaded data into batches with automatic recreation schedules (daily, weekly, monthly), making it easier to manage labeling tasks, track progress, and organize data collection efforts over time\n\n## Connecting to Other Blocks\n\nThis block receives data from workflow steps and uploads it to Roboflow:\n\n- **After detection or analysis blocks** (e.g., Object Detection Model, Instance Segmentation Model, Classification Model, Keypoint Detection Model) to upload images along with their predictions, enabling active learning by collecting inference data with model outputs for annotation and retraining\n- **After filtering or analytics blocks** (e.g., Detections Filter, Continue If, Overlap Filter) to selectively upload only specific types of data (e.g., low-confidence detections, overlapping objects, specific classes), focusing data collection on valuable edge cases or interesting scenarios\n- **After rate limiter blocks** (e.g., Rate Limiter) to throttle upload frequency and stay within usage quotas, ensuring controlled data collection that respects rate limits and prevents excessive storage usage\n- **Image inputs or preprocessing blocks** to upload raw images or processed images (e.g., crops, transformed images) without predictions, enabling collection of image data for future labeling or analysis\n- **Conditional workflows** using flow control blocks (e.g., Continue If) to upload data only when certain conditions are met (e.g., upload only when detection count exceeds threshold, upload only errors or failures), enabling selective data collection based on workflow state\n- **Batch processing workflows** where multiple images or predictions are generated, allowing bulk upload of workflow outputs to Roboflow datasets with probabilistic sampling for organized and cost-effective data collection\n\"\"\"\n\nWORKSPACE_NAME_CACHE_EXPIRE = 900  # 15 min\nTIMESTAMP_FORMAT = \"%Y_%m_%d\"\nDUPLICATED_STATUS = \"Duplicated image\"\nBatchCreationFrequency = Literal[\"never\", \"daily\", \"weekly\", \"monthly\"]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Roboflow Dataset Upload\",\n            \"version\": \"v2\",\n            \"short_description\": SHORT_DESCRIPTION,\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"sink\",\n            \"ui_manifest\": {\n                \"section\": \"data_storage\",\n                \"icon\": \"fal fa-upload\",\n                \"blockPriority\": 0,\n                \"popular\": True,\n                \"requires_rf_key\": True,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/roboflow_dataset_upload@v2\"]\n    images: Selector(kind=[IMAGE_KIND]) = Field(\n        title=\"Image\",\n        description=\"Image(s) to upload to the Roboflow dataset. Can be a single image or batch of images from workflow inputs or processing steps. Images are randomly sampled based on data_percentage, resized if they exceed max_image_size, and compressed before uploading. Supports batch processing.\",\n        examples=[\"$inputs.image\", \"$steps.cropping.crops\"],\n        validation_alias=AliasChoices(\"images\", \"image\"),\n    )\n    target_project: Union[Selector(kind=[ROBOFLOW_PROJECT_KIND]), str] = Field(\n        description=\"Roboflow project identifier where uploaded images and annotations will be saved. Must be a valid project in your Roboflow workspace. The project name can be specified directly or referenced from workflow inputs.\",\n        examples=[\"my_dataset\", \"$inputs.target_al_dataset\"],\n    )\n    predictions: Optional[\n        Selector(\n            kind=[\n                OBJECT_DETECTION_PREDICTION_KIND,\n                INSTANCE_SEGMENTATION_PREDICTION_KIND,\n                KEYPOINT_DETECTION_PREDICTION_KIND,\n                CLASSIFICATION_PREDICTION_KIND,\n            ]\n        )\n    ] = Field(\n        default=None,\n        description=\"Optional model predictions to upload alongside images. Predictions are saved as annotations (pre-labels) in the Roboflow dataset when persist_predictions is enabled, allowing predictions to serve as starting points for annotation review and correction. Supports object detection, instance segmentation, keypoint detection, and classification predictions. If None, only images are uploaded.\",\n        examples=[\"$steps.object_detection_model.predictions\"],\n        json_schema_extra={\"always_visible\": True},\n    )\n    data_percentage: Union[FloatZeroToHundred, Selector(kind=[FLOAT_KIND])] = Field(\n        default=100,\n        description=\"Percentage of input data (0.0 to 100.0) to randomly sample for upload. This enables probabilistic data collection where only a subset of inputs are uploaded, reducing storage and annotation costs. For example, 25.0 uploads approximately 25% of images (one in four on average), 50.0 uploads half, and 100.0 uploads everything (no sampling). Random sampling occurs before quota checking and image processing, making it efficient for large-scale data collection workflows.\",\n        examples=[100, 25, 50, \"$inputs.sampling_rate\"],\n    )\n    minutely_usage_limit: int = Field(\n        default=10,\n        description=\"Maximum number of image uploads allowed per minute for this quota. Part of the usage quota system that enforces rate limits for active learning data collection. Uploads exceeding this limit are skipped to prevent excessive data collection. Works together with hourly_usage_limit and daily_usage_limit to provide multi-level rate limiting. Note: This quota is checked after probabilistic sampling via data_percentage.\",\n        examples=[10, 60],\n    )\n    hourly_usage_limit: int = Field(\n        default=100,\n        description=\"Maximum number of image uploads allowed per hour for this quota. Part of the usage quota system that enforces rate limits for active learning data collection. Uploads exceeding this limit are skipped to prevent excessive data collection. Works together with minutely_usage_limit and daily_usage_limit to provide multi-level rate limiting. Note: This quota is checked after probabilistic sampling via data_percentage.\",\n        examples=[10, 60],\n    )\n    daily_usage_limit: int = Field(\n        default=1000,\n        description=\"Maximum number of image uploads allowed per day for this quota. Part of the usage quota system that enforces rate limits for active learning data collection. Uploads exceeding this limit are skipped to prevent excessive data collection. Works together with minutely_usage_limit and hourly_usage_limit to provide multi-level rate limiting. Note: This quota is checked after probabilistic sampling via data_percentage.\",\n        examples=[10, 60],\n    )\n    usage_quota_name: str = Field(\n        description=\"Unique identifier for tracking usage quotas (minutely, hourly, daily limits). Used internally to manage rate limiting across multiple upload operations. Each unique quota name maintains separate counters, allowing different upload strategies or data collection workflows to have independent rate limits.\",\n        examples=[\"quota-for-data-sampling-1\"],\n        json_schema_extra={\"hidden\": True},\n    )\n    max_image_size: Tuple[int, int] = Field(\n        default=(1920, 1080),\n        description=\"Maximum dimensions (width, height) for uploaded images. Images exceeding these dimensions are automatically resized while preserving aspect ratio before uploading. Default is (1920, 1080) for higher resolution data collection. Use smaller sizes (e.g., (512, 512)) for efficient storage and faster uploads, or keep the default for preserving image quality.\",\n        examples=[(1920, 1080), (512, 512)],\n    )\n    compression_level: int = Field(\n        default=95,\n        gt=0,\n        le=100,\n        description=\"JPEG compression quality level for uploaded images, ranging from 1 (highest compression, smallest file size, lower quality) to 100 (no compression, largest file size, highest quality). Default is 95 for better image quality preservation. Higher values preserve more image quality but increase storage and bandwidth usage. Typical values range from 70-95 for balanced quality and size.\",\n        examples=[95, 75],\n    )\n    registration_tags: Union[\n        List[Union[Selector(kind=[STRING_KIND]), str]],\n        Selector(kind=[LIST_OF_VALUES_KIND]),\n    ] = Field(\n        default_factory=list,\n        description=\"List of tags to attach to uploaded images for organization and filtering in Roboflow. Tags can be static strings (e.g., 'location-florida', 'camera-1') or dynamic values from workflow inputs. Tags help organize collected data, filter images in Roboflow, and add metadata for dataset management. Can be an empty list if no tags are needed.\",\n        examples=[\n            [\"location-florida\", \"factory-name\", \"$inputs.dynamic_tag\"],\n            \"$inputs.tags\",\n        ],\n    )\n    persist_predictions: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=True,\n        description=\"If True, model predictions are saved as annotations (pre-labels) in the Roboflow dataset alongside images. This enables predictions to serve as starting points for annotation, allowing reviewers to correct or approve labels rather than creating them from scratch. If False, only images are uploaded without annotations. Enabling this accelerates annotation workflows by providing initial labels.\",\n        examples=[True, False, \"$inputs.persist_predictions\"],\n    )\n    disable_sink: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=False,\n        description=\"If True, the block execution is disabled and no uploads occur. This allows temporarily disabling data collection without removing the block from workflows, useful for testing, debugging, or conditional data collection. When disabled, returns a message indicating the sink was disabled. Default is False (uploads enabled).\",\n        examples=[True, \"$inputs.disable_active_learning\"],\n    )\n    fire_and_forget: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=True,\n        description=\"If True, uploads execute asynchronously (fire-and-forget mode), allowing the workflow to continue immediately without waiting for upload completion. This improves workflow performance but prevents error handling. If False, uploads execute synchronously, blocking workflow execution until completion and allowing proper error handling and status reporting. Use async mode (True) for production workflows where speed is prioritized, and sync mode (False) for debugging or when error handling is critical.\",\n    )\n    labeling_batch_prefix: Union[str, Selector(kind=[STRING_KIND])] = Field(\n        default=\"workflows_data_collector\",\n        description=\"Prefix used to generate labeling batch names for organizing uploaded images in Roboflow. Combined with the batch recreation frequency and timestamps to create batch names like 'workflows_data_collector_2024_01_15'. Batches help organize collected data for labeling, making it easier to manage and review uploaded images in groups. Can be customized to match your organization scheme.\",\n        examples=[\"my_labeling_batch_name\"],\n    )\n    labeling_batches_recreation_frequency: BatchCreationFrequency = Field(\n        default=\"never\",\n        description=\"Frequency at which new labeling batches are automatically created for uploaded images. Options: 'never' (all images go to the same batch), 'daily' (new batch each day), 'weekly' (new batch each week), 'monthly' (new batch each month). Batch timestamps are appended to the labeling_batch_prefix to create unique batch names. Automatically organizing uploads into time-based batches simplifies dataset management and makes it easier to track and review collected data over time.\",\n        examples=[\"never\", \"daily\"],\n    )\n    image_name: Optional[Union[str, Selector(kind=[STRING_KIND])]] = Field(\n        default=None,\n        description=\"Optional custom name for the uploaded image. This is useful when you want to preserve the original filename or use a meaningful identifier (e.g., serial number, timestamp) for the image in the Roboflow dataset. The name should not include file extension. If not provided, a UUID will be generated automatically.\",\n        examples=[\"serial_12345\", \"camera1_frame_001\", \"$inputs.filename\"],\n    )\n    metadata: Dict[str, Union[str, int, float, bool, Selector()]] = Field(\n        default_factory=dict,\n        description=\"Optional key-value metadata to attach to uploaded images. Metadata is stored as user_metadata on the image in Roboflow and can be used for filtering and organization. Values can be static strings, numbers, booleans, or references to workflow inputs/steps.\",\n        examples=[{\"camera_id\": \"cam_01\", \"location\": \"$inputs.location\"}, {}],\n    )\n\n    @classmethod\n    def get_air_gapped_availability(cls) -> dict:\n        return {\"available\": False, \"reason\": \"requires_internet\"}\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return [\"images\", \"predictions\", \"image_name\"]\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"error_status\", kind=[BOOLEAN_KIND]),\n            OutputDefinition(name=\"message\", kind=[STRING_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass RoboflowDatasetUploadBlockV2(WorkflowBlock):\n\n    def __init__(\n        self,\n        cache: BaseCache,\n        api_key: Optional[str],\n        background_tasks: Optional[BackgroundTasks],\n        thread_pool_executor: Optional[ThreadPoolExecutor],\n    ):\n        self._cache = cache\n        self._api_key = api_key\n        self._background_tasks = background_tasks\n        self._thread_pool_executor = thread_pool_executor\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"cache\", \"api_key\", \"background_tasks\", \"thread_pool_executor\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        predictions: Optional[Batch[Union[sv.Detections, dict]]],\n        target_project: str,\n        usage_quota_name: str,\n        data_percentage: float,\n        minutely_usage_limit: int,\n        persist_predictions: bool,\n        hourly_usage_limit: int,\n        daily_usage_limit: int,\n        max_image_size: Tuple[int, int],\n        compression_level: int,\n        registration_tags: List[str],\n        disable_sink: bool,\n        fire_and_forget: bool,\n        labeling_batch_prefix: str,\n        labeling_batches_recreation_frequency: BatchCreationFrequency,\n        image_name: Optional[Batch[Optional[str]]] = None,\n        metadata: Optional[Dict[str, Any]] = None,\n    ) -> BlockResult:\n        if self._api_key is None:\n            raise ValueError(\n                \"RoboflowDataCollector block cannot run without Roboflow API key. \"\n                \"If you do not know how to get API key - visit \"\n                \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to \"\n                \"retrieve one.\"\n            )\n        if disable_sink:\n            return [\n                {\n                    \"error_status\": False,\n                    \"message\": \"Sink was disabled by parameter `disable_sink`\",\n                }\n                for _ in range(len(images))\n            ]\n        result = []\n        predictions = [None] * len(images) if predictions is None else predictions\n        image_names = [None] * len(images) if image_name is None else image_name\n        for image, prediction, img_name in zip(images, predictions, image_names):\n            error_status, message = maybe_register_datapoint_at_roboflow(\n                image=image,\n                prediction=prediction,\n                target_project=target_project,\n                usage_quota_name=usage_quota_name,\n                data_percentage=data_percentage,\n                persist_predictions=persist_predictions,\n                minutely_usage_limit=minutely_usage_limit,\n                hourly_usage_limit=hourly_usage_limit,\n                daily_usage_limit=daily_usage_limit,\n                max_image_size=max_image_size,\n                compression_level=compression_level,\n                registration_tags=registration_tags,\n                fire_and_forget=fire_and_forget,\n                labeling_batch_prefix=labeling_batch_prefix,\n                new_labeling_batch_frequency=labeling_batches_recreation_frequency,\n                cache=self._cache,\n                background_tasks=self._background_tasks,\n                thread_pool_executor=self._thread_pool_executor,\n                api_key=self._api_key,\n                image_name=img_name,\n                metadata=metadata,\n            )\n            result.append({\"error_status\": error_status, \"message\": message})\n        return result\n\n\ndef maybe_register_datapoint_at_roboflow(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    usage_quota_name: str,\n    data_percentage: float,\n    persist_predictions: bool,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    fire_and_forget: bool,\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    background_tasks: Optional[BackgroundTasks],\n    thread_pool_executor: Optional[ThreadPoolExecutor],\n    api_key: str,\n    image_name: Optional[str] = None,\n    metadata: Optional[Dict[str, Any]] = None,\n) -> Tuple[bool, str]:\n    normalised_probability = data_percentage / 100\n    if random.random() < normalised_probability:\n        return register_datapoint_at_roboflow(\n            image=image,\n            prediction=prediction,\n            target_project=target_project,\n            usage_quota_name=usage_quota_name,\n            persist_predictions=persist_predictions,\n            minutely_usage_limit=minutely_usage_limit,\n            hourly_usage_limit=hourly_usage_limit,\n            daily_usage_limit=daily_usage_limit,\n            max_image_size=max_image_size,\n            compression_level=compression_level,\n            registration_tags=registration_tags,\n            fire_and_forget=fire_and_forget,\n            labeling_batch_prefix=labeling_batch_prefix,\n            new_labeling_batch_frequency=new_labeling_batch_frequency,\n            cache=cache,\n            background_tasks=background_tasks,\n            thread_pool_executor=thread_pool_executor,\n            api_key=api_key,\n            image_name=image_name,\n            metadata=metadata,\n        )\n    return False, \"Registration skipped due to sampling settings\"\n",
    "patch": null
  },
  {
    "trace_id": "fb95b459-9700-4baa-8e9a-5dce10b8acd3",
    "function_name": "BlockManifest.get_air_gapped_availability",
    "file_path": "inference/core/workflows/core_steps/sinks/roboflow/dataset_upload/v1.py",
    "speedup_x": 0.10357735515355307,
    "review_quality": "medium",
    "pre_optimization_commit": "835af61109f8cab1d2cb51cf93d061ef3a4c5fc7",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def get_air_gapped_availability(cls) -> dict:\n        return {\"available\": False, \"reason\": \"requires_internet\"}\n",
    "optimized_function_code": "from typing import Literal\n\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nSHORT_DESCRIPTION = \"Save images and predictions to your Roboflow Dataset.\"\n\nLONG_DESCRIPTION = \"\"\"\nUpload images and model predictions to a Roboflow dataset for active learning, model improvement, and data collection, with configurable usage quotas, batch organization, image compression, and optional annotation persistence.\n\n## How This Block Works\n\nThis block uploads workflow images and predictions to your Roboflow dataset for storage, labeling, and model training. The block:\n\n1. Takes images and optional model predictions (object detection, instance segmentation, keypoint detection, or classification) as input\n2. Validates the Roboflow API key is available (required for uploading)\n3. Checks usage quotas (minutely, hourly, daily limits) to ensure uploads stay within configured rate limits for active learning strategies\n4. Prepares images by resizing if they exceed maximum size (maintaining aspect ratio) and compressing to specified quality level\n5. Generates labeling batch names based on the prefix and batch creation frequency (never, daily, weekly, or monthly), organizing uploaded data into batches\n6. Optionally persists model predictions as annotations if `persist_predictions` is enabled, allowing predictions to serve as pre-labels for review and correction\n7. Attaches registration tags to images for organization and filtering in the Roboflow platform\n8. Registers the image (and annotations if enabled) to the specified Roboflow project via the Roboflow API\n9. Executes synchronously or asynchronously based on `fire_and_forget` setting, allowing non-blocking uploads for faster workflow execution\n10. Returns error status and messages indicating upload success or failure\n\nThe block supports active learning workflows by implementing usage quotas that prevent excessive data collection, helping focus on collecting valuable training data within rate limits. Images are organized into labeling batches that can be automatically recreated on a schedule (daily, weekly, monthly), making it easier to manage and review collected data over time. The block can operate in fire-and-forget mode for asynchronous execution, allowing workflows to continue processing without waiting for uploads to complete, or synchronously for debugging and error handling.\n\n## Requirements\n\n**API Key Required**: This block requires a valid Roboflow API key to upload data. The API key must be configured in your environment or workflow configuration. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve an API key.\n\n## Common Use Cases\n\n- **Active Learning Data Collection**: Collect images and predictions from production environments where models struggle or are uncertain (e.g., low-confidence detections, edge cases), enabling iterative model improvement by gathering challenging examples for retraining\n- **Production Data Logging**: Continuously upload production inference data to Roboflow datasets for monitoring, analysis, and future model training, creating a growing dataset from real-world deployments\n- **Pre-Labeled Data Collection**: Upload images with model predictions as pre-labels (when `persist_predictions` is enabled), accelerating annotation workflows by providing initial labels that can be reviewed and corrected rather than creating them from scratch\n- **Stratified Data Sampling**: Use rate limiting and quotas to selectively collect data based on specific criteria (e.g., combine with Rate Limiter or Continue If blocks), ensuring diverse and balanced dataset collection without overwhelming storage or annotation resources\n- **Batch-Based Labeling Workflows**: Organize uploaded data into batches with automatic recreation schedules (daily, weekly, monthly), making it easier to manage labeling tasks, track progress, and organize data collection efforts over time\n- **Tagged Data Organization**: Attach metadata tags to uploaded images (e.g., location, camera ID, time period, model version), enabling filtering and organization of collected data in Roboflow for better dataset management and analysis\n\n## Connecting to Other Blocks\n\nThis block receives data from workflow steps and uploads it to Roboflow:\n\n- **After detection or analysis blocks** (e.g., Object Detection Model, Instance Segmentation Model, Classification Model, Keypoint Detection Model) to upload images along with their predictions, enabling active learning by collecting inference data with model outputs for annotation and retraining\n- **After filtering or analytics blocks** (e.g., Detections Filter, Continue If, Overlap Filter) to selectively upload only specific types of data (e.g., low-confidence detections, overlapping objects, specific classes), focusing data collection on valuable edge cases or interesting scenarios\n- **After rate limiter blocks** (e.g., Rate Limiter) to throttle upload frequency and stay within usage quotas, ensuring controlled data collection that respects rate limits and prevents excessive storage usage\n- **Image inputs or preprocessing blocks** to upload raw images or processed images (e.g., crops, transformed images) without predictions, enabling collection of image data for future labeling or analysis\n- **Conditional workflows** using flow control blocks (e.g., Continue If) to upload data only when certain conditions are met (e.g., upload only when detection count exceeds threshold, upload only errors or failures), enabling selective data collection based on workflow state\n- **Batch processing workflows** where multiple images or predictions are generated, allowing bulk upload of workflow outputs to Roboflow datasets for organized data collection and management\n\"\"\"\nBatchCreationFrequency = Literal[\"never\", \"daily\", \"weekly\", \"monthly\"]\n\n\n\n# Template used to produce a fresh dict per call while avoiding repeated literal construction\n_AIR_GAPPED_AVAILABILITY_TEMPLATE = {\"available\": False, \"reason\": \"requires_internet\"}\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_air_gapped_availability(cls) -> dict:\n        return _AIR_GAPPED_AVAILABILITY_TEMPLATE.copy()",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/sinks/roboflow/dataset_upload/v1.py\nfrom typing import Literal\n\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nSHORT_DESCRIPTION = \"Save images and predictions to your Roboflow Dataset.\"\n\nLONG_DESCRIPTION = \"\"\"\nUpload images and model predictions to a Roboflow dataset for active learning, model improvement, and data collection, with configurable usage quotas, batch organization, image compression, and optional annotation persistence.\n\n## How This Block Works\n\nThis block uploads workflow images and predictions to your Roboflow dataset for storage, labeling, and model training. The block:\n\n1. Takes images and optional model predictions (object detection, instance segmentation, keypoint detection, or classification) as input\n2. Validates the Roboflow API key is available (required for uploading)\n3. Checks usage quotas (minutely, hourly, daily limits) to ensure uploads stay within configured rate limits for active learning strategies\n4. Prepares images by resizing if they exceed maximum size (maintaining aspect ratio) and compressing to specified quality level\n5. Generates labeling batch names based on the prefix and batch creation frequency (never, daily, weekly, or monthly), organizing uploaded data into batches\n6. Optionally persists model predictions as annotations if `persist_predictions` is enabled, allowing predictions to serve as pre-labels for review and correction\n7. Attaches registration tags to images for organization and filtering in the Roboflow platform\n8. Registers the image (and annotations if enabled) to the specified Roboflow project via the Roboflow API\n9. Executes synchronously or asynchronously based on `fire_and_forget` setting, allowing non-blocking uploads for faster workflow execution\n10. Returns error status and messages indicating upload success or failure\n\nThe block supports active learning workflows by implementing usage quotas that prevent excessive data collection, helping focus on collecting valuable training data within rate limits. Images are organized into labeling batches that can be automatically recreated on a schedule (daily, weekly, monthly), making it easier to manage and review collected data over time. The block can operate in fire-and-forget mode for asynchronous execution, allowing workflows to continue processing without waiting for uploads to complete, or synchronously for debugging and error handling.\n\n## Requirements\n\n**API Key Required**: This block requires a valid Roboflow API key to upload data. The API key must be configured in your environment or workflow configuration. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve an API key.\n\n## Common Use Cases\n\n- **Active Learning Data Collection**: Collect images and predictions from production environments where models struggle or are uncertain (e.g., low-confidence detections, edge cases), enabling iterative model improvement by gathering challenging examples for retraining\n- **Production Data Logging**: Continuously upload production inference data to Roboflow datasets for monitoring, analysis, and future model training, creating a growing dataset from real-world deployments\n- **Pre-Labeled Data Collection**: Upload images with model predictions as pre-labels (when `persist_predictions` is enabled), accelerating annotation workflows by providing initial labels that can be reviewed and corrected rather than creating them from scratch\n- **Stratified Data Sampling**: Use rate limiting and quotas to selectively collect data based on specific criteria (e.g., combine with Rate Limiter or Continue If blocks), ensuring diverse and balanced dataset collection without overwhelming storage or annotation resources\n- **Batch-Based Labeling Workflows**: Organize uploaded data into batches with automatic recreation schedules (daily, weekly, monthly), making it easier to manage labeling tasks, track progress, and organize data collection efforts over time\n- **Tagged Data Organization**: Attach metadata tags to uploaded images (e.g., location, camera ID, time period, model version), enabling filtering and organization of collected data in Roboflow for better dataset management and analysis\n\n## Connecting to Other Blocks\n\nThis block receives data from workflow steps and uploads it to Roboflow:\n\n- **After detection or analysis blocks** (e.g., Object Detection Model, Instance Segmentation Model, Classification Model, Keypoint Detection Model) to upload images along with their predictions, enabling active learning by collecting inference data with model outputs for annotation and retraining\n- **After filtering or analytics blocks** (e.g., Detections Filter, Continue If, Overlap Filter) to selectively upload only specific types of data (e.g., low-confidence detections, overlapping objects, specific classes), focusing data collection on valuable edge cases or interesting scenarios\n- **After rate limiter blocks** (e.g., Rate Limiter) to throttle upload frequency and stay within usage quotas, ensuring controlled data collection that respects rate limits and prevents excessive storage usage\n- **Image inputs or preprocessing blocks** to upload raw images or processed images (e.g., crops, transformed images) without predictions, enabling collection of image data for future labeling or analysis\n- **Conditional workflows** using flow control blocks (e.g., Continue If) to upload data only when certain conditions are met (e.g., upload only when detection count exceeds threshold, upload only errors or failures), enabling selective data collection based on workflow state\n- **Batch processing workflows** where multiple images or predictions are generated, allowing bulk upload of workflow outputs to Roboflow datasets for organized data collection and management\n\"\"\"\nBatchCreationFrequency = Literal[\"never\", \"daily\", \"weekly\", \"monthly\"]\n\n\n\n# Template used to produce a fresh dict per call while avoiding repeated literal construction\n_AIR_GAPPED_AVAILABILITY_TEMPLATE = {\"available\": False, \"reason\": \"requires_internet\"}\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_air_gapped_availability(cls) -> dict:\n        return _AIR_GAPPED_AVAILABILITY_TEMPLATE.copy()\n```",
    "optimized_function_only": "    def get_air_gapped_availability(cls) -> dict:\n        return _AIR_GAPPED_AVAILABILITY_TEMPLATE.copy()",
    "original_file_content": "\"\"\"\n*****************************************************************\n*                           WARNING!                            *\n*****************************************************************\nThis module contains the utility functions used by\nRoboflowDatasetUploadBlockV2.\n\nWe do not recommend making multiple blocks dependent on the same code,\nbut the change between v1 and v2 was basically the default value of\nsome parameter - hence we decided not to replicate the code.\n\nIf you need to modify this module beware that you may introduce\nchange to RoboflowDatasetUploadBlockV2! If that happens,\nprobably that's the time to disentangle those blocks and copy the\ncode.\n\"\"\"\n\nimport hashlib\nimport json\nimport logging\nfrom collections import OrderedDict\nfrom concurrent.futures import ThreadPoolExecutor\nfrom datetime import datetime, timedelta\nfrom functools import partial\nfrom typing import Any, Dict, List, Literal, Optional, Tuple, Type, Union\nfrom uuid import uuid4\n\nimport supervision as sv\nfrom fastapi import BackgroundTasks\nfrom pydantic import AliasChoices, ConfigDict, Field\n\nfrom inference.core.active_learning.cache_operations import (\n    return_strategy_credit,\n    use_credit_of_matching_strategy,\n)\nfrom inference.core.active_learning.core import prepare_image_to_registration\nfrom inference.core.active_learning.entities import (\n    ImageDimensions,\n    StrategyLimit,\n    StrategyLimitType,\n)\nfrom inference.core.cache.base import BaseCache\nfrom inference.core.roboflow_api import (\n    annotate_image_at_roboflow,\n    get_roboflow_workspace,\n    register_image_at_roboflow,\n)\nfrom inference.core.workflows.core_steps.common.serializers import (\n    serialise_sv_detections,\n)\nfrom inference.core.workflows.core_steps.common.utils import scale_sv_detections\nfrom inference.core.workflows.execution_engine.constants import INFERENCE_ID_KEY\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    BOOLEAN_KIND,\n    CLASSIFICATION_PREDICTION_KIND,\n    IMAGE_KIND,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    KEYPOINT_DETECTION_PREDICTION_KIND,\n    LIST_OF_VALUES_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    ROBOFLOW_PROJECT_KIND,\n    STRING_KIND,\n    ImageInputField,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nSHORT_DESCRIPTION = \"Save images and predictions to your Roboflow Dataset.\"\n\nLONG_DESCRIPTION = \"\"\"\nUpload images and model predictions to a Roboflow dataset for active learning, model improvement, and data collection, with configurable usage quotas, batch organization, image compression, and optional annotation persistence.\n\n## How This Block Works\n\nThis block uploads workflow images and predictions to your Roboflow dataset for storage, labeling, and model training. The block:\n\n1. Takes images and optional model predictions (object detection, instance segmentation, keypoint detection, or classification) as input\n2. Validates the Roboflow API key is available (required for uploading)\n3. Checks usage quotas (minutely, hourly, daily limits) to ensure uploads stay within configured rate limits for active learning strategies\n4. Prepares images by resizing if they exceed maximum size (maintaining aspect ratio) and compressing to specified quality level\n5. Generates labeling batch names based on the prefix and batch creation frequency (never, daily, weekly, or monthly), organizing uploaded data into batches\n6. Optionally persists model predictions as annotations if `persist_predictions` is enabled, allowing predictions to serve as pre-labels for review and correction\n7. Attaches registration tags to images for organization and filtering in the Roboflow platform\n8. Registers the image (and annotations if enabled) to the specified Roboflow project via the Roboflow API\n9. Executes synchronously or asynchronously based on `fire_and_forget` setting, allowing non-blocking uploads for faster workflow execution\n10. Returns error status and messages indicating upload success or failure\n\nThe block supports active learning workflows by implementing usage quotas that prevent excessive data collection, helping focus on collecting valuable training data within rate limits. Images are organized into labeling batches that can be automatically recreated on a schedule (daily, weekly, monthly), making it easier to manage and review collected data over time. The block can operate in fire-and-forget mode for asynchronous execution, allowing workflows to continue processing without waiting for uploads to complete, or synchronously for debugging and error handling.\n\n## Requirements\n\n**API Key Required**: This block requires a valid Roboflow API key to upload data. The API key must be configured in your environment or workflow configuration. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve an API key.\n\n## Common Use Cases\n\n- **Active Learning Data Collection**: Collect images and predictions from production environments where models struggle or are uncertain (e.g., low-confidence detections, edge cases), enabling iterative model improvement by gathering challenging examples for retraining\n- **Production Data Logging**: Continuously upload production inference data to Roboflow datasets for monitoring, analysis, and future model training, creating a growing dataset from real-world deployments\n- **Pre-Labeled Data Collection**: Upload images with model predictions as pre-labels (when `persist_predictions` is enabled), accelerating annotation workflows by providing initial labels that can be reviewed and corrected rather than starting from scratch\n- **Stratified Data Sampling**: Use rate limiting and quotas to selectively collect data based on specific criteria (e.g., combine with Rate Limiter or Continue If blocks), ensuring diverse and balanced dataset collection without overwhelming storage or annotation resources\n- **Batch-Based Labeling Workflows**: Organize uploaded data into batches with automatic recreation schedules (daily, weekly, monthly), making it easier to manage labeling tasks, track progress, and organize data collection efforts over time\n- **Tagged Data Organization**: Attach metadata tags to uploaded images (e.g., location, camera ID, time period, model version), enabling filtering and organization of collected data in Roboflow for better dataset management and analysis\n\n## Connecting to Other Blocks\n\nThis block receives data from workflow steps and uploads it to Roboflow:\n\n- **After detection or analysis blocks** (e.g., Object Detection Model, Instance Segmentation Model, Classification Model, Keypoint Detection Model) to upload images along with their predictions, enabling active learning by collecting inference data with model outputs for annotation and retraining\n- **After filtering or analytics blocks** (e.g., Detections Filter, Continue If, Overlap Filter) to selectively upload only specific types of data (e.g., low-confidence detections, overlapping objects, specific classes), focusing data collection on valuable edge cases or interesting scenarios\n- **After rate limiter blocks** (e.g., Rate Limiter) to throttle upload frequency and stay within usage quotas, ensuring controlled data collection that respects rate limits and prevents excessive storage usage\n- **Image inputs or preprocessing blocks** to upload raw images or processed images (e.g., crops, transformed images) without predictions, enabling collection of image data for future labeling or analysis\n- **Conditional workflows** using flow control blocks (e.g., Continue If) to upload data only when certain conditions are met (e.g., upload only when detection count exceeds threshold, upload only errors or failures), enabling selective data collection based on workflow state\n- **Batch processing workflows** where multiple images or predictions are generated, allowing bulk upload of workflow outputs to Roboflow datasets for organized data collection and management\n\"\"\"\n\nWORKSPACE_NAME_CACHE_EXPIRE = 900  # 15 min\nTIMESTAMP_FORMAT = \"%Y_%m_%d\"\nDUPLICATED_STATUS = \"Duplicated image\"\nBatchCreationFrequency = Literal[\"never\", \"daily\", \"weekly\", \"monthly\"]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Roboflow Dataset Upload\",\n            \"version\": \"v1\",\n            \"short_description\": SHORT_DESCRIPTION,\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"sink\",\n            \"ui_manifest\": {\n                \"section\": \"data_storage\",\n                \"icon\": \"fal fa-upload\",\n                \"blockPriority\": 0,\n                \"popular\": True,\n                \"requires_rf_key\": True,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/roboflow_dataset_upload@v1\", \"RoboflowDatasetUpload\"]\n    images: Selector(kind=[IMAGE_KIND]) = Field(\n        title=\"Input Image\",\n        description=\"Image(s) to upload to the Roboflow dataset. Can be a single image or batch of images from workflow inputs or processing steps. Images are resized if they exceed max_image_size and compressed before uploading. Supports batch processing.\",\n        examples=[\"$inputs.image\", \"$steps.cropping.crops\"],\n        validation_alias=AliasChoices(\"image\", \"images\"),\n    )\n    predictions: Optional[\n        Selector(\n            kind=[\n                OBJECT_DETECTION_PREDICTION_KIND,\n                INSTANCE_SEGMENTATION_PREDICTION_KIND,\n                KEYPOINT_DETECTION_PREDICTION_KIND,\n                CLASSIFICATION_PREDICTION_KIND,\n            ]\n        )\n    ] = Field(\n        default=None,\n        description=\"Optional model predictions to upload alongside images. Predictions are saved as annotations (pre-labels) in the Roboflow dataset when persist_predictions is enabled, allowing predictions to serve as starting points for annotation review and correction. Supports object detection, instance segmentation, keypoint detection, and classification predictions. If None, only images are uploaded.\",\n        examples=[\"$steps.object_detection_model.predictions\"],\n    )\n    target_project: Union[Selector(kind=[ROBOFLOW_PROJECT_KIND]), str] = Field(\n        description=\"Roboflow project identifier where uploaded images and annotations will be saved. Must be a valid project in your Roboflow workspace. The project name can be specified directly or referenced from workflow inputs.\",\n        examples=[\"my_project\", \"$inputs.target_project\"],\n    )\n    minutely_usage_limit: int = Field(\n        default=10,\n        description=\"Maximum number of image uploads allowed per minute for this quota. Part of the usage quota system that enforces rate limits for active learning data collection. Uploads exceeding this limit are skipped to prevent excessive data collection. Works together with hourly_usage_limit and daily_usage_limit to provide multi-level rate limiting.\",\n        examples=[10, 60],\n    )\n    hourly_usage_limit: int = Field(\n        default=100,\n        description=\"Maximum number of image uploads allowed per hour for this quota. Part of the usage quota system that enforces rate limits for active learning data collection. Uploads exceeding this limit are skipped to prevent excessive data collection. Works together with minutely_usage_limit and daily_usage_limit to provide multi-level rate limiting.\",\n        examples=[10, 60],\n    )\n    daily_usage_limit: int = Field(\n        default=1000,\n        description=\"Maximum number of image uploads allowed per day for this quota. Part of the usage quota system that enforces rate limits for active learning data collection. Uploads exceeding this limit are skipped to prevent excessive data collection. Works together with minutely_usage_limit and hourly_usage_limit to provide multi-level rate limiting.\",\n        examples=[10, 60],\n    )\n    usage_quota_name: str = Field(\n        description=\"Unique identifier for tracking usage quotas (minutely, hourly, daily limits). Used internally to manage rate limiting across multiple upload operations. Each unique quota name maintains separate counters, allowing different upload strategies or data collection workflows to have independent rate limits.\",\n        examples=[\"quota-for-data-sampling-1\"],\n        json_schema_extra={\"hidden\": True},\n    )\n    max_image_size: Tuple[int, int] = Field(\n        default=(512, 512),\n        description=\"Maximum dimensions (width, height) for uploaded images. Images exceeding these dimensions are automatically resized while preserving aspect ratio before uploading. Smaller sizes reduce storage and bandwidth but may lose image quality. Use larger sizes (e.g., (1920, 1080)) for high-resolution data collection, or smaller sizes (e.g., (512, 512)) for efficient storage and faster uploads.\",\n        examples=[(512, 512), (1920, 1080)],\n    )\n    compression_level: int = Field(\n        default=75,\n        gt=0,\n        le=100,\n        description=\"JPEG compression quality level for uploaded images, ranging from 1 (highest compression, smallest file size, lower quality) to 100 (no compression, largest file size, highest quality). Higher values preserve more image quality but increase storage and bandwidth usage. Typical values range from 70-90 for balanced quality and size. Default of 75 provides good quality with reasonable file sizes.\",\n        examples=[75],\n    )\n    registration_tags: Union[\n        List[Union[Selector(kind=[STRING_KIND]), str]],\n        Selector(kind=[LIST_OF_VALUES_KIND]),\n    ] = Field(\n        default_factory=list,\n        description=\"List of tags to attach to uploaded images for organization and filtering in Roboflow. Tags can be static strings (e.g., 'location-florida', 'camera-1') or dynamic values from workflow inputs. Tags help organize collected data, filter images in Roboflow, and add metadata for dataset management. Can be an empty list if no tags are needed.\",\n        examples=[\n            [\"location-florida\", \"factory-name\", \"$inputs.dynamic_tag\"],\n            \"$inputs.tags\",\n        ],\n    )\n    persist_predictions: bool = Field(\n        default=True,\n        description=\"If True, model predictions are saved as annotations (pre-labels) in the Roboflow dataset alongside images. This enables predictions to serve as starting points for annotation, allowing reviewers to correct or approve labels rather than creating them from scratch. If False, only images are uploaded without annotations. Enabling this accelerates annotation workflows by providing initial labels.\",\n        examples=[True, False],\n    )\n    disable_sink: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=False,\n        description=\"If True, the block execution is disabled and no uploads occur. This allows temporarily disabling data collection without removing the block from workflows, useful for testing, debugging, or conditional data collection. When disabled, returns a message indicating the sink was disabled. Default is False (uploads enabled).\",\n        examples=[True, \"$inputs.disable_active_learning\"],\n    )\n    fire_and_forget: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=True,\n        description=\"If True, uploads execute asynchronously (fire-and-forget mode), allowing the workflow to continue immediately without waiting for upload completion. This improves workflow performance but prevents error handling. If False, uploads execute synchronously, blocking workflow execution until completion and allowing proper error handling and status reporting. Use async mode (True) for production workflows where speed is prioritized, and sync mode (False) for debugging or when error handling is critical.\",\n        examples=[True],\n    )\n    labeling_batch_prefix: Union[str, Selector(kind=[STRING_KIND])] = Field(\n        default=\"workflows_data_collector\",\n        description=\"Prefix used to generate labeling batch names for organizing uploaded images in Roboflow. Combined with the batch recreation frequency and timestamps to create batch names like 'workflows_data_collector_2024_01_15'. Batches help organize collected data for labeling, making it easier to manage and review uploaded images in groups. Can be customized to match your organization scheme.\",\n        examples=[\"my_labeling_batch_name\"],\n    )\n    labeling_batches_recreation_frequency: BatchCreationFrequency = Field(\n        default=\"never\",\n        description=\"Frequency at which new labeling batches are automatically created for uploaded images. Options: 'never' (all images go to the same batch), 'daily' (new batch each day), 'weekly' (new batch each week), 'monthly' (new batch each month). Batch timestamps are appended to the labeling_batch_prefix to create unique batch names. Automatically organizing uploads into time-based batches simplifies dataset management and makes it easier to track and review collected data over time.\",\n        examples=[\"never\", \"daily\"],\n    )\n    image_name: Optional[Union[str, Selector(kind=[STRING_KIND])]] = Field(\n        default=None,\n        description=\"Optional custom name for the uploaded image. If provided, this name will be used instead of an auto-generated UUID. This is useful when you want to preserve the original filename or use a meaningful identifier (e.g., serial number, timestamp) for the image in the Roboflow dataset. The name should not include file extension. If not provided, a UUID will be generated automatically.\",\n        examples=[\"serial_12345\", \"camera1_frame_001\", \"$inputs.filename\"],\n    )\n\n    @classmethod\n    def get_air_gapped_availability(cls) -> dict:\n        return {\"available\": False, \"reason\": \"requires_internet\"}\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return [\"images\", \"predictions\", \"image_name\"]\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"error_status\", kind=[BOOLEAN_KIND]),\n            OutputDefinition(name=\"message\", kind=[STRING_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass RoboflowDatasetUploadBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        cache: BaseCache,\n        api_key: Optional[str],\n        background_tasks: Optional[BackgroundTasks],\n        thread_pool_executor: Optional[ThreadPoolExecutor],\n    ):\n        self._cache = cache\n        self._api_key = api_key\n        self._background_tasks = background_tasks\n        self._thread_pool_executor = thread_pool_executor\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"cache\", \"api_key\", \"background_tasks\", \"thread_pool_executor\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        predictions: Optional[Batch[Union[sv.Detections, dict]]],\n        target_project: str,\n        usage_quota_name: str,\n        minutely_usage_limit: int,\n        persist_predictions: bool,\n        hourly_usage_limit: int,\n        daily_usage_limit: int,\n        max_image_size: Tuple[int, int],\n        compression_level: int,\n        registration_tags: List[str],\n        disable_sink: bool,\n        fire_and_forget: bool,\n        labeling_batch_prefix: str,\n        labeling_batches_recreation_frequency: BatchCreationFrequency,\n        image_name: Optional[Batch[Optional[str]]] = None,\n    ) -> BlockResult:\n        if self._api_key is None:\n            raise ValueError(\n                \"RoboflowDataCollector block cannot run without Roboflow API key. \"\n                \"If you do not know how to get API key - visit \"\n                \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to \"\n                \"retrieve one.\"\n            )\n        if disable_sink:\n            return [\n                {\n                    \"error_status\": False,\n                    \"message\": \"Sink was disabled by parameter `disable_sink`\",\n                }\n                for _ in range(len(images))\n            ]\n        result = []\n        predictions = [None] * len(images) if predictions is None else predictions\n        image_names = [None] * len(images) if image_name is None else image_name\n        for image, prediction, img_name in zip(images, predictions, image_names):\n            error_status, message = register_datapoint_at_roboflow(\n                image=image,\n                prediction=prediction,\n                target_project=target_project,\n                usage_quota_name=usage_quota_name,\n                persist_predictions=persist_predictions,\n                minutely_usage_limit=minutely_usage_limit,\n                hourly_usage_limit=hourly_usage_limit,\n                daily_usage_limit=daily_usage_limit,\n                max_image_size=max_image_size,\n                compression_level=compression_level,\n                registration_tags=registration_tags,\n                fire_and_forget=fire_and_forget,\n                labeling_batch_prefix=labeling_batch_prefix,\n                new_labeling_batch_frequency=labeling_batches_recreation_frequency,\n                cache=self._cache,\n                background_tasks=self._background_tasks,\n                thread_pool_executor=self._thread_pool_executor,\n                api_key=self._api_key,\n                image_name=img_name,\n            )\n            result.append({\"error_status\": error_status, \"message\": message})\n        return result\n\n\ndef register_datapoint_at_roboflow(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    usage_quota_name: str,\n    persist_predictions: bool,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    fire_and_forget: bool,\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    background_tasks: Optional[BackgroundTasks],\n    thread_pool_executor: Optional[ThreadPoolExecutor],\n    api_key: str,\n    image_name: Optional[str] = None,\n    metadata: Optional[Dict[str, Any]] = None,\n) -> Tuple[bool, str]:\n    registration_task = partial(\n        execute_registration,\n        image=image,\n        prediction=prediction,\n        target_project=target_project,\n        usage_quota_name=usage_quota_name,\n        persist_predictions=persist_predictions,\n        minutely_usage_limit=minutely_usage_limit,\n        hourly_usage_limit=hourly_usage_limit,\n        daily_usage_limit=daily_usage_limit,\n        max_image_size=max_image_size,\n        compression_level=compression_level,\n        registration_tags=registration_tags,\n        labeling_batch_prefix=labeling_batch_prefix,\n        new_labeling_batch_frequency=new_labeling_batch_frequency,\n        cache=cache,\n        api_key=api_key,\n        image_name=image_name,\n        metadata=metadata,\n    )\n    if fire_and_forget and background_tasks:\n        background_tasks.add_task(registration_task)\n        return False, \"Element registration happens in the background task\"\n    if fire_and_forget and thread_pool_executor:\n        thread_pool_executor.submit(registration_task)\n        return False, \"Element registration happens in the background task\"\n    return registration_task()\n\n\ndef execute_registration(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    persist_predictions: bool,\n    usage_quota_name: str,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    api_key: str,\n    image_name: Optional[str] = None,\n    metadata: Optional[Dict[str, Any]] = None,\n) -> Tuple[bool, str]:\n    matching_strategies_limits = OrderedDict(\n        {\n            usage_quota_name: [\n                StrategyLimit(\n                    limit_type=StrategyLimitType.MINUTELY, value=minutely_usage_limit\n                ),\n                StrategyLimit(\n                    limit_type=StrategyLimitType.HOURLY, value=hourly_usage_limit\n                ),\n                StrategyLimit(\n                    limit_type=StrategyLimitType.DAILY, value=daily_usage_limit\n                ),\n            ]\n        }\n    )\n    workspace_name = get_workspace_name(api_key=api_key, cache=cache)\n    strategy_with_spare_credit = use_credit_of_matching_strategy(\n        cache=cache,\n        workspace=workspace_name,\n        project=target_project,\n        matching_strategies_limits=matching_strategies_limits,\n    )\n    if strategy_with_spare_credit is None:\n        return False, \"Registration skipped due to usage quota exceeded\"\n    credit_to_be_returned = False\n    try:\n        local_image_id = image_name if image_name else str(uuid4())\n        encoded_image, scaling_factor = prepare_image_to_registration(\n            image=image.numpy_image,\n            desired_size=ImageDimensions(\n                width=max_image_size[0], height=max_image_size[1]\n            ),\n            jpeg_compression_level=compression_level,\n        )\n        batch_name = generate_batch_name(\n            labeling_batch_prefix=labeling_batch_prefix,\n            new_labeling_batch_frequency=new_labeling_batch_frequency,\n        )\n        if isinstance(prediction, sv.Detections):\n            prediction = scale_sv_detections(\n                detections=prediction, scale=scaling_factor\n            )\n        status = register_datapoint(\n            target_project=target_project,\n            encoded_image=encoded_image,\n            local_image_id=local_image_id,\n            prediction=prediction if persist_predictions else None,\n            api_key=api_key,\n            batch_name=batch_name,\n            tags=registration_tags,\n            metadata=metadata,\n        )\n        if status == DUPLICATED_STATUS:\n            credit_to_be_returned = True\n        return False, status\n    except Exception as error:\n        credit_to_be_returned = True\n        logging.exception(\"Failed to register datapoint on the Roboflow platform\")\n        return (\n            True,\n            f\"Error while registration. Error type: {type(error)}. Details: {error}\",\n        )\n    finally:\n        if credit_to_be_returned:\n            return_strategy_credit(\n                cache=cache,\n                workspace=workspace_name,\n                project=target_project,\n                strategy_name=strategy_with_spare_credit,\n            )\n\n\ndef get_workspace_name(\n    api_key: str,\n    cache: BaseCache,\n) -> str:\n    api_key_hash = hashlib.md5(api_key.encode(\"utf-8\")).hexdigest()\n    cache_key = f\"workflows:api_key_to_workspace:{api_key_hash}\"\n    cached_workspace_name = cache.get(cache_key)\n    if cached_workspace_name:\n        return cached_workspace_name\n    workspace_name_from_api = get_roboflow_workspace(api_key=api_key)\n    cache.set(\n        key=cache_key, value=workspace_name_from_api, expire=WORKSPACE_NAME_CACHE_EXPIRE\n    )\n    return workspace_name_from_api\n\n\ndef generate_batch_name(\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n) -> str:\n    if new_labeling_batch_frequency == \"never\":\n        return labeling_batch_prefix\n    timestamp_generator = RECREATION_INTERVAL2TIMESTAMP_GENERATOR[\n        new_labeling_batch_frequency\n    ]\n    timestamp = timestamp_generator()\n    return f\"{labeling_batch_prefix}_{timestamp}\"\n\n\ndef generate_today_timestamp() -> str:\n    return datetime.today().strftime(TIMESTAMP_FORMAT)\n\n\ndef generate_start_timestamp_for_this_week() -> str:\n    today = datetime.today()\n    return (today - timedelta(days=today.weekday())).strftime(TIMESTAMP_FORMAT)\n\n\ndef generate_start_timestamp_for_this_month() -> str:\n    return datetime.today().replace(day=1).strftime(TIMESTAMP_FORMAT)\n\n\nRECREATION_INTERVAL2TIMESTAMP_GENERATOR = {\n    \"daily\": generate_today_timestamp,\n    \"weekly\": generate_start_timestamp_for_this_week,\n    \"monthly\": generate_start_timestamp_for_this_month,\n}\n\n\ndef register_datapoint(\n    target_project: str,\n    encoded_image: bytes,\n    local_image_id: str,\n    prediction: Optional[Union[sv.Detections, dict]],\n    api_key: str,\n    batch_name: str,\n    tags: List[str],\n    metadata: Optional[Dict[str, Any]] = None,\n) -> str:\n    inference_id = None\n    if isinstance(prediction, dict):\n        inference_id = prediction.get(INFERENCE_ID_KEY)\n    if isinstance(prediction, sv.Detections) and len(prediction) > 0:\n        # TODO: Lack of inference ID for empty prediction -\n        #  dependent on https://github.com/roboflow/inference/issues/567\n        inference_id_array = prediction.data.get(INFERENCE_ID_KEY)\n        if inference_id_array is not None:\n            inference_id_list = inference_id_array.tolist()\n            inference_id = inference_id_list[0]\n    roboflow_image_id = safe_register_image_at_roboflow(\n        target_project=target_project,\n        encoded_image=encoded_image,\n        local_image_id=local_image_id,\n        api_key=api_key,\n        batch_name=batch_name,\n        tags=tags,\n        inference_id=inference_id,\n        metadata=metadata,\n    )\n    if roboflow_image_id is None:\n        return DUPLICATED_STATUS\n    if is_prediction_registration_forbidden(prediction=prediction):\n        return \"Successfully registered image\"\n    encoded_prediction, prediction_format = encode_prediction(prediction=prediction)\n    _ = annotate_image_at_roboflow(\n        api_key=api_key,\n        dataset_id=target_project,\n        local_image_id=local_image_id,\n        roboflow_image_id=roboflow_image_id,\n        annotation_content=encoded_prediction,\n        annotation_file_type=prediction_format,\n        is_prediction=True,\n    )\n    return \"Successfully registered image and annotation\"\n\n\ndef safe_register_image_at_roboflow(\n    target_project: str,\n    encoded_image: bytes,\n    local_image_id: str,\n    api_key: str,\n    batch_name: str,\n    tags: List[str],\n    inference_id: Optional[str],\n    metadata: Optional[Dict[str, Any]] = None,\n) -> Optional[str]:\n    registration_response = register_image_at_roboflow(\n        api_key=api_key,\n        dataset_id=target_project,\n        local_image_id=local_image_id,\n        image_bytes=encoded_image,\n        batch_name=batch_name,\n        tags=tags,\n        inference_id=inference_id,\n        metadata=metadata,\n    )\n    image_duplicated = registration_response.get(\"duplicate\", False)\n    if image_duplicated:\n        logging.warning(f\"Image duplication detected: {registration_response}.\")\n        return None\n    return registration_response[\"id\"]\n\n\ndef is_prediction_registration_forbidden(\n    prediction: Optional[Union[sv.Detections, dict]],\n) -> bool:\n    if prediction is None:\n        return True\n    if isinstance(prediction, sv.Detections) and len(prediction) == 0:\n        return True\n    if isinstance(prediction, dict) and (\n        \"top\" not in prediction and \"predicted_classes\" not in prediction\n    ):\n        return True\n    return False\n\n\ndef encode_prediction(\n    prediction: Union[sv.Detections, dict],\n) -> Tuple[str, str]:\n    if isinstance(prediction, dict):\n        if \"predicted_classes\" in prediction:\n            return \",\".join(prediction[\"predicted_classes\"]), \"txt\"\n        return prediction[\"top\"], \"txt\"\n    detections_in_inference_format = serialise_sv_detections(detections=prediction)\n    return json.dumps(detections_in_inference_format), \"json\"\n",
    "patch": null
  },
  {
    "trace_id": "fdcd935d-6569-45d6-b32f-147afc7402ba",
    "function_name": "BlockManifest.get_air_gapped_availability",
    "file_path": "inference/core/workflows/core_steps/sinks/roboflow/custom_metadata/v1.py",
    "speedup_x": 0.12107886474770399,
    "review_quality": "high",
    "pre_optimization_commit": "835af61109f8cab1d2cb51cf93d061ef3a4c5fc7",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def get_air_gapped_availability(cls) -> dict:\n        return {\"available\": False, \"reason\": \"requires_internet\"}\n",
    "optimized_function_code": "from inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nSHORT_DESCRIPTION = \"Add custom metadata to the Roboflow Model Monitoring dashboard.\"\n\nLONG_DESCRIPTION = \"\"\"\nAttach custom metadata fields to inference results in the Roboflow Model Monitoring dashboard by extracting inference IDs from predictions and adding name-value pairs that enable filtering, analysis, and organization of inference data for monitoring workflows, production analytics, and model performance tracking.\n\n## How This Block Works\n\nThis block adds custom metadata to inference results stored in Roboflow Model Monitoring, allowing you to attach contextual information to predictions for filtering and analysis. The block:\n\n1. Receives model predictions and metadata configuration:\n   - Takes predictions from any supported model type (object detection, instance segmentation, keypoint detection, or classification)\n   - Receives field name and field value for the custom metadata to attach\n   - Accepts fire-and-forget flag for execution mode\n2. Validates Roboflow API key:\n   - Checks that a valid Roboflow API key is available (required for API access)\n   - Raises an error if API key is missing with instructions on how to retrieve one\n3. Extracts inference IDs from predictions:\n   - For supervision Detections objects: extracts inference IDs from the data dictionary\n   - For classification predictions: extracts inference ID from the prediction dictionary\n   - Collects all unique inference IDs that need metadata attached\n   - Handles cases where no inference IDs are found (returns error message)\n4. Retrieves workspace information:\n   - Gets workspace ID from Roboflow API using the provided API key\n   - Uses caching (15-minute expiration) to avoid repeated API calls for workspace lookup\n   - Caches workspace name using MD5 hash of API key as cache key\n5. Adds custom metadata via API:\n   - Calls Roboflow API to attach custom metadata field to each inference ID\n   - Associates the field name and field value with the inference results\n   - Metadata becomes available in the Model Monitoring dashboard for filtering and analysis\n6. Executes synchronously or asynchronously:\n   - **Asynchronous mode (fire_and_forget=True)**: Submits task to background thread pool or FastAPI background tasks, allowing workflow to continue without waiting for API call to complete\n   - **Synchronous mode (fire_and_forget=False)**: Waits for API call to complete and returns immediate status, useful for debugging and error handling\n7. Returns status information:\n   - Outputs error_status indicating success (False) or failure (True)\n   - Outputs message with upload status or error details\n   - Provides feedback on whether metadata was successfully attached\n\nThe block enables attaching custom metadata to inference results, making it easier to filter and analyze predictions in the Model Monitoring dashboard. For example, you can attach location labels, quality scores, processing flags, or any other contextual information that helps organize and analyze your inference data.\n\n## Common Use Cases\n\n- **Location-Based Filtering**: Attach location metadata to inferences for geographic analysis and filtering (e.g., tag inferences with location labels like \"toronto\", \"warehouse_a\", \"production_line_1\"), enabling location-based monitoring workflows\n- **Quality Control Tagging**: Attach quality or validation metadata to inferences for quality tracking (e.g., tag inferences as \"pass\", \"fail\", \"requires_review\", \"approved\"), enabling quality control workflows\n- **Contextual Annotation**: Add contextual information to inferences for better organization and analysis (e.g., tag with camera ID, time period, batch number, operator ID, environmental conditions), enabling contextual analysis workflows\n- **Classification Enhancement**: Attach custom labels or categories to inference results beyond model predictions (e.g., tag with business logic outcomes, workflow decisions, user feedback, manual corrections), enabling enhanced classification workflows\n- **Production Analytics**: Track production metrics by attaching metadata that represents operational context (e.g., tag with shift information, production batch, equipment status, performance metrics), enabling production analytics workflows\n- **Filtering and Segmentation**: Enable advanced filtering in Model Monitoring dashboard by attaching metadata that represents data segments (e.g., tag with customer segment, product category, use case type, deployment environment), enabling segmentation workflows\n\n## Connecting to Other Blocks\n\nThis block receives predictions and outputs status information:\n\n- **After model blocks** (Object Detection Model, Instance Segmentation Model, Classification Model, Keypoint Detection Model) to attach metadata to inference results (e.g., add location tags to detections, attach quality labels to classifications, tag keypoint detections with context), enabling model-to-metadata workflows\n- **After filtering or analytics blocks** (DetectionsFilter, ContinueIf, OverlapFilter) to tag filtered or analyzed results with metadata (e.g., tag filtered detections with filter criteria, attach analytics results as metadata, label processed results with workflow state), enabling analysis-to-metadata workflows\n- **After conditional execution blocks** (ContinueIf, Expression) to attach metadata based on workflow decisions (e.g., tag with decision outcomes, attach conditional branch labels, mark results based on conditions), enabling conditional-to-metadata workflows\n- **In parallel with other sink blocks** to combine metadata tagging with other data storage operations (e.g., tag while uploading to dataset, attach metadata while logging, combine with webhook notifications), enabling parallel sink workflows\n- **Before or after visualization blocks** to ensure metadata is attached before or after visualization operations (e.g., tag visualizations with context, attach metadata to visualized results), enabling visualization workflows with metadata\n- **At workflow endpoints** to ensure all inference results are tagged with metadata before workflow completion (e.g., final metadata attachment, comprehensive result tagging, complete metadata coverage), enabling end-to-end metadata workflows\n\n## Requirements\n\nThis block requires a valid Roboflow API key configured in the environment or workflow configuration. The API key is required to authenticate with Roboflow API and access Model Monitoring features. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve an API key. The block requires predictions that contain inference IDs (predictions must have been generated by models that include inference IDs). Supported prediction types: object detection, instance segmentation, keypoint detection, and classification. The block uses workspace caching (15-minute expiration) to optimize API calls. For more information on Model Monitoring at Roboflow, see https://docs.roboflow.com/deploy/model-monitoring.\n\"\"\"\n\n\n\n\n# Module-level template dict to avoid rebuilding the same literal on each call.\n_AIR_GAPPED_AVAILABILITY_TEMPLATE = {\"available\": False, \"reason\": \"requires_internet\"}\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_air_gapped_availability(cls) -> dict:\n        return _AIR_GAPPED_AVAILABILITY_TEMPLATE.copy()",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/sinks/roboflow/custom_metadata/v1.py\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nSHORT_DESCRIPTION = \"Add custom metadata to the Roboflow Model Monitoring dashboard.\"\n\nLONG_DESCRIPTION = \"\"\"\nAttach custom metadata fields to inference results in the Roboflow Model Monitoring dashboard by extracting inference IDs from predictions and adding name-value pairs that enable filtering, analysis, and organization of inference data for monitoring workflows, production analytics, and model performance tracking.\n\n## How This Block Works\n\nThis block adds custom metadata to inference results stored in Roboflow Model Monitoring, allowing you to attach contextual information to predictions for filtering and analysis. The block:\n\n1. Receives model predictions and metadata configuration:\n   - Takes predictions from any supported model type (object detection, instance segmentation, keypoint detection, or classification)\n   - Receives field name and field value for the custom metadata to attach\n   - Accepts fire-and-forget flag for execution mode\n2. Validates Roboflow API key:\n   - Checks that a valid Roboflow API key is available (required for API access)\n   - Raises an error if API key is missing with instructions on how to retrieve one\n3. Extracts inference IDs from predictions:\n   - For supervision Detections objects: extracts inference IDs from the data dictionary\n   - For classification predictions: extracts inference ID from the prediction dictionary\n   - Collects all unique inference IDs that need metadata attached\n   - Handles cases where no inference IDs are found (returns error message)\n4. Retrieves workspace information:\n   - Gets workspace ID from Roboflow API using the provided API key\n   - Uses caching (15-minute expiration) to avoid repeated API calls for workspace lookup\n   - Caches workspace name using MD5 hash of API key as cache key\n5. Adds custom metadata via API:\n   - Calls Roboflow API to attach custom metadata field to each inference ID\n   - Associates the field name and field value with the inference results\n   - Metadata becomes available in the Model Monitoring dashboard for filtering and analysis\n6. Executes synchronously or asynchronously:\n   - **Asynchronous mode (fire_and_forget=True)**: Submits task to background thread pool or FastAPI background tasks, allowing workflow to continue without waiting for API call to complete\n   - **Synchronous mode (fire_and_forget=False)**: Waits for API call to complete and returns immediate status, useful for debugging and error handling\n7. Returns status information:\n   - Outputs error_status indicating success (False) or failure (True)\n   - Outputs message with upload status or error details\n   - Provides feedback on whether metadata was successfully attached\n\nThe block enables attaching custom metadata to inference results, making it easier to filter and analyze predictions in the Model Monitoring dashboard. For example, you can attach location labels, quality scores, processing flags, or any other contextual information that helps organize and analyze your inference data.\n\n## Common Use Cases\n\n- **Location-Based Filtering**: Attach location metadata to inferences for geographic analysis and filtering (e.g., tag inferences with location labels like \"toronto\", \"warehouse_a\", \"production_line_1\"), enabling location-based monitoring workflows\n- **Quality Control Tagging**: Attach quality or validation metadata to inferences for quality tracking (e.g., tag inferences as \"pass\", \"fail\", \"requires_review\", \"approved\"), enabling quality control workflows\n- **Contextual Annotation**: Add contextual information to inferences for better organization and analysis (e.g., tag with camera ID, time period, batch number, operator ID, environmental conditions), enabling contextual analysis workflows\n- **Classification Enhancement**: Attach custom labels or categories to inference results beyond model predictions (e.g., tag with business logic outcomes, workflow decisions, user feedback, manual corrections), enabling enhanced classification workflows\n- **Production Analytics**: Track production metrics by attaching metadata that represents operational context (e.g., tag with shift information, production batch, equipment status, performance metrics), enabling production analytics workflows\n- **Filtering and Segmentation**: Enable advanced filtering in Model Monitoring dashboard by attaching metadata that represents data segments (e.g., tag with customer segment, product category, use case type, deployment environment), enabling segmentation workflows\n\n## Connecting to Other Blocks\n\nThis block receives predictions and outputs status information:\n\n- **After model blocks** (Object Detection Model, Instance Segmentation Model, Classification Model, Keypoint Detection Model) to attach metadata to inference results (e.g., add location tags to detections, attach quality labels to classifications, tag keypoint detections with context), enabling model-to-metadata workflows\n- **After filtering or analytics blocks** (DetectionsFilter, ContinueIf, OverlapFilter) to tag filtered or analyzed results with metadata (e.g., tag filtered detections with filter criteria, attach analytics results as metadata, label processed results with workflow state), enabling analysis-to-metadata workflows\n- **After conditional execution blocks** (ContinueIf, Expression) to attach metadata based on workflow decisions (e.g., tag with decision outcomes, attach conditional branch labels, mark results based on conditions), enabling conditional-to-metadata workflows\n- **In parallel with other sink blocks** to combine metadata tagging with other data storage operations (e.g., tag while uploading to dataset, attach metadata while logging, combine with webhook notifications), enabling parallel sink workflows\n- **Before or after visualization blocks** to ensure metadata is attached before or after visualization operations (e.g., tag visualizations with context, attach metadata to visualized results), enabling visualization workflows with metadata\n- **At workflow endpoints** to ensure all inference results are tagged with metadata before workflow completion (e.g., final metadata attachment, comprehensive result tagging, complete metadata coverage), enabling end-to-end metadata workflows\n\n## Requirements\n\nThis block requires a valid Roboflow API key configured in the environment or workflow configuration. The API key is required to authenticate with Roboflow API and access Model Monitoring features. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve an API key. The block requires predictions that contain inference IDs (predictions must have been generated by models that include inference IDs). Supported prediction types: object detection, instance segmentation, keypoint detection, and classification. The block uses workspace caching (15-minute expiration) to optimize API calls. For more information on Model Monitoring at Roboflow, see https://docs.roboflow.com/deploy/model-monitoring.\n\"\"\"\n\n\n\n\n# Module-level template dict to avoid rebuilding the same literal on each call.\n_AIR_GAPPED_AVAILABILITY_TEMPLATE = {\"available\": False, \"reason\": \"requires_internet\"}\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_air_gapped_availability(cls) -> dict:\n        return _AIR_GAPPED_AVAILABILITY_TEMPLATE.copy()\n```",
    "optimized_function_only": "    def get_air_gapped_availability(cls) -> dict:\n        return _AIR_GAPPED_AVAILABILITY_TEMPLATE.copy()",
    "original_file_content": "import hashlib\nimport logging\nfrom concurrent.futures import ThreadPoolExecutor\nfrom functools import partial\nfrom typing import List, Literal, Optional, Tuple, Type, Union\n\nimport numpy as np\nimport supervision as sv\nfrom fastapi import BackgroundTasks\nfrom pydantic import ConfigDict, Field\n\nfrom inference.core.cache.base import BaseCache\nfrom inference.core.roboflow_api import add_custom_metadata, get_roboflow_workspace\nfrom inference.core.workflows.execution_engine.constants import INFERENCE_ID_KEY\nfrom inference.core.workflows.execution_engine.entities.base import OutputDefinition\nfrom inference.core.workflows.execution_engine.entities.types import (\n    BOOLEAN_KIND,\n    CLASSIFICATION_PREDICTION_KIND,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    KEYPOINT_DETECTION_PREDICTION_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    STRING_KIND,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nSHORT_DESCRIPTION = \"Add custom metadata to the Roboflow Model Monitoring dashboard.\"\n\nLONG_DESCRIPTION = \"\"\"\nAttach custom metadata fields to inference results in the Roboflow Model Monitoring dashboard by extracting inference IDs from predictions and adding name-value pairs that enable filtering, analysis, and organization of inference data for monitoring workflows, production analytics, and model performance tracking.\n\n## How This Block Works\n\nThis block adds custom metadata to inference results stored in Roboflow Model Monitoring, allowing you to attach contextual information to predictions for filtering and analysis. The block:\n\n1. Receives model predictions and metadata configuration:\n   - Takes predictions from any supported model type (object detection, instance segmentation, keypoint detection, or classification)\n   - Receives field name and field value for the custom metadata to attach\n   - Accepts fire-and-forget flag for execution mode\n2. Validates Roboflow API key:\n   - Checks that a valid Roboflow API key is available (required for API access)\n   - Raises an error if API key is missing with instructions on how to retrieve one\n3. Extracts inference IDs from predictions:\n   - For supervision Detections objects: extracts inference IDs from the data dictionary\n   - For classification predictions: extracts inference ID from the prediction dictionary\n   - Collects all unique inference IDs that need metadata attached\n   - Handles cases where no inference IDs are found (returns error message)\n4. Retrieves workspace information:\n   - Gets workspace ID from Roboflow API using the provided API key\n   - Uses caching (15-minute expiration) to avoid repeated API calls for workspace lookup\n   - Caches workspace name using MD5 hash of API key as cache key\n5. Adds custom metadata via API:\n   - Calls Roboflow API to attach custom metadata field to each inference ID\n   - Associates the field name and field value with the inference results\n   - Metadata becomes available in the Model Monitoring dashboard for filtering and analysis\n6. Executes synchronously or asynchronously:\n   - **Asynchronous mode (fire_and_forget=True)**: Submits task to background thread pool or FastAPI background tasks, allowing workflow to continue without waiting for API call to complete\n   - **Synchronous mode (fire_and_forget=False)**: Waits for API call to complete and returns immediate status, useful for debugging and error handling\n7. Returns status information:\n   - Outputs error_status indicating success (False) or failure (True)\n   - Outputs message with upload status or error details\n   - Provides feedback on whether metadata was successfully attached\n\nThe block enables attaching custom metadata to inference results, making it easier to filter and analyze predictions in the Model Monitoring dashboard. For example, you can attach location labels, quality scores, processing flags, or any other contextual information that helps organize and analyze your inference data.\n\n## Common Use Cases\n\n- **Location-Based Filtering**: Attach location metadata to inferences for geographic analysis and filtering (e.g., tag inferences with location labels like \"toronto\", \"warehouse_a\", \"production_line_1\"), enabling location-based monitoring workflows\n- **Quality Control Tagging**: Attach quality or validation metadata to inferences for quality tracking (e.g., tag inferences as \"pass\", \"fail\", \"requires_review\", \"approved\"), enabling quality control workflows\n- **Contextual Annotation**: Add contextual information to inferences for better organization and analysis (e.g., tag with camera ID, time period, batch number, operator ID, environmental conditions), enabling contextual analysis workflows\n- **Classification Enhancement**: Attach custom labels or categories to inference results beyond model predictions (e.g., tag with business logic outcomes, workflow decisions, user feedback, manual corrections), enabling enhanced classification workflows\n- **Production Analytics**: Track production metrics by attaching metadata that represents operational context (e.g., tag with shift information, production batch, equipment status, performance metrics), enabling production analytics workflows\n- **Filtering and Segmentation**: Enable advanced filtering in Model Monitoring dashboard by attaching metadata that represents data segments (e.g., tag with customer segment, product category, use case type, deployment environment), enabling segmentation workflows\n\n## Connecting to Other Blocks\n\nThis block receives predictions and outputs status information:\n\n- **After model blocks** (Object Detection Model, Instance Segmentation Model, Classification Model, Keypoint Detection Model) to attach metadata to inference results (e.g., add location tags to detections, attach quality labels to classifications, tag keypoint detections with context), enabling model-to-metadata workflows\n- **After filtering or analytics blocks** (DetectionsFilter, ContinueIf, OverlapFilter) to tag filtered or analyzed results with metadata (e.g., tag filtered detections with filter criteria, attach analytics results as metadata, label processed results with workflow state), enabling analysis-to-metadata workflows\n- **After conditional execution blocks** (ContinueIf, Expression) to attach metadata based on workflow decisions (e.g., tag with decision outcomes, attach conditional branch labels, mark results based on conditions), enabling conditional-to-metadata workflows\n- **In parallel with other sink blocks** to combine metadata tagging with other data storage operations (e.g., tag while uploading to dataset, attach metadata while logging, combine with webhook notifications), enabling parallel sink workflows\n- **Before or after visualization blocks** to ensure metadata is attached before or after visualization operations (e.g., tag visualizations with context, attach metadata to visualized results), enabling visualization workflows with metadata\n- **At workflow endpoints** to ensure all inference results are tagged with metadata before workflow completion (e.g., final metadata attachment, comprehensive result tagging, complete metadata coverage), enabling end-to-end metadata workflows\n\n## Requirements\n\nThis block requires a valid Roboflow API key configured in the environment or workflow configuration. The API key is required to authenticate with Roboflow API and access Model Monitoring features. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve an API key. The block requires predictions that contain inference IDs (predictions must have been generated by models that include inference IDs). Supported prediction types: object detection, instance segmentation, keypoint detection, and classification. The block uses workspace caching (15-minute expiration) to optimize API calls. For more information on Model Monitoring at Roboflow, see https://docs.roboflow.com/deploy/model-monitoring.\n\"\"\"\n\nWORKSPACE_NAME_CACHE_EXPIRE = 900  # 15 min\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Roboflow Custom Metadata\",\n            \"version\": \"v1\",\n            \"short_description\": SHORT_DESCRIPTION,\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"sink\",\n            \"ui_manifest\": {\n                \"section\": \"advanced\",\n                \"icon\": \"fal fa-analytics\",\n                \"blockPriority\": 8,\n                \"requires_rf_key\": True,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/roboflow_custom_metadata@v1\", \"RoboflowCustomMetadata\"]\n    predictions: Selector(\n        kind=[\n            OBJECT_DETECTION_PREDICTION_KIND,\n            INSTANCE_SEGMENTATION_PREDICTION_KIND,\n            KEYPOINT_DETECTION_PREDICTION_KIND,\n            CLASSIFICATION_PREDICTION_KIND,\n        ]\n    ) = Field(\n        description=\"Model predictions (object detection, instance segmentation, keypoint detection, or classification) to attach custom metadata to. The predictions must contain inference IDs that are used to associate metadata with specific inference results in Roboflow Model Monitoring. Inference IDs are automatically extracted from supervision Detections objects or classification prediction dictionaries. The metadata will be attached to all inference IDs found in the predictions.\",\n        examples=[\n            \"$steps.object_detection.predictions\",\n            \"$steps.classification.predictions\",\n            \"$steps.instance_segmentation.predictions\",\n        ],\n    )\n    field_name: str = Field(\n        description=\"Name of the custom metadata field to create in Roboflow Model Monitoring. This becomes the field name that can be used for filtering and analysis in the Model Monitoring dashboard. Field names should be descriptive and represent the type of metadata being attached (e.g., 'location', 'quality', 'camera_id', 'batch_number'). The field name is used to organize and categorize metadata values.\",\n        examples=[\n            \"location\",\n            \"quality\",\n            \"camera_id\",\n            \"batch_number\",\n            \"shift\",\n            \"operator\",\n        ],\n    )\n    field_value: Union[\n        str,\n        Selector(kind=[STRING_KIND]),\n        Selector(kind=[STRING_KIND]),\n    ] = Field(\n        description=\"Value to assign to the custom metadata field. This is the actual data that will be attached to inference results and can be used for filtering and analysis in the Model Monitoring dashboard. Can be a string literal or a selector that references workflow outputs. Common values: location identifiers (e.g., 'toronto', 'warehouse_a'), quality labels (e.g., 'pass', 'fail', 'review'), identifiers (e.g., camera IDs, batch numbers), or any other contextual information relevant to your use case.\",\n        examples=[\n            \"toronto\",\n            \"pass\",\n            \"fail\",\n            \"warehouse_a\",\n            \"camera_01\",\n            \"$steps.expression.output\",\n        ],\n    )\n    fire_and_forget: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=True,\n        description=\"Execution mode flag. When True (default), the block runs asynchronously in the background, allowing the workflow to continue processing without waiting for the API call to complete. This provides faster workflow execution but errors are not immediately available. When False, the block runs synchronously and waits for the API call to complete, returning immediate status and error information. Use False for debugging and error handling, True for production workflows where performance is prioritized.\",\n        examples=[True, False],\n    )\n\n    @classmethod\n    def get_air_gapped_availability(cls) -> dict:\n        return {\"available\": False, \"reason\": \"requires_internet\"}\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"error_status\", kind=[BOOLEAN_KIND]),\n            OutputDefinition(name=\"message\", kind=[STRING_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass RoboflowCustomMetadataBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        cache: BaseCache,\n        api_key: Optional[str],\n        background_tasks: Optional[BackgroundTasks],\n        thread_pool_executor: Optional[ThreadPoolExecutor],\n    ):\n        self._api_key = api_key\n        self._cache = cache\n        self._background_tasks = background_tasks\n        self._thread_pool_executor = thread_pool_executor\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"api_key\", \"cache\", \"background_tasks\", \"thread_pool_executor\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        fire_and_forget: bool,\n        field_name: str,\n        field_value: str,\n        predictions: Union[sv.Detections, dict],\n    ) -> BlockResult:\n        if self._api_key is None:\n            raise ValueError(\n                \"RoboflowCustomMetadata block cannot run without Roboflow API key. \"\n                \"If you do not know how to get API key - visit \"\n                \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to \"\n                \"retrieve one.\"\n            )\n        inference_ids: List[str] = []\n        if isinstance(predictions, sv.Detections):\n            inference_ids = predictions.data.get(INFERENCE_ID_KEY, [])\n        elif INFERENCE_ID_KEY in predictions:\n            inference_ids: List[str] = [predictions[INFERENCE_ID_KEY]]\n        if len(inference_ids) == 0:\n            return {\n                \"error_status\": True,\n                \"message\": \"Custom metadata upload failed because no inference_ids were received. \"\n                \"This is known bug (https://github.com/roboflow/inference/issues/567). \"\n                \"Please provide a report for the problem under mentioned issue.\",\n            }\n        inference_ids: List[str] = list(set(inference_ids))\n        registration_task = partial(\n            add_custom_metadata_request,\n            cache=self._cache,\n            api_key=self._api_key,\n            inference_ids=inference_ids,\n            field_name=field_name,\n            field_value=field_value,\n        )\n        error_status = False\n        message = \"Registration happens in the background task\"\n        if fire_and_forget and self._background_tasks:\n            self._background_tasks.add_task(registration_task)\n        elif fire_and_forget and self._thread_pool_executor:\n            self._thread_pool_executor.submit(registration_task)\n        else:\n            error_status, message = registration_task()\n        return {\n            \"error_status\": error_status,\n            \"message\": message,\n        }\n\n\ndef get_workspace_name(\n    api_key: str,\n    cache: BaseCache,\n) -> str:\n    api_key_hash = hashlib.md5(api_key.encode(\"utf-8\")).hexdigest()\n    cache_key = f\"workflows:api_key_to_workspace:{api_key_hash}\"\n    cached_workspace_name = cache.get(cache_key)\n    if cached_workspace_name:\n        return cached_workspace_name\n    workspace_name_from_api = get_roboflow_workspace(api_key=api_key)\n    cache.set(\n        key=cache_key, value=workspace_name_from_api, expire=WORKSPACE_NAME_CACHE_EXPIRE\n    )\n    return workspace_name_from_api\n\n\ndef add_custom_metadata_request(\n    cache: BaseCache,\n    api_key: str,\n    inference_ids: List[str],\n    field_name: str,\n    field_value: str,\n) -> Tuple[bool, str]:\n    workspace_id = get_workspace_name(api_key=api_key, cache=cache)\n    try:\n        add_custom_metadata(\n            api_key=api_key,\n            workspace_id=workspace_id,\n            inference_ids=inference_ids,\n            field_name=field_name,\n            field_value=field_value,\n        )\n        return (\n            False,\n            \"Custom metadata upload was successful\",\n        )\n    except Exception as error:\n        logging.warning(\n            f\"Could not add custom metadata for inference IDs: {inference_ids}. Reason: {error}\"\n        )\n        return (\n            True,\n            f\"Error while custom metadata registration. Error type: {type(error)}. Details: {error}\",\n        )\n",
    "patch": null
  },
  {
    "trace_id": "57b7ceaa-0a7d-4908-b833-78b7e2c8bf72",
    "function_name": "BlockManifest.get_air_gapped_availability",
    "file_path": "inference/core/workflows/core_steps/models/foundation/lmm/v1.py",
    "speedup_x": 0.12274193093841465,
    "review_quality": "medium",
    "pre_optimization_commit": "835af61109f8cab1d2cb51cf93d061ef3a4c5fc7",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def get_air_gapped_availability(cls) -> dict:\n        return {\"available\": False, \"reason\": \"requires_internet\"}\n",
    "optimized_function_code": "from typing import Literal\n\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\nfrom pydantic import BaseModel, Field\n\n\nclass LMMConfig(BaseModel):\n    max_tokens: int = Field(default=450)\n    gpt_image_detail: Literal[\"low\", \"high\", \"auto\"] = Field(\n        default=\"auto\",\n        description=\"To be used for GPT-4V only.\",\n    )\n    gpt_model_version: str = Field(default=\"gpt-4o\")\n\n\nLONG_DESCRIPTION = \"\"\"\nAsk a question to a Large Multimodal Model (LMM) with an image and text.\n\nYou can specify arbitrary text prompts to an LMMBlock.\n\nThe LLMBlock supports two LMMs:\n\n- OpenAI's GPT-4 with Vision;\n\nYou need to provide your OpenAI API key to use the GPT-4 with Vision model. \n\n_If you want to classify an image into one or more categories, we recommend using the \ndedicated LMMForClassificationBlock._\n\"\"\"\n\n\n\n# Pre-created template for availability to avoid reconstructing the literal dict on every call.\n_AIR_GAPPED_AVAILABILITY: dict = {\"available\": False, \"reason\": \"requires_internet\"}\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_air_gapped_availability(cls) -> dict:\n        return _AIR_GAPPED_AVAILABILITY.copy()",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/models/foundation/lmm/v1.py\nfrom typing import Literal\n\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\nfrom pydantic import BaseModel, Field\n\n\nclass LMMConfig(BaseModel):\n    max_tokens: int = Field(default=450)\n    gpt_image_detail: Literal[\"low\", \"high\", \"auto\"] = Field(\n        default=\"auto\",\n        description=\"To be used for GPT-4V only.\",\n    )\n    gpt_model_version: str = Field(default=\"gpt-4o\")\n\n\nLONG_DESCRIPTION = \"\"\"\nAsk a question to a Large Multimodal Model (LMM) with an image and text.\n\nYou can specify arbitrary text prompts to an LMMBlock.\n\nThe LLMBlock supports two LMMs:\n\n- OpenAI's GPT-4 with Vision;\n\nYou need to provide your OpenAI API key to use the GPT-4 with Vision model. \n\n_If you want to classify an image into one or more categories, we recommend using the \ndedicated LMMForClassificationBlock._\n\"\"\"\n\n\n\n# Pre-created template for availability to avoid reconstructing the literal dict on every call.\n_AIR_GAPPED_AVAILABILITY: dict = {\"available\": False, \"reason\": \"requires_internet\"}\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_air_gapped_availability(cls) -> dict:\n        return _AIR_GAPPED_AVAILABILITY.copy()\n```",
    "optimized_function_only": "    def get_air_gapped_availability(cls) -> dict:\n        return _AIR_GAPPED_AVAILABILITY.copy()",
    "original_file_content": "import base64\nimport json\nimport re\nfrom functools import partial\nfrom typing import Any, Dict, List, Literal, Optional, Type, Union\n\nfrom openai import OpenAI\nfrom pydantic import BaseModel, ConfigDict, Field\n\nfrom inference.core.env import (\n    LOCAL_INFERENCE_API_URL,\n    WORKFLOWS_REMOTE_API_TARGET,\n    WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS,\n)\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.utils.image_utils import encode_image_to_jpeg_bytes, load_image\nfrom inference.core.workflows.core_steps.common.entities import StepExecutionMode\nfrom inference.core.workflows.core_steps.common.utils import (\n    load_core_model,\n    run_in_parallel,\n)\nfrom inference.core.workflows.execution_engine.constants import (\n    PARENT_ID_KEY,\n    ROOT_PARENT_ID_KEY,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    DICTIONARY_KIND,\n    IMAGE_KIND,\n    IMAGE_METADATA_KIND,\n    PARENT_ID_KIND,\n    SECRET_KIND,\n    STRING_KIND,\n    WILDCARD_KIND,\n    ImageInputField,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\nfrom inference_sdk import InferenceHTTPClient\n\nGPT_4V_MODEL_TYPE = \"gpt_4v\"\nNOT_DETECTED_VALUE = \"not_detected\"\n\nJSON_MARKDOWN_BLOCK_PATTERN = re.compile(r\"```json\\n([\\s\\S]*?)\\n```\")\n\n\nclass LMMConfig(BaseModel):\n    max_tokens: int = Field(default=450)\n    gpt_image_detail: Literal[\"low\", \"high\", \"auto\"] = Field(\n        default=\"auto\",\n        description=\"To be used for GPT-4V only.\",\n    )\n    gpt_model_version: str = Field(default=\"gpt-4o\")\n\n\nLONG_DESCRIPTION = \"\"\"\nAsk a question to a Large Multimodal Model (LMM) with an image and text.\n\nYou can specify arbitrary text prompts to an LMMBlock.\n\nThe LLMBlock supports two LMMs:\n\n- OpenAI's GPT-4 with Vision;\n\nYou need to provide your OpenAI API key to use the GPT-4 with Vision model. \n\n_If you want to classify an image into one or more categories, we recommend using the \ndedicated LMMForClassificationBlock._\n\"\"\"\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"LMM\",\n            \"version\": \"v1\",\n            \"short_description\": \"Run a large multimodal model such as ChatGPT-4v.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"model\",\n            \"deprecated\": True,\n            \"ui_manifest\": {\n                \"section\": \"model\",\n                \"icon\": \"far fa-chart-network\",\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/lmm@v1\", \"LMM\"]\n    images: Selector(kind=[IMAGE_KIND]) = ImageInputField\n    prompt: Union[Selector(kind=[STRING_KIND]), str] = Field(\n        description=\"Holds unconstrained text prompt to LMM mode\",\n        examples=[\"my prompt\", \"$inputs.prompt\"],\n        json_schema_extra={\n            \"multiline\": True,\n        },\n    )\n    lmm_type: Union[Selector(kind=[STRING_KIND]), Literal[\"gpt_4v\"]] = Field(\n        description=\"Type of LMM to be used\", examples=[\"gpt_4v\", \"$inputs.lmm_type\"]\n    )\n    lmm_config: LMMConfig = Field(\n        default_factory=lambda: LMMConfig(),\n        description=\"Configuration of LMM\",\n        examples=[\n            {\n                \"max_tokens\": 200,\n                \"gpt_image_detail\": \"low\",\n                \"gpt_model_version\": \"gpt-4o\",\n            }\n        ],\n    )\n    remote_api_key: Union[Selector(kind=[STRING_KIND, SECRET_KIND]), Optional[str]] = (\n        Field(\n            default=None,\n            description=\"Holds API key required to call LMM model - in current state of development, we require OpenAI key when `lmm_type=gpt_4v`.\",\n            examples=[\"xxx-xxx\", \"$inputs.api_key\"],\n            private=True,\n        )\n    )\n    json_output: Optional[Dict[str, str]] = Field(\n        default=None,\n        description=\"Holds dictionary that maps name of requested output field into its description\",\n        examples=[{\"count\": \"number of cats in the picture\"}, \"$inputs.json_output\"],\n    )\n\n    @classmethod\n    def get_air_gapped_availability(cls) -> dict:\n        return {\"available\": False, \"reason\": \"requires_internet\"}\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return [\"images\"]\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"parent_id\", kind=[PARENT_ID_KIND]),\n            OutputDefinition(name=\"root_parent_id\", kind=[PARENT_ID_KIND]),\n            OutputDefinition(name=\"image\", kind=[IMAGE_METADATA_KIND]),\n            OutputDefinition(name=\"structured_output\", kind=[DICTIONARY_KIND]),\n            OutputDefinition(name=\"raw_output\", kind=[STRING_KIND]),\n            OutputDefinition(name=\"*\", kind=[WILDCARD_KIND]),\n        ]\n\n    def get_actual_outputs(self) -> List[OutputDefinition]:\n        result = [\n            OutputDefinition(name=\"parent_id\", kind=[PARENT_ID_KIND]),\n            OutputDefinition(name=\"root_parent_id\", kind=[PARENT_ID_KIND]),\n            OutputDefinition(name=\"image\", kind=[IMAGE_METADATA_KIND]),\n            OutputDefinition(name=\"structured_output\", kind=[DICTIONARY_KIND]),\n            OutputDefinition(name=\"raw_output\", kind=[STRING_KIND]),\n        ]\n        if self.json_output is None:\n            return result\n        for key in self.json_output.keys():\n            result.append(OutputDefinition(name=key, kind=[WILDCARD_KIND]))\n        return result\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.4.0,<2.0.0\"\n\n\nclass LMMBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"model_manager\", \"api_key\", \"step_execution_mode\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        prompt: str,\n        lmm_type: str,\n        lmm_config: LMMConfig,\n        remote_api_key: Optional[str],\n        json_output: Optional[Dict[str, str]],\n    ) -> BlockResult:\n        if self._step_execution_mode is StepExecutionMode.LOCAL:\n            return self.run_locally(\n                images=images,\n                prompt=prompt,\n                lmm_type=lmm_type,\n                lmm_config=lmm_config,\n                remote_api_key=remote_api_key,\n                json_output=json_output,\n            )\n        elif self._step_execution_mode is StepExecutionMode.REMOTE:\n            return self.run_remotely(\n                images=images,\n                prompt=prompt,\n                lmm_type=lmm_type,\n                lmm_config=lmm_config,\n                remote_api_key=remote_api_key,\n                json_output=json_output,\n            )\n        else:\n            raise ValueError(\n                f\"Unknown step execution mode: {self._step_execution_mode}\"\n            )\n\n    def run_locally(\n        self,\n        images: Batch[WorkflowImageData],\n        prompt: str,\n        lmm_type: str,\n        lmm_config: LMMConfig,\n        remote_api_key: Optional[str],\n        json_output: Optional[Dict[str, str]],\n    ) -> BlockResult:\n        if json_output:\n            prompt = (\n                f\"{prompt}\\n\\nVALID response format is JSON:\\n\"\n                f\"{json.dumps(json_output, indent=4)}\"\n            )\n        images_prepared_for_processing = [\n            image.to_inference_format(numpy_preferred=True) for image in images\n        ]\n        if lmm_type == GPT_4V_MODEL_TYPE:\n            raw_output = run_gpt_4v_llm_prompting(\n                image=images_prepared_for_processing,\n                prompt=prompt,\n                remote_api_key=remote_api_key,\n                lmm_config=lmm_config,\n            )\n        else:\n            raise ValueError(f\"CogVLM has been removed from the Roboflow Core Models.\")\n        structured_output = turn_raw_lmm_output_into_structured(\n            raw_output=raw_output,\n            expected_output=json_output,\n        )\n        predictions = [\n            {\n                \"raw_output\": raw[\"content\"],\n                \"image\": raw[\"image\"],\n                \"structured_output\": structured,\n                **structured,\n            }\n            for raw, structured in zip(raw_output, structured_output)\n        ]\n        for prediction, image in zip(predictions, images):\n            prediction[PARENT_ID_KEY] = image.parent_metadata.parent_id\n            prediction[ROOT_PARENT_ID_KEY] = (\n                image.workflow_root_ancestor_metadata.parent_id\n            )\n        return predictions\n\n    def run_remotely(\n        self,\n        images: Batch[WorkflowImageData],\n        prompt: str,\n        lmm_type: str,\n        lmm_config: LMMConfig,\n        remote_api_key: Optional[str],\n        json_output: Optional[Dict[str, str]],\n    ) -> BlockResult:\n        if json_output:\n            prompt = (\n                f\"{prompt}\\n\\nVALID response format is JSON:\\n\"\n                f\"{json.dumps(json_output, indent=4)}\"\n            )\n        inference_images = [i.to_inference_format() for i in images]\n        if lmm_type == GPT_4V_MODEL_TYPE:\n            raw_output = run_gpt_4v_llm_prompting(\n                image=inference_images,\n                prompt=prompt,\n                remote_api_key=remote_api_key,\n                lmm_config=lmm_config,\n            )\n        else:\n            raise ValueError(f\"CogVLM has been removed from the Roboflow Core Models.\")\n        structured_output = turn_raw_lmm_output_into_structured(\n            raw_output=raw_output,\n            expected_output=json_output,\n        )\n        predictions = [\n            {\n                \"raw_output\": raw[\"content\"],\n                \"image\": raw[\"image\"],\n                \"structured_output\": structured,\n                **structured,\n            }\n            for raw, structured in zip(raw_output, structured_output)\n        ]\n        for prediction, image in zip(predictions, images):\n            prediction[PARENT_ID_KEY] = image.parent_metadata.parent_id\n            prediction[ROOT_PARENT_ID_KEY] = (\n                image.workflow_root_ancestor_metadata.parent_id\n            )\n        return predictions\n\n\ndef run_gpt_4v_llm_prompting(\n    image: List[Dict[str, Any]],\n    prompt: str,\n    remote_api_key: Optional[str],\n    lmm_config: LMMConfig,\n) -> List[Dict[str, str]]:\n    if remote_api_key is None:\n        raise ValueError(\n            \"Step that involves GPT-4V prompting requires OpenAI API key which was not provided.\"\n        )\n    return execute_gpt_4v_requests(\n        image=image,\n        remote_api_key=remote_api_key,\n        prompt=prompt,\n        lmm_config=lmm_config,\n    )\n\n\ndef execute_gpt_4v_requests(\n    image: List[dict],\n    remote_api_key: str,\n    prompt: str,\n    lmm_config: LMMConfig,\n) -> List[Dict[str, str]]:\n    client = OpenAI(api_key=remote_api_key)\n    tasks = [\n        partial(\n            execute_gpt_4v_request,\n            client=client,\n            image=single_image,\n            prompt=prompt,\n            lmm_config=lmm_config,\n        )\n        for single_image in image\n    ]\n    return run_in_parallel(\n        tasks=tasks,\n        max_workers=WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS,\n    )\n\n\ndef execute_gpt_4v_request(\n    client: OpenAI,\n    image: Dict[str, Any],\n    prompt: str,\n    lmm_config: LMMConfig,\n) -> Dict[str, str]:\n    loaded_image, _ = load_image(image)\n    image_metadata = {\"width\": loaded_image.shape[1], \"height\": loaded_image.shape[0]}\n    base64_image = base64.b64encode(encode_image_to_jpeg_bytes(loaded_image)).decode(\n        \"ascii\"\n    )\n    response = client.chat.completions.create(\n        model=lmm_config.gpt_model_version,\n        messages=[\n            {\n                \"role\": \"user\",\n                \"content\": [\n                    {\"type\": \"text\", \"text\": prompt},\n                    {\n                        \"type\": \"image_url\",\n                        \"image_url\": {\n                            \"url\": f\"data:image/jpeg;base64,{base64_image}\",\n                            \"detail\": lmm_config.gpt_image_detail,\n                        },\n                    },\n                ],\n            }\n        ],\n        max_tokens=lmm_config.max_tokens,\n    )\n    return {\"content\": response.choices[0].message.content, \"image\": image_metadata}\n\n\ndef turn_raw_lmm_output_into_structured(\n    raw_output: List[Dict[str, Any]],\n    expected_output: Optional[Dict[str, str]],\n) -> List[dict]:\n    if expected_output is None:\n        return [{} for _ in range(len(raw_output))]\n    return [\n        try_parse_lmm_output_to_json(\n            output=r[\"content\"],\n            expected_output=expected_output,\n        )\n        for r in raw_output\n    ]\n\n\ndef try_parse_lmm_output_to_json(\n    output: str, expected_output: Dict[str, str]\n) -> Union[list, dict]:\n    json_blocks_found = JSON_MARKDOWN_BLOCK_PATTERN.findall(output)\n    if len(json_blocks_found) == 0:\n        return try_parse_json(output, expected_output=expected_output)\n    result = []\n    for json_block in json_blocks_found:\n        result.append(\n            try_parse_json(content=json_block, expected_output=expected_output)\n        )\n    return result if len(result) > 1 else result[0]\n\n\ndef try_parse_json(content: str, expected_output: Dict[str, str]) -> dict:\n    try:\n        data = json.loads(content)\n        return {key: data.get(key, NOT_DETECTED_VALUE) for key in expected_output}\n    except Exception:\n        return {key: NOT_DETECTED_VALUE for key in expected_output}\n",
    "patch": null
  },
  {
    "trace_id": "d30df3b9-4142-4a1e-9bff-96aaa882cd95",
    "function_name": "BlockManifest.get_required_cache_artifacts",
    "file_path": "inference/core/workflows/core_steps/models/foundation/clip_comparison/v2.py",
    "speedup_x": 1.04402072135613,
    "review_quality": "high",
    "pre_optimization_commit": "8b77ac4621cef9f731ed9fd25bd10e49372f20ac",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def get_required_cache_artifacts(cls) -> list:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        from inference.core.workflows.core_steps.models.foundation.clip.v1 import (\n            CLIP_CACHE_MODEL_IDS,\n        )\n\n        return list(CLIP_CACHE_MODEL_IDS)\n",
    "optimized_function_code": "from importlib import import_module\n\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nLONG_DESCRIPTION = \"\"\"\nUse the OpenAI CLIP zero-shot classification model to classify images.\n\nThis block accepts an image and a list of text prompts. The block then returns the \nsimilarity of each text label to the provided image.\n\nThis block is useful for classifying images without having to train a fine-tuned \nclassification model. For example, you could use CLIP to classify the type of vehicle \nin an image, or if an image contains NSFW material.\n\"\"\"\n\n\n\n# Cache the module object to avoid repeated name-binding imports while still\n# observing any runtime changes to the module's attributes.\n_clip_v1_module = None\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_required_cache_artifacts(cls) -> list:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        global _clip_v1_module\n        if _clip_v1_module is None:\n            # Import the module object once (lazy) and reuse it on subsequent calls.\n            # This preserves behavior (ImportError when the module is unavailable)\n            # while avoiding the repeated overhead of \"from ... import name\" each call.\n            _clip_v1_module = import_module(\n                \"inference.core.workflows.core_steps.models.foundation.clip.v1\"\n            )\n\n        return list(_clip_v1_module.CLIP_CACHE_MODEL_IDS)",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/models/foundation/clip_comparison/v2.py\nfrom importlib import import_module\n\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nLONG_DESCRIPTION = \"\"\"\nUse the OpenAI CLIP zero-shot classification model to classify images.\n\nThis block accepts an image and a list of text prompts. The block then returns the \nsimilarity of each text label to the provided image.\n\nThis block is useful for classifying images without having to train a fine-tuned \nclassification model. For example, you could use CLIP to classify the type of vehicle \nin an image, or if an image contains NSFW material.\n\"\"\"\n\n\n\n# Cache the module object to avoid repeated name-binding imports while still\n# observing any runtime changes to the module's attributes.\n_clip_v1_module = None\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_required_cache_artifacts(cls) -> list:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        global _clip_v1_module\n        if _clip_v1_module is None:\n            # Import the module object once (lazy) and reuse it on subsequent calls.\n            # This preserves behavior (ImportError when the module is unavailable)\n            # while avoiding the repeated overhead of \"from ... import name\" each call.\n            _clip_v1_module = import_module(\n                \"inference.core.workflows.core_steps.models.foundation.clip.v1\"\n            )\n\n        return list(_clip_v1_module.CLIP_CACHE_MODEL_IDS)\n```",
    "optimized_function_only": "    def get_required_cache_artifacts(cls) -> list:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        global _clip_v1_module\n        if _clip_v1_module is None:\n            # Import the module object once (lazy) and reuse it on subsequent calls.\n            # This preserves behavior (ImportError when the module is unavailable)\n            # while avoiding the repeated overhead of \"from ... import name\" each call.\n            _clip_v1_module = import_module(\n                \"inference.core.workflows.core_steps.models.foundation.clip.v1\"\n            )\n\n        return list(_clip_v1_module.CLIP_CACHE_MODEL_IDS)",
    "original_file_content": "from functools import partial\nfrom typing import List, Literal, Optional, Type, Union\n\nimport numpy as np\nfrom pydantic import ConfigDict, Field\n\nfrom inference.core.entities.requests.clip import ClipCompareRequest\nfrom inference.core.env import (\n    HOSTED_CORE_MODEL_URL,\n    LOCAL_INFERENCE_API_URL,\n    WORKFLOWS_REMOTE_API_TARGET,\n    WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS,\n)\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.entities import StepExecutionMode\nfrom inference.core.workflows.core_steps.common.utils import (\n    load_core_model,\n    run_in_parallel,\n)\nfrom inference.core.workflows.execution_engine.constants import (\n    PARENT_ID_KEY,\n    ROOT_PARENT_ID_KEY,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    CLASSIFICATION_PREDICTION_KIND,\n    FLOAT_ZERO_TO_ONE_KIND,\n    IMAGE_KIND,\n    LIST_OF_VALUES_KIND,\n    PARENT_ID_KIND,\n    STRING_KIND,\n    ImageInputField,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\nfrom inference_sdk import InferenceHTTPClient\n\nLONG_DESCRIPTION = \"\"\"\nUse the OpenAI CLIP zero-shot classification model to classify images.\n\nThis block accepts an image and a list of text prompts. The block then returns the \nsimilarity of each text label to the provided image.\n\nThis block is useful for classifying images without having to train a fine-tuned \nclassification model. For example, you could use CLIP to classify the type of vehicle \nin an image, or if an image contains NSFW material.\n\"\"\"\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Clip Comparison\",\n            \"version\": \"v2\",\n            \"short_description\": \"Compare CLIP image and text embeddings.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"model\",\n            \"ui_manifest\": {\n                \"section\": \"model\",\n                \"icon\": \"fak fa-message-image\",\n                \"blockPriority\": 10,\n                \"inference\": True,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/clip_comparison@v2\"]\n    name: str = Field(description=\"Unique name of step in workflows\")\n    images: Selector(kind=[IMAGE_KIND]) = ImageInputField\n    classes: Union[Selector(kind=[LIST_OF_VALUES_KIND]), List[str]] = Field(\n        description=\"List of classes to calculate similarity against each input image\",\n        examples=[[\"a\", \"b\", \"c\"], \"$inputs.texts\"],\n        min_items=1,\n    )\n    version: Union[\n        Literal[\n            \"RN101\",\n            \"RN50\",\n            \"RN50x16\",\n            \"RN50x4\",\n            \"RN50x64\",\n            \"ViT-B-16\",\n            \"ViT-B-32\",\n            \"ViT-L-14-336px\",\n            \"ViT-L-14\",\n        ],\n        Selector(kind=[STRING_KIND]),\n    ] = Field(\n        default=\"ViT-B-16\",\n        description=\"Variant of CLIP model\",\n        examples=[\"ViT-B-16\", \"$inputs.variant\"],\n    )\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return [\"images\"]\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"similarities\", kind=[LIST_OF_VALUES_KIND]),\n            OutputDefinition(name=\"max_similarity\", kind=[FLOAT_ZERO_TO_ONE_KIND]),\n            OutputDefinition(name=\"most_similar_class\", kind=[STRING_KIND]),\n            OutputDefinition(name=\"min_similarity\", kind=[FLOAT_ZERO_TO_ONE_KIND]),\n            OutputDefinition(name=\"least_similar_class\", kind=[STRING_KIND]),\n            OutputDefinition(\n                name=\"classification_predictions\",\n                kind=[CLASSIFICATION_PREDICTION_KIND],\n            ),\n            OutputDefinition(name=\"parent_id\", kind=[PARENT_ID_KIND]),\n            OutputDefinition(name=\"root_parent_id\", kind=[PARENT_ID_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n    @classmethod\n    def get_required_cache_artifacts(cls) -> list:\n        \"\"\"Return list of model_id variants that can satisfy this block.\"\"\"\n        from inference.core.workflows.core_steps.models.foundation.clip.v1 import (\n            CLIP_CACHE_MODEL_IDS,\n        )\n\n        return list(CLIP_CACHE_MODEL_IDS)\n\n\nclass ClipComparisonBlockV2(WorkflowBlock):\n\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"model_manager\", \"api_key\", \"step_execution_mode\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        classes: List[str],\n        version: str,\n    ) -> BlockResult:\n        if self._step_execution_mode is StepExecutionMode.LOCAL:\n            return self.run_locally(images=images, classes=classes, version=version)\n        elif self._step_execution_mode is StepExecutionMode.REMOTE:\n            return self.run_remotely(images=images, classes=classes, version=version)\n        else:\n            raise ValueError(\n                f\"Unknown step execution mode: {self._step_execution_mode}\"\n            )\n\n    def run_locally(\n        self,\n        images: Batch[WorkflowImageData],\n        classes: List[str],\n        version: str,\n    ) -> BlockResult:\n        predictions = []\n        for single_image in images:\n            inference_request = ClipCompareRequest(\n                clip_version_id=version,\n                subject=single_image.to_inference_format(numpy_preferred=True),\n                subject_type=\"image\",\n                prompt=classes,\n                prompt_type=\"text\",\n                api_key=self._api_key,\n            )\n            clip_model_id = load_core_model(\n                model_manager=self._model_manager,\n                inference_request=inference_request,\n                core_model=\"clip\",\n            )\n            prediction = self._model_manager.infer_from_request_sync(\n                clip_model_id, inference_request\n            )\n            predictions.append(prediction.model_dump())\n        return self._post_process_result(\n            images=images,\n            predictions=predictions,\n            classes=classes,\n        )\n\n    def run_remotely(\n        self,\n        images: Batch[WorkflowImageData],\n        classes: List[str],\n        version: str,\n    ) -> BlockResult:\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_CORE_MODEL_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        if WORKFLOWS_REMOTE_API_TARGET == \"hosted\":\n            client.select_api_v0()\n        tasks = [\n            partial(\n                client.clip_compare,\n                subject=single_image.base64_image,\n                prompt=classes,\n                clip_version=version,\n            )\n            for single_image in images\n        ]\n        predictions = run_in_parallel(\n            tasks=tasks,\n            max_workers=WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS,\n        )\n        return self._post_process_result(\n            images=images,\n            predictions=predictions,\n            classes=classes,\n        )\n\n    def _post_process_result(\n        self,\n        images: Batch[WorkflowImageData],\n        predictions: List[dict],\n        classes: List[str],\n    ) -> List[dict]:\n        results = []\n        for prediction, image in zip(predictions, images):\n            similarities = prediction[\"similarity\"]\n            max_similarity = np.max(similarities)\n            max_similarity_id = np.argmax(similarities)\n            min_similarity = np.min(similarities)\n            min_similarity_id = np.argmin(similarities)\n            most_similar_class_name = classes[max_similarity_id]\n            least_similar_class_name = classes[min_similarity_id]\n            prediction[PARENT_ID_KEY] = image.parent_metadata.parent_id\n            prediction[ROOT_PARENT_ID_KEY] = (\n                image.workflow_root_ancestor_metadata.parent_id\n            )\n            classification_predictions = {\n                \"predictions\": [\n                    {\n                        \"class\": class_name,\n                        \"class_id\": class_id,\n                        \"confidence\": confidence,\n                    }\n                    for class_id, (class_name, confidence) in enumerate(\n                        zip(classes, similarities)\n                    )\n                ],\n                \"top\": most_similar_class_name,\n                \"confidence\": max_similarity,\n                \"parent_id\": image.parent_metadata.parent_id,\n            }\n            result = {\n                PARENT_ID_KEY: image.parent_metadata.parent_id,\n                ROOT_PARENT_ID_KEY: image.workflow_root_ancestor_metadata.parent_id,\n                \"similarities\": similarities,\n                \"max_similarity\": max_similarity,\n                \"most_similar_class\": most_similar_class_name,\n                \"min_similarity\": min_similarity,\n                \"least_similar_class\": least_similar_class_name,\n                \"classification_predictions\": classification_predictions,\n            }\n            results.append(result)\n        return results\n",
    "patch": null
  },
  {
    "trace_id": "c150e8d4-55ba-4bba-b4ef-5d7e64b150ed",
    "function_name": "get_cached_models",
    "file_path": "inference/core/interfaces/http/builder/routes.py",
    "speedup_x": 0.8027776299784183,
    "review_quality": "medium",
    "pre_optimization_commit": "82e5d4ab4f32a8ddc47bc41bae39f096fc461350",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "async def get_cached_models():\n    \"\"\"Return all models available in the local cache.\n\n    Combines user-trained models discovered via ``model_type.json`` markers\n    with foundation-model blocks whose weights are fully cached.\n    Results are cached for 30 seconds to avoid repeated filesystem scans.\n    \"\"\"\n    global _models_cache  # noqa: PLW0603\n\n    async with _models_lock:\n        now = time.time()\n        if _models_cache is not None:\n            cached_at, cached_result = _models_cache\n            if now - cached_at < _MODELS_CACHE_TTL:\n                return JSONResponse(content={\"models\": cached_result})\n\n        # Inline import: inference.models.aliases transitively imports the\n        # inference_models package which may not be installed when\n        # ENABLE_BUILDER=False.  Keeping the import lazy avoids breaking\n        # the server for non-builder users.\n        from inference.models.aliases import REGISTERED_ALIASES\n\n        # Build reverse alias map: canonical_id \u2192 [alias1, alias2, ...]\n        reverse_aliases: Dict[str, List[str]] = {}\n        for alias, canonical in REGISTERED_ALIASES.items():\n            reverse_aliases.setdefault(canonical, []).append(alias)\n\n        # Load blocks once and pass to both helpers to avoid triple-loading.\n        try:\n            blocks = _load_blocks()\n        except Exception:\n            blocks = []\n\n        # Scan the filesystem for cached models.\n        user_models = scan_cached_models(MODEL_CACHE_DIR)\n        foundation_models = get_cached_foundation_models(blocks=blocks)\n\n        # De-duplicate by model_id (foundation models take precedence).\n        seen: Dict[str, Dict[str, Any]] = {}\n        for m in user_models:\n            seen[m[\"model_id\"]] = m\n        for m in foundation_models:\n            seen[m[\"model_id\"]] = m\n\n        # Enrich each model with compatible block types and aliases.\n        task_to_blocks = get_task_type_to_block_mapping(blocks=blocks)\n        models = []\n        for m in seen.values():\n            entry = dict(m)\n            # For foundation models, use block_type for compatible_block_types\n            # since they have empty task_type.\n            block_type = entry.get(\"block_type\")\n            if block_type:\n                entry.setdefault(\"compatible_block_types\", [block_type])\n            else:\n                entry.setdefault(\n                    \"compatible_block_types\",\n                    task_to_blocks.get(m.get(\"task_type\", \"\"), []),\n                )\n            # Add known aliases for this model\n            model_id = m.get(\"model_id\", \"\")\n            aliases = reverse_aliases.get(model_id, [])\n            entry[\"aliases\"] = aliases\n            # Use the shortest alias as display name if available\n            if aliases and (entry.get(\"name\") == model_id or not entry.get(\"name\")):\n                entry[\"name\"] = min(aliases, key=len)\n            # Remove internal-only keys.\n            entry.pop(\"block_type\", None)\n            models.append(entry)\n\n        _models_cache = (now, models)\n\n    return JSONResponse(content={\"models\": models})\n",
    "optimized_function_code": "import json\nimport logging\nimport os\nfrom typing import Any, Dict, List, Optional\n\nfrom inference.core.roboflow_api import MODEL_TYPE_KEY, PROJECT_TASK_TYPE_KEY\n\nlogger = logging.getLogger(__name__)\n\n# Directories directly under MODEL_CACHE_DIR that are not model trees.\n_SKIP_TOP_LEVEL = {\"workflow\", \"_file_locks\"}\n\n\n\n# Cache for loaded blocks to avoid repeatedly performing the heavy import/load.\n# Caching preserves the returned list object (as the original implementation\n# returned the same list per call) and avoids repeated expensive imports.\n_BLOCKS_CACHE: Optional[List[Any]] = None\n\n# Cache mapping block.identifier -> block_type identifier string to avoid\n# repeatedly calling model_json_schema() for the same block.\n_BLOCK_TYPE_ID_CACHE: Dict[str, str] = {}\n\n\ndef _load_blocks() -> list:\n    \"\"\"Load workflow blocks, isolating the heavy import for testability.\"\"\"\n    global _BLOCKS_CACHE  # reuse cached blocks across calls to avoid heavy import\n    if _BLOCKS_CACHE is not None:\n        return _BLOCKS_CACHE\n\n    from inference.core.workflows.execution_engine.introspection.blocks_loader import \\\n        load_workflow_blocks\n\n    # If load_workflow_blocks raises, do not set the cache so future calls\n    # will propagate the exception similarly to the original behaviour.\n    blocks = load_workflow_blocks()\n    _BLOCKS_CACHE = blocks\n    return blocks\n\n\n\n\ndef scan_cached_models(cache_dir: str) -> List[Dict[str, Any]]:\n    \"\"\"Walk *cache_dir* looking for ``model_type.json`` marker files.\n\n    Each marker is written by the model registry when a model is first\n    downloaded.  The file contains at least ``project_task_type`` and\n    ``model_type`` keys.\n\n    Returns a list of dicts with the following shape::\n\n        {\n            \"model_id\": \"workspace/project/3\",\n            \"name\": \"workspace/project/3\",\n            \"task_type\": \"object-detection\",\n            \"model_architecture\": \"yolov8n\",\n            \"is_foundation\": False,\n        }\n    \"\"\"\n    results: List[Dict[str, Any]] = []\n    if not os.path.isdir(cache_dir):\n        return results\n\n    for root, dirs, files in os.walk(cache_dir):\n        # Prune top-level directories we know are not model trees.\n        rel = os.path.relpath(root, cache_dir)\n        if rel == \".\":\n            dirs[:] = [d for d in dirs if d not in _SKIP_TOP_LEVEL]\n            continue\n\n        if \"model_type.json\" not in files:\n            continue\n\n        model_type_path = os.path.join(root, \"model_type.json\")\n        try:\n            with open(model_type_path, \"r\") as fh:\n                metadata = json.load(fh)\n        except (json.JSONDecodeError, OSError) as exc:\n            logger.warning(\n                \"Skipping unreadable model_type.json at %s: %s\",\n                model_type_path,\n                exc,\n            )\n            continue\n\n        if not isinstance(metadata, dict):\n            continue\n\n        # Support both traditional keys and inference-models metadata keys.\n        task_type = metadata.get(PROJECT_TASK_TYPE_KEY) or metadata.get(\"taskType\", \"\")\n        model_architecture = metadata.get(MODEL_TYPE_KEY) or metadata.get(\n            \"modelArchitecture\", \"\"\n        )\n\n        if not task_type:\n            continue\n\n        model_id = os.path.relpath(root, cache_dir)\n        # Normalise path separators on Windows.\n        model_id = model_id.replace(os.sep, \"/\")\n\n        results.append(\n            {\n                \"model_id\": model_id,\n                \"name\": model_id,\n                \"task_type\": task_type,\n                \"model_architecture\": model_architecture,\n                \"is_foundation\": False,\n            }\n        )\n\n    return results\n\n\ndef get_cached_foundation_models(\n    blocks: Optional[list] = None,\n) -> List[Dict[str, Any]]:\n    \"\"\"Return metadata for workflow blocks whose required weights are cached.\n\n    Each block whose manifest class exposes a ``get_required_cache_artifacts``\n    classmethod is inspected.  If every artifact it declares is already present\n    in the local cache the block is included in the result list.\n\n    Blocks that do not expose the classmethod are silently skipped.\n\n    Args:\n        blocks: Optional pre-loaded list of block specifications.  When\n            *None* (the default) the blocks are loaded via the engine's\n            block loader.\n    \"\"\"\n    results: List[Dict[str, Any]] = []\n    if blocks is None:\n        try:\n            blocks = _load_blocks()\n        except Exception:\n            logger.debug(\n                \"Could not load workflow blocks for foundation model scan\",\n                exc_info=True,\n            )\n            return results\n\n    for block in blocks:\n        manifest_cls = block.manifest_class\n        if not hasattr(manifest_cls, \"get_required_cache_artifacts\"):\n            continue\n\n        try:\n            artifacts_spec = manifest_cls.get_required_cache_artifacts()\n        except Exception:\n            logger.debug(\n                \"Error calling get_required_cache_artifacts on %s\",\n                block.identifier,\n                exc_info=True,\n            )\n            continue\n\n        if not is_block_cached(artifacts_spec):\n            continue\n\n        # Derive a representative model_id for the result entry.\n        if isinstance(artifacts_spec, list):\n            model_id = artifacts_spec[0] if artifacts_spec else \"\"\n        elif isinstance(artifacts_spec, dict):\n            model_id = artifacts_spec.get(\"model_id\", \"\")\n        else:\n            continue\n\n        # Derive name from the block's manifest schema (json_schema_extra)\n        # rather than requiring it in the artifacts dict.\n        block_name = model_id\n        try:\n            schema = manifest_cls.model_json_schema()\n            block_name = schema.get(\"name\", model_id)\n        except Exception:\n            pass\n\n        # Use the block type identifier from the manifest's type field.\n        # Cache the result per block identifier to avoid repeated schema parsing.\n        block_id = getattr(block, \"identifier\", None)\n        if block_id is not None and block_id in _BLOCK_TYPE_ID_CACHE:\n            block_type_id = _BLOCK_TYPE_ID_CACHE[block_id]\n        else:\n            block_type_id = _get_block_type_identifier(block)\n            if block_id is not None:\n                _BLOCK_TYPE_ID_CACHE[block_id] = block_type_id\n\n\n        results.append(\n            {\n                \"model_id\": model_id,\n                \"name\": block_name,\n                \"task_type\": \"\",\n                \"model_architecture\": \"\",\n                \"is_foundation\": True,\n                \"block_type\": block_type_id,\n            }\n        )\n\n    return results\n\n\ndef get_task_type_to_block_mapping(\n    blocks: Optional[list] = None,\n) -> Dict[str, List[str]]:\n    \"\"\"Build a reverse mapping from task_type to compatible block type identifiers.\n\n    Uses ``get_compatible_task_types()`` classmethod on block manifests when\n    available.  Blocks that do not expose the classmethod are skipped.\n\n    Args:\n        blocks: Optional pre-loaded list of block specifications.  When\n            *None* (the default) the blocks are loaded via the engine's\n            block loader.\n    \"\"\"\n    mapping: Dict[str, List[str]] = {}\n    if blocks is None:\n        try:\n            blocks = _load_blocks()\n        except Exception:\n            logger.debug(\n                \"Could not load workflow blocks for task-type mapping\",\n                exc_info=True,\n            )\n            return mapping\n\n    for block in blocks:\n        manifest_cls = block.manifest_class\n        if not hasattr(manifest_cls, \"get_compatible_task_types\"):\n            continue\n\n        try:\n            task_types = manifest_cls.get_compatible_task_types()\n        except Exception:\n            logger.debug(\n                \"Error calling get_compatible_task_types on %s\",\n                block.identifier,\n                exc_info=True,\n            )\n            continue\n\n        if not isinstance(task_types, (list, tuple, set)):\n            continue\n\n        # Derive the manifest type identifier\n        # (e.g. \"roboflow_core/roboflow_object_detection_model@v2\")\n        # from the block schema.\n        block_id = getattr(block, \"identifier\", None)\n        if block_id is not None and block_id in _BLOCK_TYPE_ID_CACHE:\n            block_type_id = _BLOCK_TYPE_ID_CACHE[block_id]\n        else:\n            block_type_id = _get_block_type_identifier(block)\n            if block_id is not None:\n                _BLOCK_TYPE_ID_CACHE[block_id] = block_type_id\n\n\n        for tt in task_types:\n            mapping.setdefault(tt, []).append(block_type_id)\n\n    return mapping",
    "optimized_raw_markdown": "```python:inference/core/cache/air_gapped.py\nimport json\nimport logging\nimport os\nfrom typing import Any, Dict, List, Optional\n\nfrom inference.core.roboflow_api import MODEL_TYPE_KEY, PROJECT_TASK_TYPE_KEY\n\nlogger = logging.getLogger(__name__)\n\n# Directories directly under MODEL_CACHE_DIR that are not model trees.\n_SKIP_TOP_LEVEL = {\"workflow\", \"_file_locks\"}\n\n\n\n# Cache for loaded blocks to avoid repeatedly performing the heavy import/load.\n# Caching preserves the returned list object (as the original implementation\n# returned the same list per call) and avoids repeated expensive imports.\n_BLOCKS_CACHE: Optional[List[Any]] = None\n\n# Cache mapping block.identifier -> block_type identifier string to avoid\n# repeatedly calling model_json_schema() for the same block.\n_BLOCK_TYPE_ID_CACHE: Dict[str, str] = {}\n\n\ndef _load_blocks() -> list:\n    \"\"\"Load workflow blocks, isolating the heavy import for testability.\"\"\"\n    global _BLOCKS_CACHE  # reuse cached blocks across calls to avoid heavy import\n    if _BLOCKS_CACHE is not None:\n        return _BLOCKS_CACHE\n\n    from inference.core.workflows.execution_engine.introspection.blocks_loader import \\\n        load_workflow_blocks\n\n    # If load_workflow_blocks raises, do not set the cache so future calls\n    # will propagate the exception similarly to the original behaviour.\n    blocks = load_workflow_blocks()\n    _BLOCKS_CACHE = blocks\n    return blocks\n\n\n\n\ndef scan_cached_models(cache_dir: str) -> List[Dict[str, Any]]:\n    \"\"\"Walk *cache_dir* looking for ``model_type.json`` marker files.\n\n    Each marker is written by the model registry when a model is first\n    downloaded.  The file contains at least ``project_task_type`` and\n    ``model_type`` keys.\n\n    Returns a list of dicts with the following shape::\n\n        {\n            \"model_id\": \"workspace/project/3\",\n            \"name\": \"workspace/project/3\",\n            \"task_type\": \"object-detection\",\n            \"model_architecture\": \"yolov8n\",\n            \"is_foundation\": False,\n        }\n    \"\"\"\n    results: List[Dict[str, Any]] = []\n    if not os.path.isdir(cache_dir):\n        return results\n\n    for root, dirs, files in os.walk(cache_dir):\n        # Prune top-level directories we know are not model trees.\n        rel = os.path.relpath(root, cache_dir)\n        if rel == \".\":\n            dirs[:] = [d for d in dirs if d not in _SKIP_TOP_LEVEL]\n            continue\n\n        if \"model_type.json\" not in files:\n            continue\n\n        model_type_path = os.path.join(root, \"model_type.json\")\n        try:\n            with open(model_type_path, \"r\") as fh:\n                metadata = json.load(fh)\n        except (json.JSONDecodeError, OSError) as exc:\n            logger.warning(\n                \"Skipping unreadable model_type.json at %s: %s\",\n                model_type_path,\n                exc,\n            )\n            continue\n\n        if not isinstance(metadata, dict):\n            continue\n\n        # Support both traditional keys and inference-models metadata keys.\n        task_type = metadata.get(PROJECT_TASK_TYPE_KEY) or metadata.get(\"taskType\", \"\")\n        model_architecture = metadata.get(MODEL_TYPE_KEY) or metadata.get(\n            \"modelArchitecture\", \"\"\n        )\n\n        if not task_type:\n            continue\n\n        model_id = os.path.relpath(root, cache_dir)\n        # Normalise path separators on Windows.\n        model_id = model_id.replace(os.sep, \"/\")\n\n        results.append(\n            {\n                \"model_id\": model_id,\n                \"name\": model_id,\n                \"task_type\": task_type,\n                \"model_architecture\": model_architecture,\n                \"is_foundation\": False,\n            }\n        )\n\n    return results\n\n\ndef get_cached_foundation_models(\n    blocks: Optional[list] = None,\n) -> List[Dict[str, Any]]:\n    \"\"\"Return metadata for workflow blocks whose required weights are cached.\n\n    Each block whose manifest class exposes a ``get_required_cache_artifacts``\n    classmethod is inspected.  If every artifact it declares is already present\n    in the local cache the block is included in the result list.\n\n    Blocks that do not expose the classmethod are silently skipped.\n\n    Args:\n        blocks: Optional pre-loaded list of block specifications.  When\n            *None* (the default) the blocks are loaded via the engine's\n            block loader.\n    \"\"\"\n    results: List[Dict[str, Any]] = []\n    if blocks is None:\n        try:\n            blocks = _load_blocks()\n        except Exception:\n            logger.debug(\n                \"Could not load workflow blocks for foundation model scan\",\n                exc_info=True,\n            )\n            return results\n\n    for block in blocks:\n        manifest_cls = block.manifest_class\n        if not hasattr(manifest_cls, \"get_required_cache_artifacts\"):\n            continue\n\n        try:\n            artifacts_spec = manifest_cls.get_required_cache_artifacts()\n        except Exception:\n            logger.debug(\n                \"Error calling get_required_cache_artifacts on %s\",\n                block.identifier,\n                exc_info=True,\n            )\n            continue\n\n        if not is_block_cached(artifacts_spec):\n            continue\n\n        # Derive a representative model_id for the result entry.\n        if isinstance(artifacts_spec, list):\n            model_id = artifacts_spec[0] if artifacts_spec else \"\"\n        elif isinstance(artifacts_spec, dict):\n            model_id = artifacts_spec.get(\"model_id\", \"\")\n        else:\n            continue\n\n        # Derive name from the block's manifest schema (json_schema_extra)\n        # rather than requiring it in the artifacts dict.\n        block_name = model_id\n        try:\n            schema = manifest_cls.model_json_schema()\n            block_name = schema.get(\"name\", model_id)\n        except Exception:\n            pass\n\n        # Use the block type identifier from the manifest's type field.\n        # Cache the result per block identifier to avoid repeated schema parsing.\n        block_id = getattr(block, \"identifier\", None)\n        if block_id is not None and block_id in _BLOCK_TYPE_ID_CACHE:\n            block_type_id = _BLOCK_TYPE_ID_CACHE[block_id]\n        else:\n            block_type_id = _get_block_type_identifier(block)\n            if block_id is not None:\n                _BLOCK_TYPE_ID_CACHE[block_id] = block_type_id\n\n\n        results.append(\n            {\n                \"model_id\": model_id,\n                \"name\": block_name,\n                \"task_type\": \"\",\n                \"model_architecture\": \"\",\n                \"is_foundation\": True,\n                \"block_type\": block_type_id,\n            }\n        )\n\n    return results\n\n\ndef get_task_type_to_block_mapping(\n    blocks: Optional[list] = None,\n) -> Dict[str, List[str]]:\n    \"\"\"Build a reverse mapping from task_type to compatible block type identifiers.\n\n    Uses ``get_compatible_task_types()`` classmethod on block manifests when\n    available.  Blocks that do not expose the classmethod are skipped.\n\n    Args:\n        blocks: Optional pre-loaded list of block specifications.  When\n            *None* (the default) the blocks are loaded via the engine's\n            block loader.\n    \"\"\"\n    mapping: Dict[str, List[str]] = {}\n    if blocks is None:\n        try:\n            blocks = _load_blocks()\n        except Exception:\n            logger.debug(\n                \"Could not load workflow blocks for task-type mapping\",\n                exc_info=True,\n            )\n            return mapping\n\n    for block in blocks:\n        manifest_cls = block.manifest_class\n        if not hasattr(manifest_cls, \"get_compatible_task_types\"):\n            continue\n\n        try:\n            task_types = manifest_cls.get_compatible_task_types()\n        except Exception:\n            logger.debug(\n                \"Error calling get_compatible_task_types on %s\",\n                block.identifier,\n                exc_info=True,\n            )\n            continue\n\n        if not isinstance(task_types, (list, tuple, set)):\n            continue\n\n        # Derive the manifest type identifier\n        # (e.g. \"roboflow_core/roboflow_object_detection_model@v2\")\n        # from the block schema.\n        block_id = getattr(block, \"identifier\", None)\n        if block_id is not None and block_id in _BLOCK_TYPE_ID_CACHE:\n            block_type_id = _BLOCK_TYPE_ID_CACHE[block_id]\n        else:\n            block_type_id = _get_block_type_identifier(block)\n            if block_id is not None:\n                _BLOCK_TYPE_ID_CACHE[block_id] = block_type_id\n\n\n        for tt in task_types:\n            mapping.setdefault(tt, []).append(block_type_id)\n\n    return mapping\n```",
    "optimized_function_only": null,
    "original_file_content": "import asyncio\nimport json\nimport logging\nimport os\nimport re\nimport time\nfrom hashlib import sha256\nfrom pathlib import Path\nfrom typing import Any, Dict, List, Optional, Tuple\n\nfrom fastapi import APIRouter, Body, Depends, Header, HTTPException, status\nfrom starlette.responses import HTMLResponse, JSONResponse, RedirectResponse, Response\nfrom starlette.status import HTTP_201_CREATED, HTTP_400_BAD_REQUEST, HTTP_404_NOT_FOUND\n\nfrom inference.core.cache.air_gapped import (\n    _load_blocks,\n    get_cached_foundation_models,\n    get_task_type_to_block_mapping,\n    scan_cached_models,\n)\nfrom inference.core.env import BUILDER_ORIGIN, MODEL_CACHE_DIR\nfrom inference.core.interfaces.http.error_handlers import with_route_exceptions_async\n\nlogger = logging.getLogger(__name__)\n\nworkflow_local_dir = Path(MODEL_CACHE_DIR) / \"workflow\" / \"local\"\nworkflow_local_dir.mkdir(parents=True, exist_ok=True)\n\nrouter = APIRouter()\n\n# ----------------------------------------------------------------\n# Generate or read the \"csrf\" token from disk once per server run\n# ----------------------------------------------------------------\ncsrf_file = workflow_local_dir / \".csrf\"\nif csrf_file.exists():\n    csrf = csrf_file.read_text()\nelse:\n    csrf = os.urandom(16).hex()\n    csrf_file.write_text(csrf)\n\n\n# ----------------------------------------------------------------\n# Dependency to verify the X-CSRF header on any protected route\n# ----------------------------------------------------------------\ndef verify_csrf_token(x_csrf: str = Header(None)):\n    return\n\n\n# ---------------------\n# FRONTEND HTML ROUTES\n# ---------------------\n\n\n@router.get(\n    \"\",\n    summary=\"Workflow Builder List\",\n    description=\"Loads the list of Workflows available for editing\",\n)\n@with_route_exceptions_async\nasync def builder_browse():\n    \"\"\"\n    Loads the main builder UI (editor.html).\n    Injects the CSRF token and BUILDER_ORIGIN\n    so the client can parse them on page load.\n    \"\"\"\n    base_path = Path(__file__).parent\n    file_path = base_path / \"editor.html\"\n    content = file_path.read_text(encoding=\"utf-8\")\n    content = content.replace(\"{{BUILDER_ORIGIN}}\", BUILDER_ORIGIN)\n    content = content.replace(\"{{CSRF}}\", csrf)\n\n    return HTMLResponse(content)\n\n\n@router.get(\"/\", include_in_schema=False)\nasync def builder_redirect():\n    \"\"\"\n    If user hits /build/ with trailing slash, redirect to /build\n    \"\"\"\n    return RedirectResponse(url=\"/build\", status_code=302)\n\n\n@router.get(\n    \"/edit/{workflow_id}\",\n    summary=\"Workflow Builder\",\n    description=\"Loads a specific workflow for editing\",\n)\n@with_route_exceptions_async\nasync def builder_edit(workflow_id: str):\n    \"\"\"\n    Loads a specific workflow for editing.\n\n    Args:\n        workflow_id (str): The ID of the workflow to be edited.\n    \"\"\"\n    base_path = Path(__file__).parent\n    file_path = base_path / \"editor.html\"\n    content = file_path.read_text(encoding=\"utf-8\")\n    content = content.replace(\"{{BUILDER_ORIGIN}}\", BUILDER_ORIGIN)\n    content = content.replace(\"{{CSRF}}\", csrf)\n\n    return HTMLResponse(content)\n\n\n# ----------------------\n# BACKEND JSON API ROUTES\n# ----------------------\n\n\n@router.get(\"/api\", dependencies=[Depends(verify_csrf_token)])\n@with_route_exceptions_async\nasync def get_all_workflows():\n    \"\"\"\n    Returns JSON info about all .json files in {MODEL_CACHE_DIR}/workflow/local.\n    Protected by CSRF token check.\n    \"\"\"\n    data = {}\n    for json_file in workflow_local_dir.glob(\"*.json\"):\n        stat_info = json_file.stat()\n        try:\n            with json_file.open(\"r\", encoding=\"utf-8\") as f:\n                config_contents: Dict[str, Any] = json.load(f)\n        except json.JSONDecodeError as e:\n            logger.error(f\"Error decoding JSON from {json_file}: {e}\")\n            continue\n\n        data[config_contents.get(\"id\", json_file.stem)] = {\n            \"createTime\": {\"_seconds\": int(stat_info.st_ctime)},\n            \"updateTime\": {\"_seconds\": int(stat_info.st_mtime)},\n            \"config\": config_contents,\n        }\n\n    return Response(\n        content=json.dumps({\"data\": data}, indent=4),\n        media_type=\"application/json\",\n        status_code=200,\n    )\n\n\n# ----------------------------------------------------------------\n# Models cache for /build/api/models (TTL-based)\n# IMPORTANT: This route MUST be defined BEFORE /api/{workflow_id}\n# otherwise FastAPI will match \"models\" as a workflow_id.\n# ----------------------------------------------------------------\n_models_cache: Optional[Tuple[float, List[Dict[str, Any]]]] = None\n_MODELS_CACHE_TTL = 30.0  # seconds\n_models_lock = asyncio.Lock()\n\n\n@router.get(\"/api/models\", dependencies=[Depends(verify_csrf_token)])\n@with_route_exceptions_async\nasync def get_cached_models():\n    \"\"\"Return all models available in the local cache.\n\n    Combines user-trained models discovered via ``model_type.json`` markers\n    with foundation-model blocks whose weights are fully cached.\n    Results are cached for 30 seconds to avoid repeated filesystem scans.\n    \"\"\"\n    global _models_cache  # noqa: PLW0603\n\n    async with _models_lock:\n        now = time.time()\n        if _models_cache is not None:\n            cached_at, cached_result = _models_cache\n            if now - cached_at < _MODELS_CACHE_TTL:\n                return JSONResponse(content={\"models\": cached_result})\n\n        # Inline import: inference.models.aliases transitively imports the\n        # inference_models package which may not be installed when\n        # ENABLE_BUILDER=False.  Keeping the import lazy avoids breaking\n        # the server for non-builder users.\n        from inference.models.aliases import REGISTERED_ALIASES\n\n        # Build reverse alias map: canonical_id \u2192 [alias1, alias2, ...]\n        reverse_aliases: Dict[str, List[str]] = {}\n        for alias, canonical in REGISTERED_ALIASES.items():\n            reverse_aliases.setdefault(canonical, []).append(alias)\n\n        # Load blocks once and pass to both helpers to avoid triple-loading.\n        try:\n            blocks = _load_blocks()\n        except Exception:\n            blocks = []\n\n        # Scan the filesystem for cached models.\n        user_models = scan_cached_models(MODEL_CACHE_DIR)\n        foundation_models = get_cached_foundation_models(blocks=blocks)\n\n        # De-duplicate by model_id (foundation models take precedence).\n        seen: Dict[str, Dict[str, Any]] = {}\n        for m in user_models:\n            seen[m[\"model_id\"]] = m\n        for m in foundation_models:\n            seen[m[\"model_id\"]] = m\n\n        # Enrich each model with compatible block types and aliases.\n        task_to_blocks = get_task_type_to_block_mapping(blocks=blocks)\n        models = []\n        for m in seen.values():\n            entry = dict(m)\n            # For foundation models, use block_type for compatible_block_types\n            # since they have empty task_type.\n            block_type = entry.get(\"block_type\")\n            if block_type:\n                entry.setdefault(\"compatible_block_types\", [block_type])\n            else:\n                entry.setdefault(\n                    \"compatible_block_types\",\n                    task_to_blocks.get(m.get(\"task_type\", \"\"), []),\n                )\n            # Add known aliases for this model\n            model_id = m.get(\"model_id\", \"\")\n            aliases = reverse_aliases.get(model_id, [])\n            entry[\"aliases\"] = aliases\n            # Use the shortest alias as display name if available\n            if aliases and (entry.get(\"name\") == model_id or not entry.get(\"name\")):\n                entry[\"name\"] = min(aliases, key=len)\n            # Remove internal-only keys.\n            entry.pop(\"block_type\", None)\n            models.append(entry)\n\n        _models_cache = (now, models)\n\n    return JSONResponse(content={\"models\": models})\n\n\n@router.get(\"/api/{workflow_id}\", dependencies=[Depends(verify_csrf_token)])\n@with_route_exceptions_async\nasync def get_workflow(workflow_id: str):\n    \"\"\"\n    Return JSON for workflow_id.json, or 404 if missing.\n    \"\"\"\n    if not re.match(r\"^[\\w\\-]+$\", workflow_id):\n        return JSONResponse({\"error\": \"invalid id\"}, status_code=HTTP_400_BAD_REQUEST)\n\n    workflow_hash = sha256(workflow_id.encode()).hexdigest()\n    file_path = workflow_local_dir / f\"{workflow_hash}.json\"\n    if not file_path.exists():\n        return JSONResponse({\"error\": \"not found\"}, status_code=HTTP_404_NOT_FOUND)\n\n    stat_info = file_path.stat()\n    try:\n        with file_path.open(\"r\", encoding=\"utf-8\") as f:\n            config_contents = json.load(f)\n    except json.JSONDecodeError as e:\n        logger.error(f\"Error reading JSON for {workflow_id} from '{file_path}': {e}\")\n        return JSONResponse({\"error\": \"invalid JSON\"}, status_code=500)\n\n    return Response(\n        content=json.dumps(\n            {\n                \"data\": {\n                    \"createTime\": int(stat_info.st_ctime),\n                    \"updateTime\": int(stat_info.st_mtime),\n                    \"config\": config_contents,\n                }\n            },\n            indent=4,\n        ),\n        media_type=\"application/json\",\n        status_code=200,\n    )\n\n\n@router.post(\"/api/{workflow_id}\", dependencies=[Depends(verify_csrf_token)])\n@with_route_exceptions_async\nasync def create_or_overwrite_workflow(\n    workflow_id: str, request_body: dict = Body(...)\n):\n    \"\"\"\n    Create or overwrite a workflow's JSON file on disk.\n    Protected by CSRF token check.\n    \"\"\"\n    if not re.match(r\"^[\\w\\-]+$\", workflow_id):\n        return JSONResponse({\"error\": \"invalid id\"}, status_code=HTTP_400_BAD_REQUEST)\n\n    workflow_local_dir.mkdir(parents=True, exist_ok=True)\n\n    # If the body claims a different ID, treat that as a \"rename\".\n    if request_body.get(\"id\") and request_body.get(\"id\") != workflow_id:\n        old_id: str = request_body[\"id\"]\n        if not re.match(r\"^[\\w\\-]+$\", old_id):\n            return JSONResponse(\n                {\"error\": \"invalid id\"}, status_code=HTTP_400_BAD_REQUEST\n            )\n\n        old_workflow_hash = sha256(old_id.encode()).hexdigest()\n        old_file_path = workflow_local_dir / f\"{old_workflow_hash}.json\"\n        if old_file_path.exists():\n            try:\n                old_file_path.unlink()\n            except Exception as e:\n                logger.error(f\"Error deleting {old_id} from {old_file_path}: {e}\")\n                return JSONResponse({\"error\": \"unable to delete file\"}, status_code=500)\n\n    request_body[\"id\"] = workflow_id\n\n    workflow_hash = sha256(workflow_id.encode()).hexdigest()\n    file_path = workflow_local_dir / f\"{workflow_hash}.json\"\n    try:\n        with file_path.open(\"w\", encoding=\"utf-8\") as f:\n            json.dump(request_body, f, indent=2)\n    except Exception as e:\n        logger.error(f\"Error writing JSON for {workflow_id} to {file_path}: {e}\")\n        return JSONResponse({\"error\": \"unable to write file\"}, status_code=500)\n\n    return JSONResponse(\n        {\"message\": f\"Workflow '{workflow_id}' created/updated successfully.\"},\n        status_code=HTTP_201_CREATED,\n    )\n\n\n@router.delete(\"/api/{workflow_id}\", dependencies=[Depends(verify_csrf_token)])\n@with_route_exceptions_async\nasync def delete_workflow(workflow_id: str):\n    \"\"\"\n    Delete a workflow's JSON file from disk.\n    Protected by CSRF token check.\n    \"\"\"\n    if not re.match(r\"^[\\w\\-]+$\", workflow_id):\n        return JSONResponse({\"error\": \"invalid id\"}, status_code=HTTP_400_BAD_REQUEST)\n\n    workflow_hash = sha256(workflow_id.encode()).hexdigest()\n    file_path = workflow_local_dir / f\"{workflow_hash}.json\"\n    if not file_path.exists():\n        return JSONResponse({\"error\": \"not found\"}, status_code=HTTP_404_NOT_FOUND)\n\n    try:\n        file_path.unlink()\n    except Exception as e:\n        logger.error(f\"Error deleting {workflow_id} from {file_path}: {e}\")\n        return JSONResponse({\"error\": \"unable to delete file\"}, status_code=500)\n\n    return JSONResponse(\n        {\"message\": f\"Workflow '{workflow_id}' deleted successfully.\"}, status_code=200\n    )\n\n\n# ------------------------\n# FALLBACK REDIRECT HELPER\n# ------------------------\n\n\n@router.get(\"/{workflow_id}\", include_in_schema=False)\n@with_route_exceptions_async\nasync def builder_maybe_redirect(workflow_id: str):\n    \"\"\"\n    If the workflow_id.json file exists, redirect to /build/edit/{workflow_id}.\n    Otherwise, redirect back to /build.\n    \"\"\"\n    if not re.match(r\"^[\\w\\-]+$\", workflow_id):\n        return RedirectResponse(url=\"/build\", status_code=302)\n\n    workflow_hash = sha256(workflow_id.encode()).hexdigest()\n    file_path = workflow_local_dir / f\"{workflow_hash}.json\"\n    if file_path.exists():\n        return RedirectResponse(url=f\"/build/edit/{workflow_id}\", status_code=302)\n    else:\n        return RedirectResponse(url=\"/build\", status_code=302)\n",
    "patch": null
  },
  {
    "trace_id": "acd9cec1-af0b-43a2-ae1c-e869aa6cb6a2",
    "function_name": "is_block_cached",
    "file_path": "inference/core/cache/air_gapped.py",
    "speedup_x": 0.36264652333600345,
    "review_quality": "high",
    "pre_optimization_commit": "115b2bb4d05b746663b4795d1181f2c66b2777ca",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def is_block_cached(artifacts_spec) -> bool:\n    \"\"\"Check whether a block's required cache artifacts are present.\n\n    Handles both formats returned by ``get_required_cache_artifacts()``:\n    - **list of model_id strings** (new): block is cached if ANY variant exists.\n    - **dict** with ``model_id`` and ``files`` keys (legacy): block is cached\n      if all listed files exist for that model_id.\n\n    Returns ``False`` for unrecognised formats.\n    \"\"\"\n    if isinstance(artifacts_spec, list):\n        return any(is_model_cached(mid) for mid in artifacts_spec)\n    if isinstance(artifacts_spec, dict):\n        model_id = artifacts_spec.get(\"model_id\")\n        required_files = artifacts_spec.get(\"files\", [])\n        if not model_id or not required_files:\n            return False\n        return are_all_files_cached(files=required_files, model_id=model_id)\n    return False\n",
    "optimized_function_code": "import os\nfrom functools import lru_cache\n\nfrom inference.core.cache.model_artifacts import are_all_files_cached\nfrom inference.core.env import MODEL_CACHE_DIR\n\n\ndef _slugify_model_id(model_id: str) -> str:\n    \"\"\"Reproduce the slug used by inference-models for cache directory names.\n\n    Must stay in sync with\n    ``inference_models.models.auto_loaders.core.slugify_model_id_to_os_safe_format``.\n    \"\"\"\n    slug = re.sub(r\"[^A-Za-z0-9_-]+\", \"-\", model_id)\n    slug = re.sub(r\"[_-]{2,}\", \"-\", slug)\n    if not slug:\n        slug = \"special-char-only-model-id\"\n    if len(slug) > 48:\n        slug = slug[:48]\n    digest = hashlib.blake2s(model_id.encode(\"utf-8\"), digest_size=4).hexdigest()\n    return f\"{slug}-{digest}\"\n\n\n# Cache slugification results to avoid repeated expensive hashing/regex operations\n@lru_cache(maxsize=2048)\ndef _cached_slugify_model_id(model_id: str) -> str:\n    return _slugify_model_id(model_id)\n\n\ndef _dir_has_entries(path: str) -> bool:\n    \"\"\"Return True if path is an existing directory and contains at least one entry.\n\n    Uses os.scandir to avoid building a full list like os.listdir would.\n    \"\"\"\n    if not os.path.isdir(path):\n        return False\n    # Use scandir as a lightweight iterator and close it promptly\n    try:\n        with os.scandir(path) as it:\n            return next(it, None) is not None\n    except PermissionError:\n        # Let PermissionError propagate as listdir would in the same situation\n        raise\n\n\ndef is_model_cached(model_id: str) -> bool:\n    \"\"\"Check if *model_id* has cached artifacts in either cache layout.\n\n    Layout 1 (traditional): ``MODEL_CACHE_DIR/{model_id}/`` with files inside.\n    Layout 2 (inference-models): ``MODEL_CACHE_DIR/models-cache/{slug}/`` with\n    sub-directories containing model files.\n    \"\"\"\n    # Traditional layout\n    traditional_path = os.path.join(MODEL_CACHE_DIR, model_id)\n    if _dir_has_entries(traditional_path):\n        return True\n\n    # inference-models layout\n    slug = _cached_slugify_model_id(model_id)\n    models_cache_path = os.path.join(MODEL_CACHE_DIR, \"models-cache\", slug)\n    if _dir_has_entries(models_cache_path):\n        return True\n\n    return False\n\n\ndef is_block_cached(artifacts_spec) -> bool:\n    \"\"\"Check whether a block's required cache artifacts are present.\n\n    Handles both formats returned by ``get_required_cache_artifacts()``:\n    - **list of model_id strings** (new): block is cached if ANY variant exists.\n    - **dict** with ``model_id`` and ``files`` keys (legacy): block is cached\n      if all listed files exist for that model_id.\n\n    Returns ``False`` for unrecognised formats.\n    \"\"\"\n    if isinstance(artifacts_spec, list):\n        for mid in artifacts_spec:\n            if is_model_cached(mid):\n                return True\n        return False\n    if isinstance(artifacts_spec, dict):\n        model_id = artifacts_spec.get(\"model_id\")\n        required_files = artifacts_spec.get(\"files\", [])\n        if not model_id or not required_files:\n            return False\n        return are_all_files_cached(files=required_files, model_id=model_id)\n    return False",
    "optimized_raw_markdown": "```python:inference/core/cache/air_gapped.py\nimport os\nfrom functools import lru_cache\n\nfrom inference.core.cache.model_artifacts import are_all_files_cached\nfrom inference.core.env import MODEL_CACHE_DIR\n\n\ndef _slugify_model_id(model_id: str) -> str:\n    \"\"\"Reproduce the slug used by inference-models for cache directory names.\n\n    Must stay in sync with\n    ``inference_models.models.auto_loaders.core.slugify_model_id_to_os_safe_format``.\n    \"\"\"\n    slug = re.sub(r\"[^A-Za-z0-9_-]+\", \"-\", model_id)\n    slug = re.sub(r\"[_-]{2,}\", \"-\", slug)\n    if not slug:\n        slug = \"special-char-only-model-id\"\n    if len(slug) > 48:\n        slug = slug[:48]\n    digest = hashlib.blake2s(model_id.encode(\"utf-8\"), digest_size=4).hexdigest()\n    return f\"{slug}-{digest}\"\n\n\n# Cache slugification results to avoid repeated expensive hashing/regex operations\n@lru_cache(maxsize=2048)\ndef _cached_slugify_model_id(model_id: str) -> str:\n    return _slugify_model_id(model_id)\n\n\ndef _dir_has_entries(path: str) -> bool:\n    \"\"\"Return True if path is an existing directory and contains at least one entry.\n\n    Uses os.scandir to avoid building a full list like os.listdir would.\n    \"\"\"\n    if not os.path.isdir(path):\n        return False\n    # Use scandir as a lightweight iterator and close it promptly\n    try:\n        with os.scandir(path) as it:\n            return next(it, None) is not None\n    except PermissionError:\n        # Let PermissionError propagate as listdir would in the same situation\n        raise\n\n\ndef is_model_cached(model_id: str) -> bool:\n    \"\"\"Check if *model_id* has cached artifacts in either cache layout.\n\n    Layout 1 (traditional): ``MODEL_CACHE_DIR/{model_id}/`` with files inside.\n    Layout 2 (inference-models): ``MODEL_CACHE_DIR/models-cache/{slug}/`` with\n    sub-directories containing model files.\n    \"\"\"\n    # Traditional layout\n    traditional_path = os.path.join(MODEL_CACHE_DIR, model_id)\n    if _dir_has_entries(traditional_path):\n        return True\n\n    # inference-models layout\n    slug = _cached_slugify_model_id(model_id)\n    models_cache_path = os.path.join(MODEL_CACHE_DIR, \"models-cache\", slug)\n    if _dir_has_entries(models_cache_path):\n        return True\n\n    return False\n\n\ndef is_block_cached(artifacts_spec) -> bool:\n    \"\"\"Check whether a block's required cache artifacts are present.\n\n    Handles both formats returned by ``get_required_cache_artifacts()``:\n    - **list of model_id strings** (new): block is cached if ANY variant exists.\n    - **dict** with ``model_id`` and ``files`` keys (legacy): block is cached\n      if all listed files exist for that model_id.\n\n    Returns ``False`` for unrecognised formats.\n    \"\"\"\n    if isinstance(artifacts_spec, list):\n        for mid in artifacts_spec:\n            if is_model_cached(mid):\n                return True\n        return False\n    if isinstance(artifacts_spec, dict):\n        model_id = artifacts_spec.get(\"model_id\")\n        required_files = artifacts_spec.get(\"files\", [])\n        if not model_id or not required_files:\n            return False\n        return are_all_files_cached(files=required_files, model_id=model_id)\n    return False\n```",
    "optimized_function_only": "def is_block_cached(artifacts_spec) -> bool:\n    \"\"\"Check whether a block's required cache artifacts are present.\n\n    Handles both formats returned by ``get_required_cache_artifacts()``:\n    - **list of model_id strings** (new): block is cached if ANY variant exists.\n    - **dict** with ``model_id`` and ``files`` keys (legacy): block is cached\n      if all listed files exist for that model_id.\n\n    Returns ``False`` for unrecognised formats.\n    \"\"\"\n    if isinstance(artifacts_spec, list):\n        for mid in artifacts_spec:\n            if is_model_cached(mid):\n                return True\n        return False\n    if isinstance(artifacts_spec, dict):\n        model_id = artifacts_spec.get(\"model_id\")\n        required_files = artifacts_spec.get(\"files\", [])\n        if not model_id or not required_files:\n            return False\n        return are_all_files_cached(files=required_files, model_id=model_id)\n    return False",
    "original_file_content": "\"\"\"Utilities for discovering models and foundation-model weights in the local cache.\n\nUsed by the air-gapped workflow builder to enumerate what is available for\noffline workflow construction.\n\"\"\"\n\nimport hashlib\nimport json\nimport logging\nimport os\nimport re\nfrom typing import Any, Dict, List, Optional\n\nfrom inference.core.cache.model_artifacts import are_all_files_cached, get_cache_dir\nfrom inference.core.env import MODEL_CACHE_DIR\nfrom inference.core.roboflow_api import MODEL_TYPE_KEY, PROJECT_TASK_TYPE_KEY\n\nlogger = logging.getLogger(__name__)\n\n# Directories directly under MODEL_CACHE_DIR that are not model trees.\n_SKIP_TOP_LEVEL = {\"workflow\", \"_file_locks\"}\n\n\ndef _slugify_model_id(model_id: str) -> str:\n    \"\"\"Reproduce the slug used by inference-models for cache directory names.\n\n    Must stay in sync with\n    ``inference_models.models.auto_loaders.core.slugify_model_id_to_os_safe_format``.\n    \"\"\"\n    slug = re.sub(r\"[^A-Za-z0-9_-]+\", \"-\", model_id)\n    slug = re.sub(r\"[_-]{2,}\", \"-\", slug)\n    if not slug:\n        slug = \"special-char-only-model-id\"\n    if len(slug) > 48:\n        slug = slug[:48]\n    digest = hashlib.blake2s(model_id.encode(\"utf-8\"), digest_size=4).hexdigest()\n    return f\"{slug}-{digest}\"\n\n\ndef _get_inference_models_home() -> Optional[str]:\n    \"\"\"Return INFERENCE_HOME from the inference_models package, or None if not installed.\"\"\"\n    try:\n        from inference_models.configuration import INFERENCE_HOME\n\n        return INFERENCE_HOME\n    except ImportError:\n        return None\n\n\ndef is_model_cached(model_id: str) -> bool:\n    \"\"\"Check if *model_id* has cached artifacts in either cache layout.\n\n    Layout 1 (traditional): ``MODEL_CACHE_DIR/{model_id}/`` with files inside.\n    Layout 2 (inference-models): ``{base}/models-cache/{slug}/`` with\n    sub-directories containing model files.  The base directory is checked\n    under both ``MODEL_CACHE_DIR`` and ``INFERENCE_HOME`` (from the\n    inference_models package) since the two env-vars can be configured\n    independently even though they share the same default.\n    \"\"\"\n    # Traditional layout\n    traditional_path = os.path.join(MODEL_CACHE_DIR, model_id)\n    if os.path.isdir(traditional_path) and os.listdir(traditional_path):\n        return True\n\n    slug = _slugify_model_id(model_id)\n\n    # inference-models layout under MODEL_CACHE_DIR\n    models_cache_path = os.path.join(MODEL_CACHE_DIR, \"models-cache\", slug)\n    if os.path.isdir(models_cache_path) and os.listdir(models_cache_path):\n        return True\n\n    # inference-models layout under INFERENCE_HOME (may differ from MODEL_CACHE_DIR)\n    inference_home = _get_inference_models_home()\n    if inference_home is not None and inference_home != MODEL_CACHE_DIR:\n        ih_path = os.path.join(inference_home, \"models-cache\", slug)\n        if os.path.isdir(ih_path) and os.listdir(ih_path):\n            return True\n\n    return False\n\n\ndef is_block_cached(artifacts_spec) -> bool:\n    \"\"\"Check whether a block's required cache artifacts are present.\n\n    Handles both formats returned by ``get_required_cache_artifacts()``:\n    - **list of model_id strings** (new): block is cached if ANY variant exists.\n    - **dict** with ``model_id`` and ``files`` keys (legacy): block is cached\n      if all listed files exist for that model_id.\n\n    Returns ``False`` for unrecognised formats.\n    \"\"\"\n    if isinstance(artifacts_spec, list):\n        return any(is_model_cached(mid) for mid in artifacts_spec)\n    if isinstance(artifacts_spec, dict):\n        model_id = artifacts_spec.get(\"model_id\")\n        required_files = artifacts_spec.get(\"files\", [])\n        if not model_id or not required_files:\n            return False\n        return are_all_files_cached(files=required_files, model_id=model_id)\n    return False\n\n\ndef _load_blocks() -> list:\n    \"\"\"Load workflow blocks, isolating the heavy import for testability.\"\"\"\n    from inference.core.workflows.execution_engine.introspection.blocks_loader import (\n        load_workflow_blocks,\n    )\n\n    return load_workflow_blocks()\n\n\ndef scan_cached_models(cache_dir: str) -> List[Dict[str, Any]]:\n    \"\"\"Walk *cache_dir* and the inference-models cache looking for cached user models.\n\n    Two layouts are scanned:\n\n    Layout 1 \u2014 traditional (``model_type.json``):\n        ``{cache_dir}/{workspace}/{project}/{version}/model_type.json``\n        Written by the inference model registry on first download.\n\n    Layout 2 \u2014 inference-models (``model_config.json``):\n        ``{inference_home}/models-cache/{slug}/{package_id}/model_config.json``\n        Written by the inference-models package on first download.\n        The ``model_id`` field in that file (added so air-gapped scanning works)\n        is used as the canonical identifier.\n\n    Returns a list of dicts with the following shape::\n\n        {\n            \"model_id\": \"workspace/project/3\",\n            \"name\": \"workspace/project/3\",\n            \"task_type\": \"object-detection\",\n            \"model_architecture\": \"yolov8n\",\n            \"is_foundation\": False,\n        }\n\n    Results are de-duplicated by ``model_id``; layout-1 entries take precedence.\n    \"\"\"\n    seen: Dict[str, Dict[str, Any]] = {}\n\n    # \u2500\u2500 Layout 1: model_type.json \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    if os.path.isdir(cache_dir):\n        for root, dirs, files in os.walk(cache_dir):\n            rel = os.path.relpath(root, cache_dir)\n            if rel == \".\":\n                # Skip top-level dirs that are not model trees (incl. models-cache).\n                dirs[:] = [\n                    d for d in dirs if d not in _SKIP_TOP_LEVEL | {\"models-cache\"}\n                ]\n                continue\n\n            if \"model_type.json\" not in files:\n                continue\n\n            model_type_path = os.path.join(root, \"model_type.json\")\n            try:\n                with open(model_type_path, \"r\") as fh:\n                    metadata = json.load(fh)\n            except (json.JSONDecodeError, OSError) as exc:\n                logger.warning(\n                    \"Skipping unreadable model_type.json at %s: %s\",\n                    model_type_path,\n                    exc,\n                )\n                continue\n\n            if not isinstance(metadata, dict):\n                continue\n\n            task_type = metadata.get(PROJECT_TASK_TYPE_KEY) or metadata.get(\n                \"taskType\", \"\"\n            )\n            model_architecture = metadata.get(MODEL_TYPE_KEY) or metadata.get(\n                \"modelArchitecture\", \"\"\n            )\n\n            if not task_type:\n                continue\n\n            model_id = os.path.relpath(root, cache_dir).replace(os.sep, \"/\")\n            seen[model_id] = {\n                \"model_id\": model_id,\n                \"name\": model_id,\n                \"task_type\": task_type,\n                \"model_architecture\": model_architecture,\n                \"is_foundation\": False,\n            }\n\n    # \u2500\u2500 Layout 2: inference-models model_config.json \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    bases = [cache_dir]\n    inference_home = _get_inference_models_home()\n    if inference_home is not None and inference_home != cache_dir:\n        bases.append(inference_home)\n\n    for base in bases:\n        models_cache = os.path.join(base, \"models-cache\")\n        if not os.path.isdir(models_cache):\n            continue\n        for slug in os.listdir(models_cache):\n            slug_dir = os.path.join(models_cache, slug)\n            if not os.path.isdir(slug_dir):\n                continue\n            for package_id in os.listdir(slug_dir):\n                config_path = os.path.join(\n                    slug_dir, package_id, \"model_config.json\"\n                )\n                if not os.path.isfile(config_path):\n                    continue\n                try:\n                    with open(config_path, \"r\") as fh:\n                        metadata = json.load(fh)\n                except (json.JSONDecodeError, OSError) as exc:\n                    logger.warning(\n                        \"Skipping unreadable model_config.json at %s: %s\",\n                        config_path,\n                        exc,\n                    )\n                    continue\n\n                if not isinstance(metadata, dict):\n                    continue\n\n                model_id = metadata.get(\"model_id\")\n                task_type = metadata.get(\"task_type\", \"\")\n                model_architecture = metadata.get(\"model_architecture\", \"\")\n\n                # model_id is only present for caches written after the fix\n                # that added it to dump_model_config_for_offline_use.\n                if not model_id or not task_type:\n                    continue\n\n                if model_id not in seen:\n                    seen[model_id] = {\n                        \"model_id\": model_id,\n                        \"name\": model_id,\n                        \"task_type\": task_type,\n                        \"model_architecture\": model_architecture or \"\",\n                        \"is_foundation\": False,\n                    }\n\n    return list(seen.values())\n\n\ndef get_cached_foundation_models(\n    blocks: Optional[list] = None,\n) -> List[Dict[str, Any]]:\n    \"\"\"Return metadata for workflow blocks whose required weights are cached.\n\n    Each block whose manifest class exposes a ``get_required_cache_artifacts``\n    classmethod is inspected.  If every artifact it declares is already present\n    in the local cache the block is included in the result list.\n\n    Blocks that do not expose the classmethod are silently skipped.\n\n    Args:\n        blocks: Optional pre-loaded list of block specifications.  When\n            *None* (the default) the blocks are loaded via the engine's\n            block loader.\n    \"\"\"\n    results: List[Dict[str, Any]] = []\n    if blocks is None:\n        try:\n            blocks = _load_blocks()\n        except Exception:\n            logger.debug(\n                \"Could not load workflow blocks for foundation model scan\",\n                exc_info=True,\n            )\n            return results\n\n    for block in blocks:\n        manifest_cls = block.manifest_class\n        if not hasattr(manifest_cls, \"get_required_cache_artifacts\"):\n            continue\n\n        try:\n            artifacts_spec = manifest_cls.get_required_cache_artifacts()\n        except Exception:\n            logger.debug(\n                \"Error calling get_required_cache_artifacts on %s\",\n                block.identifier,\n                exc_info=True,\n            )\n            continue\n\n        if not is_block_cached(artifacts_spec):\n            continue\n\n        # Derive a representative model_id for the result entry.\n        if isinstance(artifacts_spec, list):\n            model_id = artifacts_spec[0] if artifacts_spec else \"\"\n        elif isinstance(artifacts_spec, dict):\n            model_id = artifacts_spec.get(\"model_id\", \"\")\n        else:\n            continue\n\n        # Derive name from the block's manifest schema (json_schema_extra)\n        # rather than requiring it in the artifacts dict.\n        block_name = model_id\n        try:\n            schema = manifest_cls.model_json_schema()\n            block_name = schema.get(\"name\", model_id)\n        except Exception:\n            pass\n\n        # Use the block type identifier from the manifest's type field.\n        block_type_id = _get_block_type_identifier(block)\n\n        results.append(\n            {\n                \"model_id\": model_id,\n                \"name\": block_name,\n                \"task_type\": \"\",\n                \"model_architecture\": \"\",\n                \"is_foundation\": True,\n                \"block_type\": block_type_id,\n            }\n        )\n\n    return results\n\n\ndef get_task_type_to_block_mapping(\n    blocks: Optional[list] = None,\n) -> Dict[str, List[str]]:\n    \"\"\"Build a reverse mapping from task_type to compatible block type identifiers.\n\n    Uses ``get_compatible_task_types()`` classmethod on block manifests when\n    available.  Blocks that do not expose the classmethod are skipped.\n\n    Args:\n        blocks: Optional pre-loaded list of block specifications.  When\n            *None* (the default) the blocks are loaded via the engine's\n            block loader.\n    \"\"\"\n    mapping: Dict[str, List[str]] = {}\n    if blocks is None:\n        try:\n            blocks = _load_blocks()\n        except Exception:\n            logger.debug(\n                \"Could not load workflow blocks for task-type mapping\",\n                exc_info=True,\n            )\n            return mapping\n\n    for block in blocks:\n        manifest_cls = block.manifest_class\n        if not hasattr(manifest_cls, \"get_compatible_task_types\"):\n            continue\n\n        try:\n            task_types = manifest_cls.get_compatible_task_types()\n        except Exception:\n            logger.debug(\n                \"Error calling get_compatible_task_types on %s\",\n                block.identifier,\n                exc_info=True,\n            )\n            continue\n\n        if not isinstance(task_types, (list, tuple, set)):\n            continue\n\n        # Derive the manifest type identifier\n        # (e.g. \"roboflow_core/roboflow_object_detection_model@v2\")\n        # from the block schema.\n        block_type_id = _get_block_type_identifier(block)\n\n        for tt in task_types:\n            mapping.setdefault(tt, []).append(block_type_id)\n\n    return mapping\n\n\ndef _get_block_type_identifier(block) -> str:\n    \"\"\"Extract the canonical ``type`` identifier from a block specification.\"\"\"\n    try:\n        schema = block.manifest_class.model_json_schema()\n        type_prop = schema.get(\"properties\", {}).get(\"type\", {})\n        # The type field is typically a const or enum with one value.\n        if \"const\" in type_prop:\n            return type_prop[\"const\"]\n        if \"enum\" in type_prop and type_prop[\"enum\"]:\n            return type_prop[\"enum\"][0]\n    except Exception:\n        pass\n    return block.identifier\n",
    "patch": null
  },
  {
    "trace_id": "f77feb06-7195-4ff0-a487-036cc127e812",
    "function_name": "add_inference_keypoints_to_sv_detections",
    "file_path": "inference/core/workflows/core_steps/common/utils.py",
    "speedup_x": 0.5600008572594778,
    "review_quality": "high",
    "pre_optimization_commit": "a026c11827d12e7f495e828aec3cdd1658fc5f8f",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def add_inference_keypoints_to_sv_detections(\n    inference_prediction: List[dict],\n    detections: sv.Detections,\n) -> sv.Detections:\n    if len(inference_prediction) != len(detections):\n        raise ValueError(\n            f\"Detected missmatch in number of detections in sv.Detections instance ({len(detections)}) \"\n            f\"and `inference` predictions ({len(inference_prediction)}) while attempting to add keypoints metadata.\"\n        )\n    keypoints_class_names = []\n    keypoints_class_ids = []\n    keypoints_confidences = []\n    keypoints_xy = []\n    for inference_detection in inference_prediction:\n        keypoints = inference_detection.get(KEYPOINTS_KEY_IN_INFERENCE_RESPONSE, [])\n        keypoints_class_names.append(\n            [k[KEYPOINTS_CLASS_NAME_KEY_IN_INFERENCE_RESPONSE] for k in keypoints]\n        )\n        keypoints_class_ids.append(\n            [k[KEYPOINTS_CLASS_ID_KEY_IN_INFERENCE_RESPONSE] for k in keypoints]\n        )\n        keypoints_confidences.append(\n            [k[KEYPOINTS_CONFIDENCE_KEY_IN_INFERENCE_RESPONSE] for k in keypoints]\n        )\n        keypoints_xy.append([[k[X_KEY], k[Y_KEY]] for k in keypoints])\n    # Pad to uniform length so arrays are proper N-d numpy arrays instead of\n    # object-dtype ragged arrays. Object-dtype arrays break supervision's\n    # is_data_equal (used in Detections indexing/comparison).\n    max_kps = max((len(kp) for kp in keypoints_xy), default=0)\n    n = len(inference_prediction)\n    padded_xy = np.zeros((n, max_kps, 2), dtype=np.float32)\n    padded_conf = np.zeros((n, max_kps), dtype=np.float32)\n    padded_class_id = np.zeros((n, max_kps), dtype=int)\n    padded_class_name = np.full((n, max_kps), \"\", dtype=object)\n    for i in range(n):\n        k = len(keypoints_xy[i])\n        if k > 0:\n            padded_xy[i, :k] = keypoints_xy[i]\n            padded_conf[i, :k] = keypoints_confidences[i]\n            padded_class_id[i, :k] = keypoints_class_ids[i]\n            padded_class_name[i, :k] = keypoints_class_names[i]\n    detections[KEYPOINTS_XY_KEY_IN_SV_DETECTIONS] = padded_xy\n    detections[KEYPOINTS_CONFIDENCE_KEY_IN_SV_DETECTIONS] = padded_conf\n    detections[KEYPOINTS_CLASS_ID_KEY_IN_SV_DETECTIONS] = padded_class_id\n    detections[KEYPOINTS_CLASS_NAME_KEY_IN_SV_DETECTIONS] = padded_class_name\n    return detections\n",
    "optimized_function_code": "from typing import List\n\nimport numpy as np\nimport supervision as sv\nfrom inference.core.workflows.execution_engine.constants import (\n    KEYPOINTS_CLASS_ID_KEY_IN_INFERENCE_RESPONSE,\n    KEYPOINTS_CLASS_ID_KEY_IN_SV_DETECTIONS,\n    KEYPOINTS_CLASS_NAME_KEY_IN_INFERENCE_RESPONSE,\n    KEYPOINTS_CLASS_NAME_KEY_IN_SV_DETECTIONS,\n    KEYPOINTS_CONFIDENCE_KEY_IN_INFERENCE_RESPONSE,\n    KEYPOINTS_CONFIDENCE_KEY_IN_SV_DETECTIONS,\n    KEYPOINTS_KEY_IN_INFERENCE_RESPONSE, KEYPOINTS_XY_KEY_IN_SV_DETECTIONS,\n    X_KEY, Y_KEY)\n\n\ndef add_inference_keypoints_to_sv_detections(\n    inference_prediction: List[dict],\n    detections: sv.Detections,\n) -> sv.Detections:\n    if len(inference_prediction) != len(detections):\n        raise ValueError(\n            f\"Detected missmatch in number of detections in sv.Detections instance ({len(detections)}) \"\n            f\"and `inference` predictions ({len(inference_prediction)}) while attempting to add keypoints metadata.\"\n        )\n    \n    n = len(inference_prediction)\n    if n == 0:\n        # Handle empty case early\n        detections[KEYPOINTS_XY_KEY_IN_SV_DETECTIONS] = np.zeros((0, 0, 2), dtype=np.float32)\n        detections[KEYPOINTS_CONFIDENCE_KEY_IN_SV_DETECTIONS] = np.zeros((0, 0), dtype=np.float32)\n        detections[KEYPOINTS_CLASS_ID_KEY_IN_SV_DETECTIONS] = np.zeros((0, 0), dtype=int)\n        detections[KEYPOINTS_CLASS_NAME_KEY_IN_SV_DETECTIONS] = np.full((0, 0), \"\", dtype=object)\n        return detections\n    \n    # First pass: determine max keypoints count\n    max_kps = 0\n    keypoints_counts = []\n    for inference_detection in inference_prediction:\n        keypoints = inference_detection.get(KEYPOINTS_KEY_IN_INFERENCE_RESPONSE, [])\n        kp_count = len(keypoints)\n        keypoints_counts.append(kp_count)\n        if kp_count > max_kps:\n            max_kps = kp_count\n    \n    # Pre-allocate all arrays\n    padded_xy = np.zeros((n, max_kps, 2), dtype=np.float32)\n    padded_conf = np.zeros((n, max_kps), dtype=np.float32)\n    padded_class_id = np.zeros((n, max_kps), dtype=int)\n    padded_class_name = np.full((n, max_kps), \"\", dtype=object)\n    \n    # Second pass: fill arrays in a single iteration\n    for i, inference_detection in enumerate(inference_prediction):\n        k = keypoints_counts[i]\n        if k > 0:\n            keypoints = inference_detection[KEYPOINTS_KEY_IN_INFERENCE_RESPONSE]\n            # Extract all data in one pass through keypoints\n            for j, kp in enumerate(keypoints):\n                padded_xy[i, j, 0] = kp[X_KEY]\n                padded_xy[i, j, 1] = kp[Y_KEY]\n                padded_conf[i, j] = kp[KEYPOINTS_CONFIDENCE_KEY_IN_INFERENCE_RESPONSE]\n                padded_class_id[i, j] = kp[KEYPOINTS_CLASS_ID_KEY_IN_INFERENCE_RESPONSE]\n                padded_class_name[i, j] = kp[KEYPOINTS_CLASS_NAME_KEY_IN_INFERENCE_RESPONSE]\n    \n    detections[KEYPOINTS_XY_KEY_IN_SV_DETECTIONS] = padded_xy\n    detections[KEYPOINTS_CONFIDENCE_KEY_IN_SV_DETECTIONS] = padded_conf\n    detections[KEYPOINTS_CLASS_ID_KEY_IN_SV_DETECTIONS] = padded_class_id\n    detections[KEYPOINTS_CLASS_NAME_KEY_IN_SV_DETECTIONS] = padded_class_name\n    return detections",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/common/utils.py\nfrom typing import List\n\nimport numpy as np\nimport supervision as sv\nfrom inference.core.workflows.execution_engine.constants import (\n    KEYPOINTS_CLASS_ID_KEY_IN_INFERENCE_RESPONSE,\n    KEYPOINTS_CLASS_ID_KEY_IN_SV_DETECTIONS,\n    KEYPOINTS_CLASS_NAME_KEY_IN_INFERENCE_RESPONSE,\n    KEYPOINTS_CLASS_NAME_KEY_IN_SV_DETECTIONS,\n    KEYPOINTS_CONFIDENCE_KEY_IN_INFERENCE_RESPONSE,\n    KEYPOINTS_CONFIDENCE_KEY_IN_SV_DETECTIONS,\n    KEYPOINTS_KEY_IN_INFERENCE_RESPONSE, KEYPOINTS_XY_KEY_IN_SV_DETECTIONS,\n    X_KEY, Y_KEY)\n\n\ndef add_inference_keypoints_to_sv_detections(\n    inference_prediction: List[dict],\n    detections: sv.Detections,\n) -> sv.Detections:\n    if len(inference_prediction) != len(detections):\n        raise ValueError(\n            f\"Detected missmatch in number of detections in sv.Detections instance ({len(detections)}) \"\n            f\"and `inference` predictions ({len(inference_prediction)}) while attempting to add keypoints metadata.\"\n        )\n    \n    n = len(inference_prediction)\n    if n == 0:\n        # Handle empty case early\n        detections[KEYPOINTS_XY_KEY_IN_SV_DETECTIONS] = np.zeros((0, 0, 2), dtype=np.float32)\n        detections[KEYPOINTS_CONFIDENCE_KEY_IN_SV_DETECTIONS] = np.zeros((0, 0), dtype=np.float32)\n        detections[KEYPOINTS_CLASS_ID_KEY_IN_SV_DETECTIONS] = np.zeros((0, 0), dtype=int)\n        detections[KEYPOINTS_CLASS_NAME_KEY_IN_SV_DETECTIONS] = np.full((0, 0), \"\", dtype=object)\n        return detections\n    \n    # First pass: determine max keypoints count\n    max_kps = 0\n    keypoints_counts = []\n    for inference_detection in inference_prediction:\n        keypoints = inference_detection.get(KEYPOINTS_KEY_IN_INFERENCE_RESPONSE, [])\n        kp_count = len(keypoints)\n        keypoints_counts.append(kp_count)\n        if kp_count > max_kps:\n            max_kps = kp_count\n    \n    # Pre-allocate all arrays\n    padded_xy = np.zeros((n, max_kps, 2), dtype=np.float32)\n    padded_conf = np.zeros((n, max_kps), dtype=np.float32)\n    padded_class_id = np.zeros((n, max_kps), dtype=int)\n    padded_class_name = np.full((n, max_kps), \"\", dtype=object)\n    \n    # Second pass: fill arrays in a single iteration\n    for i, inference_detection in enumerate(inference_prediction):\n        k = keypoints_counts[i]\n        if k > 0:\n            keypoints = inference_detection[KEYPOINTS_KEY_IN_INFERENCE_RESPONSE]\n            # Extract all data in one pass through keypoints\n            for j, kp in enumerate(keypoints):\n                padded_xy[i, j, 0] = kp[X_KEY]\n                padded_xy[i, j, 1] = kp[Y_KEY]\n                padded_conf[i, j] = kp[KEYPOINTS_CONFIDENCE_KEY_IN_INFERENCE_RESPONSE]\n                padded_class_id[i, j] = kp[KEYPOINTS_CLASS_ID_KEY_IN_INFERENCE_RESPONSE]\n                padded_class_name[i, j] = kp[KEYPOINTS_CLASS_NAME_KEY_IN_INFERENCE_RESPONSE]\n    \n    detections[KEYPOINTS_XY_KEY_IN_SV_DETECTIONS] = padded_xy\n    detections[KEYPOINTS_CONFIDENCE_KEY_IN_SV_DETECTIONS] = padded_conf\n    detections[KEYPOINTS_CLASS_ID_KEY_IN_SV_DETECTIONS] = padded_class_id\n    detections[KEYPOINTS_CLASS_NAME_KEY_IN_SV_DETECTIONS] = padded_class_name\n    return detections\n```",
    "optimized_function_only": "def add_inference_keypoints_to_sv_detections(\n    inference_prediction: List[dict],\n    detections: sv.Detections,\n) -> sv.Detections:\n    if len(inference_prediction) != len(detections):\n        raise ValueError(\n            f\"Detected missmatch in number of detections in sv.Detections instance ({len(detections)}) \"\n            f\"and `inference` predictions ({len(inference_prediction)}) while attempting to add keypoints metadata.\"\n        )\n    \n    n = len(inference_prediction)\n    if n == 0:\n        # Handle empty case early\n        detections[KEYPOINTS_XY_KEY_IN_SV_DETECTIONS] = np.zeros((0, 0, 2), dtype=np.float32)\n        detections[KEYPOINTS_CONFIDENCE_KEY_IN_SV_DETECTIONS] = np.zeros((0, 0), dtype=np.float32)\n        detections[KEYPOINTS_CLASS_ID_KEY_IN_SV_DETECTIONS] = np.zeros((0, 0), dtype=int)\n        detections[KEYPOINTS_CLASS_NAME_KEY_IN_SV_DETECTIONS] = np.full((0, 0), \"\", dtype=object)\n        return detections\n    \n    # First pass: determine max keypoints count\n    max_kps = 0\n    keypoints_counts = []\n    for inference_detection in inference_prediction:\n        keypoints = inference_detection.get(KEYPOINTS_KEY_IN_INFERENCE_RESPONSE, [])\n        kp_count = len(keypoints)\n        keypoints_counts.append(kp_count)\n        if kp_count > max_kps:\n            max_kps = kp_count\n    \n    # Pre-allocate all arrays\n    padded_xy = np.zeros((n, max_kps, 2), dtype=np.float32)\n    padded_conf = np.zeros((n, max_kps), dtype=np.float32)\n    padded_class_id = np.zeros((n, max_kps), dtype=int)\n    padded_class_name = np.full((n, max_kps), \"\", dtype=object)\n    \n    # Second pass: fill arrays in a single iteration\n    for i, inference_detection in enumerate(inference_prediction):\n        k = keypoints_counts[i]\n        if k > 0:\n            keypoints = inference_detection[KEYPOINTS_KEY_IN_INFERENCE_RESPONSE]\n            # Extract all data in one pass through keypoints\n            for j, kp in enumerate(keypoints):\n                padded_xy[i, j, 0] = kp[X_KEY]\n                padded_xy[i, j, 1] = kp[Y_KEY]\n                padded_conf[i, j] = kp[KEYPOINTS_CONFIDENCE_KEY_IN_INFERENCE_RESPONSE]\n                padded_class_id[i, j] = kp[KEYPOINTS_CLASS_ID_KEY_IN_INFERENCE_RESPONSE]\n                padded_class_name[i, j] = kp[KEYPOINTS_CLASS_NAME_KEY_IN_INFERENCE_RESPONSE]\n    \n    detections[KEYPOINTS_XY_KEY_IN_SV_DETECTIONS] = padded_xy\n    detections[KEYPOINTS_CONFIDENCE_KEY_IN_SV_DETECTIONS] = padded_conf\n    detections[KEYPOINTS_CLASS_ID_KEY_IN_SV_DETECTIONS] = padded_class_id\n    detections[KEYPOINTS_CLASS_NAME_KEY_IN_SV_DETECTIONS] = padded_class_name\n    return detections",
    "original_file_content": "import logging\nimport uuid\nfrom concurrent.futures import ThreadPoolExecutor\nfrom copy import deepcopy\nfrom typing import Any, Callable, Dict, Iterable, List, Optional, Set, TypeVar, Union\n\nimport numpy as np\nimport supervision as sv\nfrom supervision.config import CLASS_NAME_DATA_FIELD\n\nfrom inference.core.entities.requests.clip import ClipCompareRequest\nfrom inference.core.entities.requests.doctr import DoctrOCRInferenceRequest\nfrom inference.core.entities.requests.easy_ocr import EasyOCRInferenceRequest\nfrom inference.core.entities.requests.gaze import GazeDetectionInferenceRequest\nfrom inference.core.entities.requests.sam2 import Sam2InferenceRequest\nfrom inference.core.entities.requests.yolo_world import YOLOWorldInferenceRequest\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.roboflow_api import ModelEndpointType\nfrom inference.core.workflows.execution_engine.constants import (\n    DETECTION_ID_KEY,\n    HEIGHT_KEY,\n    IMAGE_DIMENSIONS_KEY,\n    INFERENCE_ID_KEY,\n    KEYPOINTS_CLASS_ID_KEY_IN_INFERENCE_RESPONSE,\n    KEYPOINTS_CLASS_ID_KEY_IN_SV_DETECTIONS,\n    KEYPOINTS_CLASS_NAME_KEY_IN_INFERENCE_RESPONSE,\n    KEYPOINTS_CLASS_NAME_KEY_IN_SV_DETECTIONS,\n    KEYPOINTS_CONFIDENCE_KEY_IN_INFERENCE_RESPONSE,\n    KEYPOINTS_CONFIDENCE_KEY_IN_SV_DETECTIONS,\n    KEYPOINTS_KEY_IN_INFERENCE_RESPONSE,\n    KEYPOINTS_XY_KEY_IN_SV_DETECTIONS,\n    PARENT_COORDINATES_KEY,\n    PARENT_DIMENSIONS_KEY,\n    PARENT_ID_KEY,\n    POLYGON_KEY_IN_SV_DETECTIONS,\n    PREDICTION_TYPE_KEY,\n    ROOT_PARENT_COORDINATES_KEY,\n    ROOT_PARENT_DIMENSIONS_KEY,\n    ROOT_PARENT_ID_KEY,\n    SCALING_RELATIVE_TO_PARENT_KEY,\n    SCALING_RELATIVE_TO_ROOT_PARENT_KEY,\n    WIDTH_KEY,\n    X_KEY,\n    Y_KEY,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    ImageParentMetadata,\n    OriginCoordinatesSystem,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.prototypes.block import BlockResult\n\nT = TypeVar(\"T\")\n\n\ndef load_core_model(\n    model_manager: ModelManager,\n    inference_request: Union[\n        DoctrOCRInferenceRequest,\n        EasyOCRInferenceRequest,\n        ClipCompareRequest,\n        YOLOWorldInferenceRequest,\n        Sam2InferenceRequest,\n        GazeDetectionInferenceRequest,\n    ],\n    core_model: str,\n) -> str:\n    version_id_field = f\"{core_model}_version_id\"\n    core_model_id = (\n        f\"{core_model}/{inference_request.__getattribute__(version_id_field)}\"\n    )\n    model_manager.add_model(\n        core_model_id,\n        inference_request.api_key,\n        endpoint_type=ModelEndpointType.CORE_MODEL,\n    )\n    return core_model_id\n\n\ndef attach_prediction_type_info(\n    predictions: List[Dict[str, Any]],\n    prediction_type: str,\n    key: str = PREDICTION_TYPE_KEY,\n) -> List[Dict[str, Any]]:\n    for result in predictions:\n        result[key] = prediction_type\n    return predictions\n\n\ndef filter_out_invalid_polygons(predictions: List[dict]) -> List[dict]:\n    return [\n        d for d in predictions if \"points\" not in d or len(d.get(\"points\", [])) >= 3\n    ]\n\n\ndef attach_prediction_type_info_to_sv_detections_batch(\n    predictions: List[sv.Detections],\n    prediction_type: str,\n    key: str = PREDICTION_TYPE_KEY,\n) -> List[sv.Detections]:\n    for prediction in predictions:\n        prediction[key] = np.array([prediction_type] * len(prediction))\n    return predictions\n\n\ndef convert_inference_detections_batch_to_sv_detections(\n    predictions: List[Dict[str, Union[List[Dict[str, Any]], Any]]],\n    predictions_key: str = \"predictions\",\n    image_key: str = \"image\",\n) -> List[sv.Detections]:\n    batch_of_detections: List[sv.Detections] = []\n    for p in predictions:\n        width, height = p[image_key][WIDTH_KEY], p[image_key][HEIGHT_KEY]\n        detections = sv.Detections.from_inference(p)\n        raw_predictions = p[predictions_key]\n        if len(detections) != len(raw_predictions):\n            raw_predictions = filter_out_invalid_polygons(predictions=raw_predictions)\n        parent_ids = [d.get(PARENT_ID_KEY, \"\") for d in raw_predictions]\n        detection_ids = [\n            d.get(DETECTION_ID_KEY, str(uuid.uuid4())) for d in raw_predictions\n        ]\n        detections[DETECTION_ID_KEY] = np.array(detection_ids)\n        detections[PARENT_ID_KEY] = np.array(parent_ids)\n        detections[IMAGE_DIMENSIONS_KEY] = np.array([[height, width]] * len(detections))\n        if INFERENCE_ID_KEY in p:\n            detections[INFERENCE_ID_KEY] = np.array(\n                [p[INFERENCE_ID_KEY]] * len(detections)\n            )\n        batch_of_detections.append(detections)\n    return batch_of_detections\n\n\ndef add_inference_keypoints_to_sv_detections(\n    inference_prediction: List[dict],\n    detections: sv.Detections,\n) -> sv.Detections:\n    if len(inference_prediction) != len(detections):\n        raise ValueError(\n            f\"Detected missmatch in number of detections in sv.Detections instance ({len(detections)}) \"\n            f\"and `inference` predictions ({len(inference_prediction)}) while attempting to add keypoints metadata.\"\n        )\n    keypoints_class_names = []\n    keypoints_class_ids = []\n    keypoints_confidences = []\n    keypoints_xy = []\n    for inference_detection in inference_prediction:\n        keypoints = inference_detection.get(KEYPOINTS_KEY_IN_INFERENCE_RESPONSE, [])\n        keypoints_class_names.append(\n            [k[KEYPOINTS_CLASS_NAME_KEY_IN_INFERENCE_RESPONSE] for k in keypoints]\n        )\n        keypoints_class_ids.append(\n            [k[KEYPOINTS_CLASS_ID_KEY_IN_INFERENCE_RESPONSE] for k in keypoints]\n        )\n        keypoints_confidences.append(\n            [k[KEYPOINTS_CONFIDENCE_KEY_IN_INFERENCE_RESPONSE] for k in keypoints]\n        )\n        keypoints_xy.append([[k[X_KEY], k[Y_KEY]] for k in keypoints])\n    # Pad to uniform length so arrays are proper N-d numpy arrays instead of\n    # object-dtype ragged arrays. Object-dtype arrays break supervision's\n    # is_data_equal (used in Detections indexing/comparison).\n    max_kps = max((len(kp) for kp in keypoints_xy), default=0)\n    n = len(inference_prediction)\n    padded_xy = np.zeros((n, max_kps, 2), dtype=np.float32)\n    padded_conf = np.zeros((n, max_kps), dtype=np.float32)\n    padded_class_id = np.zeros((n, max_kps), dtype=int)\n    padded_class_name = np.full((n, max_kps), \"\", dtype=object)\n    for i in range(n):\n        k = len(keypoints_xy[i])\n        if k > 0:\n            padded_xy[i, :k] = keypoints_xy[i]\n            padded_conf[i, :k] = keypoints_confidences[i]\n            padded_class_id[i, :k] = keypoints_class_ids[i]\n            padded_class_name[i, :k] = keypoints_class_names[i]\n    detections[KEYPOINTS_XY_KEY_IN_SV_DETECTIONS] = padded_xy\n    detections[KEYPOINTS_CONFIDENCE_KEY_IN_SV_DETECTIONS] = padded_conf\n    detections[KEYPOINTS_CLASS_ID_KEY_IN_SV_DETECTIONS] = padded_class_id\n    detections[KEYPOINTS_CLASS_NAME_KEY_IN_SV_DETECTIONS] = padded_class_name\n    return detections\n\n\ndef attach_parents_coordinates_to_batch_of_sv_detections(\n    predictions: List[sv.Detections],\n    images: Iterable[WorkflowImageData],\n) -> List[sv.Detections]:\n    result = []\n    for prediction, image in zip(predictions, images):\n        result.append(\n            attach_parents_coordinates_to_sv_detections(\n                detections=prediction,\n                image=image,\n            )\n        )\n    return result\n\n\ndef attach_parents_coordinates_to_sv_detections(\n    detections: sv.Detections,\n    image: WorkflowImageData,\n) -> sv.Detections:\n    detections = attach_parent_coordinates_to_detections(\n        detections=detections,\n        parent_metadata=image.workflow_root_ancestor_metadata,\n        parent_id_key=ROOT_PARENT_ID_KEY,\n        coordinates_key=ROOT_PARENT_COORDINATES_KEY,\n        dimensions_key=ROOT_PARENT_DIMENSIONS_KEY,\n    )\n    return attach_parent_coordinates_to_detections(\n        detections=detections,\n        parent_metadata=image.parent_metadata,\n        parent_id_key=PARENT_ID_KEY,\n        coordinates_key=PARENT_COORDINATES_KEY,\n        dimensions_key=PARENT_DIMENSIONS_KEY,\n    )\n\n\ndef attach_parent_coordinates_to_detections(\n    detections: sv.Detections,\n    parent_metadata: ImageParentMetadata,\n    parent_id_key: str,\n    coordinates_key: str,\n    dimensions_key: str,\n) -> sv.Detections:\n    parent_coordinates_system = parent_metadata.origin_coordinates\n    detections[parent_id_key] = np.array([parent_metadata.parent_id] * len(detections))\n    coordinates = np.array(\n        [[parent_coordinates_system.left_top_x, parent_coordinates_system.left_top_y]]\n        * len(detections)\n    )\n    detections[coordinates_key] = coordinates\n    dimensions = np.array(\n        [\n            [\n                parent_coordinates_system.origin_height,\n                parent_coordinates_system.origin_width,\n            ]\n        ]\n        * len(detections)\n    )\n    detections[dimensions_key] = dimensions\n    return detections\n\n\nKEYS_REQUIRED_TO_EMBED_IN_ROOT_COORDINATES = {\n    ROOT_PARENT_COORDINATES_KEY,\n    ROOT_PARENT_DIMENSIONS_KEY,\n    ROOT_PARENT_ID_KEY,\n}\n\n\ndef sv_detections_to_root_coordinates(\n    detections: sv.Detections, keypoints_key: str = KEYPOINTS_XY_KEY_IN_SV_DETECTIONS\n) -> sv.Detections:\n    detections_copy = deepcopy(detections)\n    if len(detections_copy) == 0:\n        return detections_copy\n\n    if any(\n        key not in detections_copy.data\n        for key in KEYS_REQUIRED_TO_EMBED_IN_ROOT_COORDINATES\n    ):\n        logging.warning(\n            \"Could not execute detections_to_root_coordinates(...) on detections with \"\n            f\"the following metadata registered: {list(detections_copy.data.keys())}\"\n        )\n        return detections_copy\n    if SCALING_RELATIVE_TO_ROOT_PARENT_KEY in detections_copy.data:\n        scale = detections_copy[SCALING_RELATIVE_TO_ROOT_PARENT_KEY][0]\n        detections_copy = scale_sv_detections(\n            detections=detections,\n            scale=1 / scale,\n        )\n    detections_copy[SCALING_RELATIVE_TO_PARENT_KEY] = np.array(\n        [1.0] * len(detections_copy)\n    )\n    detections_copy[SCALING_RELATIVE_TO_ROOT_PARENT_KEY] = np.array(\n        [1.0] * len(detections_copy)\n    )\n    origin_height = detections_copy[ROOT_PARENT_DIMENSIONS_KEY][0][0]\n    origin_width = detections_copy[ROOT_PARENT_DIMENSIONS_KEY][0][1]\n    detections_copy[IMAGE_DIMENSIONS_KEY] = np.array(\n        [[origin_height, origin_width]] * len(detections_copy)\n    )\n    root_parent_id = detections_copy[ROOT_PARENT_ID_KEY][0]\n    shift_x, shift_y = detections_copy[ROOT_PARENT_COORDINATES_KEY][0]\n    detections_copy.xyxy += [shift_x, shift_y, shift_x, shift_y]\n    if keypoints_key in detections_copy.data:\n        for keypoints in detections_copy[keypoints_key]:\n            if len(keypoints):\n                keypoints += [shift_x, shift_y]\n    if detections_copy.mask is not None:\n        origin_mask_base = np.full((origin_height, origin_width), False)\n        new_anchored_masks = np.array(\n            [origin_mask_base.copy() for _ in detections_copy]\n        )\n        for anchored_mask, original_mask in zip(\n            new_anchored_masks, detections_copy.mask\n        ):\n            mask_h, mask_w = original_mask.shape\n            # TODO: instead of shifting mask we could store contours in data instead of storing mask (even if calculated)\n            #       it would be faster to shift contours but at expense of having to remember to generate mask from contour when it's needed\n            anchored_mask[shift_y : shift_y + mask_h, shift_x : shift_x + mask_w] = (\n                original_mask\n            )\n        detections_copy.mask = new_anchored_masks\n    new_root_metadata = ImageParentMetadata(\n        parent_id=root_parent_id,\n        origin_coordinates=OriginCoordinatesSystem(\n            left_top_y=0,\n            left_top_x=0,\n            origin_width=origin_width,\n            origin_height=origin_height,\n        ),\n    )\n    detections_copy = attach_parent_coordinates_to_detections(\n        detections=detections_copy,\n        parent_metadata=new_root_metadata,\n        parent_id_key=ROOT_PARENT_ID_KEY,\n        coordinates_key=ROOT_PARENT_COORDINATES_KEY,\n        dimensions_key=ROOT_PARENT_DIMENSIONS_KEY,\n    )\n    return attach_parent_coordinates_to_detections(\n        detections=detections_copy,\n        parent_metadata=new_root_metadata,\n        parent_id_key=PARENT_ID_KEY,\n        coordinates_key=PARENT_COORDINATES_KEY,\n        dimensions_key=PARENT_DIMENSIONS_KEY,\n    )\n\n\ndef filter_out_unwanted_classes_from_sv_detections_batch(\n    predictions: List[sv.Detections],\n    classes_to_accept: Optional[List[str]],\n) -> List[sv.Detections]:\n    if not classes_to_accept:\n        return predictions\n    filtered_predictions = []\n    for prediction in predictions:\n        filtered_prediction = prediction[\n            np.isin(prediction[CLASS_NAME_DATA_FIELD], classes_to_accept)\n        ]\n        filtered_predictions.append(filtered_prediction)\n    return filtered_predictions\n\n\ndef grab_batch_parameters(\n    operations_parameters: Dict[str, Any],\n    main_batch_size: int,\n) -> Dict[str, Any]:\n    return {\n        key: value.broadcast(n=main_batch_size)\n        for key, value in operations_parameters.items()\n        if isinstance(value, Batch)\n    }\n\n\ndef grab_non_batch_parameters(operations_parameters: Dict[str, Any]) -> Dict[str, Any]:\n    return {\n        key: value\n        for key, value in operations_parameters.items()\n        if not isinstance(value, Batch)\n    }\n\n\ndef scale_sv_detections(\n    detections: sv.Detections,\n    scale: float,\n    keypoints_key: str = KEYPOINTS_XY_KEY_IN_SV_DETECTIONS,\n) -> sv.Detections:\n    detections_copy = deepcopy(detections)\n    if len(detections_copy) == 0:\n        return detections_copy\n    detections_copy.xyxy = (detections_copy.xyxy * scale).round()\n    if keypoints_key in detections_copy.data:\n        for i in range(len(detections_copy[keypoints_key])):\n            detections_copy[keypoints_key][i] = (\n                detections_copy[keypoints_key][i].astype(np.float32) * scale\n            ).round()\n    detections_copy[IMAGE_DIMENSIONS_KEY] = (\n        detections_copy[IMAGE_DIMENSIONS_KEY] * scale\n    ).round()\n    if detections_copy.mask is not None:\n        scaled_masks = []\n        original_mask_size_wh = (\n            detections_copy.mask.shape[2],\n            detections_copy.mask.shape[1],\n        )\n        scaled_mask_size_wh = round(original_mask_size_wh[0] * scale), round(\n            original_mask_size_wh[1] * scale\n        )\n        for detection_mask in detections_copy.mask:\n            polygons = sv.mask_to_polygons(mask=detection_mask)\n            polygon_masks = []\n            for polygon in polygons:\n                scaled_polygon = (polygon * scale).round().astype(np.int32)\n                polygon_masks.append(\n                    sv.polygon_to_mask(\n                        polygon=scaled_polygon, resolution_wh=scaled_mask_size_wh\n                    )\n                )\n            scaled_detection_mask = np.sum(polygon_masks, axis=0) > 0\n            scaled_masks.append(scaled_detection_mask)\n        detections_copy.mask = np.array(scaled_masks)\n    if POLYGON_KEY_IN_SV_DETECTIONS in detections_copy.data:\n        detections_copy.data[POLYGON_KEY_IN_SV_DETECTIONS] = (\n            (detections_copy.data[POLYGON_KEY_IN_SV_DETECTIONS] * scale)\n            .round()\n            .astype(np.int32)\n        )\n    if SCALING_RELATIVE_TO_PARENT_KEY in detections_copy.data:\n        detections_copy[SCALING_RELATIVE_TO_PARENT_KEY] = (\n            detections_copy[SCALING_RELATIVE_TO_PARENT_KEY] * scale\n        )\n    else:\n        detections_copy[SCALING_RELATIVE_TO_PARENT_KEY] = np.array(\n            [scale] * len(detections_copy)\n        )\n    if SCALING_RELATIVE_TO_ROOT_PARENT_KEY in detections_copy.data:\n        detections_copy[SCALING_RELATIVE_TO_ROOT_PARENT_KEY] = (\n            detections_copy[SCALING_RELATIVE_TO_ROOT_PARENT_KEY] * scale\n        )\n    else:\n        detections_copy[SCALING_RELATIVE_TO_ROOT_PARENT_KEY] = np.array(\n            [scale] * len(detections_copy)\n        )\n    return detections_copy\n\n\ndef remove_unexpected_keys_from_dictionary(\n    dictionary: dict,\n    expected_keys: set,\n) -> dict:\n    \"\"\"This function mutates input `dictionary`\"\"\"\n    unexpected_keys = set(dictionary.keys()).difference(expected_keys)\n    for unexpected_key in unexpected_keys:\n        del dictionary[unexpected_key]\n    return dictionary\n\n\ndef post_process_ocr_result(\n    images: Batch[WorkflowImageData],\n    predictions: List[dict],\n    expected_output_keys: Set[str],\n) -> BlockResult:\n    for prediction, image in zip(predictions, images):\n        raw_predictions = prediction.get(\"predictions\", [])\n        prediction[\"predictions\"] = sv.Detections.from_inference(prediction)\n        if len(prediction[\"predictions\"]) != len(raw_predictions):\n            raw_predictions = filter_out_invalid_polygons(predictions=raw_predictions)\n        detection_ids = [\n            p.get(\"detection_id\", str(uuid.uuid4())) for p in raw_predictions\n        ]\n        prediction[\"predictions\"][\"detection_id\"] = detection_ids\n        prediction[PREDICTION_TYPE_KEY] = \"ocr\"\n        prediction[PARENT_ID_KEY] = image.parent_metadata.parent_id\n        prediction[ROOT_PARENT_ID_KEY] = image.workflow_root_ancestor_metadata.parent_id\n        _ = remove_unexpected_keys_from_dictionary(\n            dictionary=prediction,\n            expected_keys=expected_output_keys,\n        )\n    return predictions\n\n\ndef run_in_parallel(tasks: List[Callable[[], T]], max_workers: int = 1) -> List[T]:\n    tasks = _propagate_inference_context(tasks)\n    with ThreadPoolExecutor(max_workers=max_workers) as executor:\n        return list(executor.map(lambda f: f(), tasks))\n\n\ndef _propagate_inference_context(\n    tasks: List[Callable[[], T]],\n) -> List[Callable[[], T]]:\n    \"\"\"Wrap each task so that inference_sdk context vars and server-side\n    context vars are propagated into worker threads.  Returns the tasks\n    unchanged when no context is active.\n    \"\"\"\n    from inference.core.managers.model_load_collector import (\n        model_load_info,\n        request_model_ids,\n    )\n\n    load_collector = model_load_info.get(None)\n    ids_collector = request_model_ids.get(None)\n\n    try:\n        from asgi_correlation_id import correlation_id as _cid_ctx\n\n        corr_id = _cid_ctx.get()\n    except Exception:\n        corr_id = None\n\n    try:\n        from inference_sdk.config import (\n            apply_duration_minimum,\n            execution_id,\n            remote_processing_times,\n        )\n\n        exec_id = execution_id.get() if execution_id is not None else None\n        rpt_collector = (\n            remote_processing_times.get()\n            if remote_processing_times is not None\n            else None\n        )\n        duration_min = (\n            apply_duration_minimum.get() if apply_duration_minimum is not None else None\n        )\n    except ImportError:\n        exec_id = None\n        rpt_collector = None\n        duration_min = None\n\n    if (\n        exec_id is None\n        and rpt_collector is None\n        and duration_min is None\n        and load_collector is None\n        and ids_collector is None\n        and corr_id is None\n    ):\n        return tasks\n\n    def _wrap(fun: Callable[[], T]) -> Callable[[], T]:\n        def _with_context() -> T:\n            if corr_id is not None:\n                from asgi_correlation_id import correlation_id as _cid_ctx\n\n                _cid_ctx.set(corr_id)\n            if exec_id is not None:\n                from inference_sdk.config import execution_id\n\n                execution_id.set(exec_id)\n            if rpt_collector is not None:\n                from inference_sdk.config import remote_processing_times\n\n                remote_processing_times.set(rpt_collector)\n            if duration_min is not None:\n                from inference_sdk.config import apply_duration_minimum\n\n                apply_duration_minimum.set(duration_min)\n            if load_collector is not None:\n                model_load_info.set(load_collector)\n            if ids_collector is not None:\n                request_model_ids.set(ids_collector)\n            return fun()\n\n        return _with_context\n\n    return [_wrap(t) for t in tasks]\n",
    "patch": null
  },
  {
    "trace_id": "2b7a6ce7-150d-43d0-a391-46b6b8ba90e3",
    "function_name": "GLMOCRBlockV1.run_remotely",
    "file_path": "inference/core/workflows/core_steps/models/foundation/glm_ocr/v1.py",
    "speedup_x": 2.243296426557616,
    "review_quality": "medium",
    "pre_optimization_commit": "HEAD",
    "resolution_method": "db_code_only",
    "source": "db_features",
    "original_function_code": "    def run_remotely(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n    ) -> BlockResult:\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_CORE_MODEL_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        if WORKFLOWS_REMOTE_API_TARGET == \"hosted\":\n            client.select_api_v0()\n\n        prompt = prompt or DEFAULT_PROMPT\n\n        predictions = []\n        for image in images:\n            result = client.infer_lmm(\n                inference_input=image.base64_image,\n                model_id=model_version,\n                prompt=prompt,\n                model_id_in_path=True,\n            )\n            response_text = result.get(\"response\", result)\n            predictions.append({\"parsed_output\": response_text})\n\n        return predictions",
    "optimized_function_code": "from inference.core.env import HOSTED_CORE_MODEL_URL, LOCAL_INFERENCE_API_URL, WORKFLOWS_REMOTE_API_TARGET\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.entities import StepExecutionMode\nfrom inference.core.workflows.execution_engine.entities.base import Batch, WorkflowImageData\nfrom inference.core.workflows.prototypes.block import BlockResult, WorkflowBlock\nfrom inference_sdk import InferenceHTTPClient\nfrom typing import Optional\n\nDEFAULT_PROMPT = \"Text Recognition:\"\n\n\nclass GLMOCRBlockV1(WorkflowBlock):\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    def run_remotely(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n    ) -> BlockResult:\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_CORE_MODEL_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        if WORKFLOWS_REMOTE_API_TARGET == \"hosted\":\n            client.select_api_v0()\n\n        prompt = prompt or DEFAULT_PROMPT\n\n        image_inputs = [image.base64_image for image in images]\n        \n        results = client.infer_lmm(\n            inference_input=image_inputs,\n            model_id=model_version,\n            prompt=prompt,\n            model_id_in_path=True,\n        )\n        \n        if not isinstance(results, list):\n            results = [results]\n        \n        predictions = [\n            {\"parsed_output\": result.get(\"response\", result)}\n            for result in results\n        ]\n\n        return predictions",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/models/foundation/glm_ocr/v1.py\nfrom inference.core.env import HOSTED_CORE_MODEL_URL, LOCAL_INFERENCE_API_URL, WORKFLOWS_REMOTE_API_TARGET\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.entities import StepExecutionMode\nfrom inference.core.workflows.execution_engine.entities.base import Batch, WorkflowImageData\nfrom inference.core.workflows.prototypes.block import BlockResult, WorkflowBlock\nfrom inference_sdk import InferenceHTTPClient\nfrom typing import Optional\n\nDEFAULT_PROMPT = \"Text Recognition:\"\n\n\nclass GLMOCRBlockV1(WorkflowBlock):\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    def run_remotely(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n    ) -> BlockResult:\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_CORE_MODEL_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        if WORKFLOWS_REMOTE_API_TARGET == \"hosted\":\n            client.select_api_v0()\n\n        prompt = prompt or DEFAULT_PROMPT\n\n        image_inputs = [image.base64_image for image in images]\n        \n        results = client.infer_lmm(\n            inference_input=image_inputs,\n            model_id=model_version,\n            prompt=prompt,\n            model_id_in_path=True,\n        )\n        \n        if not isinstance(results, list):\n            results = [results]\n        \n        predictions = [\n            {\"parsed_output\": result.get(\"response\", result)}\n            for result in results\n        ]\n\n        return predictions\n```",
    "optimized_function_only": "    def run_remotely(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n    ) -> BlockResult:\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_CORE_MODEL_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        if WORKFLOWS_REMOTE_API_TARGET == \"hosted\":\n            client.select_api_v0()\n\n        prompt = prompt or DEFAULT_PROMPT\n\n        image_inputs = [image.base64_image for image in images]\n        \n        results = client.infer_lmm(\n            inference_input=image_inputs,\n            model_id=model_version,\n            prompt=prompt,\n            model_id_in_path=True,\n        )\n        \n        if not isinstance(results, list):\n            results = [results]\n        \n        predictions = [\n            {\"parsed_output\": result.get(\"response\", result)}\n            for result in results\n        ]\n\n        return predictions",
    "original_file_content": "from inference.core.env import HOSTED_CORE_MODEL_URL, LOCAL_INFERENCE_API_URL, WORKFLOWS_REMOTE_API_TARGET\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.entities import StepExecutionMode\nfrom inference.core.workflows.execution_engine.entities.base import Batch, WorkflowImageData\nfrom inference.core.workflows.prototypes.block import BlockResult, WorkflowBlock\nfrom inference_sdk import InferenceHTTPClient\nfrom typing import Optional\n\nDEFAULT_PROMPT = \"Text Recognition:\"\n\n\nclass GLMOCRBlockV1(WorkflowBlock):\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    def run_remotely(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n    ) -> BlockResult:\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_CORE_MODEL_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        if WORKFLOWS_REMOTE_API_TARGET == \"hosted\":\n            client.select_api_v0()\n\n        prompt = prompt or DEFAULT_PROMPT\n\n        predictions = []\n        for image in images:\n            result = client.infer_lmm(\n                inference_input=image.base64_image,\n                model_id=model_version,\n                prompt=prompt,\n                model_id_in_path=True,\n            )\n            response_text = result.get(\"response\", result)\n            predictions.append({\"parsed_output\": response_text})\n\n        return predictions",
    "patch": null
  },
  {
    "trace_id": "6b1bcc1c-0acb-4d9e-963c-65a5542ccb8b",
    "function_name": "BlockManifest.describe_outputs",
    "file_path": "inference/core/workflows/core_steps/models/foundation/glm_ocr/v1.py",
    "speedup_x": 8.3332417710563,
    "review_quality": "high",
    "pre_optimization_commit": "30bef2126dc5d10be627521312d0d2a7fac20b96",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(\n                name=\"parsed_output\",\n                kind=[STRING_KIND],\n                description=\"The recognized text from the image.\",\n            ),\n        ]\n",
    "optimized_function_code": "from inference.core.workflows.execution_engine.entities.base import OutputDefinition\nfrom inference.core.workflows.execution_engine.entities.types import STRING_KIND\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\nfrom typing import List\n\nLONG_DESCRIPTION = \"\"\"\nRecognize text in images using GLM-OCR, a vision language model by Zhipu AI specialized\nfor optical character recognition.\n\nGLM-OCR supports three built-in recognition modes controlled by the prompt:\n\n- **Text Recognition** (`Text Recognition:`) \u2014 General-purpose text recognition for\n  serial numbers, labels, scene text, and documents.\n- **Formula Recognition** (`Formula Recognition:`) \u2014 Recognizes mathematical formulas\n  and equations.\n- **Table Recognition** (`Table Recognition:`) \u2014 Recognizes table structures and content.\n\nYou can also provide a custom prompt for specialized recognition tasks.\n\nThis block pairs well with detection models and DynamicCropBlock to isolate regions of\ninterest before running OCR. For example, use an object detection model to find labels\nor text regions, crop them, then pass the crops to GLM-OCR.\n\nNote: GLM-OCR requires a GPU for inference.\n\"\"\"\n\n_CACHED_OUTPUT_DEFINITIONS = [\n    OutputDefinition(\n        name=\"parsed_output\",\n        kind=[STRING_KIND],\n        description=\"The recognized text from the image.\",\n    ),\n]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return _CACHED_OUTPUT_DEFINITIONS",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/models/foundation/glm_ocr/v1.py\nfrom inference.core.workflows.execution_engine.entities.base import OutputDefinition\nfrom inference.core.workflows.execution_engine.entities.types import STRING_KIND\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\nfrom typing import List\n\nLONG_DESCRIPTION = \"\"\"\nRecognize text in images using GLM-OCR, a vision language model by Zhipu AI specialized\nfor optical character recognition.\n\nGLM-OCR supports three built-in recognition modes controlled by the prompt:\n\n- **Text Recognition** (`Text Recognition:`) \u2014 General-purpose text recognition for\n  serial numbers, labels, scene text, and documents.\n- **Formula Recognition** (`Formula Recognition:`) \u2014 Recognizes mathematical formulas\n  and equations.\n- **Table Recognition** (`Table Recognition:`) \u2014 Recognizes table structures and content.\n\nYou can also provide a custom prompt for specialized recognition tasks.\n\nThis block pairs well with detection models and DynamicCropBlock to isolate regions of\ninterest before running OCR. For example, use an object detection model to find labels\nor text regions, crop them, then pass the crops to GLM-OCR.\n\nNote: GLM-OCR requires a GPU for inference.\n\"\"\"\n\n_CACHED_OUTPUT_DEFINITIONS = [\n    OutputDefinition(\n        name=\"parsed_output\",\n        kind=[STRING_KIND],\n        description=\"The recognized text from the image.\",\n    ),\n]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return _CACHED_OUTPUT_DEFINITIONS\n```",
    "optimized_function_only": "    def describe_outputs(cls) -> List[OutputDefinition]:\n        return _CACHED_OUTPUT_DEFINITIONS",
    "original_file_content": "from typing import List, Literal, Optional, Type, Union\n\nfrom pydantic import ConfigDict, Field, model_validator\n\nfrom inference.core.entities.requests.inference import LMMInferenceRequest\nfrom inference.core.env import (\n    HOSTED_CORE_MODEL_URL,\n    LOCAL_INFERENCE_API_URL,\n    WORKFLOWS_REMOTE_API_TARGET,\n)\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.entities import StepExecutionMode\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    IMAGE_KIND,\n    ROBOFLOW_MODEL_ID_KIND,\n    STRING_KIND,\n    ImageInputField,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\nfrom inference_sdk import InferenceHTTPClient\n\nTASK_TYPE_TO_PROMPT = {\n    \"text-recognition\": \"Text Recognition:\",\n    \"table-recognition\": \"Table Recognition:\",\n    \"formula-recognition\": \"Formula Recognition:\",\n    \"custom\": None,\n}\n\nTaskType = Literal[\n    \"text-recognition\", \"table-recognition\", \"formula-recognition\", \"custom\"\n]\n\nTASKS_METADATA = {\n    \"text-recognition\": {\n        \"name\": \"Text Recognition\",\n        \"description\": \"General-purpose text recognition for serial numbers, labels, scene text, and documents.\",\n    },\n    \"table-recognition\": {\n        \"name\": \"Table Recognition\",\n        \"description\": \"Recognizes table structures and content.\",\n    },\n    \"formula-recognition\": {\n        \"name\": \"Formula Recognition\",\n        \"description\": \"Recognizes mathematical formulas and equations.\",\n    },\n    \"custom\": {\n        \"name\": \"Custom Prompt\",\n        \"description\": \"Provide your own prompt for specialized recognition tasks.\",\n    },\n}\n\nTASKS_REQUIRING_PROMPT = {\"custom\"}\n\nLONG_DESCRIPTION = \"\"\"\nRecognize text in images using GLM-OCR, a vision language model by Zhipu AI specialized\nfor optical character recognition.\n\nGLM-OCR supports three built-in recognition modes:\n\n- **Text Recognition** \u2014 General-purpose text recognition for\n  serial numbers, labels, scene text, and documents.\n- **Formula Recognition** \u2014 Recognizes mathematical formulas\n  and equations.\n- **Table Recognition** \u2014 Recognizes table structures and content.\n\nYou can also select **Custom Prompt** to provide your own prompt for specialized\nrecognition tasks.\n\nThis block pairs well with detection models and DynamicCropBlock to isolate regions of\ninterest before running OCR. For example, use an object detection model to find labels\nor text regions, crop them, then pass the crops to GLM-OCR.\n\nNote: GLM-OCR requires a GPU for inference.\n\"\"\"\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    images: Selector(kind=[IMAGE_KIND]) = ImageInputField\n\n    task_type: TaskType = Field(\n        default=\"text-recognition\",\n        description=\"Recognition task to perform. Determines the prompt sent to GLM-OCR.\",\n        json_schema_extra={\n            \"values_metadata\": TASKS_METADATA,\n            \"always_visible\": True,\n        },\n    )\n\n    prompt: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Custom text prompt for GLM-OCR. Only used when task_type is 'custom'.\",\n        examples=[\"Describe the text in the image.\"],\n        json_schema_extra={\n            \"relevant_for\": {\n                \"task_type\": {\"values\": TASKS_REQUIRING_PROMPT, \"required\": True},\n            },\n        },\n    )\n\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"GLM-OCR\",\n            \"version\": \"v1\",\n            \"short_description\": \"Run GLM-OCR on an image to recognize text.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"model\",\n            \"search_keywords\": [\n                \"GLM-OCR\",\n                \"glm\",\n                \"OCR\",\n                \"text recognition\",\n                \"formula recognition\",\n                \"table recognition\",\n                \"Zhipu\",\n            ],\n            \"is_vlm_block\": True,\n            \"ui_manifest\": {\n                \"section\": \"model\",\n                \"icon\": \"far fa-text\",\n                \"blockPriority\": 11,\n                \"inDevelopment\": False,\n                \"inference\": True,\n            },\n        },\n        protected_namespaces=(),\n    )\n    type: Literal[\"roboflow_core/glm_ocr@v1\"]\n\n    model_version: Union[Selector(kind=[ROBOFLOW_MODEL_ID_KIND]), str] = Field(\n        default=\"glm-ocr\",\n        description=\"The GLM-OCR model to be used for inference.\",\n        examples=[\"glm-ocr\"],\n    )\n\n    @model_validator(mode=\"after\")\n    def validate_prompt(self) -> \"BlockManifest\":\n        if self.task_type == \"custom\" and not self.prompt:\n            raise ValueError(\"`prompt` is required when task_type is 'custom'.\")\n        return self\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(\n                name=\"parsed_output\",\n                kind=[STRING_KIND],\n                description=\"The recognized text from the image.\",\n            ),\n        ]\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return [\"images\"]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\ndef _resolve_prompt(task_type: str, prompt: Optional[str]) -> str:\n    if task_type == \"custom\":\n        return prompt\n    return TASK_TYPE_TO_PROMPT[task_type]\n\n\nclass GLMOCRBlockV1(WorkflowBlock):\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"model_manager\", \"api_key\", \"step_execution_mode\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        task_type: str,\n        prompt: Optional[str],\n    ) -> BlockResult:\n        resolved_prompt = _resolve_prompt(task_type, prompt)\n        if self._step_execution_mode == StepExecutionMode.LOCAL:\n            return self.run_locally(\n                images=images,\n                model_version=model_version,\n                prompt=resolved_prompt,\n            )\n        elif self._step_execution_mode == StepExecutionMode.REMOTE:\n            return self.run_remotely(\n                images=images,\n                model_version=model_version,\n                prompt=resolved_prompt,\n            )\n        else:\n            raise ValueError(\n                f\"Unknown step execution mode: {self._step_execution_mode}\"\n            )\n\n    def run_remotely(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: str,\n    ) -> BlockResult:\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_CORE_MODEL_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        if WORKFLOWS_REMOTE_API_TARGET == \"hosted\":\n            client.select_api_v0()\n\n        predictions = []\n        for image in images:\n            result = client.infer_lmm(\n                inference_input=image.base64_image,\n                model_id=model_version,\n                prompt=prompt,\n                model_id_in_path=True,\n            )\n            response_text = result.get(\"response\", result)\n            predictions.append({\"parsed_output\": response_text})\n\n        return predictions\n\n    def run_locally(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: str,\n    ) -> BlockResult:\n        inference_images = [\n            i.to_inference_format(numpy_preferred=False) for i in images\n        ]\n\n        self._model_manager.add_model(model_id=model_version, api_key=self._api_key)\n\n        predictions = []\n        for image in inference_images:\n            request = LMMInferenceRequest(\n                api_key=self._api_key,\n                model_id=model_version,\n                image=image,\n                source=\"workflow-execution\",\n                prompt=prompt,\n            )\n            prediction = self._model_manager.infer_from_request_sync(\n                model_id=model_version, request=request\n            )\n            response_text = prediction.response\n            predictions.append({\"parsed_output\": response_text})\n\n        return predictions\n",
    "patch": null
  },
  {
    "trace_id": "df1afec0-f978-4a61-9d7f-8b1d04f978a7",
    "function_name": "default_encoder",
    "file_path": "inference/core/interfaces/webrtc_worker/webrtc.py",
    "speedup_x": 0.1245199084857942,
    "review_quality": "high",
    "pre_optimization_commit": "6be60da204e3270053ac60ebb4b47556380af161",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def default_encoder(obj: Any) -> Any:\n    if isinstance(obj, bytes):\n        return base64.b64encode(obj).decode(\"ascii\")\n    return obj\n",
    "optimized_function_code": "import binascii\nfrom typing import Any\n\n\ndef default_encoder(obj: Any) -> Any:\n    if isinstance(obj, bytes):\n        return binascii.b2a_base64(obj, newline=False).decode(\"ascii\")\n    return obj",
    "optimized_raw_markdown": "```python:inference/core/interfaces/webrtc_worker/webrtc.py\nimport binascii\nfrom typing import Any\n\n\ndef default_encoder(obj: Any) -> Any:\n    if isinstance(obj, bytes):\n        return binascii.b2a_base64(obj, newline=False).decode(\"ascii\")\n    return obj\n```",
    "optimized_function_only": "def default_encoder(obj: Any) -> Any:\n    if isinstance(obj, bytes):\n        return binascii.b2a_base64(obj, newline=False).decode(\"ascii\")\n    return obj",
    "original_file_content": "import asyncio\nimport base64\nimport datetime\nimport gzip\nimport json\nimport logging\nimport struct\nimport time\nfrom typing import Any, Callable, Dict, List, Optional, Tuple\n\nimport orjson\nimport supervision as sv\nfrom aioice import ice\nfrom aiortc import (\n    RTCConfiguration,\n    RTCDataChannel,\n    RTCIceServer,\n    RTCPeerConnection,\n    RTCSessionDescription,\n    VideoStreamTrack,\n)\nfrom aiortc.contrib.media import MediaPlayer, MediaRelay, PlayerStreamTrack\nfrom aiortc.mediastreams import MediaStreamError, MediaStreamTrack\nfrom aiortc.rtcrtpreceiver import RemoteStreamTrack\nfrom av import VideoFrame\nfrom av import logging as av_logging\nfrom pydantic import ValidationError\n\nfrom inference.core import logger\nfrom inference.core.env import (\n    WEBRTC_DATA_CHANNEL_ACK_WINDOW,\n    WEBRTC_DATA_CHANNEL_BUFFER_DRAINING_DELAY,\n    WEBRTC_DATA_CHANNEL_BUFFER_SIZE_LIMIT,\n    WEBRTC_GZIP_PREVIEW_FRAME_COMPRESSION,\n    WEBRTC_MODAL_PUBLIC_STUN_SERVERS,\n    WEBRTC_MODAL_RTSP_PLACEHOLDER,\n    WEBRTC_MODAL_RTSP_PLACEHOLDER_URL,\n    WEBRTC_MODAL_SHUTDOWN_RESERVE,\n)\nfrom inference.core.exceptions import (\n    MissingApiKeyError,\n    RoboflowAPINotAuthorizedError,\n    RoboflowAPINotNotFoundError,\n    WebRTCConfigurationError,\n)\nfrom inference.core.interfaces.camera.entities import VideoFrameProducer\nfrom inference.core.interfaces.stream.inference_pipeline import InferencePipeline\nfrom inference.core.interfaces.stream_manager.manager_app.entities import (\n    WebRTCData,\n    WorkflowConfiguration,\n)\nfrom inference.core.interfaces.webrtc_worker.entities import (\n    DataOutputMode,\n    StreamOutputMode,\n    WebRTCOutput,\n    WebRTCVideoMetadata,\n    WebRTCWorkerRequest,\n    WebRTCWorkerResult,\n)\nfrom inference.core.interfaces.webrtc_worker.serializers import serialize_for_webrtc\nfrom inference.core.interfaces.webrtc_worker.sources.file import (\n    ThreadedVideoFileTrack,\n    VideoFileUploadHandler,\n)\nfrom inference.core.interfaces.webrtc_worker.utils import (\n    detect_image_output,\n    get_cv2_rotation_code,\n    get_video_fps,\n    get_video_rotation,\n    parse_video_file_chunk,\n    process_frame,\n    rotate_video_frame,\n)\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.roboflow_api import get_workflow_specification\nfrom inference.core.workflows.errors import WorkflowError, WorkflowSyntaxError\nfrom inference.core.workflows.execution_engine.entities.base import WorkflowImageData\nfrom inference.usage_tracking.collector import usage_collector\n\nlogging.getLogger(\"aiortc\").setLevel(logging.WARNING)\n\n# WebRTC data channel chunking configuration\nCHUNK_SIZE = 48 * 1024  # 48KB - safe for all WebRTC implementations\n\n\ndef create_chunked_binary_message(\n    frame_id: int, chunk_index: int, total_chunks: int, payload: bytes\n) -> bytes:\n    \"\"\"Create a binary message with standard 12-byte header.\n\n    Format: [frame_id: 4][chunk_index: 4][total_chunks: 4][payload: N]\n    All integers are uint32 little-endian.\n    \"\"\"\n    header = struct.pack(\"<III\", frame_id, chunk_index, total_chunks)\n    return header + payload\n\n\nasync def wait_for_buffer_drain(\n    data_channel: RTCDataChannel,\n    timeout: float = 30.0,\n    heartbeat_callback: Optional[Callable[[], None]] = None,\n    low_threshold: Optional[int] = None,\n) -> bool:\n    \"\"\"Wait for data channel buffer to drain below threshold, with timeout.\n\n    We use a low threshold (1/4 of limit) instead of just below the limit to avoid\n    hysteresis - constantly triggering this wait after sending just a few chunks.\n\n    And we wait WEBRTC_DATA_CHANNEL_BUFFER_DRAINING_DELAY to avoid starving the\n    event loop.\n    \"\"\"\n    if low_threshold is None:\n        low_threshold = WEBRTC_DATA_CHANNEL_BUFFER_SIZE_LIMIT // 4\n\n    start_time = asyncio.get_event_loop().time()\n\n    while data_channel.bufferedAmount > low_threshold:\n        elapsed = asyncio.get_event_loop().time() - start_time\n        if elapsed > timeout:\n            logger.error(\"[BUFFER_DRAIN] Timeout after %.1fs\", timeout)\n            return False\n        if data_channel.readyState != \"open\":\n            logger.error(\"[BUFFER_DRAIN] Channel closed: %s\", data_channel.readyState)\n            return False\n        if heartbeat_callback:\n            heartbeat_callback()\n        await asyncio.sleep(WEBRTC_DATA_CHANNEL_BUFFER_DRAINING_DELAY)\n\n    return True\n\n\nasync def send_chunked_data(\n    data_channel: RTCDataChannel,\n    frame_id: int,\n    payload_bytes: bytes,\n    chunk_size: int = CHUNK_SIZE,\n    heartbeat_callback: Optional[Callable[[], None]] = None,\n    buffer_timeout: float = 120.0,\n) -> bool:\n    \"\"\"Send payload via data channel with chunking and backpressure.\n\n    We chunk large payloads because WebRTC data channels have message size limits.\n    We apply backpressure (wait for buffer to drain) to avoid overwhelming the\n    network and causing ICE connection failures.\n\n    Heads up: buffer_timeout needs to be higher than WEBRTC_DATA_CHANNEL_BUFFER_DRAINING_DELAY!\n    Otherwise we will timeout ourselves.\n    \"\"\"\n\n    if buffer_timeout <= WEBRTC_DATA_CHANNEL_BUFFER_DRAINING_DELAY:\n        logger.warning(\n            \"[SEND_CHUNKED] buffer_timeout (%.2fs) <= WEBRTC_DATA_CHANNEL_BUFFER_DRAINING_DELAY (%.2fs), \"\n            \"this will likely cause immediate timeouts during buffer drain\",\n            buffer_timeout,\n            WEBRTC_DATA_CHANNEL_BUFFER_DRAINING_DELAY,\n        )\n\n    if data_channel.readyState != \"open\":\n        return False\n\n    payload_size = len(payload_bytes)\n    total_chunks = (payload_size + chunk_size - 1) // chunk_size\n    view = memoryview(payload_bytes)\n    high_threshold = WEBRTC_DATA_CHANNEL_BUFFER_SIZE_LIMIT\n\n    for chunk_index in range(total_chunks):\n        if data_channel.readyState != \"open\":\n            logger.error(\n                \"[SEND_CHUNKED] Channel closed at chunk %d/%d\",\n                chunk_index,\n                total_chunks,\n            )\n            return False\n\n        start = chunk_index * chunk_size\n        end = min(start + chunk_size, payload_size)\n        chunk_data = view[start:end]\n\n        message = create_chunked_binary_message(\n            frame_id, chunk_index, total_chunks, chunk_data\n        )\n\n        if data_channel.bufferedAmount > high_threshold:\n            if not await wait_for_buffer_drain(\n                data_channel, buffer_timeout, heartbeat_callback\n            ):\n                logger.error(\n                    \"[SEND_CHUNKED] Buffer drain failed at chunk %d/%d\",\n                    chunk_index,\n                    total_chunks,\n                )\n                return False\n\n        data_channel.send(message)\n\n        if heartbeat_callback:\n            heartbeat_callback()\n        await asyncio.sleep(0.001)\n\n    return True\n\n\nclass RTCPeerConnectionWithLoop(RTCPeerConnection):\n    def __init__(\n        self,\n        asyncio_loop: asyncio.AbstractEventLoop,\n        *args,\n        **kwargs,\n    ):\n        super().__init__(*args, **kwargs)\n        self._loop = asyncio_loop\n\n\nclass VideoFrameProcessor:\n    \"\"\"Base class for processing video frames through workflow.\n\n    Can be used independently for data-only processing (no video track output)\n    or as a base for VideoTransformTrackWithLoop when video output is needed.\n    \"\"\"\n\n    def __init__(\n        self,\n        asyncio_loop: asyncio.AbstractEventLoop,\n        workflow_configuration: WorkflowConfiguration,\n        api_key: str,\n        model_manager: Optional[ModelManager] = None,\n        data_output: Optional[List[str]] = None,\n        stream_output: Optional[str] = None,\n        has_video_track: bool = True,\n        declared_fps: float = 30,\n        termination_date: Optional[datetime.datetime] = None,\n        terminate_event: Optional[asyncio.Event] = None,\n        heartbeat_callback: Optional[Callable[[], None]] = None,\n        realtime_processing: bool = True,\n        is_preview: bool = False,\n    ):\n        self._file_processing = False\n        self._loop = asyncio_loop\n        self._termination_date = termination_date\n        self._terminate_event = terminate_event\n        self.track: Optional[MediaStreamTrack] = None\n        self._track_active: bool = False\n        self._av_logging_set: bool = False\n        self._received_frames = 0\n        self._declared_fps = declared_fps\n        self._fps_monitor = sv.FPSMonitor()\n        self._stop_processing = False\n        self._termination_reason: Optional[str] = None\n        self._processing_complete_sent = False\n        self.heartbeat_callback = heartbeat_callback\n\n        self.has_video_track = has_video_track\n        self.stream_output = stream_output\n        self.data_channel: Optional[RTCDataChannel] = None\n\n        # Video file upload support\n        self.video_upload_handler: Optional[VideoFileUploadHandler] = None\n        self._track_ready_event: asyncio.Event = asyncio.Event()\n        self.realtime_processing = realtime_processing\n        self._rotation_code: Optional[int] = None\n\n        # Optional receiver-paced flow control (enabled only after first ACK is received)\n        self._ack_last: int = 0\n        # If ack=1 and window=4, server may produce/send up to frame 5.\n        # Configurable via WEBRTC_DATACHANNEL_ACK_WINDOW env var.\n        self._ack_window: int = WEBRTC_DATA_CHANNEL_ACK_WINDOW\n        self._ack_event: asyncio.Event = asyncio.Event()\n\n        if data_output is None:\n            self.data_output = None\n            self._data_mode = DataOutputMode.NONE\n        elif isinstance(data_output, list):\n            self.data_output = [f for f in data_output if f]\n            if self.data_output == [\"*\"]:\n                self._data_mode = DataOutputMode.ALL\n            elif len(self.data_output) == 0:\n                self._data_mode = DataOutputMode.NONE\n            else:\n                self._data_mode = DataOutputMode.SPECIFIC\n        else:\n            raise WebRTCConfigurationError(\n                f\"data_output must be list or None, got {type(data_output).__name__}\"\n            )\n\n        self._validate_output_fields(workflow_configuration)\n\n        self._inference_pipeline = InferencePipeline.init_with_workflow(\n            video_reference=VideoFrameProducer,\n            workflow_specification=workflow_configuration.workflow_specification,\n            workspace_name=workflow_configuration.workspace_name,\n            workflow_id=workflow_configuration.workflow_id,\n            api_key=api_key,\n            image_input_name=workflow_configuration.image_input_name,\n            workflows_parameters=workflow_configuration.workflows_parameters,\n            workflows_thread_pool_workers=workflow_configuration.workflows_thread_pool_workers,\n            cancel_thread_pool_tasks_on_exit=workflow_configuration.cancel_thread_pool_tasks_on_exit,\n            video_metadata_input_name=workflow_configuration.video_metadata_input_name,\n            model_manager=model_manager,\n            _is_preview=is_preview,\n            workflow_version_id=workflow_configuration.workflow_version_id,\n        )\n\n    def set_track(self, track: MediaStreamTrack, rotation_code: Optional[int] = None):\n        if not self.track:\n            self.track = track\n            self._rotation_code = rotation_code\n            self._track_ready_event.set()\n\n    async def close(self):\n        self._track_active = False\n        self._stop_processing = True\n        # Clean up video upload handler if present\n        if self.video_upload_handler is not None:\n            await self.video_upload_handler.cleanup()\n\n    def record_ack(self, ack: int) -> None:\n        \"\"\"Record cumulative ACK from the client.\n\n        ACK semantics: client has fully handled all frames <= ack.\n        Backwards compatible: pacing is disabled until we receive the first ACK.\n        \"\"\"\n        try:\n            ack_int = int(ack)\n        except (TypeError, ValueError):\n            logger.warning(\"Invalid ACK value: %s\", ack)\n            return\n        if ack_int < 0:\n            logger.warning(\"Invalid ACK value: %s\", ack)\n            return\n        if ack_int > self._ack_last:\n            if ack_int % 100 == 1:\n                logger.info(\"ACK received: %s\", ack_int)\n            self._ack_last = ack_int\n            self._ack_event.set()\n\n    async def _wait_for_ack_window(self, next_frame_id: int) -> None:\n        \"\"\"Block frame production when too far ahead of client ACKs.\"\"\"\n        if self.realtime_processing or self._ack_last == 0:\n            return\n\n        wait_counter = 0\n        while not self._stop_processing and next_frame_id > (\n            self._ack_last + self._ack_window\n        ):\n            if self._check_termination():\n                return\n            if self.heartbeat_callback:\n                self.heartbeat_callback()\n\n            self._ack_event.clear()\n            try:\n                await asyncio.wait_for(self._ack_event.wait(), timeout=0.2)\n            except asyncio.TimeoutError:\n                wait_counter += 1\n                if wait_counter % 5 == 1:\n                    logger.info(\n                        \"Waiting for ACK window (next=%d, ack_last=%d, window=%d)\",\n                        next_frame_id,\n                        self._ack_last,\n                        self._ack_window,\n                    )\n\n    def _check_termination(self):\n        \"\"\"Check if we should terminate based on timeout.\n\n        Does NOT set terminate_event \u2014 callers must call _signal_termination()\n        after sending final data-channel messages to avoid a race with the\n        cleanup task closing the peer connection.\n        \"\"\"\n        if self._termination_date and self._termination_date < datetime.datetime.now():\n            logger.info(\"Timeout reached, terminating inference pipeline\")\n            self._termination_reason = \"timeout_reached\"\n            return True\n        if self._terminate_event and self._terminate_event.is_set():\n            logger.info(\"Terminate event set, terminating inference pipeline\")\n            return True\n        return False\n\n    def _signal_termination(self):\n        if self._terminate_event:\n            self._terminate_event.set()\n\n    @staticmethod\n    def serialize_outputs_sync(\n        fields_to_send: List[str],\n        workflow_output: Dict[str, Any],\n        data_output_mode: DataOutputMode,\n    ) -> Tuple[Dict[str, Any], List[str]]:\n        \"\"\"Serialize workflow outputs for WebRTC transmission.\"\"\"\n        serialized = {}\n        serialization_errors = []\n\n        for field_name in fields_to_send:\n            if field_name not in workflow_output:\n                serialization_errors.append(f\"Output '{field_name}' not found\")\n                continue\n\n            output_data = workflow_output[field_name]\n\n            if data_output_mode == DataOutputMode.ALL and isinstance(\n                output_data, WorkflowImageData\n            ):\n                continue\n\n            try:\n                serialized[field_name] = serialize_for_webrtc(output_data)\n            except Exception as e:\n                serialization_errors.append(f\"{field_name}: {e}\")\n                serialized[field_name] = {\"__serialization_error__\": str(e)}\n                logger.error(\"[SERIALIZE] Error: %s - %s\", field_name, e)\n\n        return serialized, serialization_errors\n\n    async def _send_data_output(\n        self,\n        workflow_output: Dict[str, Any],\n        frame_timestamp: datetime.datetime,\n        frame: VideoFrame,\n        errors: List[str],\n    ):\n        frame_id = self._received_frames\n\n        if not self.data_channel or self.data_channel.readyState != \"open\":\n            return\n\n        video_metadata = WebRTCVideoMetadata(\n            frame_id=frame_id,\n            received_at=frame_timestamp.isoformat(),\n            pts=frame.pts,\n            time_base=frame.time_base,\n            declared_fps=self._declared_fps,\n            height=frame.height,\n            width=frame.width,\n        )\n\n        webrtc_output = WebRTCOutput(\n            serialized_output_data=None,\n            video_metadata=video_metadata,\n            errors=errors.copy(),\n        )\n\n        if self._data_mode == DataOutputMode.NONE:\n            json_bytes = await asyncio.to_thread(\n                lambda: json.dumps(webrtc_output.model_dump()).encode(\"utf-8\")\n            )\n            await send_chunked_data(\n                self.data_channel,\n                frame_id,\n                json_bytes,\n                heartbeat_callback=self.heartbeat_callback,\n            )\n            return\n\n        if self._data_mode == DataOutputMode.ALL:\n            fields_to_send = list(workflow_output.keys())\n        else:\n            fields_to_send = self.data_output\n\n        serialized_outputs, serialization_errors = await asyncio.to_thread(\n            VideoFrameProcessor.serialize_outputs_sync,\n            fields_to_send,\n            workflow_output,\n            self._data_mode,\n        )\n\n        webrtc_output.errors.extend(serialization_errors)\n        if serialized_outputs:\n            webrtc_output.serialized_output_data = serialized_outputs\n\n        # TODO: use orjson\n        json_bytes = await asyncio.to_thread(\n            lambda: orjson.dumps(\n                webrtc_output.model_dump(),\n                default=default_encoder,\n                option=orjson.OPT_NON_STR_KEYS | orjson.OPT_SERIALIZE_NUMPY,\n            )\n        )\n\n        if WEBRTC_GZIP_PREVIEW_FRAME_COMPRESSION:\n\n            def compress_json():\n                return gzip.compress(json_bytes, compresslevel=6)\n\n            output_bytes = await asyncio.to_thread(compress_json)\n        else:\n            output_bytes = json_bytes\n\n        success = await send_chunked_data(\n            self.data_channel,\n            frame_id,\n            output_bytes,\n            heartbeat_callback=self.heartbeat_callback,\n        )\n        if not success:\n            logger.error(\"[SEND_OUTPUT] Frame %d failed\", frame_id)\n\n    async def _send_processing_complete(self):\n        \"\"\"Send final message indicating processing is complete.\n\n        Also drains the data channel buffer to ensure delivery before the\n        connection is closed.\n        \"\"\"\n        if self._processing_complete_sent:\n            return\n        if not self.data_channel or self.data_channel.readyState != \"open\":\n            return\n\n        self._processing_complete_sent = True\n        completion_output = WebRTCOutput(\n            processing_complete=True,\n            termination_reason=self._termination_reason,\n            video_metadata=WebRTCVideoMetadata(\n                frame_id=self._received_frames,\n                received_at=datetime.datetime.now().isoformat(),\n            ),\n        )\n        json_bytes = json.dumps(completion_output.model_dump()).encode(\"utf-8\")\n        await send_chunked_data(\n            self.data_channel, self._received_frames + 1, json_bytes\n        )\n        if not await wait_for_buffer_drain(\n            self.data_channel, timeout=2.0, low_threshold=0\n        ):\n            logger.warning(\n                \"Buffer drain timed out, processing_complete may not reach client\"\n            )\n\n    async def process_frames_data_only(self):\n        \"\"\"Process frames for data extraction only, without video track output.\"\"\"\n        if not self._av_logging_set:\n            av_logging.set_libav_level(av_logging.ERROR)\n            self._av_logging_set = True\n\n        try:\n            while not self._stop_processing:\n                await self._wait_for_ack_window(next_frame_id=self._received_frames + 1)\n                if self._check_termination():\n                    await self._send_processing_complete()\n                    self._signal_termination()\n                    break\n                if self.heartbeat_callback:\n                    self.heartbeat_callback()\n                if not self.track or self.track.readyState == \"ended\":\n                    break\n\n                # Drain queue for realtime RTSP\n                if (\n                    isinstance(self.track, PlayerStreamTrack)\n                    and self.realtime_processing\n                ):\n                    while self.track._queue.qsize() > 30:\n                        self.track._queue.get_nowait()\n\n                frame = await self.track.recv()\n                self._received_frames += 1\n                self._fps_monitor.tick()\n                frame_timestamp = datetime.datetime.now()\n\n                workflow_output, _, errors = await self._process_frame_async(\n                    frame=frame,\n                    frame_id=self._received_frames,\n                    render_output=False,\n                    include_errors_on_frame=False,\n                )\n\n                await self._send_data_output(\n                    workflow_output, frame_timestamp, frame, errors\n                )\n\n        except asyncio.CancelledError as exc:\n            # No one will catch this exception as it's executed in a create_task\n            logger.info(\"[DATA_ONLY] Processing cancelled: %s\", exc)\n        except MediaStreamError as exc:\n            logger.info(\"[DATA_ONLY] Media stream ended: %s\", exc)\n        except Exception as exc:\n            logger.error(\n                \"[DATA_ONLY] Error at frame %d: %s\", self._received_frames, exc\n            )\n        finally:\n            await self._send_processing_complete()\n\n    @staticmethod\n    def _ensure_workflow_specification(\n        workflow_configuration: WorkflowConfiguration, api_key: str\n    ) -> None:\n        has_specification = workflow_configuration.workflow_specification is not None\n        has_workspace_and_workflow_id = (\n            workflow_configuration.workspace_name is not None\n            and workflow_configuration.workflow_id is not None\n        )\n\n        if not has_specification and not has_workspace_and_workflow_id:\n            raise WebRTCConfigurationError(\n                \"Either 'workflow_specification' or both 'workspace_name' and 'workflow_id' must be provided\"\n            )\n\n        if not has_specification and has_workspace_and_workflow_id:\n            try:\n                workflow_configuration.workflow_specification = (\n                    get_workflow_specification(\n                        api_key=api_key,\n                        workspace_id=workflow_configuration.workspace_name,\n                        workflow_id=workflow_configuration.workflow_id,\n                        workflow_version_id=workflow_configuration.workflow_version_id,\n                    )\n                )\n                workflow_configuration.workspace_name = None\n                workflow_configuration.workflow_id = None\n            except Exception as e:\n                raise WebRTCConfigurationError(\n                    f\"Failed to fetch workflow specification from API: {str(e)}\"\n                )\n\n    def _validate_output_fields(\n        self, workflow_configuration: WorkflowConfiguration\n    ) -> None:\n        if workflow_configuration.workflow_specification is None:\n            return\n\n        workflow_outputs = workflow_configuration.workflow_specification.get(\n            \"outputs\", []\n        )\n        available_output_names = [o.get(\"name\") for o in workflow_outputs]\n\n        if self._data_mode == DataOutputMode.SPECIFIC:\n            invalid_fields = [\n                field\n                for field in self.data_output\n                if field not in available_output_names\n            ]\n            if invalid_fields:\n                raise WebRTCConfigurationError(\n                    f\"Invalid data_output fields: {invalid_fields}. \"\n                    f\"Available workflow outputs: {available_output_names}\"\n                )\n\n        if self.stream_output and self.stream_output not in available_output_names:\n            raise WebRTCConfigurationError(\n                f\"Invalid stream_output field: '{self.stream_output}'. \"\n                f\"Available workflow outputs: {available_output_names}\"\n            )\n\n    async def _process_frame_async(\n        self,\n        frame: VideoFrame,\n        frame_id: int,\n        stream_output: Optional[str] = None,\n        render_output: bool = True,\n        include_errors_on_frame: bool = True,\n    ) -> Tuple[Dict[str, Any], Optional[VideoFrame], List[str]]:\n        \"\"\"Async wrapper for process_frame using executor.\"\"\"\n\n        if self._rotation_code is not None:\n            frame = rotate_video_frame(frame, self._rotation_code)\n\n        loop = asyncio.get_running_loop()\n        return await loop.run_in_executor(\n            None,\n            process_frame,\n            frame,\n            frame_id,\n            self._declared_fps,\n            (\n                self._fps_monitor.fps\n                if len(self._fps_monitor.all_timestamps) > 1\n                else self._declared_fps\n            ),\n            self._file_processing,\n            self._inference_pipeline,\n            stream_output,\n            render_output,\n            include_errors_on_frame,\n        )\n\n\nclass VideoTransformTrackWithLoop(VideoStreamTrack, VideoFrameProcessor):\n    \"\"\"Video track that processes frames through workflow and sends video back.\n\n    Inherits from both VideoStreamTrack (for WebRTC video track functionality)\n    and VideoFrameProcessor (for workflow processing logic).\n    \"\"\"\n\n    def __init__(\n        self,\n        asyncio_loop: asyncio.AbstractEventLoop,\n        workflow_configuration: WorkflowConfiguration,\n        api_key: str,\n        model_manager: Optional[ModelManager] = None,\n        data_output: Optional[List[str]] = None,\n        stream_output: Optional[str] = None,\n        has_video_track: bool = True,\n        declared_fps: float = 30,\n        termination_date: Optional[datetime.datetime] = None,\n        terminate_event: Optional[asyncio.Event] = None,\n        heartbeat_callback: Optional[Callable[[], None]] = None,\n        realtime_processing: bool = True,\n        is_preview: bool = False,\n        *args,\n        **kwargs,\n    ):\n        VideoStreamTrack.__init__(self, *args, **kwargs)\n        VideoFrameProcessor.__init__(\n            self,\n            asyncio_loop=asyncio_loop,\n            workflow_configuration=workflow_configuration,\n            api_key=api_key,\n            data_output=data_output,\n            stream_output=stream_output,\n            has_video_track=has_video_track,\n            declared_fps=declared_fps,\n            termination_date=termination_date,\n            terminate_event=terminate_event,\n            model_manager=model_manager,\n            heartbeat_callback=heartbeat_callback,\n            realtime_processing=realtime_processing,\n            is_preview=is_preview,\n        )\n\n    async def _auto_detect_stream_output(\n        self, frame: VideoFrame, frame_id: int\n    ) -> None:\n        workflow_output_for_detect, _, _ = await self._process_frame_async(\n            frame=frame,\n            frame_id=frame_id,\n            render_output=False,\n            include_errors_on_frame=False,\n        )\n        detected_output = detect_image_output(workflow_output_for_detect)\n        if detected_output:\n            self.stream_output = detected_output\n            logger.info(f\"Auto-detected stream_output: {detected_output}\")\n        else:\n            logger.warning(\"No image output detected, will use fallback\")\n            self.stream_output = \"\"\n\n    async def recv(self):\n        # Silencing swscaler warnings in multi-threading environment\n        if not self._av_logging_set:\n            av_logging.set_libav_level(av_logging.ERROR)\n            self._av_logging_set = True\n\n        if self.heartbeat_callback:\n            self.heartbeat_callback()\n\n        # Wait for track to be ready (video file upload case)\n        if self.track is None:\n            logger.info(\"[RECV] Track is None, waiting for track_ready_event...\")\n            await self._track_ready_event.wait()\n            if self.track is None:\n                logger.error(\"[RECV] Track still None after wait!\")\n                raise MediaStreamError(\"Track not available after wait\")\n\n        # Optional ACK pacing: block producing the next frame if we're too far ahead.\n        await self._wait_for_ack_window(next_frame_id=self._received_frames + 1)\n\n        if self._check_termination():\n            logger.warning(\"[RECV] Termination triggered, closing gracefully\")\n            await self._send_processing_complete()\n            self._signal_termination()\n            reason = self._termination_reason or \"terminate_event\"\n            raise MediaStreamError(f\"Processing terminated: {reason}\")\n\n        # Drain queue if using PlayerStreamTrack (RTSP/video file)\n        if isinstance(self.track, PlayerStreamTrack) and self.realtime_processing:\n            queue_size = self.track._queue.qsize()\n            if queue_size > 30:\n                drained = 0\n                while self.track._queue.qsize() > 30:\n                    self.track._queue.get_nowait()\n                    drained += 1\n                logger.info(\n                    \"[RECV] Drained %d frames from queue (was %d)\", drained, queue_size\n                )\n\n        try:\n            frame: VideoFrame = await self.track.recv()\n        except MediaStreamError:\n            logger.info(\"[RECV] Track ended after %d frames\", self._received_frames)\n            await self._send_processing_complete()\n            raise\n\n        self._received_frames += 1\n        self._fps_monitor.tick()\n        frame_id = self._received_frames\n        frame_timestamp = datetime.datetime.now()\n\n        if self.stream_output is None and frame_id == 1:\n            await self._auto_detect_stream_output(frame, frame_id)\n\n        workflow_output, new_frame, errors = await self._process_frame_async(\n            frame=frame,\n            frame_id=frame_id,\n            stream_output=self.stream_output,\n            render_output=True,\n            include_errors_on_frame=True,\n        )\n\n        new_frame.pts = frame.pts\n        new_frame.time_base = frame.time_base\n\n        await self._send_data_output(workflow_output, frame_timestamp, frame, errors)\n\n        if errors:\n            logger.warning(\"[RECV] Frame %d errors: %s\", frame_id, errors)\n\n        return new_frame\n\n\nasync def _wait_ice_complete(peer_connection: RTCPeerConnectionWithLoop, timeout=2.0):\n    if peer_connection.iceGatheringState == \"complete\":\n        logger.info(\"ICE gathering state already complete\")\n        return\n    fut = asyncio.get_running_loop().create_future()\n\n    @peer_connection.on(\"icegatheringstatechange\")\n    def _():\n        logger.info(\n            \"ICE gathering state changed to %s\", peer_connection.iceGatheringState\n        )\n        if not fut.done() and peer_connection.iceGatheringState == \"complete\":\n            fut.set_result(True)\n\n    try:\n        logger.info(\"Waiting for ICE gathering to complete...\")\n        await asyncio.wait_for(fut, timeout)\n        logger.info(\"ICE gathering completed\")\n    except asyncio.TimeoutError:\n        logger.info(\"ICE gathering did not complete in %s seconds\", timeout)\n        pass\n\n\nasync def init_rtc_peer_connection_with_loop(\n    webrtc_request: WebRTCWorkerRequest,\n    send_answer: Callable[[WebRTCWorkerResult], None],\n    asyncio_loop: Optional[asyncio.AbstractEventLoop] = None,\n    model_manager: Optional[ModelManager] = None,\n    shutdown_reserve: int = WEBRTC_MODAL_SHUTDOWN_RESERVE,\n    heartbeat_callback: Optional[Callable[[], None]] = None,\n    connection_established_callback: Optional[Callable[[], None]] = None,\n) -> RTCPeerConnectionWithLoop:\n    logger.info(\n        \"=\" * 60 + \"\\n\"\n        \"[WEBRTC_SESSION] STARTING NEW SESSION\\n\"\n        \"  stream_output=%s\\n\"\n        \"  data_output=%s\\n\"\n        \"  timeout=%s\\n\" + \"=\" * 60,\n        webrtc_request.stream_output,\n        webrtc_request.data_output,\n        webrtc_request.processing_timeout,\n    )\n\n    # ice._mdns is instantiated on the module level, it has a lock that is bound to the event loop\n    # avoid RuntimeError: asyncio.locks.Lock is bound to a different event loop\n    if hasattr(ice, \"_mdns\"):\n        if hasattr(ice._mdns, \"lock\"):\n            logger.info(\"Removing lock from aioice.ice._mdns\")\n            delattr(ice._mdns, \"lock\")\n    else:\n        logger.warning(\n            \"aioice.ice implementation was changed, _mdns attribute is not available\"\n        )\n\n    termination_date = None\n    terminate_event = asyncio.Event()\n\n    if webrtc_request.processing_timeout is not None:\n        try:\n            time_limit_seconds = int(webrtc_request.processing_timeout)\n            datetime_now = webrtc_request.processing_session_started\n            if datetime_now is None:\n                datetime_now = datetime.datetime.now()\n            termination_date = datetime_now + datetime.timedelta(\n                seconds=time_limit_seconds - shutdown_reserve\n            )\n            logger.info(\n                \"Setting termination date to %s (%s seconds from %s)\",\n                termination_date.isoformat(),\n                time_limit_seconds,\n                datetime_now.isoformat(),\n            )\n        except (TypeError, ValueError):\n            pass\n    if webrtc_request.stream_output is None:\n        stream_mode = StreamOutputMode.AUTO_DETECT\n        stream_field = None\n    elif len(webrtc_request.stream_output) == 0:\n        stream_mode = StreamOutputMode.NO_VIDEO\n        stream_field = None\n    else:\n        filtered = [s for s in webrtc_request.stream_output if s]\n        if filtered:\n            stream_mode = StreamOutputMode.SPECIFIC_FIELD\n            stream_field = filtered[0]\n        else:\n            stream_mode = StreamOutputMode.NO_VIDEO\n            stream_field = None\n\n    if webrtc_request.data_output is None or len(webrtc_request.data_output) == 0:\n        data_fields = None\n    elif webrtc_request.data_output == [\"*\"]:\n        data_fields = [\"*\"]\n    else:\n        data_fields = webrtc_request.data_output\n\n    try:\n        should_send_video = stream_mode != StreamOutputMode.NO_VIDEO\n\n        if should_send_video:\n            video_processor = VideoTransformTrackWithLoop(\n                asyncio_loop=asyncio_loop,\n                workflow_configuration=webrtc_request.workflow_configuration,\n                model_manager=model_manager,\n                api_key=webrtc_request.api_key,\n                data_output=data_fields,\n                stream_output=stream_field,\n                has_video_track=True,\n                declared_fps=webrtc_request.declared_fps,\n                termination_date=termination_date,\n                terminate_event=terminate_event,\n                heartbeat_callback=heartbeat_callback,\n                realtime_processing=webrtc_request.webrtc_realtime_processing,\n                is_preview=webrtc_request.is_preview,\n            )\n        else:\n            # No video track - use base VideoFrameProcessor\n            video_processor = VideoFrameProcessor(\n                asyncio_loop=asyncio_loop,\n                workflow_configuration=webrtc_request.workflow_configuration,\n                model_manager=model_manager,\n                api_key=webrtc_request.api_key,\n                data_output=data_fields,\n                stream_output=None,\n                has_video_track=False,\n                declared_fps=webrtc_request.declared_fps,\n                termination_date=termination_date,\n                terminate_event=terminate_event,\n                heartbeat_callback=heartbeat_callback,\n                realtime_processing=webrtc_request.webrtc_realtime_processing,\n                is_preview=webrtc_request.is_preview,\n            )\n    except (\n        ValidationError,\n        MissingApiKeyError,\n        KeyError,\n        NotImplementedError,\n    ) as error:\n        if heartbeat_callback:\n            heartbeat_callback()\n        send_answer(\n            WebRTCWorkerResult(\n                exception_type=error.__class__.__name__,\n                error_message=\"Could not decode InferencePipeline initialisation command payload.\",\n            )\n        )\n        return\n    except WebRTCConfigurationError as error:\n        if heartbeat_callback:\n            heartbeat_callback()\n        send_answer(\n            WebRTCWorkerResult(\n                exception_type=error.__class__.__name__,\n                error_message=str(error),\n            )\n        )\n        return\n    except RoboflowAPINotAuthorizedError:\n        if heartbeat_callback:\n            heartbeat_callback()\n        send_answer(\n            WebRTCWorkerResult(\n                exception_type=RoboflowAPINotAuthorizedError.__name__,\n                error_message=\"Invalid API key used or API key is missing. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key\",\n            )\n        )\n        return\n    except RoboflowAPINotNotFoundError:\n        if heartbeat_callback:\n            heartbeat_callback()\n        send_answer(\n            WebRTCWorkerResult(\n                exception_type=RoboflowAPINotNotFoundError.__name__,\n                error_message=\"Requested Roboflow resources (models / workflows etc.) not available or wrong API key used.\",\n            )\n        )\n        return\n    except WorkflowSyntaxError as error:\n        if heartbeat_callback:\n            heartbeat_callback()\n        send_answer(\n            WebRTCWorkerResult(\n                exception_type=WorkflowSyntaxError.__name__,\n                error_message=str(error),\n                error_context=str(error.context),\n                inner_error=str(error.inner_error),\n            )\n        )\n        return\n    except WorkflowError as error:\n        if heartbeat_callback:\n            heartbeat_callback()\n        send_answer(\n            WebRTCWorkerResult(\n                exception_type=WorkflowError.__name__,\n                error_message=str(error),\n            )\n        )\n        return\n    except Exception as error:\n        send_answer(\n            WebRTCWorkerResult(\n                exception_type=error.__class__.__name__,\n                error_message=str(error),\n            )\n        )\n        return\n\n    if webrtc_request.webrtc_config is not None:\n        ice_servers = []\n        for ice_server in webrtc_request.webrtc_config.iceServers:\n            ice_servers.append(\n                RTCIceServer(\n                    urls=ice_server.urls,\n                    username=ice_server.username,\n                    credential=ice_server.credential,\n                )\n            )\n        # Always add public stun servers (if specified)\n        if WEBRTC_MODAL_PUBLIC_STUN_SERVERS:\n            for stun_server in WEBRTC_MODAL_PUBLIC_STUN_SERVERS.split(\",\"):\n                try:\n                    ice_servers.append(RTCIceServer(urls=stun_server.strip()))\n                except Exception as e:\n                    logger.warning(\n                        \"Failed to add public stun server '%s': %s\", stun_server, e\n                    )\n    else:\n        ice_servers = None\n    peer_connection = RTCPeerConnectionWithLoop(\n        configuration=RTCConfiguration(iceServers=ice_servers) if ice_servers else None,\n        asyncio_loop=asyncio_loop,\n    )\n\n    relay = MediaRelay()\n\n    # Add video track early for SDP negotiation when stream_output is requested\n    # The track source will be set later by the appropriate handler (RTSP, on_track, video_upload)\n    if should_send_video:\n        logger.info(\"Adding video track early for SDP negotiation\")\n        peer_connection.addTrack(video_processor)\n\n    player: Optional[MediaPlayer] = None\n    if webrtc_request.rtsp_url:\n        if webrtc_request.rtsp_url == WEBRTC_MODAL_RTSP_PLACEHOLDER:\n            webrtc_request.rtsp_url = WEBRTC_MODAL_RTSP_PLACEHOLDER_URL\n        logger.info(\"Processing RTSP URL: %s\", webrtc_request.rtsp_url)\n        player = MediaPlayer(\n            webrtc_request.rtsp_url,\n            format=\"rtsp\",\n            options={\n                \"rtsp_transport\": \"tcp\",\n                \"rtsp_flags\": \"prefer_tcp\",\n                \"stimeout\": \"2000000\",  # 2s socket timeout\n            },\n        )\n        video_processor.set_track(track=player.video)\n\n        # For DATA_ONLY mode, start data-only processing task\n        if not should_send_video:\n            logger.info(\"Starting data-only processing for RTSP stream\")\n            asyncio.create_task(video_processor.process_frames_data_only())\n\n    elif webrtc_request.mjpeg_url:\n        logger.info(\"Processing MJPEG URL: %s\", webrtc_request.mjpeg_url)\n        player = MediaPlayer(webrtc_request.mjpeg_url)\n        video_processor.set_track(track=player.video)\n\n        if not should_send_video:\n            logger.info(\"Starting data-only processing for MJPEG stream\")\n            asyncio.create_task(video_processor.process_frames_data_only())\n\n    @peer_connection.on(\"track\")\n    def on_track(track: RemoteStreamTrack):\n        logger.info(\"Track received from client\")\n        relayed_track = relay.subscribe(\n            track,\n            buffered=False if webrtc_request.webrtc_realtime_processing else True,\n        )\n        video_processor.set_track(track=relayed_track)\n\n        # For DATA_ONLY mode, start data-only processing task\n        if not should_send_video:\n            logger.info(\"Starting data-only processing (no video track)\")\n            asyncio.create_task(video_processor.process_frames_data_only())\n\n    @peer_connection.on(\"connectionstatechange\")\n    async def on_connectionstatechange():\n        state = peer_connection.connectionState\n        ice_state = peer_connection.iceConnectionState\n        logger.warning(\n            \"[CONNECTION_STATE] Changed to: %s (ICE state: %s, \"\n            \"frames_received: %d, data_channel: %s)\",\n            state,\n            ice_state,\n            video_processor._received_frames,\n            (\n                video_processor.data_channel.readyState\n                if video_processor.data_channel\n                else \"N/A\"\n            ),\n        )\n        if state == \"connected\":\n            if connection_established_callback:\n                connection_established_callback()\n        if state in {\"failed\", \"closed\"}:\n            logger.error(\n                \"[CONNECTION_STATE] FATAL: Connection %s! ICE=%s, \"\n                \"frames_processed=%d. Cleaning up...\",\n                state,\n                ice_state,\n                video_processor._received_frames,\n            )\n            if video_processor.track:\n                logger.info(\"[CONNECTION_STATE] Stopping video processor track\")\n                video_processor.track.stop()\n            await video_processor.close()\n            logger.info(\"[CONNECTION_STATE] Stopping WebRTC peer\")\n            await peer_connection.close()\n            terminate_event.set()\n\n    # Monitor ICE connection state - consent expires after ~30s without STUN refresh\n    @peer_connection.on(\"iceconnectionstatechange\")\n    async def on_iceconnectionstatechange():\n        state = peer_connection.iceConnectionState\n        conn_state = peer_connection.connectionState\n        logger.warning(\n            \"[ICE_STATE] Changed to: %s (connection state: %s, \"\n            \"frames_received: %d, data_channel: %s)\",\n            state,\n            conn_state,\n            video_processor._received_frames,\n            (\n                video_processor.data_channel.readyState\n                if video_processor.data_channel\n                else \"N/A\"\n            ),\n        )\n\n        if state == \"failed\":\n            logger.error(\n                \"[ICE_STATE] FAILED! This typically means STUN consent expired. \"\n                \"Causes: (1) Event loop starvation preventing aioice from sending \"\n                \"STUN packets, (2) Network issues, (3) NAT/firewall blocking. \"\n                \"Check logs for [BUFFER_DRAIN] timeouts or missing asyncio.sleep(0) yields.\"\n            )\n            # The connectionstatechange handler will clean up\n        elif state == \"disconnected\":\n            logger.warning(\n                \"[ICE_STATE] DISCONNECTED - may recover automatically. \"\n                \"If this persists for >30s, will transition to 'failed'.\"\n            )\n        elif state == \"checking\":\n            logger.info(\"[ICE_STATE] Checking connectivity candidates...\")\n        elif state == \"connected\":\n            logger.info(\"[ICE_STATE] Successfully connected via ICE\")\n\n    def process_video_upload_message(\n        message: bytes, video_processor: VideoTransformTrackWithLoop\n    ):\n        chunk_index, total_chunks, data = parse_video_file_chunk(message)\n        video_processor.video_upload_handler.handle_chunk(\n            chunk_index, total_chunks, data\n        )\n\n        video_path = video_processor.video_upload_handler.try_start_processing()\n        return video_path\n\n    @peer_connection.on(\"datachannel\")\n    def on_datachannel(channel: RTCDataChannel):\n        logger.info(\"Data channel '%s' received\", channel.label)\n        # Handle video file upload channel\n        if channel.label == \"video_upload\":\n            logger.info(\"Video upload channel established\")\n\n            video_processor.video_upload_handler = VideoFileUploadHandler()\n\n            @channel.on(\"message\")\n            async def on_upload_message(message):\n                # Keep watchdog alive during upload and keepalive pings\n                if video_processor.heartbeat_callback:\n                    video_processor.heartbeat_callback()\n\n                # Ignore keepalive pings (1-byte messages)\n                if len(message) <= 1:\n                    channel.send(message)\n                    return\n                loop = asyncio.get_running_loop()\n                video_path = await loop.run_in_executor(\n                    None, process_video_upload_message, message, video_processor\n                )\n                if video_path:\n                    video_processor._file_processing = True\n                    logger.info(\n                        \"Video upload complete, processing: realtime=%s, path=%s\",\n                        webrtc_request.webrtc_realtime_processing,\n                        video_path,\n                    )\n\n                    rotation = get_video_rotation(video_path)\n                    rotation_code = get_cv2_rotation_code(rotation)\n                    if rotation_code is not None:\n                        logger.info(\"Video has %d\u00b0 rotation, will correct\", rotation)\n\n                    detected_fps = get_video_fps(video_path)\n                    if detected_fps is not None:\n                        logger.info(\n                            \"FPS detection: detected=%.2f, previous=%s\",\n                            detected_fps,\n                            video_processor._declared_fps,\n                        )\n                        video_processor._declared_fps = detected_fps\n                    else:\n                        logger.warning(\n                            \"FPS detection failed, keeping default: %s\",\n                            video_processor._declared_fps,\n                        )\n\n                    if webrtc_request.webrtc_realtime_processing:\n                        # We are dealing with a live video stream,\n                        player = MediaPlayer(video_path, loop=False)\n                        player._throttle_playback = True\n                        video_processor.set_track(\n                            track=player.video, rotation_code=rotation_code\n                        )\n                    else:\n                        # we are dealing with a video file,\n                        track = ThreadedVideoFileTrack(video_path)\n                        video_processor.set_track(\n                            track=track, rotation_code=rotation_code\n                        )\n\n                    if not should_send_video:\n                        logger.info(\"Starting data-only processing for video file\")\n                        asyncio.create_task(video_processor.process_frames_data_only())\n\n            return\n\n        # Handle inference control channel (bidirectional communication)\n        @channel.on(\"message\")\n        def on_message(message):\n            try:\n                message_data = WebRTCData(**json.loads(message))\n            except json.JSONDecodeError:\n                logger.error(\"Failed to decode webrtc data payload: %s\", message)\n                return\n            # Optional ACK-based flow control (enabled only after first ACK is received)\n            if message_data.ack is not None:\n                video_processor.record_ack(message_data.ack)\n\n            # Handle stream_output changes\n            if message_data.stream_output is not None:\n                if not video_processor.has_video_track:\n                    logger.warning(\n                        \"Cannot change stream_output: video track was not initialized. \"\n                        \"stream_output must be set at initialization to enable video.\"\n                    )\n                else:\n                    if len(message_data.stream_output) == 0:\n                        video_processor.stream_output = None\n                    else:\n                        filtered = [s for s in message_data.stream_output if s]\n                        video_processor.stream_output = (\n                            filtered[0] if filtered else None\n                        )\n\n            # Handle data_output changes (always allowed)\n            if message_data.data_output is not None:\n                video_processor.data_output = message_data.data_output\n                if (\n                    message_data.data_output is None\n                    or len(message_data.data_output) == 0\n                ):\n                    video_processor._data_mode = DataOutputMode.NONE\n                elif message_data.data_output == [\"*\"]:\n                    video_processor._data_mode = DataOutputMode.ALL\n                else:\n                    video_processor._data_mode = DataOutputMode.SPECIFIC\n\n        video_processor.data_channel = channel\n\n    await peer_connection.setRemoteDescription(\n        RTCSessionDescription(\n            sdp=webrtc_request.webrtc_offer.sdp, type=webrtc_request.webrtc_offer.type\n        )\n    )\n    answer = await peer_connection.createAnswer()\n    await peer_connection.setLocalDescription(answer)\n\n    await _wait_ice_complete(peer_connection, timeout=2.0)\n\n    logger.info(\n        \"Initialized RTC peer connection with loop (status: %s), sending answer\",\n        peer_connection.connectionState,\n    )\n\n    send_answer(\n        WebRTCWorkerResult(\n            answer={\n                \"type\": peer_connection.localDescription.type,\n                \"sdp\": peer_connection.localDescription.sdp,\n            },\n        )\n    )\n\n    logger.info(\"Answer sent, waiting for termination event\")\n    await terminate_event.wait()\n    logger.info(\"Termination event received, closing WebRTC connection\")\n    if player:\n        logger.info(\"Stopping player\")\n        player.video.stop()\n    if peer_connection.connectionState != \"closed\":\n        logger.info(\"Closing WebRTC connection\")\n        await peer_connection.close()\n    if video_processor.track:\n        logger.info(\"Stopping video processor track\")\n        video_processor.track.stop()\n    await video_processor.close()\n    await usage_collector.async_push_usage_payloads()\n    logger.info(\"WebRTC peer connection closed\")\n\n\ndef default_encoder(obj: Any) -> Any:\n    if isinstance(obj, bytes):\n        return base64.b64encode(obj).decode(\"ascii\")\n    return obj\n",
    "patch": null
  },
  {
    "trace_id": "00153aa0-c1f3-4723-bb46-fdb56a1ad5fe",
    "function_name": "BlockManifest.get_air_gapped_availability",
    "file_path": "inference/core/workflows/core_steps/models/foundation/anthropic_claude/v3.py",
    "speedup_x": 0.45016307118217946,
    "review_quality": "high",
    "pre_optimization_commit": "835af61109f8cab1d2cb51cf93d061ef3a4c5fc7",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def get_air_gapped_availability(cls) -> dict:\n        return {\"available\": False, \"reason\": \"requires_internet\"}\n",
    "optimized_function_code": "from typing import Literal\n\nfrom inference.core.workflows.core_steps.common.vlms import VLM_TASKS_METADATA\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nCLAUDE_MODELS = [\n    {\n        \"id\": \"claude-opus-4-6\",\n        \"name\": \"Claude Opus 4.6\",\n        \"exact_version\": \"claude-opus-4-6\",\n        \"max_output_tokens\": 128000,\n    },\n    {\n        \"id\": \"claude-sonnet-4-6\",\n        \"name\": \"Claude Sonnet 4.6\",\n        \"exact_version\": \"claude-sonnet-4-6\",\n        \"max_output_tokens\": 64000,\n    },\n    {\n        \"id\": \"claude-sonnet-4-5\",\n        \"name\": \"Claude Sonnet 4.5\",\n        \"exact_version\": \"claude-sonnet-4-5-20250929\",\n        \"max_output_tokens\": 64000,\n    },\n    {\n        \"id\": \"claude-haiku-4-5\",\n        \"name\": \"Claude Haiku 4.5\",\n        \"exact_version\": \"claude-haiku-4-5-20251001\",\n        \"max_output_tokens\": 64000,\n    },\n    {\n        \"id\": \"claude-opus-4-5\",\n        \"name\": \"Claude Opus 4.5\",\n        \"exact_version\": \"claude-opus-4-5-20251101\",\n        \"max_output_tokens\": 64000,\n    },\n    {\n        \"id\": \"claude-sonnet-4\",\n        \"name\": \"Claude Sonnet 4\",\n        \"exact_version\": \"claude-sonnet-4-20250514\",\n        \"max_output_tokens\": 64000,\n    },\n    {\n        \"id\": \"claude-opus-4-1\",\n        \"name\": \"Claude Opus 4.1\",\n        \"exact_version\": \"claude-opus-4-1-20250805\",\n        \"max_output_tokens\": 32000,\n    },\n    {\n        \"id\": \"claude-opus-4\",\n        \"name\": \"Claude Opus 4\",\n        \"exact_version\": \"claude-opus-4-20250514\",\n        \"max_output_tokens\": 32000,\n    },\n]\n\nMODEL_VERSION_IDS = tuple(model[\"id\"] for model in CLAUDE_MODELS)\n\n\nMODEL_VERSION_METADATA = {\n    model[\"id\"]: {\"name\": model[\"name\"]} for model in CLAUDE_MODELS\n}\n\nSUPPORTED_TASK_TYPES_LIST = (\n    \"unconstrained\",\n    \"ocr\",\n    \"structured-answering\",\n    \"classification\",\n    \"multi-label-classification\",\n    \"visual-question-answering\",\n    \"caption\",\n    \"detailed-caption\",\n    \"object-detection\",\n)\nSUPPORTED_TASK_TYPES = set(SUPPORTED_TASK_TYPES_LIST)\nRELEVANT_TASKS_METADATA = {\n    k: v for k, v in VLM_TASKS_METADATA.items() if k in SUPPORTED_TASK_TYPES\n}\nRELEVANT_TASKS_DOCS_DESCRIPTION = \"\\n\\n\".join(\n    f\"* **{v['name']}** (`{k}`) - {v['description']}\"\n    for k, v in RELEVANT_TASKS_METADATA.items()\n)\nLONG_DESCRIPTION = f\"\"\"\nAsk a question to Anthropic Claude model with vision capabilities.\n\nYou can specify arbitrary text prompts or predefined ones, the block supports the following types of prompt:\n\n{RELEVANT_TASKS_DOCS_DESCRIPTION}\n\n### API Key Options\n\nThis block supports two API key modes:\n\n1. **Roboflow Managed API Key (Default)** - Use `rf_key:account` to proxy requests through Roboflow's API:\n   * **Simplified setup** - no Anthropic API key required\n   * **Secure** - your workflow API key is used for authentication\n   * **Usage-based billing** - charged per token based on the model used\n\n2. **Custom Anthropic API Key** - Provide your own Anthropic API key:\n   * Full control over API usage\n   * You pay Anthropic directly\n\"\"\"\n\nTaskType = Literal[tuple(SUPPORTED_TASK_TYPES_LIST)]\n\nTASKS_REQUIRING_PROMPT = {\n    \"unconstrained\",\n    \"visual-question-answering\",\n}\n\nTASKS_REQUIRING_CLASSES = {\n    \"classification\",\n    \"multi-label-classification\",\n    \"object-detection\",\n}\n\nTASKS_REQUIRING_OUTPUT_STRUCTURE = {\n    \"structured-answering\",\n}\n\n\n\n# Module-level constant to avoid allocating a new dict on every call.\n_AIR_GAPPED_AVAILABILITY = {\"available\": False, \"reason\": \"requires_internet\"}\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_air_gapped_availability(cls) -> dict:\n        return _AIR_GAPPED_AVAILABILITY",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/models/foundation/anthropic_claude/v3.py\nfrom typing import Literal\n\nfrom inference.core.workflows.core_steps.common.vlms import VLM_TASKS_METADATA\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nCLAUDE_MODELS = [\n    {\n        \"id\": \"claude-opus-4-6\",\n        \"name\": \"Claude Opus 4.6\",\n        \"exact_version\": \"claude-opus-4-6\",\n        \"max_output_tokens\": 128000,\n    },\n    {\n        \"id\": \"claude-sonnet-4-6\",\n        \"name\": \"Claude Sonnet 4.6\",\n        \"exact_version\": \"claude-sonnet-4-6\",\n        \"max_output_tokens\": 64000,\n    },\n    {\n        \"id\": \"claude-sonnet-4-5\",\n        \"name\": \"Claude Sonnet 4.5\",\n        \"exact_version\": \"claude-sonnet-4-5-20250929\",\n        \"max_output_tokens\": 64000,\n    },\n    {\n        \"id\": \"claude-haiku-4-5\",\n        \"name\": \"Claude Haiku 4.5\",\n        \"exact_version\": \"claude-haiku-4-5-20251001\",\n        \"max_output_tokens\": 64000,\n    },\n    {\n        \"id\": \"claude-opus-4-5\",\n        \"name\": \"Claude Opus 4.5\",\n        \"exact_version\": \"claude-opus-4-5-20251101\",\n        \"max_output_tokens\": 64000,\n    },\n    {\n        \"id\": \"claude-sonnet-4\",\n        \"name\": \"Claude Sonnet 4\",\n        \"exact_version\": \"claude-sonnet-4-20250514\",\n        \"max_output_tokens\": 64000,\n    },\n    {\n        \"id\": \"claude-opus-4-1\",\n        \"name\": \"Claude Opus 4.1\",\n        \"exact_version\": \"claude-opus-4-1-20250805\",\n        \"max_output_tokens\": 32000,\n    },\n    {\n        \"id\": \"claude-opus-4\",\n        \"name\": \"Claude Opus 4\",\n        \"exact_version\": \"claude-opus-4-20250514\",\n        \"max_output_tokens\": 32000,\n    },\n]\n\nMODEL_VERSION_IDS = tuple(model[\"id\"] for model in CLAUDE_MODELS)\n\n\nMODEL_VERSION_METADATA = {\n    model[\"id\"]: {\"name\": model[\"name\"]} for model in CLAUDE_MODELS\n}\n\nSUPPORTED_TASK_TYPES_LIST = (\n    \"unconstrained\",\n    \"ocr\",\n    \"structured-answering\",\n    \"classification\",\n    \"multi-label-classification\",\n    \"visual-question-answering\",\n    \"caption\",\n    \"detailed-caption\",\n    \"object-detection\",\n)\nSUPPORTED_TASK_TYPES = set(SUPPORTED_TASK_TYPES_LIST)\nRELEVANT_TASKS_METADATA = {\n    k: v for k, v in VLM_TASKS_METADATA.items() if k in SUPPORTED_TASK_TYPES\n}\nRELEVANT_TASKS_DOCS_DESCRIPTION = \"\\n\\n\".join(\n    f\"* **{v['name']}** (`{k}`) - {v['description']}\"\n    for k, v in RELEVANT_TASKS_METADATA.items()\n)\nLONG_DESCRIPTION = f\"\"\"\nAsk a question to Anthropic Claude model with vision capabilities.\n\nYou can specify arbitrary text prompts or predefined ones, the block supports the following types of prompt:\n\n{RELEVANT_TASKS_DOCS_DESCRIPTION}\n\n### API Key Options\n\nThis block supports two API key modes:\n\n1. **Roboflow Managed API Key (Default)** - Use `rf_key:account` to proxy requests through Roboflow's API:\n   * **Simplified setup** - no Anthropic API key required\n   * **Secure** - your workflow API key is used for authentication\n   * **Usage-based billing** - charged per token based on the model used\n\n2. **Custom Anthropic API Key** - Provide your own Anthropic API key:\n   * Full control over API usage\n   * You pay Anthropic directly\n\"\"\"\n\nTaskType = Literal[tuple(SUPPORTED_TASK_TYPES_LIST)]\n\nTASKS_REQUIRING_PROMPT = {\n    \"unconstrained\",\n    \"visual-question-answering\",\n}\n\nTASKS_REQUIRING_CLASSES = {\n    \"classification\",\n    \"multi-label-classification\",\n    \"object-detection\",\n}\n\nTASKS_REQUIRING_OUTPUT_STRUCTURE = {\n    \"structured-answering\",\n}\n\n\n\n# Module-level constant to avoid allocating a new dict on every call.\n_AIR_GAPPED_AVAILABILITY = {\"available\": False, \"reason\": \"requires_internet\"}\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def get_air_gapped_availability(cls) -> dict:\n        return _AIR_GAPPED_AVAILABILITY\n```",
    "optimized_function_only": "    def get_air_gapped_availability(cls) -> dict:\n        return _AIR_GAPPED_AVAILABILITY",
    "original_file_content": "import base64\nimport json\nfrom functools import partial\nfrom typing import Any, Dict, List, Literal, Optional, Tuple, Type, Union\n\nimport anthropic\nimport requests\nfrom anthropic import NOT_GIVEN\nfrom pydantic import ConfigDict, Field, model_validator\n\nfrom inference.core.env import WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.roboflow_api import post_to_roboflow_api\nfrom inference.core.utils.image_utils import encode_image_to_jpeg_bytes, load_image\nfrom inference.core.utils.preprocess import downscale_image_keeping_aspect_ratio\nfrom inference.core.workflows.core_steps.common.utils import run_in_parallel\nfrom inference.core.workflows.core_steps.common.vlms import VLM_TASKS_METADATA\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    FLOAT_KIND,\n    IMAGE_KIND,\n    INTEGER_KIND,\n    LANGUAGE_MODEL_OUTPUT_KIND,\n    LIST_OF_VALUES_KIND,\n    ROBOFLOW_MANAGED_KEY,\n    SECRET_KIND,\n    STRING_KIND,\n    ImageInputField,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nCLAUDE_MODELS = [\n    {\n        \"id\": \"claude-opus-4-6\",\n        \"name\": \"Claude Opus 4.6\",\n        \"exact_version\": \"claude-opus-4-6\",\n        \"max_output_tokens\": 128000,\n    },\n    {\n        \"id\": \"claude-sonnet-4-6\",\n        \"name\": \"Claude Sonnet 4.6\",\n        \"exact_version\": \"claude-sonnet-4-6\",\n        \"max_output_tokens\": 64000,\n    },\n    {\n        \"id\": \"claude-sonnet-4-5\",\n        \"name\": \"Claude Sonnet 4.5\",\n        \"exact_version\": \"claude-sonnet-4-5-20250929\",\n        \"max_output_tokens\": 64000,\n    },\n    {\n        \"id\": \"claude-haiku-4-5\",\n        \"name\": \"Claude Haiku 4.5\",\n        \"exact_version\": \"claude-haiku-4-5-20251001\",\n        \"max_output_tokens\": 64000,\n    },\n    {\n        \"id\": \"claude-opus-4-5\",\n        \"name\": \"Claude Opus 4.5\",\n        \"exact_version\": \"claude-opus-4-5-20251101\",\n        \"max_output_tokens\": 64000,\n    },\n    {\n        \"id\": \"claude-sonnet-4\",\n        \"name\": \"Claude Sonnet 4\",\n        \"exact_version\": \"claude-sonnet-4-20250514\",\n        \"max_output_tokens\": 64000,\n    },\n    {\n        \"id\": \"claude-opus-4-1\",\n        \"name\": \"Claude Opus 4.1\",\n        \"exact_version\": \"claude-opus-4-1-20250805\",\n        \"max_output_tokens\": 32000,\n    },\n    {\n        \"id\": \"claude-opus-4\",\n        \"name\": \"Claude Opus 4\",\n        \"exact_version\": \"claude-opus-4-20250514\",\n        \"max_output_tokens\": 32000,\n    },\n]\n\nMODEL_VERSION_IDS = [model[\"id\"] for model in CLAUDE_MODELS]\nEXACT_MODEL_VERSIONS = {model[\"id\"]: model[\"exact_version\"] for model in CLAUDE_MODELS}\n\nMODEL_VERSION_METADATA = {\n    model[\"id\"]: {\"name\": model[\"name\"]} for model in CLAUDE_MODELS\n}\n\nMAX_OUTPUT_TOKENS = {model[\"id\"]: model[\"max_output_tokens\"] for model in CLAUDE_MODELS}\nDEFAULT_MAX_OUTPUT_TOKENS = 64000\n\nSUPPORTED_TASK_TYPES_LIST = [\n    \"unconstrained\",\n    \"ocr\",\n    \"structured-answering\",\n    \"classification\",\n    \"multi-label-classification\",\n    \"visual-question-answering\",\n    \"caption\",\n    \"detailed-caption\",\n    \"object-detection\",\n]\nSUPPORTED_TASK_TYPES = set(SUPPORTED_TASK_TYPES_LIST)\nRELEVANT_TASKS_METADATA = {\n    k: v for k, v in VLM_TASKS_METADATA.items() if k in SUPPORTED_TASK_TYPES\n}\nRELEVANT_TASKS_DOCS_DESCRIPTION = \"\\n\\n\".join(\n    f\"* **{v['name']}** (`{k}`) - {v['description']}\"\n    for k, v in RELEVANT_TASKS_METADATA.items()\n)\nLONG_DESCRIPTION = f\"\"\"\nAsk a question to Anthropic Claude model with vision capabilities.\n\nYou can specify arbitrary text prompts or predefined ones, the block supports the following types of prompt:\n\n{RELEVANT_TASKS_DOCS_DESCRIPTION}\n\n### API Key Options\n\nThis block supports two API key modes:\n\n1. **Roboflow Managed API Key (Default)** - Use `rf_key:account` to proxy requests through Roboflow's API:\n   * **Simplified setup** - no Anthropic API key required\n   * **Secure** - your workflow API key is used for authentication\n   * **Usage-based billing** - charged per token based on the model used\n\n2. **Custom Anthropic API Key** - Provide your own Anthropic API key:\n   * Full control over API usage\n   * You pay Anthropic directly\n\"\"\"\n\nTaskType = Literal[tuple(SUPPORTED_TASK_TYPES_LIST)]\n\nTASKS_REQUIRING_PROMPT = {\n    \"unconstrained\",\n    \"visual-question-answering\",\n}\n\nTASKS_REQUIRING_CLASSES = {\n    \"classification\",\n    \"multi-label-classification\",\n    \"object-detection\",\n}\n\nTASKS_REQUIRING_OUTPUT_STRUCTURE = {\n    \"structured-answering\",\n}\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Anthropic Claude\",\n            \"version\": \"v3\",\n            \"short_description\": \"Run Anthropic Claude model with vision capabilities.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"model\",\n            \"search_keywords\": [\"LMM\", \"VLM\", \"Claude\", \"Anthropic\"],\n            \"is_vlm_block\": True,\n            \"task_type_property\": \"task_type\",\n            \"ui_manifest\": {\n                \"section\": \"model\",\n                \"icon\": \"far fa-a\",\n                \"blockPriority\": 5,\n            },\n        },\n        protected_namespaces=(),\n    )\n    type: Literal[\"roboflow_core/anthropic_claude@v3\"]\n    images: Selector(kind=[IMAGE_KIND]) = ImageInputField\n    task_type: TaskType = Field(\n        default=\"unconstrained\",\n        description=\"Task type to be performed by model. Value determines required parameters and output response.\",\n        json_schema_extra={\n            \"values_metadata\": RELEVANT_TASKS_METADATA,\n            \"recommended_parsers\": {\n                \"structured-answering\": \"roboflow_core/json_parser@v1\",\n                \"classification\": \"roboflow_core/vlm_as_classifier@v2\",\n                \"multi-label-classification\": \"roboflow_core/vlm_as_classifier@v2\",\n                \"object-detection\": \"roboflow_core/vlm_as_detector@v2\",\n            },\n            \"always_visible\": True,\n        },\n    )\n    prompt: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Text prompt to the Claude model\",\n        examples=[\"my prompt\", \"$inputs.prompt\"],\n        json_schema_extra={\n            \"relevant_for\": {\n                \"task_type\": {\"values\": TASKS_REQUIRING_PROMPT, \"required\": True},\n            },\n            \"multiline\": True,\n        },\n    )\n    output_structure: Optional[Dict[str, str]] = Field(\n        default=None,\n        description=\"Dictionary with structure of expected JSON response\",\n        examples=[{\"my_key\": \"description\"}, \"$inputs.output_structure\"],\n        json_schema_extra={\n            \"relevant_for\": {\n                \"task_type\": {\n                    \"values\": TASKS_REQUIRING_OUTPUT_STRUCTURE,\n                    \"required\": True,\n                },\n            },\n        },\n    )\n    classes: Optional[Union[Selector(kind=[LIST_OF_VALUES_KIND]), List[str]]] = Field(\n        default=None,\n        description=\"List of classes to be used\",\n        examples=[[\"class-a\", \"class-b\"], \"$inputs.classes\"],\n        json_schema_extra={\n            \"relevant_for\": {\n                \"task_type\": {\n                    \"values\": TASKS_REQUIRING_CLASSES,\n                    \"required\": True,\n                },\n            },\n        },\n    )\n    api_key: Union[\n        Selector(kind=[STRING_KIND, SECRET_KIND, ROBOFLOW_MANAGED_KEY]), str\n    ] = Field(\n        default=\"rf_key:account\",\n        description=\"Your Anthropic API key or 'rf_key:account' to use Roboflow's managed API key\",\n        examples=[\"rf_key:account\", \"xxx-xxx\", \"$inputs.anthropic_api_key\"],\n        private=True,\n    )\n    model_version: Union[\n        Selector(kind=[STRING_KIND]),\n        Literal[tuple(MODEL_VERSION_IDS)],\n    ] = Field(\n        default=\"claude-sonnet-4-5\",\n        description=\"Model to be used\",\n        examples=[\"claude-sonnet-4-5\", \"$inputs.claude_model\"],\n        json_schema_extra={\n            \"values_metadata\": MODEL_VERSION_METADATA,\n        },\n    )\n    extended_thinking: Optional[bool] = Field(\n        default=None,\n        description=\"Enable extended thinking for deeper reasoning on complex tasks. \"\n        \"Note: temperature cannot be used when extended thinking is enabled.\",\n    )\n    thinking_budget_tokens: Optional[int] = Field(\n        default=None,\n        description=\"Maximum number of tokens for internal thinking when extended thinking is enabled. \"\n        \"Higher values allow deeper reasoning but increase latency and cost. \"\n        \"Must be less than max_tokens. Minimum: 1024.\",\n        ge=1024,\n        json_schema_extra={\n            \"relevant_for\": {\n                \"extended_thinking\": {\n                    \"values\": [True],\n                    \"required\": False,\n                },\n            },\n        },\n    )\n    max_tokens: Optional[int] = Field(\n        default=None,\n        description=\"Maximum number of tokens the model can generate in its response.\",\n    )\n    temperature: Optional[Union[float, Selector(kind=[FLOAT_KIND])]] = Field(\n        default=None,\n        description=\"Temperature to sample from the model - value in range 0.0-1.0, the higher - the more \"\n        'random / \"creative\" the generations are. Cannot be used when extended_thinking is enabled.',\n        ge=0.0,\n        le=1.0,\n    )\n    max_image_size: Union[int, Selector(kind=[INTEGER_KIND])] = Field(\n        description=\"Maximum size of the image - if input has larger side, it will be downscaled, keeping aspect ratio\",\n        default=1024,\n    )\n    max_concurrent_requests: Optional[int] = Field(\n        default=None,\n        description=\"Number of concurrent requests that can be executed by block when batch of input images provided. \"\n        \"If not given - block defaults to value configured globally in Workflows Execution Engine. \"\n        \"Please restrict if you hit Anthropic API limits.\",\n    )\n\n    @model_validator(mode=\"after\")\n    def validate(self) -> \"BlockManifest\":\n        if self.task_type in TASKS_REQUIRING_PROMPT and self.prompt is None:\n            raise ValueError(\n                f\"`prompt` parameter required to be set for task `{self.task_type}`\"\n            )\n        if self.task_type in TASKS_REQUIRING_CLASSES and self.classes is None:\n            raise ValueError(\n                f\"`classes` parameter required to be set for task `{self.task_type}`\"\n            )\n        if (\n            self.task_type in TASKS_REQUIRING_OUTPUT_STRUCTURE\n            and self.output_structure is None\n        ):\n            raise ValueError(\n                f\"`output_structure` parameter required to be set for task `{self.task_type}`\"\n            )\n        if self.extended_thinking:\n            if self.temperature is not None:\n                raise ValueError(\n                    \"`temperature` cannot be used when `extended_thinking` is enabled\"\n                )\n            budget_tokens = self.thinking_budget_tokens\n            max_tokens = self.max_tokens\n            if budget_tokens and max_tokens and budget_tokens >= max_tokens:\n                raise ValueError(\n                    f\"`thinking_budget_tokens` ({budget_tokens}) must be less than `max_tokens` ({max_tokens})\"\n                )\n        return self\n\n    @classmethod\n    def get_air_gapped_availability(cls) -> dict:\n        return {\"available\": False, \"reason\": \"requires_internet\"}\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return [\"images\"]\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(\n                name=\"output\", kind=[STRING_KIND, LANGUAGE_MODEL_OUTPUT_KIND]\n            ),\n            OutputDefinition(name=\"classes\", kind=[LIST_OF_VALUES_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.4.0,<2.0.0\"\n\n\nclass AnthropicClaudeBlockV3(WorkflowBlock):\n\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"model_manager\", \"api_key\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        task_type: TaskType,\n        prompt: Optional[str],\n        output_structure: Optional[Dict[str, str]],\n        classes: Optional[List[str]],\n        model_version: str,\n        max_tokens: Optional[int],\n        temperature: Optional[float],\n        extended_thinking: Optional[bool],\n        thinking_budget_tokens: Optional[int],\n        max_image_size: int,\n        max_concurrent_requests: Optional[int],\n        api_key: str = \"rf_key:account\",\n    ) -> BlockResult:\n        inference_images = [i.to_inference_format() for i in images]\n        raw_outputs = run_claude_prompting(\n            roboflow_api_key=self._api_key,\n            images=inference_images,\n            task_type=task_type,\n            prompt=prompt,\n            output_structure=output_structure,\n            classes=classes,\n            anthropic_api_key=api_key,\n            model_version=model_version,\n            max_tokens=max_tokens,\n            temperature=temperature,\n            extended_thinking=extended_thinking,\n            thinking_budget_tokens=thinking_budget_tokens,\n            max_image_size=max_image_size,\n            max_concurrent_requests=max_concurrent_requests,\n        )\n        return [\n            {\"output\": raw_output, \"classes\": classes} for raw_output in raw_outputs\n        ]\n\n\ndef run_claude_prompting(\n    roboflow_api_key: Optional[str],\n    images: List[Dict[str, Any]],\n    task_type: TaskType,\n    prompt: Optional[str],\n    output_structure: Optional[Dict[str, str]],\n    classes: Optional[List[str]],\n    anthropic_api_key: str,\n    model_version: str,\n    max_tokens: Optional[int],\n    temperature: Optional[float],\n    extended_thinking: Optional[bool],\n    thinking_budget_tokens: Optional[int],\n    max_image_size: int,\n    max_concurrent_requests: Optional[int],\n) -> List[str]:\n    if task_type not in PROMPT_BUILDERS:\n        raise ValueError(f\"Task type: {task_type} not supported.\")\n    prompts = []\n    for image in images:\n        loaded_image, _ = load_image(image)\n        loaded_image = downscale_image_keeping_aspect_ratio(\n            image=loaded_image, desired_size=(max_image_size, max_image_size)\n        )\n        base64_image = base64.b64encode(\n            encode_image_to_jpeg_bytes(loaded_image)\n        ).decode(\"ascii\")\n        generated_prompt = PROMPT_BUILDERS[task_type](\n            base64_image=base64_image,\n            prompt=prompt,\n            output_structure=output_structure,\n            classes=classes,\n        )\n        prompts.append(generated_prompt)\n    return execute_claude_requests(\n        roboflow_api_key=roboflow_api_key,\n        anthropic_api_key=anthropic_api_key,\n        prompts=prompts,\n        model_version=model_version,\n        max_tokens=max_tokens,\n        temperature=temperature,\n        extended_thinking=extended_thinking,\n        thinking_budget_tokens=thinking_budget_tokens,\n        max_concurrent_requests=max_concurrent_requests,\n    )\n\n\ndef execute_claude_requests(\n    roboflow_api_key: Optional[str],\n    anthropic_api_key: str,\n    prompts: List[Tuple[Optional[str], List[dict]]],\n    model_version: str,\n    max_tokens: Optional[int],\n    temperature: Optional[float],\n    extended_thinking: Optional[bool],\n    thinking_budget_tokens: Optional[int],\n    max_concurrent_requests: Optional[int],\n) -> List[str]:\n    tasks = [\n        partial(\n            execute_claude_request,\n            roboflow_api_key=roboflow_api_key,\n            anthropic_api_key=anthropic_api_key,\n            system_prompt=prompt[0],\n            messages=prompt[1],\n            model_version=model_version,\n            max_tokens=max_tokens,\n            temperature=temperature,\n            extended_thinking=extended_thinking,\n            thinking_budget_tokens=thinking_budget_tokens,\n        )\n        for prompt in prompts\n    ]\n    max_workers = (\n        max_concurrent_requests\n        or WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS\n    )\n    return run_in_parallel(\n        tasks=tasks,\n        max_workers=max_workers,\n    )\n\n\ndef execute_claude_request(\n    roboflow_api_key: Optional[str],\n    anthropic_api_key: str,\n    system_prompt: Optional[str],\n    messages: List[dict],\n    model_version: str,\n    max_tokens: Optional[int],\n    temperature: Optional[float],\n    extended_thinking: Optional[bool],\n    thinking_budget_tokens: Optional[int],\n) -> str:\n    \"\"\"Route to proxied or direct execution based on API key format.\"\"\"\n    if anthropic_api_key.startswith((\"rf_key:account\", \"rf_key:user:\")):\n        return _execute_proxied_claude_request(\n            roboflow_api_key=roboflow_api_key,\n            anthropic_api_key=anthropic_api_key,\n            system_prompt=system_prompt,\n            messages=messages,\n            model_version=model_version,\n            max_tokens=max_tokens,\n            temperature=temperature,\n            extended_thinking=extended_thinking,\n            thinking_budget_tokens=thinking_budget_tokens,\n        )\n    else:\n        return _execute_direct_claude_request(\n            anthropic_api_key=anthropic_api_key,\n            system_prompt=system_prompt,\n            messages=messages,\n            model_version=model_version,\n            max_tokens=max_tokens,\n            temperature=temperature,\n            extended_thinking=extended_thinking,\n            thinking_budget_tokens=thinking_budget_tokens,\n        )\n\n\ndef _execute_proxied_claude_request(\n    roboflow_api_key: str,\n    anthropic_api_key: str,\n    system_prompt: Optional[str],\n    messages: List[dict],\n    model_version: str,\n    max_tokens: Optional[int],\n    temperature: Optional[float],\n    extended_thinking: Optional[bool],\n    thinking_budget_tokens: Optional[int],\n) -> str:\n    \"\"\"Execute Claude request via Roboflow proxy.\"\"\"\n    model_max_output = MAX_OUTPUT_TOKENS.get(model_version, DEFAULT_MAX_OUTPUT_TOKENS)\n    effective_max_tokens = max_tokens if max_tokens is not None else model_max_output\n\n    payload = {\n        \"model\": model_version,\n        \"anthropic_api_key\": anthropic_api_key,\n        \"messages\": messages,\n        \"max_tokens\": effective_max_tokens,\n    }\n\n    if system_prompt is not None:\n        payload[\"system\"] = system_prompt\n\n    if temperature is not None and not extended_thinking:\n        payload[\"temperature\"] = temperature\n\n    if extended_thinking:\n        effective_budget = (\n            thinking_budget_tokens\n            if thinking_budget_tokens is not None\n            else model_max_output // 2\n        )\n        payload[\"thinking\"] = {\n            \"type\": \"enabled\",\n            \"budget_tokens\": effective_budget,\n        }\n\n    endpoint = \"apiproxy/anthropic\"\n\n    try:\n        response_data = post_to_roboflow_api(\n            endpoint=endpoint,\n            api_key=roboflow_api_key,\n            payload=payload,\n        )\n        return _extract_claude_response_text(response_data)\n    except requests.exceptions.RequestException as e:\n        raise RuntimeError(f\"Failed to connect to Roboflow proxy: {e}\") from e\n    except (KeyError, IndexError) as e:\n        raise RuntimeError(\n            f\"Invalid response structure from Roboflow proxy: {e}\"\n        ) from e\n\n\ndef _execute_direct_claude_request(\n    anthropic_api_key: str,\n    system_prompt: Optional[str],\n    messages: List[dict],\n    model_version: str,\n    max_tokens: Optional[int],\n    temperature: Optional[float],\n    extended_thinking: Optional[bool],\n    thinking_budget_tokens: Optional[int],\n) -> str:\n    \"\"\"Execute Claude request directly to Anthropic API.\"\"\"\n    client = anthropic.Anthropic(api_key=anthropic_api_key)\n\n    if system_prompt is None:\n        system_prompt = NOT_GIVEN\n\n    if temperature is None or extended_thinking:\n        temperature = NOT_GIVEN\n\n    model_max_output = MAX_OUTPUT_TOKENS.get(model_version, DEFAULT_MAX_OUTPUT_TOKENS)\n    effective_max_tokens = max_tokens if max_tokens is not None else model_max_output\n\n    request_params = {\n        \"system\": system_prompt,\n        \"messages\": messages,\n        \"max_tokens\": effective_max_tokens,\n        \"model\": EXACT_MODEL_VERSIONS.get(model_version, model_version),\n        \"temperature\": temperature,\n    }\n\n    if extended_thinking:\n        effective_budget = (\n            thinking_budget_tokens\n            if thinking_budget_tokens is not None\n            else model_max_output // 2\n        )\n        request_params[\"thinking\"] = {\n            \"type\": \"enabled\",\n            \"budget_tokens\": effective_budget,\n        }\n\n    # Stream response to avoid max_tokens limitation\n    with client.messages.stream(**request_params) as stream:\n        result = stream.get_final_message()\n\n    return _validate_and_extract_direct_response(result)\n\n\ndef _validate_and_extract_direct_response(result) -> str:\n    \"\"\"Validate and extract text from direct Anthropic API response.\"\"\"\n    stop_reason = result.stop_reason\n\n    if stop_reason == \"max_tokens\":\n        raise ValueError(\n            \"Claude API stopped generation because the max_tokens limit was reached. \"\n            \"Please increase the max_tokens parameter to allow for a complete response.\"\n        )\n\n    if stop_reason not in [\"end_turn\", \"stop_sequence\"]:\n        raise ValueError(\n            f\"Claude API stopped generation with unexpected stop reason: {stop_reason}.\"\n        )\n\n    # Ignore thinking blocks and return text content\n    for block in result.content:\n        if block.type == \"text\":\n            return block.text\n\n    raise ValueError(\"Claude API returned no text content in response.\")\n\n\ndef _extract_claude_response_text(response_data: dict) -> str:\n    \"\"\"Extract text content from Claude API response (proxied).\"\"\"\n    stop_reason = response_data.get(\"stop_reason\")\n\n    if stop_reason == \"max_tokens\":\n        raise ValueError(\n            \"Claude API stopped generation because the max_tokens limit was reached. \"\n            \"Please increase the max_tokens parameter to allow for a complete response.\"\n        )\n\n    if stop_reason not in [\"end_turn\", \"stop_sequence\", None]:\n        raise ValueError(\n            f\"Claude API stopped generation with unexpected stop reason: {stop_reason}.\"\n        )\n\n    content = response_data.get(\"content\", [])\n    if not content:\n        raise ValueError(\"Claude API returned no content in response.\")\n\n    # Ignore thinking blocks and return text content\n    for block in content:\n        if isinstance(block, dict) and block.get(\"type\") == \"text\":\n            return block.get(\"text\", \"\")\n\n    raise ValueError(\"Claude API returned no text content in response.\")\n\n\ndef prepare_unconstrained_prompt(\n    base64_image: str,\n    prompt: str,\n    **kwargs,\n) -> Tuple[Optional[str], List[dict]]:\n    messages = [\n        {\n            \"role\": \"user\",\n            \"content\": [\n                {\n                    \"type\": \"image\",\n                    \"source\": {\n                        \"type\": \"base64\",\n                        \"media_type\": \"image/jpeg\",\n                        \"data\": base64_image,\n                    },\n                },\n                {\n                    \"type\": \"text\",\n                    \"text\": prompt,\n                },\n            ],\n        }\n    ]\n    return None, messages\n\n\ndef prepare_classification_prompt(\n    base64_image: str,\n    classes: List[str],\n    **kwargs,\n) -> Tuple[Optional[str], List[dict]]:\n    serialised_classes = \", \".join(classes)\n    system_prompt = (\n        \"You act as single-class classification model. You must provide reasonable predictions. \"\n        \"You are only allowed to produce JSON document. \"\n        'Expected structure of json: {\"class_name\": \"class-name\", \"confidence\": 0.4}. '\n        \"`class-name` must be one of the class names defined by user. You are only allowed to return \"\n        \"single JSON document, even if there are potentially multiple classes. You are not allowed to \"\n        \"return list.\"\n    )\n    messages = [\n        {\n            \"role\": \"user\",\n            \"content\": [\n                {\n                    \"type\": \"image\",\n                    \"source\": {\n                        \"type\": \"base64\",\n                        \"media_type\": \"image/jpeg\",\n                        \"data\": base64_image,\n                    },\n                },\n                {\n                    \"type\": \"text\",\n                    \"text\": f\"List of all classes to be recognised by model: {serialised_classes}\",\n                },\n            ],\n        }\n    ]\n    return system_prompt, messages\n\n\ndef prepare_multi_label_classification_prompt(\n    base64_image: str,\n    classes: List[str],\n    **kwargs,\n) -> Tuple[Optional[str], List[dict]]:\n    serialised_classes = \", \".join(classes)\n    system_prompt = (\n        \"You act as multi-label classification model. You must provide reasonable predictions. \"\n        \"You are only allowed to produce JSON document. \"\n        'Expected structure of json: {\"predicted_classes\": [{\"class\": \"class-name-1\", \"confidence\": 0.9}, '\n        '{\"class\": \"class-name-2\", \"confidence\": 0.7}]}.'\n        \"`class-name-X` must be one of the class names defined by user and `confidence` is a float value \"\n        \"in range 0.0-1.0 that represents how sure you are that the class is present in the image. \"\n        \"Only return class names that are visible.\"\n    )\n    messages = [\n        {\n            \"role\": \"user\",\n            \"content\": [\n                {\n                    \"type\": \"image\",\n                    \"source\": {\n                        \"type\": \"base64\",\n                        \"media_type\": \"image/jpeg\",\n                        \"data\": base64_image,\n                    },\n                },\n                {\n                    \"type\": \"text\",\n                    \"text\": f\"List of all classes to be recognised by model: {serialised_classes}\",\n                },\n            ],\n        }\n    ]\n    return system_prompt, messages\n\n\ndef prepare_vqa_prompt(\n    base64_image: str,\n    prompt: str,\n    **kwargs,\n) -> Tuple[Optional[str], List[dict]]:\n    system_prompt = (\n        \"You act as Visual Question Answering model. Your task is to provide answer to question\"\n        \"submitted by user. If this is open-question - answer with few sentences, for ABCD question, \"\n        \"return only the indicator of the answer.\"\n    )\n    messages = [\n        {\n            \"role\": \"user\",\n            \"content\": [\n                {\n                    \"type\": \"image\",\n                    \"source\": {\n                        \"type\": \"base64\",\n                        \"media_type\": \"image/jpeg\",\n                        \"data\": base64_image,\n                    },\n                },\n                {\n                    \"type\": \"text\",\n                    \"text\": f\"Question: {prompt}\",\n                },\n            ],\n        }\n    ]\n    return system_prompt, messages\n\n\ndef prepare_ocr_prompt(\n    base64_image: str,\n    **kwargs,\n) -> Tuple[Optional[str], List[dict]]:\n    system_prompt = (\n        \"You act as OCR model. Your task is to read text from the image and return it in \"\n        \"paragraphs representing the structure of texts in the image. You should only return \"\n        \"recognised text, nothing else.\"\n    )\n    messages = [\n        {\n            \"role\": \"user\",\n            \"content\": [\n                {\n                    \"type\": \"image\",\n                    \"source\": {\n                        \"type\": \"base64\",\n                        \"media_type\": \"image/jpeg\",\n                        \"data\": base64_image,\n                    },\n                },\n            ],\n        }\n    ]\n    return system_prompt, messages\n\n\ndef prepare_caption_prompt(\n    base64_image: str,\n    short_description: bool,\n    **kwargs,\n) -> Tuple[Optional[str], List[dict]]:\n    caption_detail_level = \"Caption should be short.\"\n    if not short_description:\n        caption_detail_level = \"Caption should be extensive.\"\n    system_prompt = (\n        f\"You act as image caption model. Your task is to provide description of the image. \"\n        f\"{caption_detail_level}\"\n    )\n    messages = [\n        {\n            \"role\": \"user\",\n            \"content\": [\n                {\n                    \"type\": \"image\",\n                    \"source\": {\n                        \"type\": \"base64\",\n                        \"media_type\": \"image/jpeg\",\n                        \"data\": base64_image,\n                    },\n                },\n            ],\n        }\n    ]\n    return system_prompt, messages\n\n\ndef prepare_structured_answering_prompt(\n    base64_image: str,\n    output_structure: Dict[str, str],\n    **kwargs,\n) -> Tuple[Optional[str], List[dict]]:\n    output_structure_serialised = json.dumps(output_structure, indent=4)\n    system_prompt = (\n        \"You are supposed to produce responses in JSON. User is to provide you dictionary with \"\n        \"keys and values. Each key must be present in your response. Values in user dictionary \"\n        \"represent descriptions for JSON fields to be generated. Provide only JSON in response.\"\n    )\n    messages = [\n        {\n            \"role\": \"user\",\n            \"content\": [\n                {\n                    \"type\": \"image\",\n                    \"source\": {\n                        \"type\": \"base64\",\n                        \"media_type\": \"image/jpeg\",\n                        \"data\": base64_image,\n                    },\n                },\n                {\n                    \"type\": \"text\",\n                    \"text\": f\"Specification of requirements regarding output fields: \\n\"\n                    f\"{output_structure_serialised}\",\n                },\n            ],\n        }\n    ]\n    return system_prompt, messages\n\n\ndef prepare_object_detection_prompt(\n    base64_image: str,\n    classes: List[str],\n    **kwargs,\n) -> Tuple[Optional[str], List[dict]]:\n    serialised_classes = \", \".join(classes)\n    system_prompt = (\n        \"You act as object-detection model. You must provide reasonable predictions. \"\n        \"You are only allowed to produce JSON document. \"\n        'Expected structure of json: {\"detections\": [{\"x_min\": 0.1, \"y_min\": 0.2, \"x_max\": 0.3, \"y_max\": 0.4, \"class_name\": \"my-class-X\", \"confidence\": 0.7}]} '\n        \"- remember to close top-level dictionary at the end. \"\n        \"`my-class-X` must be one of the class names defined by user. All coordinates must be in range 0.0-1.0, representing percentage of image dimensions. \"\n        \"`confidence` is a value in range 0.0-1.0 representing your confidence in prediction. You should detect all instances of classes provided by user.\"\n    )\n    messages = [\n        {\n            \"role\": \"user\",\n            \"content\": [\n                {\n                    \"type\": \"image\",\n                    \"source\": {\n                        \"type\": \"base64\",\n                        \"media_type\": \"image/jpeg\",\n                        \"data\": base64_image,\n                    },\n                },\n                {\n                    \"type\": \"text\",\n                    \"text\": f\"List of all classes to be recognised by model: {serialised_classes}\",\n                },\n            ],\n        }\n    ]\n    return system_prompt, messages\n\n\nPROMPT_BUILDERS = {\n    \"unconstrained\": prepare_unconstrained_prompt,\n    \"ocr\": prepare_ocr_prompt,\n    \"visual-question-answering\": prepare_vqa_prompt,\n    \"caption\": partial(prepare_caption_prompt, short_description=True),\n    \"detailed-caption\": partial(prepare_caption_prompt, short_description=False),\n    \"classification\": prepare_classification_prompt,\n    \"multi-label-classification\": prepare_multi_label_classification_prompt,\n    \"structured-answering\": prepare_structured_answering_prompt,\n    \"object-detection\": prepare_object_detection_prompt,\n}\n",
    "patch": null
  },
  {
    "trace_id": "c133ab14-0250-443b-ac9d-4ec0ed559f41",
    "function_name": "_get_block_type_identifier",
    "file_path": "inference/core/cache/air_gapped.py",
    "speedup_x": 0.10788924446918047,
    "review_quality": "medium",
    "pre_optimization_commit": "f297c436b732f5012a51f7b04c135db9133c2370",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def _get_block_type_identifier(block) -> str:\n    \"\"\"Extract the canonical ``type`` identifier from a block specification.\"\"\"\n    try:\n        schema = block.manifest_class.model_json_schema()\n        type_prop = schema.get(\"properties\", {}).get(\"type\", {})\n        # The type field is typically a const or enum with one value.\n        if \"const\" in type_prop:\n            return type_prop[\"const\"]\n        if \"enum\" in type_prop and type_prop[\"enum\"]:\n            return type_prop[\"enum\"][0]\n    except Exception:\n        pass\n    return block.identifier\n",
    "optimized_function_code": "def _get_block_type_identifier(block) -> str:\n    \"\"\"Extract the canonical ``type`` identifier from a block specification.\"\"\"\n    try:\n        schema = block.manifest_class.model_json_schema()\n        properties = schema.get(\"properties\")\n        if properties is None:\n            return block.identifier\n        \n        type_prop = properties.get(\"type\")\n        if type_prop is None:\n            return block.identifier\n        \n        # The type field is typically a const or enum with one value.\n        # The type field is typically a const or enum with one value.\n        if \"const\" in type_prop:\n            return type_prop[\"const\"]\n        if \"enum\" in type_prop:\n            enum_values = type_prop[\"enum\"]\n            if enum_values:\n                return enum_values[0]\n    except Exception:\n        pass\n    return block.identifier",
    "optimized_raw_markdown": "```python:inference/core/cache/air_gapped.py\ndef _get_block_type_identifier(block) -> str:\n    \"\"\"Extract the canonical ``type`` identifier from a block specification.\"\"\"\n    try:\n        schema = block.manifest_class.model_json_schema()\n        properties = schema.get(\"properties\")\n        if properties is None:\n            return block.identifier\n        \n        type_prop = properties.get(\"type\")\n        if type_prop is None:\n            return block.identifier\n        \n        # The type field is typically a const or enum with one value.\n        # The type field is typically a const or enum with one value.\n        if \"const\" in type_prop:\n            return type_prop[\"const\"]\n        if \"enum\" in type_prop:\n            enum_values = type_prop[\"enum\"]\n            if enum_values:\n                return enum_values[0]\n    except Exception:\n        pass\n    return block.identifier\n```",
    "optimized_function_only": "def _get_block_type_identifier(block) -> str:\n    \"\"\"Extract the canonical ``type`` identifier from a block specification.\"\"\"\n    try:\n        schema = block.manifest_class.model_json_schema()\n        properties = schema.get(\"properties\")\n        if properties is None:\n            return block.identifier\n        \n        type_prop = properties.get(\"type\")\n        if type_prop is None:\n            return block.identifier\n        \n        # The type field is typically a const or enum with one value.\n        # The type field is typically a const or enum with one value.\n        if \"const\" in type_prop:\n            return type_prop[\"const\"]\n        if \"enum\" in type_prop:\n            enum_values = type_prop[\"enum\"]\n            if enum_values:\n                return enum_values[0]\n    except Exception:\n        pass\n    return block.identifier",
    "original_file_content": "\"\"\"Utilities for discovering models and foundation-model weights in the local cache.\n\nUsed by the air-gapped workflow builder to enumerate what is available for\noffline workflow construction.\n\"\"\"\n\nimport hashlib\nimport json\nimport logging\nimport os\nimport re\nfrom typing import Any, Dict, List, Optional\n\nfrom inference.core.env import MODEL_CACHE_DIR, USE_INFERENCE_MODELS\nfrom inference.core.roboflow_api import MODEL_TYPE_KEY, PROJECT_TASK_TYPE_KEY\n\nlogger = logging.getLogger(__name__)\n\n# Directories directly under MODEL_CACHE_DIR that are not model trees.\n_SKIP_TOP_LEVEL = {\"workflow\", \"_file_locks\"}\n\n\ndef _slugify_model_id(model_id: str) -> str:\n    \"\"\"Reproduce the slug used by inference-models for cache directory names.\n\n    Must stay in sync with\n    ``inference_models.models.auto_loaders.core.slugify_model_id_to_os_safe_format``.\n    \"\"\"\n    slug = re.sub(r\"[^A-Za-z0-9_-]+\", \"-\", model_id)\n    slug = re.sub(r\"[_-]{2,}\", \"-\", slug)\n    if not slug:\n        slug = \"special-char-only-model-id\"\n    if len(slug) > 48:\n        slug = slug[:48]\n    digest = hashlib.blake2s(model_id.encode(\"utf-8\"), digest_size=4).hexdigest()\n    return f\"{slug}-{digest}\"\n\n\ndef _has_non_hidden_children(path: str) -> bool:\n    \"\"\"Return True if *path* contains at least one non-hidden entry.\n\n    Hidden files (names starting with ``\".\"``) are excluded because they may be\n    stale lock-file leftovers that do not represent usable model artifacts.\n    \"\"\"\n    try:\n        return any(not f.startswith(\".\") for f in os.listdir(path))\n    except OSError:\n        return False\n\n\ndef is_model_cached(model_id: str) -> bool:\n    \"\"\"Best-effort check whether *model_id* has cached artifacts.\n\n    Checks both the traditional and ``inference-models`` cache layouts,\n    respecting the ``USE_INFERENCE_MODELS`` flag to avoid false positives\n    from one layout when the runtime uses the other.\n\n    .. note::\n\n       This is intentionally optimistic \u2014 a directory with non-hidden files\n       is assumed to contain a usable model.  Full integrity verification\n       (hash checks, registry validation) happens at model-load time inside\n       ``inference-models``.  Treat the result as *\"there is a chance the\n       model is cached\"* rather than a guarantee.\n    \"\"\"\n    if not USE_INFERENCE_MODELS:\n        # Only check the traditional layout when inference-models is disabled.\n        traditional_path = os.path.join(MODEL_CACHE_DIR, model_id)\n        return os.path.isdir(traditional_path) and _has_non_hidden_children(\n            traditional_path\n        )\n\n    # When inference-models is enabled, check both layouts \u2014 models cached\n    # before the migration still sit in the traditional tree.\n    traditional_path = os.path.join(MODEL_CACHE_DIR, model_id)\n    if os.path.isdir(traditional_path) and _has_non_hidden_children(traditional_path):\n        return True\n\n    slug = _slugify_model_id(model_id)\n    models_cache_path = os.path.join(MODEL_CACHE_DIR, \"models-cache\", slug)\n    if os.path.isdir(models_cache_path) and _has_non_hidden_children(models_cache_path):\n        return True\n\n    return False\n\n\ndef has_cached_model_variant(model_variants: Optional[List[str]]) -> bool:\n    \"\"\"Return True if **any** of the given model variant IDs has cached artifacts.\n\n    Args:\n        model_variants: List of model IDs as returned by\n            ``WorkflowBlockManifest.get_supported_model_variants()``.\n            Returns ``False`` when *None* or empty.\n    \"\"\"\n    if not model_variants:\n        return False\n    return any(is_model_cached(mid) for mid in model_variants)\n\n\ndef _load_blocks() -> list:\n    \"\"\"Load workflow blocks, isolating the heavy import for testability.\"\"\"\n    from inference.core.workflows.execution_engine.introspection.blocks_loader import (\n        load_workflow_blocks,\n    )\n\n    return load_workflow_blocks()\n\n\ndef scan_cached_models(cache_dir: str) -> List[Dict[str, Any]]:\n    \"\"\"Walk *cache_dir* looking for ``model_type.json`` marker files.\n\n    Each marker is written by the model registry when a model is first\n    downloaded.  The file contains at least ``project_task_type`` and\n    ``model_type`` keys.\n\n    Returns a list of dicts with the following shape::\n\n        {\n            \"model_id\": \"workspace/project/3\",\n            \"name\": \"workspace/project/3\",\n            \"task_type\": \"object-detection\",\n            \"model_architecture\": \"yolov8n\",\n            \"is_foundation\": False,\n        }\n    \"\"\"\n    results: List[Dict[str, Any]] = []\n    if not os.path.isdir(cache_dir):\n        return results\n\n    for root, dirs, files in os.walk(cache_dir):\n        # Prune top-level directories we know are not model trees.\n        rel = os.path.relpath(root, cache_dir)\n        if rel == \".\":\n            dirs[:] = [d for d in dirs if d not in _SKIP_TOP_LEVEL]\n            continue\n\n        if \"model_type.json\" not in files:\n            continue\n\n        model_type_path = os.path.join(root, \"model_type.json\")\n        try:\n            with open(model_type_path, \"r\") as fh:\n                metadata = json.load(fh)\n        except (json.JSONDecodeError, OSError) as exc:\n            logger.warning(\n                \"Skipping unreadable model_type.json at %s: %s\",\n                model_type_path,\n                exc,\n            )\n            continue\n\n        if not isinstance(metadata, dict):\n            continue\n\n        # Support both traditional keys and inference-models metadata keys.\n        task_type = metadata.get(PROJECT_TASK_TYPE_KEY) or metadata.get(\"taskType\", \"\")\n        model_architecture = metadata.get(MODEL_TYPE_KEY) or metadata.get(\n            \"modelArchitecture\", \"\"\n        )\n\n        if not task_type:\n            continue\n\n        model_id = os.path.relpath(root, cache_dir)\n        # Normalise path separators on Windows.\n        model_id = model_id.replace(os.sep, \"/\")\n\n        results.append(\n            {\n                \"model_id\": model_id,\n                \"name\": model_id,\n                \"task_type\": task_type,\n                \"model_architecture\": model_architecture,\n                \"is_foundation\": False,\n            }\n        )\n\n    return results\n\n\ndef get_cached_foundation_models(\n    blocks: Optional[list] = None,\n) -> List[Dict[str, Any]]:\n    \"\"\"Return metadata for workflow blocks whose required weights are cached.\n\n    Each block whose manifest class exposes ``get_supported_model_variants``\n    is inspected.  If any variant it declares is present in the local cache\n    the block is included in the result list.\n\n    Args:\n        blocks: Optional pre-loaded list of block specifications.  When\n            *None* (the default) the blocks are loaded via the engine's\n            block loader.\n    \"\"\"\n    results: List[Dict[str, Any]] = []\n    if blocks is None:\n        try:\n            blocks = _load_blocks()\n        except Exception:\n            logger.debug(\n                \"Could not load workflow blocks for foundation model scan\",\n                exc_info=True,\n            )\n            return results\n\n    for block in blocks:\n        manifest_cls = block.manifest_class\n        model_variants = manifest_cls.get_supported_model_variants()\n        if model_variants is None:\n            continue\n\n        if not has_cached_model_variant(model_variants):\n            continue\n\n        model_id = model_variants[0] if model_variants else \"\"\n\n        block_name = model_id\n        try:\n            schema = manifest_cls.model_json_schema()\n            block_name = schema.get(\"name\", model_id)\n        except Exception:\n            pass\n\n        block_type_id = _get_block_type_identifier(block)\n\n        results.append(\n            {\n                \"model_id\": model_id,\n                \"name\": block_name,\n                \"task_type\": \"\",\n                \"model_architecture\": \"\",\n                \"is_foundation\": True,\n                \"block_type\": block_type_id,\n            }\n        )\n\n    return results\n\n\ndef get_task_type_to_block_mapping(\n    blocks: Optional[list] = None,\n) -> Dict[str, List[str]]:\n    \"\"\"Build a reverse mapping from task_type to compatible block type identifiers.\n\n    Uses ``get_compatible_task_types()`` on block manifests.  Blocks whose\n    method returns *None* (the base-class default) are skipped.\n\n    Args:\n        blocks: Optional pre-loaded list of block specifications.  When\n            *None* (the default) the blocks are loaded via the engine's\n            block loader.\n    \"\"\"\n    mapping: Dict[str, List[str]] = {}\n    if blocks is None:\n        try:\n            blocks = _load_blocks()\n        except Exception:\n            logger.debug(\n                \"Could not load workflow blocks for task-type mapping\",\n                exc_info=True,\n            )\n            return mapping\n\n    for block in blocks:\n        manifest_cls = block.manifest_class\n        task_types = manifest_cls.get_compatible_task_types()\n        if task_types is None:\n            continue\n\n        block_type_id = _get_block_type_identifier(block)\n        for tt in task_types:\n            mapping.setdefault(tt, []).append(block_type_id)\n\n    return mapping\n\n\ndef _get_block_type_identifier(block) -> str:\n    \"\"\"Extract the canonical ``type`` identifier from a block specification.\"\"\"\n    try:\n        schema = block.manifest_class.model_json_schema()\n        type_prop = schema.get(\"properties\", {}).get(\"type\", {})\n        # The type field is typically a const or enum with one value.\n        if \"const\" in type_prop:\n            return type_prop[\"const\"]\n        if \"enum\" in type_prop and type_prop[\"enum\"]:\n            return type_prop[\"enum\"][0]\n    except Exception:\n        pass\n    return block.identifier\n",
    "patch": null
  },
  {
    "trace_id": "60269a07-78e4-422b-8e45-cd3907b13c7b",
    "function_name": "_is_model_cached",
    "file_path": "inference/core/cache/air_gapped.py",
    "speedup_x": 0.23888454256186395,
    "review_quality": "high",
    "pre_optimization_commit": "835af61109f8cab1d2cb51cf93d061ef3a4c5fc7",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def _is_model_cached(model_id: str) -> bool:\n    \"\"\"Check if *model_id* has cached artifacts in either cache layout.\n\n    Layout 1 (traditional): ``MODEL_CACHE_DIR/{model_id}/`` with files inside.\n    Layout 2 (inference-models): ``MODEL_CACHE_DIR/models-cache/{slug}/`` with\n    sub-directories containing model files.\n    \"\"\"\n    # Traditional layout\n    traditional_path = os.path.join(MODEL_CACHE_DIR, model_id)\n    if os.path.isdir(traditional_path) and os.listdir(traditional_path):\n        return True\n\n    # inference-models layout\n    slug = _slugify_model_id(model_id)\n    models_cache_path = os.path.join(MODEL_CACHE_DIR, \"models-cache\", slug)\n    if os.path.isdir(models_cache_path) and os.listdir(models_cache_path):\n        return True\n\n    return False\n",
    "optimized_function_code": "import hashlib\nimport os\nimport re\n\nfrom inference.core.env import MODEL_CACHE_DIR\n\n# Pre-compile regex patterns to avoid recompilation overhead\n_PATTERN_NON_ALPHANUM = re.compile(r\"[^A-Za-z0-9_-]+\")\n_PATTERN_MULTIPLE_SEPARATORS = re.compile(r\"[_-]{2,}\")\n\ndef _slugify_model_id(model_id: str) -> str:\n    \"\"\"Reproduce the slug used by inference-models for cache directory names.\n\n    Must stay in sync with\n    ``inference_models.models.auto_loaders.core.slugify_model_id_to_os_safe_format``.\n    \"\"\"\n    slug = _PATTERN_NON_ALPHANUM.sub(\"-\", model_id)\n    slug = _PATTERN_MULTIPLE_SEPARATORS.sub(\"-\", slug)\n    if not slug:\n        slug = \"special-char-only-model-id\"\n    if len(slug) > 48:\n        slug = slug[:48]\n    digest = hashlib.blake2s(model_id.encode(\"utf-8\"), digest_size=4).hexdigest()\n    return f\"{slug}-{digest}\"\n\n\ndef _is_model_cached(model_id: str) -> bool:\n    \"\"\"Check if *model_id* has cached artifacts in either cache layout.\n\n    Layout 1 (traditional): ``MODEL_CACHE_DIR/{model_id}/`` with files inside.\n    Layout 2 (inference-models): ``MODEL_CACHE_DIR/models-cache/{slug}/`` with\n    sub-directories containing model files.\n    \"\"\"\n    # Traditional layout\n    traditional_path = os.path.join(MODEL_CACHE_DIR, model_id)\n    try:\n        with os.scandir(traditional_path) as entries:\n            if next(entries, None) is not None:\n                return True\n    except (FileNotFoundError, NotADirectoryError):\n        pass\n\n    # inference-models layout\n\n    # inference-models layout\n    slug = _slugify_model_id(model_id)\n    models_cache_path = os.path.join(MODEL_CACHE_DIR, \"models-cache\", slug)\n    try:\n        with os.scandir(models_cache_path) as entries:\n            if next(entries, None) is not None:\n                return True\n    except (FileNotFoundError, NotADirectoryError):\n        pass\n\n    return False",
    "optimized_raw_markdown": "```python:inference/core/cache/air_gapped.py\nimport hashlib\nimport os\nimport re\n\nfrom inference.core.env import MODEL_CACHE_DIR\n\n# Pre-compile regex patterns to avoid recompilation overhead\n_PATTERN_NON_ALPHANUM = re.compile(r\"[^A-Za-z0-9_-]+\")\n_PATTERN_MULTIPLE_SEPARATORS = re.compile(r\"[_-]{2,}\")\n\ndef _slugify_model_id(model_id: str) -> str:\n    \"\"\"Reproduce the slug used by inference-models for cache directory names.\n\n    Must stay in sync with\n    ``inference_models.models.auto_loaders.core.slugify_model_id_to_os_safe_format``.\n    \"\"\"\n    slug = _PATTERN_NON_ALPHANUM.sub(\"-\", model_id)\n    slug = _PATTERN_MULTIPLE_SEPARATORS.sub(\"-\", slug)\n    if not slug:\n        slug = \"special-char-only-model-id\"\n    if len(slug) > 48:\n        slug = slug[:48]\n    digest = hashlib.blake2s(model_id.encode(\"utf-8\"), digest_size=4).hexdigest()\n    return f\"{slug}-{digest}\"\n\n\ndef _is_model_cached(model_id: str) -> bool:\n    \"\"\"Check if *model_id* has cached artifacts in either cache layout.\n\n    Layout 1 (traditional): ``MODEL_CACHE_DIR/{model_id}/`` with files inside.\n    Layout 2 (inference-models): ``MODEL_CACHE_DIR/models-cache/{slug}/`` with\n    sub-directories containing model files.\n    \"\"\"\n    # Traditional layout\n    traditional_path = os.path.join(MODEL_CACHE_DIR, model_id)\n    try:\n        with os.scandir(traditional_path) as entries:\n            if next(entries, None) is not None:\n                return True\n    except (FileNotFoundError, NotADirectoryError):\n        pass\n\n    # inference-models layout\n\n    # inference-models layout\n    slug = _slugify_model_id(model_id)\n    models_cache_path = os.path.join(MODEL_CACHE_DIR, \"models-cache\", slug)\n    try:\n        with os.scandir(models_cache_path) as entries:\n            if next(entries, None) is not None:\n                return True\n    except (FileNotFoundError, NotADirectoryError):\n        pass\n\n    return False\n```",
    "optimized_function_only": "def _is_model_cached(model_id: str) -> bool:\n    \"\"\"Check if *model_id* has cached artifacts in either cache layout.\n\n    Layout 1 (traditional): ``MODEL_CACHE_DIR/{model_id}/`` with files inside.\n    Layout 2 (inference-models): ``MODEL_CACHE_DIR/models-cache/{slug}/`` with\n    sub-directories containing model files.\n    \"\"\"\n    # Traditional layout\n    traditional_path = os.path.join(MODEL_CACHE_DIR, model_id)\n    try:\n        with os.scandir(traditional_path) as entries:\n            if next(entries, None) is not None:\n                return True\n    except (FileNotFoundError, NotADirectoryError):\n        pass\n\n    # inference-models layout\n\n    # inference-models layout\n    slug = _slugify_model_id(model_id)\n    models_cache_path = os.path.join(MODEL_CACHE_DIR, \"models-cache\", slug)\n    try:\n        with os.scandir(models_cache_path) as entries:\n            if next(entries, None) is not None:\n                return True\n    except (FileNotFoundError, NotADirectoryError):\n        pass\n\n    return False",
    "original_file_content": "\"\"\"Utilities for discovering models and foundation-model weights in the local cache.\n\nUsed by the air-gapped workflow builder to enumerate what is available for\noffline workflow construction.\n\"\"\"\n\nimport hashlib\nimport json\nimport logging\nimport os\nimport re\nfrom typing import Any, Dict, List, Optional\n\nfrom inference.core.cache.model_artifacts import are_all_files_cached, get_cache_dir\nfrom inference.core.env import MODEL_CACHE_DIR\nfrom inference.core.roboflow_api import MODEL_TYPE_KEY, PROJECT_TASK_TYPE_KEY\n\nlogger = logging.getLogger(__name__)\n\n# Directories directly under MODEL_CACHE_DIR that are not model trees.\n_SKIP_TOP_LEVEL = {\"workflow\", \"_file_locks\"}\n\n\ndef _slugify_model_id(model_id: str) -> str:\n    \"\"\"Reproduce the slug used by inference-models for cache directory names.\n\n    Must stay in sync with\n    ``inference_models.models.auto_loaders.core.slugify_model_id_to_os_safe_format``.\n    \"\"\"\n    slug = re.sub(r\"[^A-Za-z0-9_-]+\", \"-\", model_id)\n    slug = re.sub(r\"[_-]{2,}\", \"-\", slug)\n    if not slug:\n        slug = \"special-char-only-model-id\"\n    if len(slug) > 48:\n        slug = slug[:48]\n    digest = hashlib.blake2s(model_id.encode(\"utf-8\"), digest_size=4).hexdigest()\n    return f\"{slug}-{digest}\"\n\n\ndef _is_model_cached(model_id: str) -> bool:\n    \"\"\"Check if *model_id* has cached artifacts in either cache layout.\n\n    Layout 1 (traditional): ``MODEL_CACHE_DIR/{model_id}/`` with files inside.\n    Layout 2 (inference-models): ``MODEL_CACHE_DIR/models-cache/{slug}/`` with\n    sub-directories containing model files.\n    \"\"\"\n    # Traditional layout\n    traditional_path = os.path.join(MODEL_CACHE_DIR, model_id)\n    if os.path.isdir(traditional_path) and os.listdir(traditional_path):\n        return True\n\n    # inference-models layout\n    slug = _slugify_model_id(model_id)\n    models_cache_path = os.path.join(MODEL_CACHE_DIR, \"models-cache\", slug)\n    if os.path.isdir(models_cache_path) and os.listdir(models_cache_path):\n        return True\n\n    return False\n\n\ndef _load_blocks() -> list:\n    \"\"\"Load workflow blocks, isolating the heavy import for testability.\"\"\"\n    from inference.core.workflows.execution_engine.introspection.blocks_loader import (\n        load_workflow_blocks,\n    )\n\n    return load_workflow_blocks()\n\n\ndef scan_cached_models(cache_dir: str) -> List[Dict[str, Any]]:\n    \"\"\"Walk *cache_dir* looking for ``model_type.json`` marker files.\n\n    Each marker is written by the model registry when a model is first\n    downloaded.  The file contains at least ``project_task_type`` and\n    ``model_type`` keys.\n\n    Returns a list of dicts with the following shape::\n\n        {\n            \"model_id\": \"workspace/project/3\",\n            \"name\": \"workspace/project/3\",\n            \"task_type\": \"object-detection\",\n            \"model_architecture\": \"yolov8n\",\n            \"is_foundation\": False,\n        }\n    \"\"\"\n    results: List[Dict[str, Any]] = []\n    if not os.path.isdir(cache_dir):\n        return results\n\n    for root, dirs, files in os.walk(cache_dir):\n        # Prune top-level directories we know are not model trees.\n        rel = os.path.relpath(root, cache_dir)\n        if rel == \".\":\n            dirs[:] = [d for d in dirs if d not in _SKIP_TOP_LEVEL]\n            continue\n\n        if \"model_type.json\" not in files:\n            continue\n\n        model_type_path = os.path.join(root, \"model_type.json\")\n        try:\n            with open(model_type_path, \"r\") as fh:\n                metadata = json.load(fh)\n        except (json.JSONDecodeError, OSError) as exc:\n            logger.warning(\n                \"Skipping unreadable model_type.json at %s: %s\",\n                model_type_path,\n                exc,\n            )\n            continue\n\n        if not isinstance(metadata, dict):\n            continue\n\n        # Support both traditional keys and inference-models metadata keys.\n        task_type = metadata.get(PROJECT_TASK_TYPE_KEY) or metadata.get(\"taskType\", \"\")\n        model_architecture = metadata.get(MODEL_TYPE_KEY) or metadata.get(\n            \"modelArchitecture\", \"\"\n        )\n\n        if not task_type:\n            continue\n\n        model_id = os.path.relpath(root, cache_dir)\n        # Normalise path separators on Windows.\n        model_id = model_id.replace(os.sep, \"/\")\n\n        results.append(\n            {\n                \"model_id\": model_id,\n                \"name\": model_id,\n                \"task_type\": task_type,\n                \"model_architecture\": model_architecture,\n                \"is_foundation\": False,\n            }\n        )\n\n    return results\n\n\ndef get_cached_foundation_models(\n    blocks: Optional[list] = None,\n) -> List[Dict[str, Any]]:\n    \"\"\"Return metadata for workflow blocks whose required weights are cached.\n\n    Each block whose manifest class exposes a ``get_required_cache_artifacts``\n    classmethod is inspected.  If every artifact it declares is already present\n    in the local cache the block is included in the result list.\n\n    Blocks that do not expose the classmethod are silently skipped.\n\n    Args:\n        blocks: Optional pre-loaded list of block specifications.  When\n            *None* (the default) the blocks are loaded via the engine's\n            block loader.\n    \"\"\"\n    results: List[Dict[str, Any]] = []\n    if blocks is None:\n        try:\n            blocks = _load_blocks()\n        except Exception:\n            logger.debug(\n                \"Could not load workflow blocks for foundation model scan\",\n                exc_info=True,\n            )\n            return results\n\n    for block in blocks:\n        manifest_cls = block.manifest_class\n        if not hasattr(manifest_cls, \"get_required_cache_artifacts\"):\n            continue\n\n        try:\n            artifacts_spec = manifest_cls.get_required_cache_artifacts()\n        except Exception:\n            logger.debug(\n                \"Error calling get_required_cache_artifacts on %s\",\n                block.identifier,\n                exc_info=True,\n            )\n            continue\n\n        # artifacts_spec can be:\n        #   - list of model_id strings (new format): block is cached if ANY\n        #     variant directory exists and contains files\n        #   - dict with {\"model_id\": ..., \"files\": [...]} (legacy format)\n        if isinstance(artifacts_spec, list):\n            cached = any(_is_model_cached(mid) for mid in artifacts_spec)\n            if not cached:\n                continue\n            model_id = artifacts_spec[0] if artifacts_spec else \"\"\n        elif isinstance(artifacts_spec, dict):\n            model_id = artifacts_spec.get(\"model_id\")\n            required_files = artifacts_spec.get(\"files\", [])\n            if not model_id or not required_files:\n                continue\n            if not are_all_files_cached(files=required_files, model_id=model_id):\n                continue\n        else:\n            continue\n\n        # Derive name from the block's manifest schema (json_schema_extra)\n        # rather than requiring it in the artifacts dict.\n        block_name = model_id\n        try:\n            schema = manifest_cls.model_json_schema()\n            block_name = schema.get(\"name\", model_id)\n        except Exception:\n            pass\n\n        # Use the block type identifier from the manifest's type field.\n        block_type_id = _get_block_type_identifier(block)\n\n        results.append(\n            {\n                \"model_id\": model_id,\n                \"name\": block_name,\n                \"task_type\": \"\",\n                \"model_architecture\": \"\",\n                \"is_foundation\": True,\n                \"block_type\": block_type_id,\n            }\n        )\n\n    return results\n\n\ndef get_task_type_to_block_mapping(\n    blocks: Optional[list] = None,\n) -> Dict[str, List[str]]:\n    \"\"\"Build a reverse mapping from task_type to compatible block type identifiers.\n\n    Uses ``get_compatible_task_types()`` classmethod on block manifests when\n    available.  Blocks that do not expose the classmethod are skipped.\n\n    Args:\n        blocks: Optional pre-loaded list of block specifications.  When\n            *None* (the default) the blocks are loaded via the engine's\n            block loader.\n    \"\"\"\n    mapping: Dict[str, List[str]] = {}\n    if blocks is None:\n        try:\n            blocks = _load_blocks()\n        except Exception:\n            logger.debug(\n                \"Could not load workflow blocks for task-type mapping\",\n                exc_info=True,\n            )\n            return mapping\n\n    for block in blocks:\n        manifest_cls = block.manifest_class\n        if not hasattr(manifest_cls, \"get_compatible_task_types\"):\n            continue\n\n        try:\n            task_types = manifest_cls.get_compatible_task_types()\n        except Exception:\n            logger.debug(\n                \"Error calling get_compatible_task_types on %s\",\n                block.identifier,\n                exc_info=True,\n            )\n            continue\n\n        if not isinstance(task_types, (list, tuple, set)):\n            continue\n\n        # Derive the manifest type identifier\n        # (e.g. \"roboflow_core/roboflow_object_detection_model@v2\")\n        # from the block schema.\n        block_type_id = _get_block_type_identifier(block)\n\n        for tt in task_types:\n            mapping.setdefault(tt, []).append(block_type_id)\n\n    return mapping\n\n\ndef _get_block_type_identifier(block) -> str:\n    \"\"\"Extract the canonical ``type`` identifier from a block specification.\"\"\"\n    try:\n        schema = block.manifest_class.model_json_schema()\n        type_prop = schema.get(\"properties\", {}).get(\"type\", {})\n        # The type field is typically a const or enum with one value.\n        if \"const\" in type_prop:\n            return type_prop[\"const\"]\n        if \"enum\" in type_prop and type_prop[\"enum\"]:\n            return type_prop[\"enum\"][0]\n    except Exception:\n        pass\n    return block.identifier\n",
    "patch": null
  },
  {
    "trace_id": "013776ec-6202-49c6-a9ae-d8ccf8a6131f",
    "function_name": "ModelManager.infer_from_request_sync",
    "file_path": "inference/core/managers/base.py",
    "speedup_x": 0.4579793719483347,
    "review_quality": "high",
    "pre_optimization_commit": "607c853289559d1117ee503cf7c703552e1306a7",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def infer_from_request_sync(\n        self, model_id: str, request: InferenceRequest, **kwargs\n    ) -> InferenceResponse:\n        \"\"\"Runs inference on the specified model with the given request.\n\n        Args:\n            model_id (str): The identifier of the model.\n            request (InferenceRequest): The request to process.\n\n        Returns:\n            InferenceResponse: The response from the inference.\n        \"\"\"\n        logger.debug(\n            f\"ModelManager - inference from request started for model_id={model_id}.\"\n        )\n        enable_model_monitoring = not getattr(\n            request, \"disable_model_monitoring\", False\n        )\n        if METRICS_ENABLED and self.pingback and enable_model_monitoring:\n            logger.debug(\"ModelManager - setting pingback fallback api key...\")\n            self.pingback.fallback_api_key = request.api_key\n        with start_span(\"model.infer\", {\"model.id\": model_id}):\n            try:\n                t_infer_start = time.perf_counter()\n                rtn_val = self.model_infer_sync(\n                    model_id=model_id, request=request, **kwargs\n                )\n                record_inference(model_id, time.perf_counter() - t_infer_start)\n                logger.debug(\n                    f\"ModelManager - inference from request finished for model_id={model_id}.\"\n                )\n                finish_time = time.time()\n                if not DISABLE_INFERENCE_CACHE and enable_model_monitoring:\n                    try:\n                        logger.debug(\n                            f\"ModelManager - caching inference request started for model_id={model_id}\"\n                        )\n                        cache.zadd(\n                            f\"models\",\n                            value=f\"{GLOBAL_INFERENCE_SERVER_ID}:{request.api_key}:{model_id}\",\n                            score=finish_time,\n                            expire=METRICS_INTERVAL * 2,\n                        )\n                        if (\n                            hasattr(request, \"image\")\n                            and hasattr(request.image, \"type\")\n                            and request.image.type == \"numpy\"\n                        ):\n                            request.image.value = str(request.image.value)\n                        cache.zadd(\n                            f\"inference:{GLOBAL_INFERENCE_SERVER_ID}:{model_id}\",\n                            value=to_cachable_inference_item(request, rtn_val),\n                            score=finish_time,\n                            expire=METRICS_INTERVAL * 2,\n                        )\n                        logger.debug(\n                            f\"ModelManager - caching inference request finished for model_id={model_id}\"\n                        )\n                    except Exception as cache_error:\n                        logger.warning(\n                            f\"Failed to cache inference data for model {model_id}: {cache_error}\"\n                        )\n                return rtn_val\n            except Exception as e:\n                record_error(e)\n                finish_time = time.time()\n                if not DISABLE_INFERENCE_CACHE and enable_model_monitoring:\n                    try:\n                        cache.zadd(\n                            f\"models\",\n                            value=f\"{GLOBAL_INFERENCE_SERVER_ID}:{request.api_key}:{model_id}\",\n                            score=finish_time,\n                            expire=METRICS_INTERVAL * 2,\n                        )\n                        cache.zadd(\n                            f\"error:{GLOBAL_INFERENCE_SERVER_ID}:{model_id}\",\n                            value={\n                                \"request\": jsonable_encoder(\n                                    request.dict(exclude={\"image\", \"subject\", \"prompt\"})\n                                ),\n                                \"error\": str(e),\n                            },\n                            score=finish_time,\n                            expire=METRICS_INTERVAL * 2,\n                        )\n                    except Exception as cache_error:\n                        logger.warning(\n                            f\"Failed to cache error data for model {model_id}: {cache_error}\"\n                        )\n                raise\n",
    "optimized_function_code": "import time\nfrom threading import Lock\nfrom typing import Dict, List, Optional, Union\n\nfrom fastapi.encoders import jsonable_encoder\nfrom inference.core.cache import cache\nfrom inference.core.cache.serializers import to_cachable_inference_item\nfrom inference.core.devices.utils import GLOBAL_INFERENCE_SERVER_ID\nfrom inference.core.entities.requests.inference import InferenceRequest\nfrom inference.core.entities.responses.inference import InferenceResponse\nfrom inference.core.env import (DISABLE_INFERENCE_CACHE, METRICS_ENABLED,\n                                METRICS_INTERVAL)\nfrom inference.core.logger import logger\nfrom inference.core.models.base import Model\nfrom inference.core.registries.base import ModelRegistry\nfrom inference.core.telemetry import record_error, record_inference, start_span\n\n\nclass ModelManager:\n\n    def __init__(self, model_registry: ModelRegistry, models: Optional[dict] = None):\n        self.model_registry = model_registry\n        self._models: Dict[str, Model] = models if models is not None else {}\n        self.pingback = None\n        self._state_lock = Lock()\n        self._models_state_locks: Dict[str, Lock] = {}\n\n    def infer_from_request_sync(\n        self, model_id: str, request: InferenceRequest, **kwargs\n    ) -> InferenceResponse:\n        \"\"\"Runs inference on the specified model with the given request.\n\n        Args:\n            model_id (str): The identifier of the model.\n            request (InferenceRequest): The request to process.\n\n        Returns:\n            InferenceResponse: The response from the inference.\n        \"\"\"\n        logger.debug(\n            f\"ModelManager - inference from request started for model_id={model_id}.\"\n        )\n        enable_model_monitoring = not getattr(\n            request, \"disable_model_monitoring\", False\n        )\n        if METRICS_ENABLED and self.pingback and enable_model_monitoring:\n            logger.debug(\"ModelManager - setting pingback fallback api key...\")\n            self.pingback.fallback_api_key = request.api_key\n        with start_span(\"model.infer\", {\"model.id\": model_id}):\n            try:\n                t_infer_start = time.perf_counter()\n                rtn_val = self.model_infer_sync(\n                    model_id=model_id, request=request, **kwargs\n                )\n                record_inference(model_id, time.perf_counter() - t_infer_start)\n                logger.debug(\n                    f\"ModelManager - inference from request finished for model_id={model_id}.\"\n                )\n                finish_time = time.time()\n                if not DISABLE_INFERENCE_CACHE and enable_model_monitoring:\n                    try:\n                        logger.debug(\n                            f\"ModelManager - caching inference request started for model_id={model_id}\"\n                        )\n                        cache.zadd(\n                            f\"models\",\n                            value=f\"{GLOBAL_INFERENCE_SERVER_ID}:{request.api_key}:{model_id}\",\n                            score=finish_time,\n                            expire=METRICS_INTERVAL * 2,\n                        )\n                        if (\n                            hasattr(request, \"image\")\n                            and hasattr(request.image, \"type\")\n                            and request.image.type == \"numpy\"\n                        ):\n                            request.image.value = str(request.image.value)\n                        cache.zadd(\n                            f\"inference:{GLOBAL_INFERENCE_SERVER_ID}:{model_id}\",\n                            value=to_cachable_inference_item(request, rtn_val),\n                            score=finish_time,\n                            expire=METRICS_INTERVAL * 2,\n                        )\n                        logger.debug(\n                            f\"ModelManager - caching inference request finished for model_id={model_id}\"\n                        )\n                    except Exception as cache_error:\n                        logger.warning(\n                            f\"Failed to cache inference data for model {model_id}: {cache_error}\"\n                        )\n                return rtn_val\n            except Exception as e:\n                record_error(e)\n                finish_time = time.time()\n                if not DISABLE_INFERENCE_CACHE and enable_model_monitoring:\n                    try:\n                        cache.zadd(\n                            f\"models\",\n                            value=f\"{GLOBAL_INFERENCE_SERVER_ID}:{request.api_key}:{model_id}\",\n                            score=finish_time,\n                            expire=METRICS_INTERVAL * 2,\n                        )\n                        cache.zadd(\n                            f\"error:{GLOBAL_INFERENCE_SERVER_ID}:{model_id}\",\n                            value={\n                                \"request\": jsonable_encoder(\n                                    request.dict(exclude={\"image\", \"subject\", \"prompt\"})\n                                ),\n                                \"error\": str(e),\n                            },\n                            score=finish_time,\n                            expire=METRICS_INTERVAL * 2,\n                        )\n                    except Exception as cache_error:\n                        logger.warning(\n                            f\"Failed to cache error data for model {model_id}: {cache_error}\"\n                        )\n                raise\n\n    def model_infer_sync(\n        self, model_id: str, request: InferenceRequest, **kwargs\n    ) -> Union[List[InferenceResponse], InferenceResponse]:\n        model = self._get_model_reference(model_id=model_id)\n        return model.infer_from_request(request)",
    "optimized_raw_markdown": "```python:inference/core/cache/memory.py\nimport threading\nimport time\nfrom typing import Any\n\nfrom inference.core.cache.base import BaseCache\n\n\nclass MemoryCache(BaseCache):\n\n    def __init__(self) -> None:\n        \"\"\"\n        Initializes a new instance of the MemoryCache class.\n        \"\"\"\n        self.cache = dict()\n        self.expires = dict()\n        self.zexpires = dict()\n\n        self._expire_thread = threading.Thread(target=self._expire)\n        self._expire_thread.daemon = True\n        self._expire_thread.start()\n\n    def zadd(self, key: str, value: Any, score: float, expire: float = None):\n        \"\"\"\n        Adds a member with the specified score to the sorted set stored at key.\n\n        Args:\n            key (str): The key of the sorted set.\n            value (str): The value to add to the sorted set.\n            score (float): The score associated with the value.\n            expire (float, optional): The time, in seconds, after which the key will expire. Defaults to None.\n        \"\"\"\n        if key not in self.cache:\n            self.cache[key] = dict()\n        self.cache[key][score] = value\n        if expire:\n            self.zexpires[(key, score)] = expire + time.time()\n```\n```python:inference/core/cache/serializers.py\nfrom typing import List, Union\n\nfrom fastapi.encoders import jsonable_encoder\nfrom inference.core.devices.utils import GLOBAL_INFERENCE_SERVER_ID\nfrom inference.core.entities.requests.inference import InferenceRequest\nfrom inference.core.entities.responses.inference import InferenceResponse\nfrom inference.core.env import TINY_CACHE\nfrom inference.core.version import __version__\n\n\ndef to_cachable_inference_item(\n    infer_request: InferenceRequest,\n    infer_response: Union[InferenceResponse, List[InferenceResponse]],\n) -> dict:\n    if not TINY_CACHE:\n        return {\n            \"inference_id\": infer_request.id,\n            \"inference_server_version\": __version__,\n            \"inference_server_id\": GLOBAL_INFERENCE_SERVER_ID,\n            \"request\": jsonable_encoder(infer_request),\n            \"response\": jsonable_encoder(infer_response),\n        }\n\n    included_request_fields = {\n        \"api_key\",\n        \"confidence\",\n        \"model_id\",\n        \"model_type\",\n        \"source\",\n        \"source_info\",\n    }\n    request = infer_request.dict(include=included_request_fields)\n    response = build_condensed_response(infer_response)\n    return {\n        \"inference_id\": infer_request.id,\n        \"inference_server_version\": __version__,\n        \"inference_server_id\": GLOBAL_INFERENCE_SERVER_ID,\n        \"request\": request,\n        \"response\": response,\n    }\n```\n```python:inference/core/managers/base.py\nimport time\nfrom threading import Lock\nfrom typing import Dict, List, Optional, Union\n\nfrom fastapi.encoders import jsonable_encoder\nfrom inference.core.cache import cache\nfrom inference.core.cache.serializers import to_cachable_inference_item\nfrom inference.core.devices.utils import GLOBAL_INFERENCE_SERVER_ID\nfrom inference.core.entities.requests.inference import InferenceRequest\nfrom inference.core.entities.responses.inference import InferenceResponse\nfrom inference.core.env import (DISABLE_INFERENCE_CACHE, METRICS_ENABLED,\n                                METRICS_INTERVAL)\nfrom inference.core.logger import logger\nfrom inference.core.models.base import Model\nfrom inference.core.registries.base import ModelRegistry\nfrom inference.core.telemetry import record_error, record_inference, start_span\n\n\nclass ModelManager:\n\n    def __init__(self, model_registry: ModelRegistry, models: Optional[dict] = None):\n        self.model_registry = model_registry\n        self._models: Dict[str, Model] = models if models is not None else {}\n        self.pingback = None\n        self._state_lock = Lock()\n        self._models_state_locks: Dict[str, Lock] = {}\n\n    def infer_from_request_sync(\n        self, model_id: str, request: InferenceRequest, **kwargs\n    ) -> InferenceResponse:\n        \"\"\"Runs inference on the specified model with the given request.\n\n        Args:\n            model_id (str): The identifier of the model.\n            request (InferenceRequest): The request to process.\n\n        Returns:\n            InferenceResponse: The response from the inference.\n        \"\"\"\n        logger.debug(\n            f\"ModelManager - inference from request started for model_id={model_id}.\"\n        )\n        enable_model_monitoring = not getattr(\n            request, \"disable_model_monitoring\", False\n        )\n        if METRICS_ENABLED and self.pingback and enable_model_monitoring:\n            logger.debug(\"ModelManager - setting pingback fallback api key...\")\n            self.pingback.fallback_api_key = request.api_key\n        with start_span(\"model.infer\", {\"model.id\": model_id}):\n            try:\n                t_infer_start = time.perf_counter()\n                rtn_val = self.model_infer_sync(\n                    model_id=model_id, request=request, **kwargs\n                )\n                record_inference(model_id, time.perf_counter() - t_infer_start)\n                logger.debug(\n                    f\"ModelManager - inference from request finished for model_id={model_id}.\"\n                )\n                finish_time = time.time()\n                if not DISABLE_INFERENCE_CACHE and enable_model_monitoring:\n                    try:\n                        logger.debug(\n                            f\"ModelManager - caching inference request started for model_id={model_id}\"\n                        )\n                        cache.zadd(\n                            f\"models\",\n                            value=f\"{GLOBAL_INFERENCE_SERVER_ID}:{request.api_key}:{model_id}\",\n                            score=finish_time,\n                            expire=METRICS_INTERVAL * 2,\n                        )\n                        if (\n                            hasattr(request, \"image\")\n                            and hasattr(request.image, \"type\")\n                            and request.image.type == \"numpy\"\n                        ):\n                            request.image.value = str(request.image.value)\n                        cache.zadd(\n                            f\"inference:{GLOBAL_INFERENCE_SERVER_ID}:{model_id}\",\n                            value=to_cachable_inference_item(request, rtn_val),\n                            score=finish_time,\n                            expire=METRICS_INTERVAL * 2,\n                        )\n                        logger.debug(\n                            f\"ModelManager - caching inference request finished for model_id={model_id}\"\n                        )\n                    except Exception as cache_error:\n                        logger.warning(\n                            f\"Failed to cache inference data for model {model_id}: {cache_error}\"\n                        )\n                return rtn_val\n            except Exception as e:\n                record_error(e)\n                finish_time = time.time()\n                if not DISABLE_INFERENCE_CACHE and enable_model_monitoring:\n                    try:\n                        cache.zadd(\n                            f\"models\",\n                            value=f\"{GLOBAL_INFERENCE_SERVER_ID}:{request.api_key}:{model_id}\",\n                            score=finish_time,\n                            expire=METRICS_INTERVAL * 2,\n                        )\n                        cache.zadd(\n                            f\"error:{GLOBAL_INFERENCE_SERVER_ID}:{model_id}\",\n                            value={\n                                \"request\": jsonable_encoder(\n                                    request.dict(exclude={\"image\", \"subject\", \"prompt\"})\n                                ),\n                                \"error\": str(e),\n                            },\n                            score=finish_time,\n                            expire=METRICS_INTERVAL * 2,\n                        )\n                    except Exception as cache_error:\n                        logger.warning(\n                            f\"Failed to cache error data for model {model_id}: {cache_error}\"\n                        )\n                raise\n\n    def model_infer_sync(\n        self, model_id: str, request: InferenceRequest, **kwargs\n    ) -> Union[List[InferenceResponse], InferenceResponse]:\n        model = self._get_model_reference(model_id=model_id)\n        return model.infer_from_request(request)\n```",
    "optimized_function_only": "    def infer_from_request_sync(\n        self, model_id: str, request: InferenceRequest, **kwargs\n    ) -> InferenceResponse:\n        \"\"\"Runs inference on the specified model with the given request.\n\n        Args:\n            model_id (str): The identifier of the model.\n            request (InferenceRequest): The request to process.\n\n        Returns:\n            InferenceResponse: The response from the inference.\n        \"\"\"\n        logger.debug(\n            f\"ModelManager - inference from request started for model_id={model_id}.\"\n        )\n        enable_model_monitoring = not getattr(\n            request, \"disable_model_monitoring\", False\n        )\n        if METRICS_ENABLED and self.pingback and enable_model_monitoring:\n            logger.debug(\"ModelManager - setting pingback fallback api key...\")\n            self.pingback.fallback_api_key = request.api_key\n        with start_span(\"model.infer\", {\"model.id\": model_id}):\n            try:\n                t_infer_start = time.perf_counter()\n                rtn_val = self.model_infer_sync(\n                    model_id=model_id, request=request, **kwargs\n                )\n                record_inference(model_id, time.perf_counter() - t_infer_start)\n                logger.debug(\n                    f\"ModelManager - inference from request finished for model_id={model_id}.\"\n                )\n                finish_time = time.time()\n                if not DISABLE_INFERENCE_CACHE and enable_model_monitoring:\n                    try:\n                        logger.debug(\n                            f\"ModelManager - caching inference request started for model_id={model_id}\"\n                        )\n                        cache.zadd(\n                            f\"models\",\n                            value=f\"{GLOBAL_INFERENCE_SERVER_ID}:{request.api_key}:{model_id}\",\n                            score=finish_time,\n                            expire=METRICS_INTERVAL * 2,\n                        )\n                        if (\n                            hasattr(request, \"image\")\n                            and hasattr(request.image, \"type\")\n                            and request.image.type == \"numpy\"\n                        ):\n                            request.image.value = str(request.image.value)\n                        cache.zadd(\n                            f\"inference:{GLOBAL_INFERENCE_SERVER_ID}:{model_id}\",\n                            value=to_cachable_inference_item(request, rtn_val),\n                            score=finish_time,\n                            expire=METRICS_INTERVAL * 2,\n                        )\n                        logger.debug(\n                            f\"ModelManager - caching inference request finished for model_id={model_id}\"\n                        )\n                    except Exception as cache_error:\n                        logger.warning(\n                            f\"Failed to cache inference data for model {model_id}: {cache_error}\"\n                        )\n                return rtn_val\n            except Exception as e:\n                record_error(e)\n                finish_time = time.time()\n                if not DISABLE_INFERENCE_CACHE and enable_model_monitoring:\n                    try:\n                        cache.zadd(\n                            f\"models\",\n                            value=f\"{GLOBAL_INFERENCE_SERVER_ID}:{request.api_key}:{model_id}\",\n                            score=finish_time,\n                            expire=METRICS_INTERVAL * 2,\n                        )\n                        cache.zadd(\n                            f\"error:{GLOBAL_INFERENCE_SERVER_ID}:{model_id}\",\n                            value={\n                                \"request\": jsonable_encoder(\n                                    request.dict(exclude={\"image\", \"subject\", \"prompt\"})\n                                ),\n                                \"error\": str(e),\n                            },\n                            score=finish_time,\n                            expire=METRICS_INTERVAL * 2,\n                        )\n                    except Exception as cache_error:\n                        logger.warning(\n                            f\"Failed to cache error data for model {model_id}: {cache_error}\"\n                        )\n                raise\n",
    "original_file_content": "import time\nfrom contextlib import contextmanager\nfrom threading import Lock\nfrom typing import Dict, Generator, List, Optional, Tuple, Union\n\nimport numpy as np\nfrom fastapi.encoders import jsonable_encoder\n\nfrom inference.core.cache import cache\nfrom inference.core.cache.serializers import to_cachable_inference_item\nfrom inference.core.devices.utils import GLOBAL_INFERENCE_SERVER_ID\nfrom inference.core.entities.requests.inference import InferenceRequest\nfrom inference.core.entities.responses.inference import InferenceResponse\nfrom inference.core.env import (\n    DISABLE_INFERENCE_CACHE,\n    INTERNAL_WEIGHTS_URL_SUFFIX,\n    METRICS_ENABLED,\n    METRICS_INTERVAL,\n    MODEL_LOCK_ACQUIRE_TIMEOUT,\n    MODELS_CACHE_AUTH_ENABLED,\n    ROBOFLOW_SERVER_UUID,\n    USE_INFERENCE_MODELS,\n)\nfrom inference.core.exceptions import (\n    InferenceModelNotFound,\n    ModelManagerLockAcquisitionError,\n    RoboflowAPINotAuthorizedError,\n)\nfrom inference.core.logger import logger\nfrom inference.core.managers.entities import ModelDescription\nfrom inference.core.managers.model_load_collector import (\n    model_load_info,\n    request_model_ids,\n)\nfrom inference.core.managers.pingback import PingbackInfo\nfrom inference.core.models.base import Model, PreprocessReturnMetadata\nfrom inference.core.registries.base import ModelRegistry\nfrom inference.core.registries.roboflow import (\n    ModelEndpointType,\n    _check_if_api_key_has_access_to_model,\n)\nfrom inference.core.telemetry import (\n    record_error,\n    record_inference,\n    record_model_loaded,\n    record_model_unloaded,\n    set_span_attribute,\n    start_span,\n)\n\n\nclass ModelManager:\n    \"\"\"Model managers keep track of a dictionary of Model objects and is responsible for passing requests to the right model using the infer method.\"\"\"\n\n    def __init__(self, model_registry: ModelRegistry, models: Optional[dict] = None):\n        self.model_registry = model_registry\n        self._models: Dict[str, Model] = models if models is not None else {}\n        self.pingback = None\n        self._state_lock = Lock()\n        self._models_state_locks: Dict[str, Lock] = {}\n\n    def init_pingback(self):\n        \"\"\"Initializes pingback mechanism.\"\"\"\n        self.num_errors = 0  # in the device\n        self.uuid = ROBOFLOW_SERVER_UUID\n        if METRICS_ENABLED:\n            self.pingback = PingbackInfo(self)\n            self.pingback.start()\n\n    def add_model(\n        self,\n        model_id: str,\n        api_key: str,\n        model_id_alias: Optional[str] = None,\n        endpoint_type: ModelEndpointType = ModelEndpointType.ORT,\n        countinference: Optional[bool] = None,\n        service_secret: Optional[str] = None,\n    ) -> None:\n        \"\"\"Adds a new model to the manager.\n\n        Args:\n            model_id (str): The identifier of the model.\n            model (Model): The model instance.\n            endpoint_type (ModelEndpointType, optional): The endpoint type to use for the model.\n        \"\"\"\n        if MODELS_CACHE_AUTH_ENABLED:\n            if not _check_if_api_key_has_access_to_model(\n                api_key=api_key,\n                model_id=model_id,\n                endpoint_type=endpoint_type,\n                countinference=countinference,\n                service_secret=service_secret,\n            ):\n                raise RoboflowAPINotAuthorizedError(\n                    f\"API key {api_key} does not have access to model {model_id}\"\n                )\n\n        logger.debug(\n            f\"ModelManager - Adding model with model_id={model_id}, model_id_alias={model_id_alias}\"\n        )\n        resolved_identifier = model_id if model_id_alias is None else model_id_alias\n        ids_collector = request_model_ids.get(None)\n        if ids_collector is not None:\n            ids_collector.add(resolved_identifier)\n        model_lock = self._get_lock_for_a_model(model_id=resolved_identifier)\n        with acquire_with_timeout(lock=model_lock) as acquired:\n            if not acquired:\n                # if failed to acquire - then in use, no need to purge lock\n                raise ModelManagerLockAcquisitionError(\n                    f\"Could not acquire lock for model with id={resolved_identifier}.\"\n                )\n            if resolved_identifier in self._models:\n                logger.debug(\n                    f\"ModelManager - model with model_id={resolved_identifier} is already loaded.\"\n                )\n                return\n            try:\n                with start_span(\"model.load\", {\"model.id\": resolved_identifier}):\n                    logger.debug(\"ModelManager - model initialisation...\")\n                    t_load_start = time.perf_counter()\n                    model_class = self.model_registry.get_model(\n                        resolved_identifier,\n                        api_key,\n                        countinference=countinference,\n                        service_secret=service_secret,\n                    )\n\n                    model = model_class(\n                        model_id=model_id,\n                        api_key=api_key,\n                        countinference=countinference,\n                        service_secret=service_secret,\n                    )\n\n                    # Pass countinference and service_secret to download_model_artifacts_from_roboflow_api if available\n                    if (\n                        hasattr(model, \"download_model_artifacts_from_roboflow_api\")\n                        and INTERNAL_WEIGHTS_URL_SUFFIX == \"serverless\"\n                    ):\n                        # Only pass these parameters if INTERNAL_WEIGHTS_URL_SUFFIX is \"serverless\"\n                        if (\n                            hasattr(model, \"cache_model_artefacts\")\n                            and not model.has_model_metadata\n                        ):\n                            # Override the download_model_artifacts_from_roboflow_api method with parameters\n                            original_method = (\n                                model.download_model_artifacts_from_roboflow_api\n                            )\n                            model.download_model_artifacts_from_roboflow_api = (\n                                lambda: original_method(\n                                    countinference=countinference,\n                                    service_secret=service_secret,\n                                )\n                            )\n\n                    load_time = time.perf_counter() - t_load_start\n                    set_span_attribute(\"model.load_time_seconds\", load_time)\n                    record_model_loaded(resolved_identifier, load_time)\n                    logger.debug(\n                        f\"ModelManager - model successfully loaded in {load_time:.2f}s.\"\n                    )\n                    self._models[resolved_identifier] = model\n                    collector = model_load_info.get(None)\n                    if collector is not None:\n                        collector.record(\n                            model_id=resolved_identifier, load_time=load_time\n                        )\n            except Exception as error:\n                record_error(error)\n                self._dispose_model_lock(model_id=resolved_identifier)\n                raise error\n\n    def check_for_model(self, model_id: str) -> None:\n        \"\"\"Checks whether the model with the given ID is in the manager.\n\n        Args:\n            model_id (str): The identifier of the model.\n\n        Raises:\n            InferenceModelNotFound: If the model is not found in the manager.\n        \"\"\"\n        if model_id not in self:\n            raise InferenceModelNotFound(f\"Model with id {model_id} not loaded.\")\n\n    async def infer_from_request(\n        self, model_id: str, request: InferenceRequest, **kwargs\n    ) -> InferenceResponse:\n        \"\"\"Runs inference on the specified model with the given request.\n\n        Args:\n            model_id (str): The identifier of the model.\n            request (InferenceRequest): The request to process.\n\n        Returns:\n            InferenceResponse: The response from the inference.\n        \"\"\"\n        logger.debug(\n            f\"ModelManager - inference from request started for model_id={model_id}.\"\n        )\n        enable_model_monitoring = not getattr(\n            request, \"disable_model_monitoring\", False\n        )\n        if METRICS_ENABLED and self.pingback and enable_model_monitoring:\n            logger.debug(\"ModelManager - setting pingback fallback api key...\")\n            self.pingback.fallback_api_key = request.api_key\n        with start_span(\"model.infer\", {\"model.id\": model_id}):\n            try:\n                t_infer_start = time.perf_counter()\n                rtn_val = await self.model_infer(\n                    model_id=model_id, request=request, **kwargs\n                )\n                record_inference(model_id, time.perf_counter() - t_infer_start)\n                logger.debug(\n                    f\"ModelManager - inference from request finished for model_id={model_id}.\"\n                )\n                finish_time = time.time()\n                if not DISABLE_INFERENCE_CACHE and enable_model_monitoring:\n                    try:\n                        logger.debug(\n                            f\"ModelManager - caching inference request started for model_id={model_id}\"\n                        )\n                        cache.zadd(\n                            f\"models\",\n                            value=f\"{GLOBAL_INFERENCE_SERVER_ID}:{request.api_key}:{model_id}\",\n                            score=finish_time,\n                            expire=METRICS_INTERVAL * 2,\n                        )\n                        if (\n                            hasattr(request, \"image\")\n                            and hasattr(request.image, \"type\")\n                            and request.image.type == \"numpy\"\n                        ):\n                            request.image.value = str(request.image.value)\n                        cache.zadd(\n                            f\"inference:{GLOBAL_INFERENCE_SERVER_ID}:{model_id}\",\n                            value=to_cachable_inference_item(request, rtn_val),\n                            score=finish_time,\n                            expire=METRICS_INTERVAL * 2,\n                        )\n                        logger.debug(\n                            f\"ModelManager - caching inference request finished for model_id={model_id}\"\n                        )\n                    except Exception as cache_error:\n                        logger.warning(\n                            f\"Failed to cache inference data for model {model_id}: {cache_error}\"\n                        )\n                return rtn_val\n            except Exception as e:\n                record_error(e)\n                finish_time = time.time()\n                if not DISABLE_INFERENCE_CACHE and enable_model_monitoring:\n                    try:\n                        cache.zadd(\n                            f\"models\",\n                            value=f\"{GLOBAL_INFERENCE_SERVER_ID}:{request.api_key}:{model_id}\",\n                            score=finish_time,\n                            expire=METRICS_INTERVAL * 2,\n                        )\n                        cache.zadd(\n                            f\"error:{GLOBAL_INFERENCE_SERVER_ID}:{model_id}\",\n                            value={\n                                \"request\": jsonable_encoder(\n                                    request.dict(exclude={\"image\", \"subject\", \"prompt\"})\n                                ),\n                                \"error\": str(e),\n                            },\n                            score=finish_time,\n                            expire=METRICS_INTERVAL * 2,\n                        )\n                    except Exception as cache_error:\n                        logger.warning(\n                            f\"Failed to cache error data for model {model_id}: {cache_error}\"\n                        )\n                raise\n\n    def infer_from_request_sync(\n        self, model_id: str, request: InferenceRequest, **kwargs\n    ) -> InferenceResponse:\n        \"\"\"Runs inference on the specified model with the given request.\n\n        Args:\n            model_id (str): The identifier of the model.\n            request (InferenceRequest): The request to process.\n\n        Returns:\n            InferenceResponse: The response from the inference.\n        \"\"\"\n        logger.debug(\n            f\"ModelManager - inference from request started for model_id={model_id}.\"\n        )\n        enable_model_monitoring = not getattr(\n            request, \"disable_model_monitoring\", False\n        )\n        if METRICS_ENABLED and self.pingback and enable_model_monitoring:\n            logger.debug(\"ModelManager - setting pingback fallback api key...\")\n            self.pingback.fallback_api_key = request.api_key\n        with start_span(\"model.infer\", {\"model.id\": model_id}):\n            try:\n                t_infer_start = time.perf_counter()\n                rtn_val = self.model_infer_sync(\n                    model_id=model_id, request=request, **kwargs\n                )\n                record_inference(model_id, time.perf_counter() - t_infer_start)\n                logger.debug(\n                    f\"ModelManager - inference from request finished for model_id={model_id}.\"\n                )\n                finish_time = time.time()\n                if not DISABLE_INFERENCE_CACHE and enable_model_monitoring:\n                    try:\n                        logger.debug(\n                            f\"ModelManager - caching inference request started for model_id={model_id}\"\n                        )\n                        cache.zadd(\n                            f\"models\",\n                            value=f\"{GLOBAL_INFERENCE_SERVER_ID}:{request.api_key}:{model_id}\",\n                            score=finish_time,\n                            expire=METRICS_INTERVAL * 2,\n                        )\n                        if (\n                            hasattr(request, \"image\")\n                            and hasattr(request.image, \"type\")\n                            and request.image.type == \"numpy\"\n                        ):\n                            request.image.value = str(request.image.value)\n                        cache.zadd(\n                            f\"inference:{GLOBAL_INFERENCE_SERVER_ID}:{model_id}\",\n                            value=to_cachable_inference_item(request, rtn_val),\n                            score=finish_time,\n                            expire=METRICS_INTERVAL * 2,\n                        )\n                        logger.debug(\n                            f\"ModelManager - caching inference request finished for model_id={model_id}\"\n                        )\n                    except Exception as cache_error:\n                        logger.warning(\n                            f\"Failed to cache inference data for model {model_id}: {cache_error}\"\n                        )\n                return rtn_val\n            except Exception as e:\n                record_error(e)\n                finish_time = time.time()\n                if not DISABLE_INFERENCE_CACHE and enable_model_monitoring:\n                    try:\n                        cache.zadd(\n                            f\"models\",\n                            value=f\"{GLOBAL_INFERENCE_SERVER_ID}:{request.api_key}:{model_id}\",\n                            score=finish_time,\n                            expire=METRICS_INTERVAL * 2,\n                        )\n                        cache.zadd(\n                            f\"error:{GLOBAL_INFERENCE_SERVER_ID}:{model_id}\",\n                            value={\n                                \"request\": jsonable_encoder(\n                                    request.dict(exclude={\"image\", \"subject\", \"prompt\"})\n                                ),\n                                \"error\": str(e),\n                            },\n                            score=finish_time,\n                            expire=METRICS_INTERVAL * 2,\n                        )\n                    except Exception as cache_error:\n                        logger.warning(\n                            f\"Failed to cache error data for model {model_id}: {cache_error}\"\n                        )\n                raise\n\n    async def model_infer(self, model_id: str, request: InferenceRequest, **kwargs):\n        model = self._get_model_reference(model_id=model_id)\n        return model.infer_from_request(request)\n\n    def model_infer_sync(\n        self, model_id: str, request: InferenceRequest, **kwargs\n    ) -> Union[List[InferenceResponse], InferenceResponse]:\n        model = self._get_model_reference(model_id=model_id)\n        return model.infer_from_request(request)\n\n    def make_response(\n        self, model_id: str, predictions: List[List[float]], *args, **kwargs\n    ) -> InferenceResponse:\n        \"\"\"Creates a response object from the model's predictions.\n\n        Args:\n            model_id (str): The identifier of the model.\n            predictions (List[List[float]]): The model's predictions.\n\n        Returns:\n            InferenceResponse: The created response object.\n        \"\"\"\n        model = self._get_model_reference(model_id=model_id)\n        return model.make_response(predictions, *args, **kwargs)\n\n    def postprocess(\n        self,\n        model_id: str,\n        predictions: Tuple[np.ndarray, ...],\n        preprocess_return_metadata: PreprocessReturnMetadata,\n        *args,\n        **kwargs,\n    ) -> List[List[float]]:\n        \"\"\"Processes the model's predictions after inference.\n\n        Args:\n            model_id (str): The identifier of the model.\n            predictions (np.ndarray): The model's predictions.\n\n        Returns:\n            List[List[float]]: The post-processed predictions.\n        \"\"\"\n        model = self._get_model_reference(model_id=model_id)\n        return model.postprocess(\n            predictions, preprocess_return_metadata, *args, **kwargs\n        )\n\n    def predict(self, model_id: str, *args, **kwargs) -> Tuple[np.ndarray, ...]:\n        \"\"\"Runs prediction on the specified model.\n\n        Args:\n            model_id (str): The identifier of the model.\n\n        Returns:\n            np.ndarray: The predictions from the model.\n        \"\"\"\n        model = self._get_model_reference(model_id=model_id)\n        model.metrics[\"num_inferences\"] += 1\n        tic = time.perf_counter()\n        res = model.predict(*args, **kwargs)\n        toc = time.perf_counter()\n        model.metrics[\"avg_inference_time\"] += toc - tic\n        return res\n\n    def preprocess(\n        self, model_id: str, request: InferenceRequest\n    ) -> Tuple[np.ndarray, PreprocessReturnMetadata]:\n        \"\"\"Preprocesses the request before inference.\n\n        Args:\n            model_id (str): The identifier of the model.\n            request (InferenceRequest): The request to preprocess.\n\n        Returns:\n            Tuple[np.ndarray, List[Tuple[int, int]]]: The preprocessed data.\n        \"\"\"\n        model = self._get_model_reference(model_id=model_id)\n        return model.preprocess(**request.dict())\n\n    def get_class_names(self, model_id):\n        \"\"\"Retrieves the class names for a given model.\n\n        Args:\n            model_id (str): The identifier of the model.\n\n        Returns:\n            List[str]: The class names of the model.\n        \"\"\"\n        model = self._get_model_reference(model_id=model_id)\n        return model.class_names\n\n    def get_task_type(self, model_id: str, api_key: str = None) -> str:\n        \"\"\"Retrieves the task type for a given model.\n\n        Args:\n            model_id (str): The identifier of the model.\n\n        Returns:\n            str: The task type of the model.\n        \"\"\"\n        model = self._get_model_reference(model_id=model_id)\n        return model.task_type\n\n    def remove(self, model_id: str, delete_from_disk: bool = True) -> None:\n        \"\"\"Removes a model from the manager.\n\n        Args:\n            model_id (str): The identifier of the model.\n        \"\"\"\n        try:\n            logger.debug(f\"Removing model {model_id} from base model manager\")\n            model_lock = self._get_lock_for_a_model(model_id=model_id)\n            with acquire_with_timeout(lock=model_lock) as acquired:\n                if not acquired:\n                    raise ModelManagerLockAcquisitionError(\n                        f\"Could not acquire lock for model with id={model_id}.\"\n                    )\n                if model_id not in self._models:\n                    return None\n                self._models[model_id].clear_cache(delete_from_disk=delete_from_disk)\n                del self._models[model_id]\n                record_model_unloaded(model_id)\n                self._dispose_model_lock(model_id=model_id)\n                try_releasing_cuda_memory()\n        except InferenceModelNotFound:\n            logger.warning(\n                f\"Attempted to remove model with id {model_id}, but it is not loaded. Skipping...\"\n            )\n\n    def clear(self) -> None:\n        \"\"\"Removes all models from the manager.\"\"\"\n        model_ids = list(self.keys())\n        for model_id in model_ids:\n            self.remove(model_id)\n\n    def _get_model_reference(self, model_id: str) -> Model:\n        try:\n            return self._models[model_id]\n        except KeyError as error:\n            raise InferenceModelNotFound(\n                f\"Model with id {model_id} not loaded.\"\n            ) from error\n\n    def __contains__(self, model_id: str) -> bool:\n        \"\"\"Checks if the model is contained in the manager.\n\n        Args:\n            model_id (str): The identifier of the model.\n\n        Returns:\n            bool: Whether the model is in the manager.\n        \"\"\"\n        return model_id in self._models\n\n    def __getitem__(self, key: str) -> Model:\n        \"\"\"Retrieve a model from the manager by key.\n\n        Args:\n            key (str): The identifier of the model.\n\n        Returns:\n            Model: The model corresponding to the key.\n        \"\"\"\n        return self._get_model_reference(model_id=key)\n\n    def __len__(self) -> int:\n        \"\"\"Retrieve the number of models in the manager.\n\n        Returns:\n            int: The number of models in the manager.\n        \"\"\"\n        return len(self._models)\n\n    def keys(self):\n        \"\"\"Retrieve the keys (model identifiers) from the manager.\n\n        Returns:\n            List[str]: The keys of the models in the manager.\n        \"\"\"\n        return self._models.keys()\n\n    def models(self) -> Dict[str, Model]:\n        \"\"\"Retrieve the models dictionary from the manager.\n\n        Returns:\n            Dict[str, Model]: The keys of the models in the manager.\n        \"\"\"\n        return self._models\n\n    def describe_models(self) -> List[ModelDescription]:\n        return [\n            ModelDescription(\n                model_id=model_id,\n                task_type=model.task_type,\n                batch_size=getattr(model, \"batch_size\", None),\n                input_width=getattr(model, \"img_size_w\", None),\n                input_height=getattr(model, \"img_size_h\", None),\n            )\n            for model_id, model in self._models.items()\n        ]\n\n    def _get_lock_for_a_model(self, model_id: str) -> Lock:\n        with acquire_with_timeout(lock=self._state_lock) as acquired:\n            if not acquired:\n                raise ModelManagerLockAcquisitionError(\n                    \"Could not acquire lock on Model Manager state to retrieve model lock.\"\n                )\n            if model_id not in self._models_state_locks:\n                self._models_state_locks[model_id] = Lock()\n            return self._models_state_locks[model_id]\n\n    def _dispose_model_lock(self, model_id: str) -> None:\n        with acquire_with_timeout(lock=self._state_lock) as acquired:\n            if not acquired:\n                raise ModelManagerLockAcquisitionError(\n                    \"Could not acquire lock on Model Manager state to dispose model lock.\"\n                )\n            if model_id not in self._models_state_locks:\n                return None\n            del self._models_state_locks[model_id]\n\n\n@contextmanager\ndef acquire_with_timeout(\n    lock: Lock, timeout: float = MODEL_LOCK_ACQUIRE_TIMEOUT\n) -> Generator[bool, None, None]:\n    acquired = lock.acquire(timeout=timeout)\n    try:\n        yield acquired\n    finally:\n        if acquired:\n            lock.release()\n\n\ndef try_releasing_cuda_memory() -> None:\n    if not USE_INFERENCE_MODELS:\n        # For now, we only want to have purge CUDA memory when USE_INFERENCE_MODELS is True\n        return None\n    try:\n        import torch\n\n        if torch.cuda.is_available():\n            torch.cuda.empty_cache()\n    except ImportError:\n        pass\n    except Exception as error:\n        logger.warning(f\"Attempted to purge CUDA memory but failed with error: {error}\")\n",
    "patch": null
  },
  {
    "trace_id": "bd427253-a203-4e11-98a8-acbc4f1dcfe3",
    "function_name": "DetectionEventLogBlockV1._get_relative_time",
    "file_path": "inference/core/workflows/core_steps/analytics/detection_event_log/v1.py",
    "speedup_x": 0.18604095855143932,
    "review_quality": "high",
    "pre_optimization_commit": "10079df8d89971ef2493e294d6d7d99038802b5e",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def _get_relative_time(\n        self,\n        video_id: str,\n        current_frame: int,\n        metadata: VideoMetadata,\n        fallback_fps: float,\n    ) -> float:\n        \"\"\"Calculate relative time in seconds since video started.\n\n        Uses frame_timestamp from metadata when available for accurate timing,\n        even when inference doesn't run at the camera's reported FPS (e.g. due\n        to dropped frames or processing lag). Falls back to internal frame\n        counter / FPS when frame_timestamp is not available.\n        \"\"\"\n        if metadata.frame_timestamp is not None:\n            frame_ts = metadata.frame_timestamp.timestamp()\n            if video_id not in self._first_frame_timestamps:\n                self._first_frame_timestamps[video_id] = frame_ts\n            return frame_ts - self._first_frame_timestamps[video_id]\n\n        # Fallback: use internal frame counter and FPS\n        fps = metadata.fps if metadata.fps and metadata.fps != 0 else fallback_fps\n        return (current_frame - 1) / fps\n",
    "optimized_function_code": "from dataclasses import dataclass\nfrom typing import Dict\n\nfrom inference.core.workflows.execution_engine.entities.base import \\\n    VideoMetadata\nfrom inference.core.workflows.prototypes.block import WorkflowBlock\n\n\n@dataclass\nclass DetectionEvent:\n    \"\"\"Stores event data for a tracked detection.\"\"\"\n\n    tracker_id: int\n    class_name: str\n    first_seen_frame: int\n    first_seen_timestamp: float  # Unix wall-clock time (frame_timestamp or time.time())\n    last_seen_frame: int\n    last_seen_timestamp: float  # Unix wall-clock time (frame_timestamp or time.time())\n    first_seen_relative: float = 0.0  # seconds since video start\n    last_seen_relative: float = 0.0  # seconds since video start\n    frame_count: int = 1\n    logged: bool = False\n\n\nclass DetectionEventLogBlockV1(WorkflowBlock):\n\n    def __init__(self):\n        # Dict[video_id, Dict[tracker_id, DetectionEvent]]\n        self._event_logs: Dict[str, Dict[int, DetectionEvent]] = {}\n        # Dict[video_id, last_flush_frame]\n        self._last_flush_frame: Dict[str, int] = {}\n        # Dict[video_id, frame_count] - internal frame counter (increments each run)\n        self._frame_count: Dict[str, int] = {}\n        # Dict[video_id, last_access_frame] - tracks when each video was last accessed (global frame count)\n        self._last_access: Dict[str, int] = {}\n        # Dict[video_id, first_frame_timestamp] - stores the first frame's wall-clock timestamp\n        # Used as the anchor for frame_timestamp-based relative time calculation\n        self._first_frame_timestamps: Dict[str, float] = {}\n        # Global frame counter for tracking video access order\n        self._global_frame: int = 0\n\n    def _get_relative_time(\n        self,\n        video_id: str,\n        current_frame: int,\n        metadata: VideoMetadata,\n        fallback_fps: float,\n    ) -> float:\n        \"\"\"Calculate relative time in seconds since video started.\n\n        Uses frame_timestamp from metadata when available for accurate timing,\n        even when inference doesn't run at the camera's reported FPS (e.g. due\n        to dropped frames or processing lag). Falls back to internal frame\n        counter / FPS when frame_timestamp is not available.\n        \"\"\"\n        if metadata.frame_timestamp is not None:\n            frame_ts = metadata.frame_timestamp.timestamp()\n            first_ts = self._first_frame_timestamps.get(video_id)\n            if first_ts is None:\n                # Store the first-seen timestamp and return zero elapsed time\n                self._first_frame_timestamps[video_id] = frame_ts\n                return 0.0\n            return frame_ts - first_ts\n\n        # Fallback: use internal frame counter and FPS\n        fps = metadata.fps or fallback_fps\n        return (current_frame - 1) / fps",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/analytics/detection_event_log/v1.py\nfrom dataclasses import dataclass\nfrom typing import Dict\n\nfrom inference.core.workflows.execution_engine.entities.base import \\\n    VideoMetadata\nfrom inference.core.workflows.prototypes.block import WorkflowBlock\n\n\n@dataclass\nclass DetectionEvent:\n    \"\"\"Stores event data for a tracked detection.\"\"\"\n\n    tracker_id: int\n    class_name: str\n    first_seen_frame: int\n    first_seen_timestamp: float  # Unix wall-clock time (frame_timestamp or time.time())\n    last_seen_frame: int\n    last_seen_timestamp: float  # Unix wall-clock time (frame_timestamp or time.time())\n    first_seen_relative: float = 0.0  # seconds since video start\n    last_seen_relative: float = 0.0  # seconds since video start\n    frame_count: int = 1\n    logged: bool = False\n\n\nclass DetectionEventLogBlockV1(WorkflowBlock):\n\n    def __init__(self):\n        # Dict[video_id, Dict[tracker_id, DetectionEvent]]\n        self._event_logs: Dict[str, Dict[int, DetectionEvent]] = {}\n        # Dict[video_id, last_flush_frame]\n        self._last_flush_frame: Dict[str, int] = {}\n        # Dict[video_id, frame_count] - internal frame counter (increments each run)\n        self._frame_count: Dict[str, int] = {}\n        # Dict[video_id, last_access_frame] - tracks when each video was last accessed (global frame count)\n        self._last_access: Dict[str, int] = {}\n        # Dict[video_id, first_frame_timestamp] - stores the first frame's wall-clock timestamp\n        # Used as the anchor for frame_timestamp-based relative time calculation\n        self._first_frame_timestamps: Dict[str, float] = {}\n        # Global frame counter for tracking video access order\n        self._global_frame: int = 0\n\n    def _get_relative_time(\n        self,\n        video_id: str,\n        current_frame: int,\n        metadata: VideoMetadata,\n        fallback_fps: float,\n    ) -> float:\n        \"\"\"Calculate relative time in seconds since video started.\n\n        Uses frame_timestamp from metadata when available for accurate timing,\n        even when inference doesn't run at the camera's reported FPS (e.g. due\n        to dropped frames or processing lag). Falls back to internal frame\n        counter / FPS when frame_timestamp is not available.\n        \"\"\"\n        if metadata.frame_timestamp is not None:\n            frame_ts = metadata.frame_timestamp.timestamp()\n            first_ts = self._first_frame_timestamps.get(video_id)\n            if first_ts is None:\n                # Store the first-seen timestamp and return zero elapsed time\n                self._first_frame_timestamps[video_id] = frame_ts\n                return 0.0\n            return frame_ts - first_ts\n\n        # Fallback: use internal frame counter and FPS\n        fps = metadata.fps or fallback_fps\n        return (current_frame - 1) / fps\n```",
    "optimized_function_only": "    def _get_relative_time(\n        self,\n        video_id: str,\n        current_frame: int,\n        metadata: VideoMetadata,\n        fallback_fps: float,\n    ) -> float:\n        \"\"\"Calculate relative time in seconds since video started.\n\n        Uses frame_timestamp from metadata when available for accurate timing,\n        even when inference doesn't run at the camera's reported FPS (e.g. due\n        to dropped frames or processing lag). Falls back to internal frame\n        counter / FPS when frame_timestamp is not available.\n        \"\"\"\n        if metadata.frame_timestamp is not None:\n            frame_ts = metadata.frame_timestamp.timestamp()\n            first_ts = self._first_frame_timestamps.get(video_id)\n            if first_ts is None:\n                # Store the first-seen timestamp and return zero elapsed time\n                self._first_frame_timestamps[video_id] = frame_ts\n                return 0.0\n            return frame_ts - first_ts\n\n        # Fallback: use internal frame counter and FPS\n        fps = metadata.fps or fallback_fps\n        return (current_frame - 1) / fps",
    "original_file_content": "import time\nfrom dataclasses import asdict, dataclass\nfrom typing import Tuple, Any, Dict, List, Literal, Optional, Type, Union\n\nimport numpy as np\nimport supervision as sv\nfrom pydantic import ConfigDict, Field\n\nfrom inference.core import logger\nfrom inference.core.workflows.execution_engine.entities.base import (\n    OutputDefinition,\n    VideoMetadata,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    DICTIONARY_KIND,\n    FLOAT_KIND,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    INTEGER_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    Selector,\n    WorkflowImageSelector,\n    WorkflowParameterSelector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\nimport heapq\n\nOUTPUT_KEY = \"event_log\"\nDETECTIONS_OUTPUT_KEY = \"detections\"\nMAX_VIDEOS = 100  # Maximum number of video streams to track before evicting oldest\n\n\n@dataclass\nclass DetectionEvent:\n    \"\"\"Stores event data for a tracked detection.\"\"\"\n\n    tracker_id: int\n    class_name: str\n    first_seen_frame: int\n    first_seen_timestamp: float  # Unix wall-clock time (frame_timestamp or time.time())\n    last_seen_frame: int\n    last_seen_timestamp: float  # Unix wall-clock time (frame_timestamp or time.time())\n    first_seen_relative: float = 0.0  # seconds since video start\n    last_seen_relative: float = 0.0  # seconds since video start\n    frame_count: int = 1\n    logged: bool = False\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Detection Event Log\",\n            \"version\": \"v1\",\n            \"short_description\": \"Tracks detection events over time, logging when objects first appear and persist.\",\n            \"long_description\": (\n                \"This block maintains a log of detection events from tracked objects. \"\n                \"For each tracked object it records: class name, first and last seen frame numbers, \"\n                \"absolute wall-clock timestamps (Unix epoch floats derived from frame_timestamp metadata, \"\n                \"or time.time() as fallback), and relative timestamps in seconds since the video started. \"\n                \"Objects must be seen for a minimum number of frames (frame_threshold) before being moved \"\n                \"from 'pending' to 'logged' status. \"\n                \"Stale events (not seen for stale_frames frames) are removed during periodic cleanup \"\n                \"(every flush_interval frames). When a logged event goes stale it is emitted in the \"\n                \"complete_events output, which contains the full event data for objects that were tracked \"\n                \"long enough to be logged and have since left the scene. \"\n                \"The reference_timestamp parameter is deprecated and no longer used.\"\n            ),\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"analytics\",\n            \"ui_manifest\": {\n                \"section\": \"analytics\",\n                \"icon\": \"fal fa-list-timeline\",\n                \"blockPriority\": 3,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/detection_event_log@v1\"]\n\n    image: WorkflowImageSelector = Field(\n        description=\"Reference to the image for video metadata (frame number, timestamp).\",\n        examples=[\"$inputs.image\"],\n    )\n\n    detections: Selector(\n        kind=[\n            OBJECT_DETECTION_PREDICTION_KIND,\n            INSTANCE_SEGMENTATION_PREDICTION_KIND,\n        ]\n    ) = Field(\n        description=\"Tracked detections from byte tracker (must have tracker_id).\",\n        examples=[\"$steps.byte_tracker.tracked_detections\"],\n    )\n\n    frame_threshold: Union[int, WorkflowParameterSelector(kind=[INTEGER_KIND])] = Field(\n        default=30,\n        description=\"Number of frames an object must be seen before being logged.\",\n        examples=[5, 10],\n        ge=1,\n    )\n\n    flush_interval: Union[int, WorkflowParameterSelector(kind=[INTEGER_KIND])] = Field(\n        default=30,\n        description=\"How often (in frames) to run the cleanup operation for stale events.\",\n        examples=[30, 60],\n        ge=1,\n    )\n\n    stale_frames: Union[int, WorkflowParameterSelector(kind=[INTEGER_KIND])] = Field(\n        default=300,\n        description=\"Remove events that haven't been seen for this many frames.\",\n        examples=[150, 300],\n        ge=1,\n    )\n\n    reference_timestamp: Optional[Union[float, Selector(kind=[FLOAT_KIND])]] = Field(\n        default=None,\n        description=\"Deprecated, no longer used. Absolute timestamps are now taken directly from frame_timestamp metadata (or time.time() as fallback).\",\n        examples=[1726570875.0],\n    )\n\n    fallback_fps: Union[float, WorkflowParameterSelector(kind=[FLOAT_KIND])] = Field(\n        default=1.0,\n        description=\"Fallback FPS to use when video metadata does not provide FPS information. Used to calculate relative timestamps.\",\n        examples=[1.0, 30.0],\n        gt=0,\n    )\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(\n                name=OUTPUT_KEY,\n                kind=[DICTIONARY_KIND],\n            ),\n            OutputDefinition(\n                name=DETECTIONS_OUTPUT_KEY,\n                kind=[\n                    OBJECT_DETECTION_PREDICTION_KIND,\n                    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n                ],\n            ),\n            OutputDefinition(\n                name=\"total_logged\",\n                kind=[INTEGER_KIND],\n            ),\n            OutputDefinition(\n                name=\"total_pending\",\n                kind=[INTEGER_KIND],\n            ),\n            OutputDefinition(\n                name=\"complete_events\",\n                kind=[DICTIONARY_KIND],\n            ),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass DetectionEventLogBlockV1(WorkflowBlock):\n    \"\"\"\n    Block that tracks detection events over time.\n\n    Maintains a dictionary of tracked objects with:\n    - First seen timestamp and frame\n    - Last seen timestamp and frame\n    - Class name\n    - Frame count (number of frames the object has been seen)\n\n    Only logs objects that have been seen for at least frame_threshold frames.\n    Runs cleanup every flush_interval frames, removing events not seen for stale_frames.\n    \"\"\"\n\n    def __init__(self):\n        # Dict[video_id, Dict[tracker_id, DetectionEvent]]\n        self._event_logs: Dict[str, Dict[int, DetectionEvent]] = {}\n        # Dict[video_id, last_flush_frame]\n        self._last_flush_frame: Dict[str, int] = {}\n        # Dict[video_id, frame_count] - internal frame counter (increments each run)\n        self._frame_count: Dict[str, int] = {}\n        # Dict[video_id, last_access_frame] - tracks when each video was last accessed (global frame count)\n        self._last_access: Dict[str, int] = {}\n        # Dict[video_id, first_frame_timestamp] - stores the first frame's wall-clock timestamp\n        # Used as the anchor for frame_timestamp-based relative time calculation\n        self._first_frame_timestamps: Dict[str, float] = {}\n        # Global frame counter for tracking video access order\n        self._global_frame: int = 0\n        # Min-heap of (last_access_frame, video_id) for efficient oldest video lookup\n        self._access_heap: List[Tuple[int, str]] = []\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def _get_relative_time(\n        self,\n        video_id: str,\n        current_frame: int,\n        metadata: VideoMetadata,\n        fallback_fps: float,\n    ) -> float:\n        \"\"\"Calculate relative time in seconds since video started.\n\n        Uses frame_timestamp from metadata when available for accurate timing,\n        even when inference doesn't run at the camera's reported FPS (e.g. due\n        to dropped frames or processing lag). Falls back to internal frame\n        counter / FPS when frame_timestamp is not available.\n        \"\"\"\n        if metadata.frame_timestamp is not None:\n            frame_ts = metadata.frame_timestamp.timestamp()\n            if video_id not in self._first_frame_timestamps:\n                self._first_frame_timestamps[video_id] = frame_ts\n            return frame_ts - self._first_frame_timestamps[video_id]\n\n        # Fallback: use internal frame counter and FPS\n        fps = metadata.fps if metadata.fps and metadata.fps != 0 else fallback_fps\n        return (current_frame - 1) / fps\n\n    def _evict_oldest_video(self) -> None:\n        \"\"\"Remove the oldest video stream data when MAX_VIDEOS is exceeded.\"\"\"\n        if len(self._event_logs) <= MAX_VIDEOS:\n            return\n\n        # Rebuild heap if out of sync with current state\n        if len(self._access_heap) < len(self._last_access):\n            self._access_heap[:] = [\n                (frame, vid) for vid, frame in self._last_access.items()\n            ]\n            heapq.heapify(self._access_heap)\n\n        # Pop stale entries until we find a valid current entry\n        while self._access_heap:\n            frame, vid = heapq.heappop(self._access_heap)\n            if self._last_access.get(vid) == frame and vid in self._event_logs:\n                oldest_video_id = vid\n                break\n        else:\n            # If heap is empty but we have event_logs, use fallback\n            oldest_video_id = min(self._last_access, key=self._last_access.get)\n\n        # Remove all data for this video\n        self._event_logs.pop(oldest_video_id, None)\n        self._last_flush_frame.pop(oldest_video_id, None)\n        self._frame_count.pop(oldest_video_id, None)\n        self._last_access.pop(oldest_video_id, None)\n        self._first_frame_timestamps.pop(oldest_video_id, None)\n\n    def _remove_stale_events(\n        self,\n        event_log: Dict[int, DetectionEvent],\n        current_frame: int,\n        stale_frames: int,\n        frame_threshold: int,\n    ) -> List[DetectionEvent]:\n        \"\"\"Remove events that haven't been seen for stale_frames.\n\n        Returns list of removed LOGGED events (events that met frame_threshold).\n        These are \"complete\" events - objects that were tracked long enough\n        to be logged and have now left the scene.\n        \"\"\"\n        stale_tracker_ids = []\n        complete_events = []\n\n        for tracker_id, event in event_log.items():\n            frames_since_seen = current_frame - event.last_seen_frame\n            if frames_since_seen > stale_frames:\n                stale_tracker_ids.append(tracker_id)\n                # Only return logged events as \"complete\" - pending events are just discarded\n                if event.frame_count >= frame_threshold:\n                    complete_events.append(event)\n\n        for tracker_id in stale_tracker_ids:\n            del event_log[tracker_id]\n\n        return complete_events\n\n    def run(\n        self,\n        image: WorkflowImageData,\n        detections: sv.Detections,\n        frame_threshold: int,\n        flush_interval: int,\n        stale_frames: int,\n        fallback_fps: float = 1.0,\n        reference_timestamp: Optional[float] = None,\n    ) -> BlockResult:\n        \"\"\"Process detections and update the event log.\n\n        Args:\n            image: Workflow image data containing video metadata.\n            detections: Tracked detections with tracker_id from ByteTracker.\n            frame_threshold: Minimum frames an object must be seen before logging.\n            flush_interval: How often to run stale event cleanup.\n            stale_frames: Remove events not seen for this many frames.\n            fallback_fps: FPS to use when video metadata doesn't provide FPS.\n            reference_timestamp: Unused, kept for backward compatibility.\n\n        Returns:\n            Dictionary containing event_log, detections, total_logged, and total_pending.\n        \"\"\"\n        metadata = image.video_metadata\n        video_id = metadata.video_identifier\n\n        # Track global frame count and video access for eviction\n        self._global_frame += 1\n        self._last_access[video_id] = self._global_frame\n\n        # Increment internal frame counter\n        current_frame = self._frame_count.get(video_id, 0) + 1\n        self._frame_count[video_id] = current_frame\n\n        current_time = self._get_relative_time(\n            video_id, current_frame, metadata, fallback_fps\n        )\n\n        # Use frame_timestamp for absolute time when available (reflects actual capture\n        # time, not inference processing time). Falls back to time.time().\n        current_absolute_time = (\n            metadata.frame_timestamp.timestamp()\n            if metadata.frame_timestamp is not None\n            else time.time()\n        )\n\n        # Initialize event log for this video if needed\n        event_log = self._event_logs.setdefault(video_id, {})\n\n        # Evict oldest video if we've exceeded MAX_VIDEOS (after adding current video)\n        self._evict_oldest_video()\n\n        # Initialize last flush frame if not set\n        if video_id not in self._last_flush_frame:\n            self._last_flush_frame[video_id] = current_frame\n\n        # Check if it's time to run cleanup\n        complete_events_list = []\n        last_flush = self._last_flush_frame.get(video_id, 0)\n        if (current_frame - last_flush) >= flush_interval:\n            complete_events_list = self._remove_stale_events(\n                event_log, current_frame, stale_frames, frame_threshold\n            )\n            self._last_flush_frame[video_id] = current_frame\n\n        # Format complete events\n        complete_events = self._format_complete_events(complete_events_list)\n\n        # Process detections\n        if detections.tracker_id is None or len(detections.tracker_id) == 0:\n            # No tracked detections, return current log\n            event_log_dict, total_logged, total_pending = self._format_event_log(\n                event_log, frame_threshold\n            )\n            return {\n                OUTPUT_KEY: event_log_dict,\n                DETECTIONS_OUTPUT_KEY: detections,\n                \"total_logged\": total_logged,\n                \"total_pending\": total_pending,\n                \"complete_events\": complete_events,\n            }\n\n        # Get class names\n        class_names = detections.data.get(\"class_name\", [])\n        if (\n            len(class_names) == 0\n            and hasattr(detections, \"class_id\")\n            and detections.class_id is not None\n        ):\n            class_names = [f\"class_{cid}\" for cid in detections.class_id]\n\n        # Update event log for each tracked detection\n        for i, tracker_id in enumerate(detections.tracker_id):\n            tracker_id = int(tracker_id)\n            class_name = str(class_names[i]) if len(class_names) > 0 else \"unknown\"\n\n            if tracker_id in event_log:\n                # Update existing event\n                event = event_log[tracker_id]\n                event.last_seen_frame = current_frame\n                event.last_seen_timestamp = current_absolute_time\n                event.last_seen_relative = current_time\n                event.frame_count += 1\n\n                # Mark as logged once threshold is reached\n                if event.frame_count >= frame_threshold and not event.logged:\n                    event.logged = True\n                    logger.debug(\n                        f\"Object {tracker_id} ({event.class_name}) logged after {event.frame_count} frames\"\n                    )\n            else:\n                # Create new event\n                event_log[tracker_id] = DetectionEvent(\n                    tracker_id=tracker_id,\n                    class_name=class_name,\n                    first_seen_frame=current_frame,\n                    first_seen_timestamp=current_absolute_time,\n                    last_seen_frame=current_frame,\n                    last_seen_timestamp=current_absolute_time,\n                    first_seen_relative=current_time,\n                    last_seen_relative=current_time,\n                    frame_count=1,\n                    logged=False,\n                )\n\n        event_log_dict, total_logged, total_pending = self._format_event_log(\n            event_log, frame_threshold\n        )\n        return {\n            OUTPUT_KEY: event_log_dict,\n            DETECTIONS_OUTPUT_KEY: detections,\n            \"total_logged\": total_logged,\n            \"total_pending\": total_pending,\n            \"complete_events\": complete_events,\n        }\n\n    def _format_complete_events(\n        self,\n        complete_events: List[DetectionEvent],\n    ) -> Dict[str, Any]:\n        \"\"\"Format complete events for output.\n\n        Args:\n            complete_events: List of DetectionEvent objects that have completed (gone stale).\n\n        Returns:\n            Dictionary with tracker_id as key and event data as value.\n        \"\"\"\n        formatted = {}\n        for event in complete_events:\n            event_data = event.__dict__.copy()\n            del event_data[\"logged\"]\n            formatted[str(event.tracker_id)] = event_data\n\n        return formatted\n\n    def _format_event_log(\n        self,\n        event_log: Dict[int, DetectionEvent],\n        frame_threshold: int,\n    ) -> tuple:\n        \"\"\"Format the event log for output.\n\n        Returns:\n            Tuple of (event_log_dict, total_logged, total_pending)\n        \"\"\"\n        logged_events = {}\n        pending_events = {}\n\n        for tracker_id, event in event_log.items():\n            event_data = event.__dict__.copy()\n            del event_data[\"logged\"]\n\n            if event.frame_count >= frame_threshold:\n                logged_events[str(tracker_id)] = event_data\n            else:\n                pending_events[str(tracker_id)] = event_data\n\n        event_log_dict = {\n            \"logged\": logged_events,\n            \"pending\": pending_events,\n        }\n\n        return event_log_dict, len(logged_events), len(pending_events)\n",
    "patch": null
  },
  {
    "trace_id": "4ca3d060-c10b-439e-b179-94fbacba1e3f",
    "function_name": "BaseInference.infer",
    "file_path": "inference/core/models/base.py",
    "speedup_x": 1.3246993075301743,
    "review_quality": "medium",
    "pre_optimization_commit": "3d23a0e028b2aba8cea9eaf037e6ebccad8cac97",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def infer(self, image: Any, **kwargs) -> Any:\n        \"\"\"Runs inference on given data.\n        - image:\n            can be a BGR numpy array, filepath, InferenceRequestImage, PIL Image, byte-string, etc.\n        \"\"\"\n        with start_span(\"model.preprocess\"):\n            preproc_image, returned_metadata = self.preprocess(image, **kwargs)\n            logger.debug(\n                f\"Preprocessed input shape: {getattr(preproc_image, 'shape', None)}\"\n            )\n            if hasattr(preproc_image, \"shape\"):\n                set_span_attribute(\"model.input_shape\", str(preproc_image.shape))\n        with start_span(\"model.predict\"):\n            predicted_arrays = self.predict(preproc_image, **kwargs)\n        with start_span(\"model.postprocess\"):\n            postprocessed = self.postprocess(\n                predicted_arrays, returned_metadata, **kwargs\n            )\n\n        return postprocessed\n",
    "optimized_function_code": "# ---------------------------------------------------------------------------\n# Graceful opentelemetry imports \u2014 everything below is noop when not installed\n# ---------------------------------------------------------------------------\nfrom typing import Any, Dict, Optional\n\nfrom opentelemetry import trace\n\ntry:\n\n    _OTEL_AVAILABLE = True\nexcept ImportError:\n    _OTEL_AVAILABLE = False\n\n_tracer = None\n\n\ndef _get_tracer():\n    global _tracer\n    if _tracer is None and _OTEL_AVAILABLE:\n        _tracer = trace.get_tracer(\"inference\")\n    return _tracer\n\n\n# ---------------------------------------------------------------------------\n# Public helpers \u2014 always safe to call\n# ---------------------------------------------------------------------------\n\n\nclass _NoopSpanCM:\n    \"\"\"A tiny no-op context manager that yields None.\n\n    Implemented as a class to avoid the overhead of the generator-based\n    contextmanager wrapper in hot paths.\n    \"\"\"\n\n    __slots__ = ()\n\n    def __enter__(self):\n        return None\n\n    def __exit__(self, exc_type, exc, tb):\n        # Do not suppress exceptions\n        return False\n\n\ndef start_span(name: str, attributes: Optional[Dict[str, Any]] = None):\n    \"\"\"Start a new span as a child of the current context.\n\n    Yields the span (or None when OTel is not available).\n    \"\"\"\n    if not _OTEL_AVAILABLE:\n        return _NoopSpanCM()\n    tracer = _get_tracer()\n    # tracer.start_as_current_span(...) already returns a context manager\n    return tracer.start_as_current_span(name, attributes=attributes)\n\n\n\n\ndef set_span_attribute(key: str, value: Any) -> None:\n    \"\"\"Set an attribute on the current active span.\n\n    Noop when OTel is unavailable or there is no recording span.\n    Callers never need to check for None spans.\n    \"\"\"\n    if not _OTEL_AVAILABLE:\n        return\n    span = trace.get_current_span()\n    if span and span.is_recording():\n        span.set_attribute(key, value)",
    "optimized_raw_markdown": "```python:inference/core/telemetry.py\n# ---------------------------------------------------------------------------\n# Graceful opentelemetry imports \u2014 everything below is noop when not installed\n# ---------------------------------------------------------------------------\nfrom typing import Any, Dict, Optional\n\nfrom opentelemetry import trace\n\ntry:\n\n    _OTEL_AVAILABLE = True\nexcept ImportError:\n    _OTEL_AVAILABLE = False\n\n_tracer = None\n\n\ndef _get_tracer():\n    global _tracer\n    if _tracer is None and _OTEL_AVAILABLE:\n        _tracer = trace.get_tracer(\"inference\")\n    return _tracer\n\n\n# ---------------------------------------------------------------------------\n# Public helpers \u2014 always safe to call\n# ---------------------------------------------------------------------------\n\n\nclass _NoopSpanCM:\n    \"\"\"A tiny no-op context manager that yields None.\n\n    Implemented as a class to avoid the overhead of the generator-based\n    contextmanager wrapper in hot paths.\n    \"\"\"\n\n    __slots__ = ()\n\n    def __enter__(self):\n        return None\n\n    def __exit__(self, exc_type, exc, tb):\n        # Do not suppress exceptions\n        return False\n\n\ndef start_span(name: str, attributes: Optional[Dict[str, Any]] = None):\n    \"\"\"Start a new span as a child of the current context.\n\n    Yields the span (or None when OTel is not available).\n    \"\"\"\n    if not _OTEL_AVAILABLE:\n        return _NoopSpanCM()\n    tracer = _get_tracer()\n    # tracer.start_as_current_span(...) already returns a context manager\n    return tracer.start_as_current_span(name, attributes=attributes)\n\n\n\n\ndef set_span_attribute(key: str, value: Any) -> None:\n    \"\"\"Set an attribute on the current active span.\n\n    Noop when OTel is unavailable or there is no recording span.\n    Callers never need to check for None spans.\n    \"\"\"\n    if not _OTEL_AVAILABLE:\n        return\n    span = trace.get_current_span()\n    if span and span.is_recording():\n        span.set_attribute(key, value)\n```",
    "optimized_function_only": null,
    "original_file_content": "from time import perf_counter\nfrom typing import Any, List, Tuple, Union\n\nimport numpy as np\n\nfrom inference.core import logger\nfrom inference.core.entities.requests.inference import InferenceRequest\nfrom inference.core.entities.responses.inference import InferenceResponse\nfrom inference.core.models.types import PreprocessReturnMetadata\nfrom inference.core.telemetry import set_span_attribute, start_span\nfrom inference.usage_tracking.collector import usage_collector\n\n\nclass BaseInference:\n    \"\"\"General inference class.\n\n    This class provides a basic interface for inference tasks.\n    \"\"\"\n\n    @usage_collector(\"model\")\n    def infer(self, image: Any, **kwargs) -> Any:\n        \"\"\"Runs inference on given data.\n        - image:\n            can be a BGR numpy array, filepath, InferenceRequestImage, PIL Image, byte-string, etc.\n        \"\"\"\n        with start_span(\"model.preprocess\"):\n            preproc_image, returned_metadata = self.preprocess(image, **kwargs)\n            logger.debug(\n                f\"Preprocessed input shape: {getattr(preproc_image, 'shape', None)}\"\n            )\n            if hasattr(preproc_image, \"shape\"):\n                set_span_attribute(\"model.input_shape\", str(preproc_image.shape))\n        with start_span(\"model.predict\"):\n            predicted_arrays = self.predict(preproc_image, **kwargs)\n        with start_span(\"model.postprocess\"):\n            postprocessed = self.postprocess(\n                predicted_arrays, returned_metadata, **kwargs\n            )\n\n        return postprocessed\n\n    def preprocess(\n        self, image: Any, **kwargs\n    ) -> Tuple[np.ndarray, PreprocessReturnMetadata]:\n        raise NotImplementedError\n\n    def predict(self, img_in: np.ndarray, **kwargs) -> Tuple[np.ndarray, ...]:\n        raise NotImplementedError\n\n    def postprocess(\n        self,\n        predictions: Tuple[np.ndarray, ...],\n        preprocess_return_metadata: PreprocessReturnMetadata,\n        **kwargs,\n    ) -> Any:\n        raise NotImplementedError\n\n    def infer_from_request(\n        self, request: InferenceRequest\n    ) -> Union[InferenceResponse, List[InferenceResponse]]:\n        \"\"\"Runs inference on a request\n\n        Args:\n            request (InferenceRequest): The request object.\n\n        Returns:\n            Union[CVInferenceResponse, List[CVInferenceResponse]]: The response object(s).\n\n        Raises:\n            NotImplementedError: This method must be implemented by a subclass.\n        \"\"\"\n        raise NotImplementedError\n\n    def make_response(\n        self, *args, **kwargs\n    ) -> Union[InferenceResponse, List[InferenceResponse]]:\n        \"\"\"Constructs an object detection response.\n\n        Raises:\n            NotImplementedError: This method must be implemented by a subclass.\n        \"\"\"\n        raise NotImplementedError\n\n\nclass Model(BaseInference):\n    \"\"\"Base Inference Model (Inherits from BaseInference to define the needed methods)\n\n    This class provides the foundational methods for inference and logging, and can be extended by specific models.\n\n    Methods:\n        log(m): Print the given message.\n        clear_cache(): Clears any cache if necessary.\n    \"\"\"\n\n    def log(self, m):\n        \"\"\"Prints the given message.\n\n        Args:\n            m (str): The message to print.\n        \"\"\"\n        print(m)\n\n    def clear_cache(self, delete_from_disk: bool = True) -> None:\n        \"\"\"Clears any cache if necessary. This method should be implemented in derived classes as needed.\n\n        Args:\n            delete_from_disk (bool, optional): Whether to delete cached files from disk. Defaults to True.\n        \"\"\"\n        pass\n\n    def infer_from_request(\n        self,\n        request: InferenceRequest,\n    ) -> Union[List[InferenceResponse], InferenceResponse]:\n        \"\"\"\n        Perform inference based on the details provided in the request, and return the associated responses.\n        The function can handle both single and multiple image inference requests. Optionally, it also provides\n        a visualization of the predictions if requested.\n\n        Args:\n            request (InferenceRequest): The request object containing details for inference, such as the image or\n                images to process, any classes to filter by, and whether or not to visualize the predictions.\n\n        Returns:\n            Union[List[InferenceResponse], InferenceResponse]: A list of response objects if the request contains\n            multiple images, or a single response object if the request contains one image. Each response object\n            contains details about the segmented instances, the time taken for inference, and optionally, a visualization.\n\n        Examples:\n            >>> request = InferenceRequest(image=my_image, visualize_predictions=True)\n            >>> response = infer_from_request(request)\n            >>> print(response.time)  # Prints the time taken for inference\n            0.125\n            >>> print(response.visualization)  # Accesses the visualization of the prediction if available\n\n        Notes:\n            - The processing time for each response is included within the response itself.\n            - If `visualize_predictions` is set to True in the request, a visualization of the prediction\n              is also included in the response.\n        \"\"\"\n        t1 = perf_counter()\n        responses = self.infer(**request.dict(), return_image_dims=False)\n        for response in responses:\n            response.time = perf_counter() - t1\n            logger.debug(f\"model infer time: {response.time * 1000.0} ms\")\n            if request.id:\n                response.inference_id = request.id\n\n        if hasattr(request, \"visualize_predictions\") and request.visualize_predictions:\n            for response in responses:\n                response.visualization = self.draw_predictions(request, response)\n\n        if not isinstance(request.image, list) and len(responses) > 0:\n            responses = responses[0]\n\n        return responses\n\n    def make_response(\n        self, *args, **kwargs\n    ) -> Union[InferenceResponse, List[InferenceResponse]]:\n        \"\"\"Makes an inference response from the given arguments.\n\n        Args:\n            *args: Variable length argument list.\n            **kwargs: Arbitrary keyword arguments.\n\n        Returns:\n            InferenceResponse: The inference response.\n        \"\"\"\n        raise NotImplementedError(self.__class__.__name__ + \".make_response\")\n",
    "patch": null
  },
  {
    "trace_id": "784b482e-eb6b-4cf5-8dcb-382e57d05c99",
    "function_name": "_run_workflow",
    "file_path": "inference/core/workflows/execution_engine/v1/executor/core.py",
    "speedup_x": 0.2187610742682488,
    "review_quality": "high",
    "pre_optimization_commit": "607c853289559d1117ee503cf7c703552e1306a7",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def _run_workflow(\n    workflow: CompiledWorkflow,\n    runtime_parameters: Dict[str, Any],\n    max_concurrent_steps: int,\n    kinds_serializers: Optional[Dict[str, Callable[[Any], Any]]],\n    serialize_results: bool = False,\n    profiler: Optional[WorkflowsProfiler] = None,\n    executor: Optional[ThreadPoolExecutor] = None,\n    step_error_handler: Optional[Callable[[Exception], None]] = None,\n) -> List[Dict[str, Any]]:\n    execution_data_manager = ExecutionDataManager.init(\n        execution_graph=workflow.execution_graph,\n        runtime_parameters=runtime_parameters,\n    )\n    execution_coordinator = ParallelStepExecutionCoordinator.init(\n        execution_graph=workflow.execution_graph,\n    )\n    next_steps = execution_coordinator.get_steps_to_execute_next(profiler=profiler)\n    while next_steps is not None:\n        execute_steps(\n            next_steps=next_steps,\n            workflow=workflow,\n            execution_data_manager=execution_data_manager,\n            max_concurrent_steps=max_concurrent_steps,\n            profiler=profiler,\n            executor=executor,\n            step_error_handler=step_error_handler,\n        )\n        next_steps = execution_coordinator.get_steps_to_execute_next(profiler=profiler)\n    with profiler.profile_execution_phase(\n        name=\"outputs_construction\",\n        categories=[\"execution_engine_operation\"],\n    ):\n        return construct_workflow_output(\n            workflow_outputs=workflow.workflow_definition.outputs,\n            execution_graph=workflow.execution_graph,\n            execution_data_manager=execution_data_manager,\n            serialize_results=serialize_results,\n            kinds_serializers=kinds_serializers,\n        )\n",
    "optimized_function_code": "from inference.core.workflows.execution_engine.v1.executor.execution_data_manager.branching_manager import BranchingManager\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.dynamic_batches_manager import DynamicBatchesManager\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.execution_cache import ExecutionCache\nfrom networkx import DiGraph\nfrom typing import Any, Dict\n\nclass ExecutionDataManager:\n\n    @classmethod\n    def init(\n        cls,\n        execution_graph: DiGraph,\n        runtime_parameters: Dict[str, Any],\n    ) -> \"ExecutionDataManager\":\n        execution_cache = ExecutionCache.init(execution_graph=execution_graph)\n        dynamic_batches_manager = DynamicBatchesManager.init(\n            execution_graph=execution_graph,\n            runtime_parameters=runtime_parameters,\n        )\n        branching_manager = BranchingManager.init()\n        return cls(\n            execution_graph=execution_graph,\n            runtime_parameters=runtime_parameters,\n            execution_cache=execution_cache,\n            dynamic_batches_manager=dynamic_batches_manager,\n            branching_manager=branching_manager,\n        )\n\n    def __init__(\n        self,\n        execution_graph: DiGraph,\n        runtime_parameters: Dict[str, Any],\n        execution_cache: ExecutionCache,\n        dynamic_batches_manager: DynamicBatchesManager,\n        branching_manager: BranchingManager,\n    ):\n        self._execution_graph = execution_graph\n        self._runtime_parameters = runtime_parameters\n        self._execution_cache = execution_cache\n        self._dynamic_batches_manager = dynamic_batches_manager\n        self._branching_manager = branching_manager",
    "optimized_raw_markdown": "```python:inference/core/workflows/execution_engine/v1/executor/execution_data_manager/manager.py\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.branching_manager import BranchingManager\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.dynamic_batches_manager import DynamicBatchesManager\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.execution_cache import ExecutionCache\nfrom networkx import DiGraph\nfrom typing import Any, Dict\n\nclass ExecutionDataManager:\n\n    @classmethod\n    def init(\n        cls,\n        execution_graph: DiGraph,\n        runtime_parameters: Dict[str, Any],\n    ) -> \"ExecutionDataManager\":\n        execution_cache = ExecutionCache.init(execution_graph=execution_graph)\n        dynamic_batches_manager = DynamicBatchesManager.init(\n            execution_graph=execution_graph,\n            runtime_parameters=runtime_parameters,\n        )\n        branching_manager = BranchingManager.init()\n        return cls(\n            execution_graph=execution_graph,\n            runtime_parameters=runtime_parameters,\n            execution_cache=execution_cache,\n            dynamic_batches_manager=dynamic_batches_manager,\n            branching_manager=branching_manager,\n        )\n\n    def __init__(\n        self,\n        execution_graph: DiGraph,\n        runtime_parameters: Dict[str, Any],\n        execution_cache: ExecutionCache,\n        dynamic_batches_manager: DynamicBatchesManager,\n        branching_manager: BranchingManager,\n    ):\n        self._execution_graph = execution_graph\n        self._runtime_parameters = runtime_parameters\n        self._execution_cache = execution_cache\n        self._dynamic_batches_manager = dynamic_batches_manager\n        self._branching_manager = branching_manager\n```\n```python:inference/core/workflows/execution_engine/v1/executor/flow_coordinator.py\nimport abc\nimport networkx as nx\nfrom inference.core.workflows.execution_engine.profiling.core import WorkflowsProfiler\nfrom typing import List, Optional\n\n\nclass StepExecutionCoordinator(metaclass=abc.ABCMeta):\n\n    @abc.abstractmethod\n    def get_steps_to_execute_next(\n        self, profiler: Optional[WorkflowsProfiler] = None\n    ) -> Optional[List[str]]:\n        pass\n\n\nclass ParallelStepExecutionCoordinator(StepExecutionCoordinator):\n\n    @classmethod\n    def init(cls, execution_graph: nx.DiGraph) -> \"StepExecutionCoordinator\":\n        return cls(execution_graph=execution_graph)\n\n    def __init__(self, execution_graph: nx.DiGraph):\n        self._execution_graph = execution_graph\n        self.__execution_order: Optional[List[List[str]]] = None\n        self.__execution_pointer = 0\n```\n```python:inference/core/workflows/execution_engine/v1/executor/output_constructor.py\nfrom collections import defaultdict\nfrom inference.core.workflows.execution_engine.constants import WORKFLOW_INPUT_BATCH_LINEAGE_ID\nfrom inference.core.workflows.execution_engine.entities.base import JsonField\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import OutputNode\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import construct_output_selector, node_as\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.manager import ExecutionDataManager\nfrom networkx import DiGraph\nfrom typing import Any, Callable, Dict, List\n\n\ndef construct_workflow_output(\n    workflow_outputs: List[JsonField],\n    execution_graph: DiGraph,\n    execution_data_manager: ExecutionDataManager,\n    serialize_results: bool,\n    kinds_serializers: Dict[str, Callable[[Any], Any]],\n) -> List[Dict[str, Any]]:\n    # Maybe we should make blocks to change coordinates systems:\n    # https://github.com/roboflow/inference/issues/440\n    output_name2indices = {}\n    batch_oriented_outputs = set()\n    \n    for output in workflow_outputs:\n        indices = execution_data_manager.get_selector_indices(selector=output.selector)\n        output_name2indices[output.name] = indices\n        if indices is not None:\n            batch_oriented_outputs.add(output.name)\n    \n    kinds_of_output_nodes = {\n        output.name: node_as(\n            execution_graph=execution_graph,\n            node=construct_output_selector(name=output.name),\n            expected_type=OutputNode,\n        ).kind\n        for output in workflow_outputs\n    }\n    non_batch_outputs = {}\n    for output in workflow_outputs:\n        if output.name in batch_oriented_outputs:\n            continue\n        data_piece = execution_data_manager.get_non_batch_data(selector=output.selector)\n        if serialize_results:\n            output_kind = kinds_of_output_nodes[output.name]\n            data_piece = serialize_data_piece(\n                output_name=output.name,\n                data_piece=data_piece,\n                kind=output_kind,\n                kinds_serializers=kinds_serializers,\n            )\n        non_batch_outputs[output.name] = data_piece\n    if not batch_oriented_outputs:\n        return [non_batch_outputs]\n    outputs_for_generated_lineage = defaultdict(set)\n    outputs_for_input_dictated_lineage = set()\n    for output in workflow_outputs:\n        if output.name not in batch_oriented_outputs:\n            outputs_for_input_dictated_lineage.add(output.name)\n            continue\n        top_level_lineage = node_as(\n            execution_graph=execution_graph,\n            node=construct_output_selector(name=output.name),\n            expected_type=OutputNode,\n        ).data_lineage[0]\n        if top_level_lineage == WORKFLOW_INPUT_BATCH_LINEAGE_ID:\n            outputs_for_input_dictated_lineage.add(output.name)\n        else:\n            outputs_for_generated_lineage[top_level_lineage].add(output.name)\n    dimensionality_for_output_nodes = {\n        output.name: node_as(\n            execution_graph=execution_graph,\n            node=construct_output_selector(name=output.name),\n            expected_type=OutputNode,\n        ).dimensionality\n        for output in workflow_outputs\n    }\n    results = create_outputs_for_input_induced_lineages(\n        output_name2indices=output_name2indices,\n        outputs_for_input_dictated_lineage=outputs_for_input_dictated_lineage,\n        workflow_outputs=workflow_outputs,\n        execution_data_manager=execution_data_manager,\n        serialize_results=serialize_results,\n        kinds_serializers=kinds_serializers,\n        kinds_of_output_nodes=kinds_of_output_nodes,\n        non_batch_outputs=non_batch_outputs,\n        dimensionality_for_output_nodes=dimensionality_for_output_nodes,\n        batch_oriented_outputs=batch_oriented_outputs,\n    )\n    if len(results) == 0 and len(outputs_for_generated_lineage) > 0:\n        results.append({})\n    for generated_lineage, outputs_names in outputs_for_generated_lineage.items():\n        results_for_outputs_of_generated_lineage = (\n            create_outputs_for_generated_lineage_outputs(\n                generated_lineage=generated_lineage,\n                output_name2indices=output_name2indices,\n                outputs_for_generated_lineage=outputs_names,\n                workflow_outputs=workflow_outputs,\n                execution_data_manager=execution_data_manager,\n                serialize_results=serialize_results,\n                kinds_serializers=kinds_serializers,\n                kinds_of_output_nodes=kinds_of_output_nodes,\n                dimensionality_for_output_nodes=dimensionality_for_output_nodes,\n            )\n        )\n        for output in results:\n            output.update(results_for_outputs_of_generated_lineage)\n    return results\n```",
    "optimized_function_only": null,
    "original_file_content": "import os\nimport traceback\nfrom concurrent.futures import ThreadPoolExecutor\nfrom datetime import datetime\nfrom functools import partial\nfrom typing import Any, Callable, Dict, List, Optional, Set\nfrom uuid import uuid4\n\nimport cv2\nimport numpy as np\n\ntry:\n    from inference_sdk.config import (\n        apply_duration_minimum,\n        execution_id,\n        remote_processing_times,\n    )\nexcept ImportError:\n    apply_duration_minimum = None\n    execution_id = None\n    remote_processing_times = None\n\nfrom inference.core import logger\nfrom inference.core.env import INFERENCE_DEBUG_OUTPUT_DIR\nfrom inference.core.telemetry import (\n    attach_context,\n    capture_context,\n    detach_context,\n    start_span,\n)\nfrom inference.core.workflows.errors import StepExecutionError, WorkflowError\nfrom inference.core.workflows.execution_engine.profiling.core import (\n    NullWorkflowsProfiler,\n    WorkflowsProfiler,\n    execution_phase,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import (\n    CompiledWorkflow,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import (\n    get_last_chunk_of_selector,\n)\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.manager import (\n    ExecutionDataManager,\n)\nfrom inference.core.workflows.execution_engine.v1.executor.flow_coordinator import (\n    ParallelStepExecutionCoordinator,\n)\nfrom inference.core.workflows.execution_engine.v1.executor.output_constructor import (\n    construct_workflow_output,\n)\nfrom inference.core.workflows.execution_engine.v1.executor.utils import (\n    run_steps_in_parallel,\n)\nfrom inference.core.workflows.prototypes.block import WorkflowBlock\nfrom inference.usage_tracking.collector import usage_collector\n\n\ndef _store_crash_info(\n    image: np.ndarray,\n    exception: Optional[Exception] = None,\n) -> None:\n    if image is None or not INFERENCE_DEBUG_OUTPUT_DIR:\n        logger.error(\"Failed attempt to store crash info\")\n        return\n    try:\n        timestamp = datetime.now().strftime(\"%Y%m%d_%H%M%S_%f\")\n        file_name = f\"image_{timestamp}_{uuid4().hex[:5]}\"\n        os.makedirs(INFERENCE_DEBUG_OUTPUT_DIR, exist_ok=True)\n        if exception is not None:\n            traceback_str = traceback.format_exc()\n            with open(\n                os.path.join(INFERENCE_DEBUG_OUTPUT_DIR, f\"{file_name}.txt\"), \"w\"\n            ) as f:\n                f.write(str(exception))\n                f.write(\"\\n\")\n                f.write(traceback_str)\n        image_path = os.path.join(INFERENCE_DEBUG_OUTPUT_DIR, f\"{file_name}.jpg\")\n        cv2.imwrite(image_path, image)\n    except Exception as e:\n        logger.error(f\"Failed to store crash info: {e}\")\n\n\n@usage_collector(\"workflows\")\n@execution_phase(\n    name=\"workflow_execution\",\n    categories=[\"execution_engine_operation\"],\n)\ndef run_workflow(\n    workflow: CompiledWorkflow,\n    runtime_parameters: Dict[str, Any],\n    max_concurrent_steps: int,\n    kinds_serializers: Optional[Dict[str, Callable[[Any], Any]]],\n    serialize_results: bool = False,\n    profiler: Optional[WorkflowsProfiler] = None,\n    executor: Optional[ThreadPoolExecutor] = None,\n    step_error_handler: Optional[Callable[[Exception], None]] = None,\n) -> List[Dict[str, Any]]:\n    with start_span(\"workflow.run\"):\n        return _run_workflow(\n            workflow=workflow,\n            runtime_parameters=runtime_parameters,\n            max_concurrent_steps=max_concurrent_steps,\n            kinds_serializers=kinds_serializers,\n            serialize_results=serialize_results,\n            profiler=profiler,\n            executor=executor,\n            step_error_handler=step_error_handler,\n        )\n\n\ndef _run_workflow(\n    workflow: CompiledWorkflow,\n    runtime_parameters: Dict[str, Any],\n    max_concurrent_steps: int,\n    kinds_serializers: Optional[Dict[str, Callable[[Any], Any]]],\n    serialize_results: bool = False,\n    profiler: Optional[WorkflowsProfiler] = None,\n    executor: Optional[ThreadPoolExecutor] = None,\n    step_error_handler: Optional[Callable[[Exception], None]] = None,\n) -> List[Dict[str, Any]]:\n    execution_data_manager = ExecutionDataManager.init(\n        execution_graph=workflow.execution_graph,\n        runtime_parameters=runtime_parameters,\n    )\n    execution_coordinator = ParallelStepExecutionCoordinator.init(\n        execution_graph=workflow.execution_graph,\n    )\n    next_steps = execution_coordinator.get_steps_to_execute_next(profiler=profiler)\n    while next_steps is not None:\n        execute_steps(\n            next_steps=next_steps,\n            workflow=workflow,\n            execution_data_manager=execution_data_manager,\n            max_concurrent_steps=max_concurrent_steps,\n            profiler=profiler,\n            executor=executor,\n            step_error_handler=step_error_handler,\n        )\n        next_steps = execution_coordinator.get_steps_to_execute_next(profiler=profiler)\n    with profiler.profile_execution_phase(\n        name=\"outputs_construction\",\n        categories=[\"execution_engine_operation\"],\n    ):\n        return construct_workflow_output(\n            workflow_outputs=workflow.workflow_definition.outputs,\n            execution_graph=workflow.execution_graph,\n            execution_data_manager=execution_data_manager,\n            serialize_results=serialize_results,\n            kinds_serializers=kinds_serializers,\n        )\n\n\n@execution_phase(\n    name=\"group_of_steps_execution\",\n    categories=[\"execution_engine_operation\"],\n    runtime_metadata=[\"next_steps\", \"max_concurrent_steps\"],\n)\ndef execute_steps(\n    next_steps: List[str],\n    workflow: CompiledWorkflow,\n    execution_data_manager: ExecutionDataManager,\n    max_concurrent_steps: int,\n    profiler: Optional[WorkflowsProfiler] = None,\n    executor: Optional[ThreadPoolExecutor] = None,\n    step_error_handler: Optional[Callable[[str, Exception], None]] = None,\n) -> None:\n    if execution_id is not None:\n        workflow_execution_id = execution_id.get()\n    else:\n        workflow_execution_id = None\n    if remote_processing_times is not None:\n        processing_time_collector = remote_processing_times.get()\n    else:\n        processing_time_collector = None\n    if apply_duration_minimum is not None:\n        duration_minimum_value = apply_duration_minimum.get()\n    else:\n        duration_minimum_value = None\n    # Capture OTel context so it can be re-attached inside worker threads\n    otel_ctx = capture_context()\n    logger.debug(f\"Executing steps: {next_steps}.\")\n    steps_functions = [\n        partial(\n            safe_execute_step,\n            step_selector=step_selector,\n            workflow=workflow,\n            execution_data_manager=execution_data_manager,\n            profiler=profiler,\n            workflow_execution_id=workflow_execution_id,\n            processing_time_collector=processing_time_collector,\n            duration_minimum_value=duration_minimum_value,\n            step_error_handler=step_error_handler,\n            otel_ctx=otel_ctx,\n        )\n        for step_selector in next_steps\n    ]\n    _ = run_steps_in_parallel(\n        steps=steps_functions, max_workers=max_concurrent_steps, executor=executor\n    )\n\n\n@execution_phase(\n    name=\"step_execution\",\n    categories=[\"execution_engine_operation\"],\n    runtime_metadata=[\"step_selector\"],\n)\ndef safe_execute_step(\n    step_selector: str,\n    workflow: CompiledWorkflow,\n    execution_data_manager: ExecutionDataManager,\n    profiler: Optional[WorkflowsProfiler] = None,\n    workflow_execution_id: Optional[str] = None,\n    processing_time_collector=None,\n    duration_minimum_value=None,\n    step_error_handler: Optional[Callable[[str, Exception], None]] = None,\n    otel_ctx=None,\n) -> None:\n    if execution_id is not None:\n        execution_id.set(workflow_execution_id)\n    if remote_processing_times is not None and processing_time_collector is not None:\n        remote_processing_times.set(processing_time_collector)\n    if apply_duration_minimum is not None and duration_minimum_value is not None:\n        apply_duration_minimum.set(duration_minimum_value)\n    # Re-attach OTel context in worker thread so trace propagation works.\n    # Must detach when done \u2014 threads are reused in the pool, and leaked\n    # contexts cause incorrect span parenting on subsequent tasks.\n    _otel_token = attach_context(otel_ctx)\n    if profiler is None:\n        profiler = NullWorkflowsProfiler.init()\n    step_name = get_last_chunk_of_selector(selector=step_selector)\n    try:\n        with start_span(\"workflow.step\", {\"workflow.step\": step_name}):\n            try:\n                logger.debug(\n                    f\"started execution of: {step_selector} - {datetime.now().isoformat()}\"\n                )\n                run_step(\n                    step_selector=step_selector,\n                    workflow=workflow,\n                    execution_data_manager=execution_data_manager,\n                    profiler=profiler,\n                )\n                logger.debug(\n                    f\"finished execution of: {step_selector} - {datetime.now().isoformat()}\"\n                )\n            except WorkflowError as error:\n                raise error\n            except Exception as error:\n                if step_error_handler:\n                    step_error_handler(step_name, error)\n                logger.exception(\n                    f\"Execution of step {step_selector} encountered error.\"\n                )\n                raise StepExecutionError(\n                    block_id=step_name,\n                    block_type=workflow.steps[step_name].manifest.type,\n                    public_message=str(error),\n                    context=\"workflow_execution | step_execution\",\n                    inner_error=str(error),\n                ) from error\n    finally:\n        detach_context(_otel_token)\n\n\ndef run_step(\n    step_selector: str,\n    workflow: CompiledWorkflow,\n    execution_data_manager: ExecutionDataManager,\n    profiler: WorkflowsProfiler,\n) -> None:\n    if execution_data_manager.is_step_simd(step_selector=step_selector):\n        return run_simd_step(\n            step_selector=step_selector,\n            workflow=workflow,\n            execution_data_manager=execution_data_manager,\n            profiler=profiler,\n        )\n    return run_non_simd_step(\n        step_selector=step_selector,\n        workflow=workflow,\n        execution_data_manager=execution_data_manager,\n        profiler=profiler,\n    )\n\n\ndef run_simd_step(\n    step_selector: str,\n    workflow: CompiledWorkflow,\n    execution_data_manager: ExecutionDataManager,\n    profiler: Optional[WorkflowsProfiler] = None,\n) -> None:\n    step_name = get_last_chunk_of_selector(selector=step_selector)\n    step_instance = workflow.steps[step_name].step\n    step_manifest = workflow.steps[step_name].manifest\n    collapse_of_batch_to_scalar_expected = (\n        step_manifest.get_output_dimensionality_offset() < 0\n        and not execution_data_manager.does_step_produce_batches(\n            step_selector=step_selector\n        )\n    )\n    if step_manifest.accepts_batch_input() or collapse_of_batch_to_scalar_expected:\n        return run_simd_step_in_batch_mode(\n            step_selector=step_selector,\n            step_instance=step_instance,\n            execution_data_manager=execution_data_manager,\n            profiler=profiler,\n        )\n    return run_simd_step_in_non_batch_mode(\n        step_selector=step_selector,\n        step_instance=step_instance,\n        execution_data_manager=execution_data_manager,\n        profiler=profiler,\n    )\n\n\ndef run_simd_step_in_batch_mode(\n    step_selector: str,\n    step_instance: WorkflowBlock,\n    execution_data_manager: ExecutionDataManager,\n    profiler: Optional[WorkflowsProfiler] = None,\n) -> None:\n    with profiler.profile_execution_phase(\n        name=\"step_input_assembly\",\n        categories=[\"execution_engine_operation\"],\n        metadata={\"step\": step_selector},\n    ):\n        step_input = execution_data_manager.get_simd_step_input(\n            step_selector=step_selector,\n        )\n    with profiler.profile_execution_phase(\n        name=\"step_code_execution\",\n        categories=[\"workflow_block_operation\"],\n        metadata={\n            \"step\": step_selector,\n            \"data_size\": len(step_input.indices),\n        },\n    ):\n        if not step_input.indices:\n            # no inputs - discarded either by conditional exec or by not accepting empty\n            outputs = []\n        else:\n            try:\n                outputs = step_instance.run(**step_input.parameters)\n            except Exception as exc:\n                if INFERENCE_DEBUG_OUTPUT_DIR:\n                    _store_crash_info(\n                        image=execution_data_manager._runtime_parameters[\"image\"][\n                            0\n                        ].numpy_image,\n                        exception=exc,\n                    )\n                raise exc\n    with profiler.profile_execution_phase(\n        name=\"step_output_registration\",\n        categories=[\"execution_engine_operation\"],\n        metadata={\"step\": step_selector},\n    ):\n        execution_data_manager.register_simd_step_output(\n            step_selector=step_selector,\n            indices=step_input.indices,\n            outputs=outputs,\n        )\n\n\ndef run_simd_step_in_non_batch_mode(\n    step_selector: str,\n    step_instance: WorkflowBlock,\n    execution_data_manager: ExecutionDataManager,\n    profiler: Optional[WorkflowsProfiler] = None,\n) -> None:\n    indices, results = [], []\n    with profiler.profile_execution_phase(\n        name=\"iterative_step_code_execution\",\n        categories=[\"execution_engine_operation\", \"workflow_block_operation\"],\n        metadata={\n            \"step\": step_selector,\n        },\n    ):\n        for input_definition in execution_data_manager.iterate_over_simd_step_input(\n            step_selector=step_selector\n        ):\n            with profiler.profile_execution_phase(\n                name=\"step_code_execution\",\n                categories=[\"workflow_block_operation\"],\n                metadata={\n                    \"step\": step_selector,\n                },\n            ):\n                result = step_instance.run(**input_definition.parameters)\n            results.append(result)\n            indices.append(input_definition.index)\n    with profiler.profile_execution_phase(\n        name=\"step_output_registration\",\n        categories=[\"execution_engine_operation\"],\n        metadata={\"step\": step_selector},\n    ):\n        execution_data_manager.register_simd_step_output(\n            step_selector=step_selector,\n            indices=indices,\n            outputs=results,\n        )\n\n\ndef run_non_simd_step(\n    step_selector: str,\n    workflow: CompiledWorkflow,\n    execution_data_manager: ExecutionDataManager,\n    profiler: Optional[WorkflowsProfiler] = None,\n) -> None:\n    with profiler.profile_execution_phase(\n        name=\"step_input_assembly\",\n        categories=[\"execution_engine_operation\"],\n        metadata={\"step\": step_selector},\n    ):\n        step_input = execution_data_manager.get_non_simd_step_input(\n            step_selector=step_selector\n        )\n    if step_input is None:\n        # discarded by conditional execution or empty value from upstream step\n        return None\n    step_name = get_last_chunk_of_selector(selector=step_selector)\n    step_instance = workflow.steps[step_name].step\n    with profiler.profile_execution_phase(\n        name=\"step_code_execution\",\n        categories=[\"workflow_block_operation\"],\n        metadata={\n            \"step\": step_selector,\n        },\n    ):\n        step_result = step_instance.run(**step_input)\n    with profiler.profile_execution_phase(\n        name=\"step_output_registration\",\n        categories=[\"execution_engine_operation\"],\n        metadata={\"step\": step_selector},\n    ):\n        execution_data_manager.register_non_simd_step_output(\n            step_selector=step_selector,\n            output=step_result,\n        )\n",
    "patch": null
  },
  {
    "trace_id": "f3ade831-2f5e-4826-a60a-a16c4d6c7541",
    "function_name": "wrap_roboflow_api_errors",
    "file_path": "inference/core/roboflow_api.py",
    "speedup_x": 0.27644051667539593,
    "review_quality": "high",
    "pre_optimization_commit": "87db05d80c0789f027cc99ba1491c312b40026f6",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def wrap_roboflow_api_errors(\n    http_errors_handlers: Optional[\n        Dict[int, Callable[[Union[requests.exceptions.HTTPError]], None]]\n    ] = None,\n) -> callable:\n    def decorator(function: callable) -> callable:\n        def wrapper(*args, **kwargs) -> Any:\n            t_start = time.perf_counter()\n            with start_span(\n                \"roboflow_api.call\",\n                {\"roboflow_api.function\": function.__name__},\n            ):\n                try:\n                    try:\n                        result = function(*args, **kwargs)\n                        record_api_call(\n                            function.__name__, time.perf_counter() - t_start\n                        )\n                        return result\n                    except RetryRequestError as error:\n                        raise error.inner_error\n                except Timeout as error:\n                    record_api_call(function.__name__, time.perf_counter() - t_start)\n                    record_error(error)\n                    raise RoboflowAPITimeoutError(\n                        \"Timeout when attempting to connect to Roboflow API.\"\n                    ) from error\n                except (\n                    requests.exceptions.ConnectionError,\n                    ConnectionError,\n                ) as error:\n                    record_api_call(function.__name__, time.perf_counter() - t_start)\n                    record_error(error)\n                    raise RoboflowAPIConnectionError(\n                        \"Could not connect to Roboflow API.\"\n                    ) from error\n                except requests.exceptions.HTTPError as error:\n                    record_api_call(function.__name__, time.perf_counter() - t_start)\n                    record_error(error)\n                    user_handler_override = (\n                        http_errors_handlers if http_errors_handlers is not None else {}\n                    )\n                    status_code = error.response.status_code\n                    default_handler = DEFAULT_ERROR_HANDLERS.get(status_code)\n                    error_handler = user_handler_override.get(\n                        status_code, default_handler\n                    )\n                    if error_handler is not None:\n                        error_handler(error)\n                    raise RoboflowAPIUnsuccessfulRequestError(\n                        f\"Unsuccessful request to Roboflow API with response code: {status_code}\"\n                    ) from error\n                except requests.exceptions.InvalidJSONError as error:\n                    record_api_call(function.__name__, time.perf_counter() - t_start)\n                    record_error(error)\n                    raise MalformedRoboflowAPIResponseError(\n                        \"Could not decode JSON response from Roboflow API.\"\n                    ) from error\n\n        return wrapper\n\n    return decorator\n",
    "optimized_function_code": "import time\nfrom typing import Any, Callable, Dict, Optional, Union\n\nimport requests\nfrom inference.core.exceptions import (MalformedRoboflowAPIResponseError,\n                                       PaymentRequiredError, RetryRequestError,\n                                       RoboflowAPIConnectionError,\n                                       RoboflowAPIForbiddenError,\n                                       RoboflowAPINotAuthorizedError,\n                                       RoboflowAPINotNotFoundError,\n                                       RoboflowAPITimeoutError,\n                                       RoboflowAPIUnsuccessfulRequestError,\n                                       RoboflowAPIUsagePausedError)\nfrom inference.core.telemetry import record_api_call, record_error, start_span\nfrom requests import Timeout\n\nNOT_FOUND_ERROR_MESSAGE = (\n    \"Could not find requested Roboflow resource. Check that the provided dataset and \"\n    \"version are correct, and check that the provided Roboflow API key has the correct permissions.\"\n)\n\n\nDEFAULT_ERROR_HANDLERS = {\n    401: lambda e: raise_from_lambda(\n        e,\n        RoboflowAPINotAuthorizedError,\n        \"Unauthorized access to roboflow API - check API key. Visit \"\n        \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve one.\",\n    ),\n    402: lambda e: raise_from_lambda(\n        e,\n        PaymentRequiredError,\n        \"Not enough credits to perform this request. Verify your workspace billing page.\",\n    ),\n    403: lambda e: raise_from_lambda(\n        e,\n        RoboflowAPIForbiddenError,\n        \"Unauthorized access to roboflow API - check API key regarding correctness and required scopes. Visit \"\n        \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve one.\",\n    ),\n    404: lambda e: raise_from_lambda(\n        e, RoboflowAPINotNotFoundError, NOT_FOUND_ERROR_MESSAGE\n    ),\n    423: lambda e: raise_from_lambda(\n        e,\n        RoboflowAPIUsagePausedError,\n        \"Roboflow API usage is paused. Please contact your workspace administrator to re-enable api keys.\",\n    ),\n}\n\n\n\n\n_cached_default_decorator = None\n\n\ndef wrap_roboflow_api_errors(\n    http_errors_handlers: Optional[\n        Dict[int, Callable[[Union[requests.exceptions.HTTPError]], None]]\n    ] = None,\n) -> callable:\n    global _cached_default_decorator\n    \n    # Cache the default decorator when no custom error handlers are provided\n    if http_errors_handlers is None and _cached_default_decorator is not None:\n        return _cached_default_decorator\n    \n    def decorator(function: callable) -> callable:\n        def wrapper(*args, **kwargs) -> Any:\n            t_start = time.perf_counter()\n            with start_span(\n                \"roboflow_api.call\",\n                {\"roboflow_api.function\": function.__name__},\n            ):\n                try:\n                    try:\n                        result = function(*args, **kwargs)\n                        record_api_call(\n                            function.__name__, time.perf_counter() - t_start\n                        )\n                        return result\n                    except RetryRequestError as error:\n                        raise error.inner_error\n                except Timeout as error:\n                    record_api_call(function.__name__, time.perf_counter() - t_start)\n                    record_error(error)\n                    raise RoboflowAPITimeoutError(\n                        \"Timeout when attempting to connect to Roboflow API.\"\n                    ) from error\n                except (\n                    requests.exceptions.ConnectionError,\n                    ConnectionError,\n                ) as error:\n                    record_api_call(function.__name__, time.perf_counter() - t_start)\n                    record_error(error)\n                    raise RoboflowAPIConnectionError(\n                        \"Could not connect to Roboflow API.\"\n                    ) from error\n                except requests.exceptions.HTTPError as error:\n                    record_api_call(function.__name__, time.perf_counter() - t_start)\n                    record_error(error)\n                    user_handler_override = (\n                        http_errors_handlers if http_errors_handlers is not None else {}\n                    )\n                    status_code = error.response.status_code\n                    default_handler = DEFAULT_ERROR_HANDLERS.get(status_code)\n                    error_handler = user_handler_override.get(\n                        status_code, default_handler\n                    )\n                    if error_handler is not None:\n                        error_handler(error)\n                    raise RoboflowAPIUnsuccessfulRequestError(\n                        f\"Unsuccessful request to Roboflow API with response code: {status_code}\"\n                    ) from error\n                except requests.exceptions.InvalidJSONError as error:\n                    record_api_call(function.__name__, time.perf_counter() - t_start)\n                    record_error(error)\n                    raise MalformedRoboflowAPIResponseError(\n                        \"Could not decode JSON response from Roboflow API.\"\n                    ) from error\n\n        return wrapper\n\n    if http_errors_handlers is None:\n        _cached_default_decorator = decorator\n    \n    return decorator",
    "optimized_raw_markdown": "```python:inference/core/roboflow_api.py\nimport time\nfrom typing import Any, Callable, Dict, Optional, Union\n\nimport requests\nfrom inference.core.exceptions import (MalformedRoboflowAPIResponseError,\n                                       PaymentRequiredError, RetryRequestError,\n                                       RoboflowAPIConnectionError,\n                                       RoboflowAPIForbiddenError,\n                                       RoboflowAPINotAuthorizedError,\n                                       RoboflowAPINotNotFoundError,\n                                       RoboflowAPITimeoutError,\n                                       RoboflowAPIUnsuccessfulRequestError,\n                                       RoboflowAPIUsagePausedError)\nfrom inference.core.telemetry import record_api_call, record_error, start_span\nfrom requests import Timeout\n\nNOT_FOUND_ERROR_MESSAGE = (\n    \"Could not find requested Roboflow resource. Check that the provided dataset and \"\n    \"version are correct, and check that the provided Roboflow API key has the correct permissions.\"\n)\n\n\nDEFAULT_ERROR_HANDLERS = {\n    401: lambda e: raise_from_lambda(\n        e,\n        RoboflowAPINotAuthorizedError,\n        \"Unauthorized access to roboflow API - check API key. Visit \"\n        \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve one.\",\n    ),\n    402: lambda e: raise_from_lambda(\n        e,\n        PaymentRequiredError,\n        \"Not enough credits to perform this request. Verify your workspace billing page.\",\n    ),\n    403: lambda e: raise_from_lambda(\n        e,\n        RoboflowAPIForbiddenError,\n        \"Unauthorized access to roboflow API - check API key regarding correctness and required scopes. Visit \"\n        \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve one.\",\n    ),\n    404: lambda e: raise_from_lambda(\n        e, RoboflowAPINotNotFoundError, NOT_FOUND_ERROR_MESSAGE\n    ),\n    423: lambda e: raise_from_lambda(\n        e,\n        RoboflowAPIUsagePausedError,\n        \"Roboflow API usage is paused. Please contact your workspace administrator to re-enable api keys.\",\n    ),\n}\n\n\n\n\n_cached_default_decorator = None\n\n\ndef wrap_roboflow_api_errors(\n    http_errors_handlers: Optional[\n        Dict[int, Callable[[Union[requests.exceptions.HTTPError]], None]]\n    ] = None,\n) -> callable:\n    global _cached_default_decorator\n    \n    # Cache the default decorator when no custom error handlers are provided\n    if http_errors_handlers is None and _cached_default_decorator is not None:\n        return _cached_default_decorator\n    \n    def decorator(function: callable) -> callable:\n        def wrapper(*args, **kwargs) -> Any:\n            t_start = time.perf_counter()\n            with start_span(\n                \"roboflow_api.call\",\n                {\"roboflow_api.function\": function.__name__},\n            ):\n                try:\n                    try:\n                        result = function(*args, **kwargs)\n                        record_api_call(\n                            function.__name__, time.perf_counter() - t_start\n                        )\n                        return result\n                    except RetryRequestError as error:\n                        raise error.inner_error\n                except Timeout as error:\n                    record_api_call(function.__name__, time.perf_counter() - t_start)\n                    record_error(error)\n                    raise RoboflowAPITimeoutError(\n                        \"Timeout when attempting to connect to Roboflow API.\"\n                    ) from error\n                except (\n                    requests.exceptions.ConnectionError,\n                    ConnectionError,\n                ) as error:\n                    record_api_call(function.__name__, time.perf_counter() - t_start)\n                    record_error(error)\n                    raise RoboflowAPIConnectionError(\n                        \"Could not connect to Roboflow API.\"\n                    ) from error\n                except requests.exceptions.HTTPError as error:\n                    record_api_call(function.__name__, time.perf_counter() - t_start)\n                    record_error(error)\n                    user_handler_override = (\n                        http_errors_handlers if http_errors_handlers is not None else {}\n                    )\n                    status_code = error.response.status_code\n                    default_handler = DEFAULT_ERROR_HANDLERS.get(status_code)\n                    error_handler = user_handler_override.get(\n                        status_code, default_handler\n                    )\n                    if error_handler is not None:\n                        error_handler(error)\n                    raise RoboflowAPIUnsuccessfulRequestError(\n                        f\"Unsuccessful request to Roboflow API with response code: {status_code}\"\n                    ) from error\n                except requests.exceptions.InvalidJSONError as error:\n                    record_api_call(function.__name__, time.perf_counter() - t_start)\n                    record_error(error)\n                    raise MalformedRoboflowAPIResponseError(\n                        \"Could not decode JSON response from Roboflow API.\"\n                    ) from error\n\n        return wrapper\n\n    if http_errors_handlers is None:\n        _cached_default_decorator = decorator\n    \n    return decorator\n```",
    "optimized_function_only": "def wrap_roboflow_api_errors(\n    http_errors_handlers: Optional[\n        Dict[int, Callable[[Union[requests.exceptions.HTTPError]], None]]\n    ] = None,\n) -> callable:\n    global _cached_default_decorator\n    \n    # Cache the default decorator when no custom error handlers are provided\n    if http_errors_handlers is None and _cached_default_decorator is not None:\n        return _cached_default_decorator\n    \n    def decorator(function: callable) -> callable:\n        def wrapper(*args, **kwargs) -> Any:\n            t_start = time.perf_counter()\n            with start_span(\n                \"roboflow_api.call\",\n                {\"roboflow_api.function\": function.__name__},\n            ):\n                try:\n                    try:\n                        result = function(*args, **kwargs)\n                        record_api_call(\n                            function.__name__, time.perf_counter() - t_start\n                        )\n                        return result\n                    except RetryRequestError as error:\n                        raise error.inner_error\n                except Timeout as error:\n                    record_api_call(function.__name__, time.perf_counter() - t_start)\n                    record_error(error)\n                    raise RoboflowAPITimeoutError(\n                        \"Timeout when attempting to connect to Roboflow API.\"\n                    ) from error\n                except (\n                    requests.exceptions.ConnectionError,\n                    ConnectionError,\n                ) as error:\n                    record_api_call(function.__name__, time.perf_counter() - t_start)\n                    record_error(error)\n                    raise RoboflowAPIConnectionError(\n                        \"Could not connect to Roboflow API.\"\n                    ) from error\n                except requests.exceptions.HTTPError as error:\n                    record_api_call(function.__name__, time.perf_counter() - t_start)\n                    record_error(error)\n                    user_handler_override = (\n                        http_errors_handlers if http_errors_handlers is not None else {}\n                    )\n                    status_code = error.response.status_code\n                    default_handler = DEFAULT_ERROR_HANDLERS.get(status_code)\n                    error_handler = user_handler_override.get(\n                        status_code, default_handler\n                    )\n                    if error_handler is not None:\n                        error_handler(error)\n                    raise RoboflowAPIUnsuccessfulRequestError(\n                        f\"Unsuccessful request to Roboflow API with response code: {status_code}\"\n                    ) from error\n                except requests.exceptions.InvalidJSONError as error:\n                    record_api_call(function.__name__, time.perf_counter() - t_start)\n                    record_error(error)\n                    raise MalformedRoboflowAPIResponseError(\n                        \"Could not decode JSON response from Roboflow API.\"\n                    ) from error\n\n        return wrapper\n\n    if http_errors_handlers is None:\n        _cached_default_decorator = decorator\n    \n    return decorator",
    "original_file_content": "import asyncio\nimport base64\nimport binascii\nimport hashlib\nimport json\nimport os\nimport re\nimport time\nimport urllib.parse\nfrom enum import Enum\nfrom hashlib import sha256\nfrom json import JSONDecodeError\nfrom pathlib import Path\nfrom typing import Any, Callable, Dict, List, Optional, Tuple, Type, Union\n\nimport aiohttp\nimport backoff\nimport requests\nfrom cachetools.func import ttl_cache\nfrom requests import Response, Timeout\nfrom requests_toolbelt import MultipartEncoder\n\nfrom inference.core import logger\nfrom inference.core.cache import cache\nfrom inference.core.cache.base import BaseCache\nfrom inference.core.cache.model_artifacts import get_cache_dir, initialise_cache\nfrom inference.core.entities.types import (\n    DatasetID,\n    ModelID,\n    ModelType,\n    TaskType,\n    VersionID,\n    WorkspaceID,\n)\nfrom inference.core.env import (\n    API_BASE_URL,\n    ENFORCE_CREDITS_VERIFICATION,\n    GCP_SERVERLESS,\n    INTERNAL_WEIGHTS_URL_SUFFIX,\n    MD5_VERIFICATION_ENABLED,\n    MODEL_CACHE_DIR,\n    MODELS_CACHE_AUTH_CACHE_MAX_SIZE,\n    MODELS_CACHE_AUTH_CACHE_TTL,\n    MODELS_CACHE_AUTH_ENABLED,\n    RETRY_CONNECTION_ERRORS_TO_ROBOFLOW_API,\n    ROBOFLOW_API_EXTRA_HEADERS,\n    ROBOFLOW_API_REQUEST_TIMEOUT,\n    ROBOFLOW_API_VERIFY_SSL,\n    ROBOFLOW_SERVICE_SECRET,\n    SINGLE_TENANT_WORKFLOW_CACHE,\n    TRANSIENT_ROBOFLOW_API_ERRORS,\n    TRANSIENT_ROBOFLOW_API_ERRORS_RETRIES,\n    TRANSIENT_ROBOFLOW_API_ERRORS_RETRY_INTERVAL,\n    USE_FILE_CACHE_FOR_WORKFLOWS_DEFINITIONS,\n    WORKFLOWS_DEFINITION_CACHE_EXPIRY,\n)\nfrom inference.core.exceptions import (\n    MalformedRoboflowAPIResponseError,\n    MalformedWorkflowResponseError,\n    MissingDefaultModelError,\n    PaymentRequiredError,\n    RetryRequestError,\n    RoboflowAPIConnectionError,\n    RoboflowAPIForbiddenError,\n    RoboflowAPIIAlreadyAnnotatedError,\n    RoboflowAPIIAnnotationRejectionError,\n    RoboflowAPIImageUploadRejectionError,\n    RoboflowAPINotAuthorizedError,\n    RoboflowAPINotNotFoundError,\n    RoboflowAPITimeoutError,\n    RoboflowAPIUnsuccessfulRequestError,\n    RoboflowAPIUsagePausedError,\n    WorkspaceLoadError,\n)\nfrom inference.core.telemetry import record_api_call, record_error, start_span\nfrom inference.core.utils.file_system import sanitize_path_segment\nfrom inference.core.utils.requests import (\n    api_key_safe_raise_for_status,\n    api_key_safe_raise_for_status_aiohttp,\n)\nfrom inference.core.utils.url_utils import wrap_url\nfrom inference.core.version import __version__\n\nENFORCE_CREDITS_VERIFICATION_HEADER = \"x-enforce-credits-verification\"\nENFORCE_INTERNAL_ARTIFACTS_URLS_HEADER = \"x-enforce-internal-artefacts-urls\"\n\nMODEL_TYPE_DEFAULTS = {\n    \"object-detection\": \"yolov5v2s\",\n    \"instance-segmentation\": \"yolact\",\n    \"classification\": \"vit\",\n    \"keypoint-detection\": \"yolov8n\",\n}\nPROJECT_TASK_TYPE_KEY = \"project_task_type\"\nMODEL_TYPE_KEY = \"model_type\"\n\nNOT_FOUND_ERROR_MESSAGE = (\n    \"Could not find requested Roboflow resource. Check that the provided dataset and \"\n    \"version are correct, and check that the provided Roboflow API key has the correct permissions.\"\n)\n\nROBOFLOW_INFERENCE_VERSION_HEADER = \"X-Roboflow-Inference-Version\"\nALLOW_CHUNKED_RESPONSE_HEADER = \"X-Allow-Chunked\"\n\n\ndef raise_from_lambda(\n    inner_error: Exception, exception_type: Type[Exception], message: str\n) -> None:\n    raise exception_type(message) from inner_error\n\n\nDEFAULT_ERROR_HANDLERS = {\n    401: lambda e: raise_from_lambda(\n        e,\n        RoboflowAPINotAuthorizedError,\n        \"Unauthorized access to roboflow API - check API key. Visit \"\n        \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve one.\",\n    ),\n    402: lambda e: raise_from_lambda(\n        e,\n        PaymentRequiredError,\n        \"Not enough credits to perform this request. Verify your workspace billing page.\",\n    ),\n    403: lambda e: raise_from_lambda(\n        e,\n        RoboflowAPIForbiddenError,\n        \"Unauthorized access to roboflow API - check API key regarding correctness and required scopes. Visit \"\n        \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve one.\",\n    ),\n    404: lambda e: raise_from_lambda(\n        e, RoboflowAPINotNotFoundError, NOT_FOUND_ERROR_MESSAGE\n    ),\n    423: lambda e: raise_from_lambda(\n        e,\n        RoboflowAPIUsagePausedError,\n        \"Roboflow API usage is paused. Please contact your workspace administrator to re-enable api keys.\",\n    ),\n}\n\n\ndef wrap_roboflow_api_errors(\n    http_errors_handlers: Optional[\n        Dict[int, Callable[[Union[requests.exceptions.HTTPError]], None]]\n    ] = None,\n) -> callable:\n    def decorator(function: callable) -> callable:\n        def wrapper(*args, **kwargs) -> Any:\n            t_start = time.perf_counter()\n            with start_span(\n                \"roboflow_api.call\",\n                {\"roboflow_api.function\": function.__name__},\n            ):\n                try:\n                    try:\n                        result = function(*args, **kwargs)\n                        record_api_call(\n                            function.__name__, time.perf_counter() - t_start\n                        )\n                        return result\n                    except RetryRequestError as error:\n                        raise error.inner_error\n                except Timeout as error:\n                    record_api_call(function.__name__, time.perf_counter() - t_start)\n                    record_error(error)\n                    raise RoboflowAPITimeoutError(\n                        \"Timeout when attempting to connect to Roboflow API.\"\n                    ) from error\n                except (\n                    requests.exceptions.ConnectionError,\n                    ConnectionError,\n                ) as error:\n                    record_api_call(function.__name__, time.perf_counter() - t_start)\n                    record_error(error)\n                    raise RoboflowAPIConnectionError(\n                        \"Could not connect to Roboflow API.\"\n                    ) from error\n                except requests.exceptions.HTTPError as error:\n                    record_api_call(function.__name__, time.perf_counter() - t_start)\n                    record_error(error)\n                    user_handler_override = (\n                        http_errors_handlers if http_errors_handlers is not None else {}\n                    )\n                    status_code = error.response.status_code\n                    default_handler = DEFAULT_ERROR_HANDLERS.get(status_code)\n                    error_handler = user_handler_override.get(\n                        status_code, default_handler\n                    )\n                    if error_handler is not None:\n                        error_handler(error)\n                    raise RoboflowAPIUnsuccessfulRequestError(\n                        f\"Unsuccessful request to Roboflow API with response code: {status_code}\"\n                    ) from error\n                except requests.exceptions.InvalidJSONError as error:\n                    record_api_call(function.__name__, time.perf_counter() - t_start)\n                    record_error(error)\n                    raise MalformedRoboflowAPIResponseError(\n                        \"Could not decode JSON response from Roboflow API.\"\n                    ) from error\n\n        return wrapper\n\n    return decorator\n\n\ndef wrap_roboflow_api_errors_async(\n    http_errors_handlers: Optional[\n        Dict[int, Callable[[Union[aiohttp.ClientError]], None]]\n    ] = None,\n) -> callable:\n    def decorator(function: callable) -> callable:\n        async def wrapper(*args, **kwargs) -> Any:\n            t_start = time.perf_counter()\n            with start_span(\n                \"roboflow_api.call\",\n                {\"roboflow_api.function\": function.__name__},\n            ):\n                try:\n                    try:\n                        result = await function(*args, **kwargs)\n                        record_api_call(\n                            function.__name__, time.perf_counter() - t_start\n                        )\n                        return result\n                    except RetryRequestError as error:\n                        raise error.inner_error\n                except asyncio.TimeoutError as error:\n                    record_api_call(function.__name__, time.perf_counter() - t_start)\n                    record_error(error)\n                    raise RoboflowAPITimeoutError(\n                        \"Timeout when attempting to connect to Roboflow API.\"\n                    ) from error\n                except (aiohttp.ClientConnectionError, ConnectionError) as error:\n                    record_api_call(function.__name__, time.perf_counter() - t_start)\n                    record_error(error)\n                    raise RoboflowAPIConnectionError(\n                        \"Could not connect to Roboflow API.\"\n                    ) from error\n                except (aiohttp.ContentTypeError, JSONDecodeError) as error:\n                    record_api_call(function.__name__, time.perf_counter() - t_start)\n                    record_error(error)\n                    raise MalformedRoboflowAPIResponseError(\n                        \"Could not decode JSON response from Roboflow API.\"\n                    ) from error\n                except aiohttp.ClientResponseError as error:\n                    record_api_call(function.__name__, time.perf_counter() - t_start)\n                    record_error(error)\n                    user_handler_override = (\n                        http_errors_handlers if http_errors_handlers is not None else {}\n                    )\n                    status_code = error.status\n                    default_handler = DEFAULT_ERROR_HANDLERS.get(status_code)\n                    error_handler = user_handler_override.get(\n                        status_code, default_handler\n                    )\n                    if error_handler is not None:\n                        error_handler(error)\n                    raise RoboflowAPIUnsuccessfulRequestError(\n                        f\"Unsuccessful request to Roboflow API with response code: {status_code}\"\n                    ) from error\n                # remaining aiohttp.ClientError seems to qualify to simply pass-through raise, as\n                # this seems to be adequate to trigger HTTP 500 upstream or let final client to handle\n                # such cases like invalid pattern of API_BASE_URL (as we are setting it correctly)\n\n        return wrapper\n\n    return decorator\n\n\n@ttl_cache(ttl=MODELS_CACHE_AUTH_CACHE_TTL, maxsize=MODELS_CACHE_AUTH_CACHE_MAX_SIZE)\n@wrap_roboflow_api_errors()\ndef get_roboflow_workspace(api_key: str) -> WorkspaceID:\n    if not api_key:\n        raise WorkspaceLoadError(\"Empty workspace encountered, check your API key.\")\n\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/\",\n        params=[(\"api_key\", api_key), (\"nocache\", \"true\")],\n    )\n    api_key_info = _get_from_url(url=api_url)\n    workspace_id = api_key_info.get(\"workspace\")\n    if workspace_id is None:\n        raise WorkspaceLoadError(\"Empty workspace encountered, check your API key.\")\n    return workspace_id\n\n\n@wrap_roboflow_api_errors_async()\n@backoff.on_exception(\n    backoff.constant,\n    exception=RetryRequestError,\n    max_tries=TRANSIENT_ROBOFLOW_API_ERRORS_RETRIES,\n    interval=TRANSIENT_ROBOFLOW_API_ERRORS_RETRY_INTERVAL,\n)\nasync def get_roboflow_workspace_async(api_key: str) -> WorkspaceID:\n    try:\n        headers = build_roboflow_api_headers()\n        async with aiohttp.ClientSession() as session:\n            async with session.get(\n                f\"{API_BASE_URL}/\",\n                params={\"api_key\": api_key, \"nocache\": \"true\"},\n                headers=headers,\n                timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n            ) as response:\n                try:\n                    api_key_safe_raise_for_status_aiohttp(response=response)\n                except Exception as error:\n                    if response.status in TRANSIENT_ROBOFLOW_API_ERRORS:\n                        raise RetryRequestError(\n                            message=str(error), inner_error=error\n                        ) from error\n                    raise error\n                response_payload = await response.json()\n                workspace_id = response_payload.get(\"workspace\")\n                if workspace_id is None:\n                    raise WorkspaceLoadError(\n                        \"Empty workspace encountered, check your API key.\"\n                    )\n                return workspace_id\n    except (aiohttp.ClientConnectionError, ConnectionError) as error:\n        if RETRY_CONNECTION_ERRORS_TO_ROBOFLOW_API:\n            raise RetryRequestError(\n                message=\"Connectivity error\", inner_error=error\n            ) from error\n        raise error\n\n\n@wrap_roboflow_api_errors()\ndef add_custom_metadata(\n    api_key: str,\n    workspace_id: WorkspaceID,\n    inference_ids: List[str],\n    field_name: str,\n    field_value: str,\n):\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/inference-stats/metadata\",\n        params=[(\"api_key\", api_key), (\"nocache\", \"true\")],\n    )\n    response = requests.post(\n        url=api_url,\n        json={\n            \"data\": [\n                {\n                    \"inference_ids\": inference_ids,\n                    \"field_name\": field_name,\n                    \"field_value\": field_value,\n                }\n            ]\n        },\n        headers=build_roboflow_api_headers(),\n        timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n        verify=ROBOFLOW_API_VERIFY_SSL,\n    )\n    api_key_safe_raise_for_status(response=response)\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_dataset_type(\n    api_key: str, workspace_id: WorkspaceID, dataset_id: DatasetID\n) -> TaskType:\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/{dataset_id}\",\n        params=[(\"api_key\", api_key), (\"nocache\", \"true\")],\n    )\n    dataset_info = _get_from_url(url=api_url)\n    project_task_type = dataset_info.get(\"project\", {})\n    if \"type\" not in project_task_type:\n        logger.warning(\n            f\"Project task type not defined for workspace={workspace_id} and dataset={dataset_id}, defaulting \"\n            f\"to object-detection.\"\n        )\n    return project_task_type.get(\"type\", \"object-detection\")\n\n\n@wrap_roboflow_api_errors(\n    http_errors_handlers={\n        500: lambda e: raise_from_lambda(\n            e, RoboflowAPINotNotFoundError, NOT_FOUND_ERROR_MESSAGE\n        )\n        # this is temporary solution, empirically checked that backend API responds HTTP 500 on incorrect version.\n        # TO BE FIXED at backend, otherwise this error handling may overshadow existing backend problems.\n    }\n)\ndef get_roboflow_model_type(\n    api_key: str,\n    workspace_id: WorkspaceID,\n    dataset_id: DatasetID,\n    version_id: VersionID,\n    project_task_type: ModelType,\n) -> ModelType:\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/{dataset_id}/{version_id}\",\n        params=[(\"api_key\", api_key), (\"nocache\", \"true\")],\n    )\n    version_info = _get_from_url(url=api_url)\n    model_type = version_info[\"version\"]\n    if \"modelType\" not in model_type:\n        if project_task_type not in MODEL_TYPE_DEFAULTS:\n            raise MissingDefaultModelError(\n                f\"Could not set default model for {project_task_type}\"\n            )\n        logger.warning(\n            f\"Model type not defined - using default for {project_task_type} task.\"\n        )\n    return model_type.get(\"modelType\", MODEL_TYPE_DEFAULTS[project_task_type])\n\n\nclass ModelEndpointType(Enum):\n    ORT = \"ort\"\n    CORE_MODEL = \"core_model\"\n    OWLV2 = \"owlv2\"\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_model_data(\n    api_key: str,\n    model_id: str,\n    endpoint_type: ModelEndpointType,\n    device_id: str,\n    countinference: Optional[bool] = None,\n    service_secret: Optional[str] = None,\n) -> dict:\n    api_data_cache_key = f\"roboflow_api_data:{endpoint_type.value}:{model_id}\"\n    api_data = None\n    if not MODELS_CACHE_AUTH_ENABLED:\n        api_data = cache.get(api_data_cache_key)\n    if api_data is not None:\n        logger.debug(f\"Loaded model data from cache with key: {api_data_cache_key}.\")\n        return api_data\n    else:\n        params = [\n            (\"nocache\", \"true\"),\n            (\"device\", device_id),\n            (\"dynamic\", \"true\"),\n        ]\n        if api_key is not None:\n            params.append((\"api_key\", api_key))\n\n        if (\n            INTERNAL_WEIGHTS_URL_SUFFIX == \"serverless\"\n            and countinference is False\n            and service_secret == ROBOFLOW_SERVICE_SECRET\n        ):\n            params.append((\"countinference\", str(countinference).lower()))\n            params.append((\"service_secret\", service_secret))\n\n        api_base_url = urllib.parse.urljoin(API_BASE_URL, INTERNAL_WEIGHTS_URL_SUFFIX)\n        api_url = _add_params_to_url(\n            url=f\"{api_base_url}/{endpoint_type.value}/{model_id}\",\n            params=params,\n        )\n        api_data = _get_from_url(url=api_url)\n        cache.set(\n            api_data_cache_key,\n            api_data,\n            expire=10,\n        )\n        logger.debug(\n            f\"Loaded model data from Roboflow API and saved to cache with key: {api_data_cache_key}.\"\n        )\n        return api_data\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_instant_model_data(\n    api_key: str,\n    model_id: ModelID,\n    cache_prefix: str = \"roboflow_api_data\",\n    countinference: Optional[bool] = None,\n    service_secret: Optional[str] = None,\n) -> dict:\n    api_data_cache_key = f\"{cache_prefix}:{model_id}\"\n    api_data = None\n    if not MODELS_CACHE_AUTH_ENABLED:\n        api_data = cache.get(api_data_cache_key)\n    if api_data is not None:\n        logger.debug(f\"Loaded model data from cache with key: {api_data_cache_key}.\")\n        return api_data\n    else:\n        params = [\n            (\"model\", model_id),\n        ]\n        if api_key is not None:\n            params.append((\"api_key\", api_key))\n\n        if (\n            INTERNAL_WEIGHTS_URL_SUFFIX == \"serverless\"\n            and countinference is False\n            and service_secret == ROBOFLOW_SERVICE_SECRET\n        ):\n            params.append((\"countinference\", str(countinference).lower()))\n            params.append((\"service_secret\", service_secret))\n\n        api_base_url = urllib.parse.urljoin(API_BASE_URL, INTERNAL_WEIGHTS_URL_SUFFIX)\n        api_url = _add_params_to_url(\n            url=f\"{api_base_url}/getWeights\",\n            params=params,\n        )\n        api_data = _get_from_url(url=api_url)\n        cache.set(\n            api_data_cache_key,\n            api_data,\n            expire=10,\n        )\n        logger.debug(\n            f\"Loaded model data from Roboflow API and saved to cache with key: {api_data_cache_key}.\"\n        )\n        return api_data\n\n\n@wrap_roboflow_api_errors()\ndef get_model_metadata_from_inference_models_registry(\n    api_key: str,\n    model_id: ModelID,\n    cache_prefix: str = \"roboflow_api_data:inference_models_registry\",\n    countinference: Optional[bool] = None,\n    service_secret: Optional[str] = None,\n) -> dict:\n    # Watch out - this function should only be used to substitute get_roboflow_instant_model_data()\n    # and only in terms of getting model type and task type\n    # this is only stub to make sure auth works as it should for models which are not\n    # associated to project via version (for which old auth and metadata retrieval method work).\n    api_data_cache_key = f\"{cache_prefix}:{model_id}\"\n    api_data = None\n    if not MODELS_CACHE_AUTH_ENABLED:\n        api_data = cache.get(api_data_cache_key)\n    if api_data is not None:\n        logger.debug(f\"Loaded model data from cache with key: {api_data_cache_key}.\")\n        return api_data\n    query = [(\"modelId\", model_id)]\n    headers = {\"Authorization\": f\"Bearer {api_key}\"}\n    if GCP_SERVERLESS:\n        headers[ENFORCE_INTERNAL_ARTIFACTS_URLS_HEADER] = \"true\"\n    if ENFORCE_CREDITS_VERIFICATION:\n        skip = (\n            countinference is False\n            and service_secret is not None\n            and service_secret == ROBOFLOW_SERVICE_SECRET\n        )\n        if not skip:\n            headers[ENFORCE_CREDITS_VERIFICATION_HEADER] = \"true\"\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/models/v1/external/weights\",\n        params=query,\n    )\n    raw_api_data = _get_from_url(url=api_url, headers=headers)\n    api_data = {\n        \"modelType\": raw_api_data[\"modelMetadata\"][\"modelArchitecture\"],\n        \"taskType\": raw_api_data[\"modelMetadata\"][\"taskType\"],\n    }\n    cache.set(\n        api_data_cache_key,\n        api_data,\n        expire=10,\n    )\n    logger.debug(\n        f\"Loaded model data from Roboflow API (inference-models registry) \"\n        f\"and saved to cache with key: {api_data_cache_key}.\"\n    )\n    return api_data\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_base_lora(\n    api_key: str, repo: str, revision: str, device_id: str\n) -> dict:\n    full_path = f\"{repo.strip('/')}/{revision.strip('/')}\"\n    api_data_cache_key = f\"roboflow_api_data:lora-bases:{full_path}\"\n    api_data = None\n    if not MODELS_CACHE_AUTH_ENABLED:\n        api_data = cache.get(api_data_cache_key)\n    if api_data is not None:\n        logger.debug(f\"Loaded model data from cache with key: {api_data_cache_key}.\")\n        return api_data\n    else:\n        params = [\n            (\"nocache\", \"true\"),\n            (\"device\", device_id),\n            (\"repoAndRevision\", full_path),\n        ]\n        if api_key is not None:\n            params.append((\"api_key\", api_key))\n        api_url = _add_params_to_url(\n            url=f\"{API_BASE_URL}/lora_bases\",\n            params=params,\n        )\n        api_data = _get_from_url(url=api_url)\n        cache.set(\n            api_data_cache_key,\n            api_data,\n            expire=10,\n        )\n        logger.debug(\n            f\"Loaded lora base model data from Roboflow API and saved to cache with key: {api_data_cache_key}.\"\n        )\n        return api_data\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_active_learning_configuration(\n    api_key: str,\n    workspace_id: WorkspaceID,\n    dataset_id: DatasetID,\n) -> dict:\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/{dataset_id}/active_learning\",\n        params=[(\"api_key\", api_key)],\n    )\n    return _get_from_url(url=api_url)\n\n\n@wrap_roboflow_api_errors()\ndef register_image_at_roboflow(\n    api_key: str,\n    dataset_id: DatasetID,\n    local_image_id: str,\n    image_bytes: bytes,\n    batch_name: str,\n    tags: Optional[List[str]] = None,\n    inference_id: Optional[str] = None,\n    metadata: Optional[Dict[str, Any]] = None,\n) -> dict:\n    url = f\"{API_BASE_URL}/dataset/{dataset_id}/upload\"\n    params = [\n        (\"api_key\", api_key),\n        (\"batch\", batch_name),\n    ]\n    if inference_id is not None:\n        params.append((\"inference_id\", inference_id))\n    tags = tags if tags is not None else []\n    for tag in tags:\n        params.append((\"tag\", tag))\n    wrapped_url = wrap_url(_add_params_to_url(url=url, params=params))\n    fields = {\n        \"name\": f\"{local_image_id}.jpg\",\n        \"file\": (\"imageToUpload\", image_bytes, \"image/jpeg\"),\n    }\n    if metadata is not None:\n        fields[\"metadata\"] = json.dumps(metadata)\n    m = MultipartEncoder(fields=fields)\n    headers = build_roboflow_api_headers(\n        explicit_headers={\"Content-Type\": m.content_type},\n    )\n    response = requests.post(\n        url=wrapped_url,\n        data=m,\n        headers=headers,\n        timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n        verify=ROBOFLOW_API_VERIFY_SSL,\n    )\n    api_key_safe_raise_for_status(response=response)\n    parsed_response = response.json()\n    if not parsed_response.get(\"duplicate\") and not parsed_response.get(\"success\"):\n        raise RoboflowAPIImageUploadRejectionError(\n            f\"Server rejected image: {parsed_response}\"\n        )\n    return parsed_response\n\n\n@wrap_roboflow_api_errors(\n    http_errors_handlers={\n        409: lambda e: raise_from_lambda(\n            e,\n            RoboflowAPIIAlreadyAnnotatedError,\n            \"Given datapoint already has annotation.\",\n        )\n    }\n)\ndef annotate_image_at_roboflow(\n    api_key: str,\n    dataset_id: DatasetID,\n    local_image_id: str,\n    roboflow_image_id: str,\n    annotation_content: str,\n    annotation_file_type: str,\n    is_prediction: bool = True,\n) -> dict:\n    url = f\"{API_BASE_URL}/dataset/{dataset_id}/annotate/{roboflow_image_id}\"\n    params = [\n        (\"api_key\", api_key),\n        (\"name\", f\"{local_image_id}.{annotation_file_type}\"),\n        (\"prediction\", str(is_prediction).lower()),\n    ]\n    wrapped_url = wrap_url(_add_params_to_url(url=url, params=params))\n    headers = build_roboflow_api_headers(\n        explicit_headers={\"Content-Type\": \"text/plain\"},\n    )\n    response = requests.post(\n        wrapped_url,\n        data=annotation_content,\n        headers=headers,\n        timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n        verify=ROBOFLOW_API_VERIFY_SSL,\n    )\n    api_key_safe_raise_for_status(response=response)\n    parsed_response = response.json()\n    if \"error\" in parsed_response or not parsed_response.get(\"success\"):\n        raise RoboflowAPIIAnnotationRejectionError(\n            f\"Failed to save annotation for {roboflow_image_id}. API response: {parsed_response}\"\n        )\n    return parsed_response\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_labeling_batches(\n    api_key: str, workspace_id: WorkspaceID, dataset_id: str\n) -> dict:\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/{dataset_id}/batches\",\n        params=[(\"api_key\", api_key)],\n    )\n    return _get_from_url(url=api_url)\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_labeling_jobs(\n    api_key: str, workspace_id: WorkspaceID, dataset_id: str\n) -> dict:\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/{dataset_id}/jobs\",\n        params=[(\"api_key\", api_key)],\n    )\n    return _get_from_url(url=api_url)\n\n\ndef get_workflow_cache_file(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    workflow_version_id: Optional[str] = None,\n) -> str:\n    sanitized_workspace_id = sanitize_path_segment(workspace_id)\n    sanitized_workflow_id = sanitize_path_segment(workflow_id)\n    if SINGLE_TENANT_WORKFLOW_CACHE:\n        version_suffix = (\n            f\"_v{sanitize_path_segment(workflow_version_id)}\"\n            if workflow_version_id\n            else \"\"\n        )\n        filename = f\"{sanitized_workflow_id}{version_suffix}.json\"\n    else:\n        cache_seed = f\"{workspace_id}:{api_key or ''}\"\n        cache_fingerprint = hashlib.sha256(\n            cache_seed.encode(\"utf-8\"), usedforsecurity=False\n        ).hexdigest()\n        filename = f\"{sanitized_workflow_id}_{cache_fingerprint}.json\"\n    prefix = os.path.abspath(os.path.join(MODEL_CACHE_DIR, \"workflow\"))\n    result = os.path.abspath(\n        os.path.join(\n            prefix,\n            sanitized_workspace_id,\n            filename,\n        )\n    )\n    if not result.startswith(prefix):\n        raise ValueError(\n            \"Detected attempt to save workflow definition in insecure location\"\n        )\n    return result\n\n\ndef cache_workflow_response(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    response: dict,\n    workflow_version_id: Optional[str] = None,\n):\n    workflow_cache_file = get_workflow_cache_file(\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        api_key=api_key,\n        workflow_version_id=workflow_version_id,\n    )\n    workflow_cache_dir = os.path.dirname(workflow_cache_file)\n    if not os.path.exists(workflow_cache_dir):\n        os.makedirs(workflow_cache_dir, exist_ok=True)\n    with open(workflow_cache_file, \"w\") as f:\n        json.dump(response, f)\n\n\ndef delete_cached_workflow_response_if_exists(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    workflow_version_id: Optional[str] = None,\n) -> None:\n    workflow_cache_file = get_workflow_cache_file(\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        api_key=api_key,\n        workflow_version_id=workflow_version_id,\n    )\n    if os.path.exists(workflow_cache_file):\n        os.remove(workflow_cache_file)\n\n\ndef load_cached_workflow_response(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    workflow_version_id: Optional[str] = None,\n) -> Optional[dict]:\n    workflow_cache_file = get_workflow_cache_file(\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        api_key=api_key,\n        workflow_version_id=workflow_version_id,\n    )\n    if not os.path.exists(workflow_cache_file):\n        return None\n    try:\n        with open(workflow_cache_file, \"r\") as f:\n            return json.load(f)\n    except Exception:\n        delete_cached_workflow_response_if_exists(\n            workspace_id=workspace_id,\n            workflow_id=workflow_id,\n            api_key=api_key,\n            workflow_version_id=workflow_version_id,\n        )\n\n\n@wrap_roboflow_api_errors()\ndef get_workflow_specification(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    use_cache: bool = True,\n    ephemeral_cache: Optional[BaseCache] = None,\n    workflow_version_id: Optional[str] = None,\n) -> dict:\n    ephemeral_cache = ephemeral_cache or cache\n    if use_cache:\n        cached_entry = _retrieve_workflow_specification_from_ephemeral_cache(\n            api_key=api_key,\n            workspace_id=workspace_id,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n            ephemeral_cache=ephemeral_cache,\n        )\n        if cached_entry:\n            return cached_entry\n\n    if workspace_id == \"local\":\n        if not re.match(r\"^[\\w\\-]+$\", workflow_id):\n            raise ValueError(\"Invalid workflow id\")\n\n        workflow_hash = sha256(workflow_id.encode()).hexdigest()\n        local_file_path = (\n            Path(MODEL_CACHE_DIR) / \"workflow\" / \"local\" / f\"{workflow_hash}.json\"\n        )\n        if not local_file_path.exists():\n            raise FileNotFoundError(f\"Local workflow file not found: {local_file_path}\")\n\n        with local_file_path.open(\"r\", encoding=\"utf-8\") as f:\n            local_config = json.load(f)\n\n        # Mimic the same shape as the cloud response:\n        response = {\"workflow\": local_config}\n    else:\n        params = []\n        if api_key is not None:\n            params.append((\"api_key\", api_key))\n        if workflow_version_id is not None:\n            params.append((\"workflow_version\", workflow_version_id))\n        api_url = _add_params_to_url(\n            url=f\"{API_BASE_URL}/{workspace_id}/workflows/{workflow_id}\",\n            params=params,\n        )\n        try:\n            response = _get_from_url(url=api_url)\n            if USE_FILE_CACHE_FOR_WORKFLOWS_DEFINITIONS:\n                cache_workflow_response(\n                    workspace_id=workspace_id,\n                    workflow_id=workflow_id,\n                    api_key=api_key,\n                    response=response,\n                    workflow_version_id=workflow_version_id,\n                )\n        except (\n            requests.exceptions.ConnectionError,\n            ConnectionError,\n            requests.exceptions.Timeout,\n        ) as error:\n            if not USE_FILE_CACHE_FOR_WORKFLOWS_DEFINITIONS:\n                raise error\n            response = load_cached_workflow_response(\n                workspace_id=workspace_id,\n                workflow_id=workflow_id,\n                api_key=api_key,\n                workflow_version_id=workflow_version_id,\n            )\n            if response is None:\n                raise error\n\n    if \"workflow\" not in response or \"config\" not in response[\"workflow\"]:\n        raise MalformedWorkflowResponseError(\n            \"Could not find workflow specification in API response\"\n        )\n    try:\n        workflow_config = json.loads(response[\"workflow\"][\"config\"])\n        specification = workflow_config[\"specification\"]\n        if isinstance(specification, dict):\n            specification[\"id\"] = response[\"workflow\"].get(\"id\")\n        if use_cache:\n            _cache_workflow_specification_in_ephemeral_cache(\n                api_key=api_key,\n                workspace_id=workspace_id,\n                workflow_id=workflow_id,\n                workflow_version_id=workflow_version_id,\n                specification=specification,\n                ephemeral_cache=ephemeral_cache,\n            )\n        return specification\n    except KeyError as error:\n        raise MalformedWorkflowResponseError(\n            \"Workflow specification not found in Roboflow API response\"\n        ) from error\n    except (ValueError, TypeError) as error:\n        raise MalformedWorkflowResponseError(\n            \"Could not decode workflow specification in Roboflow API response\"\n        ) from error\n\n\ndef _retrieve_workflow_specification_from_ephemeral_cache(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    ephemeral_cache: BaseCache,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[dict]:\n    cache_key = _prepare_workflow_response_cache_key(\n        api_key=api_key,\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        workflow_version_id=workflow_version_id,\n    )\n    return ephemeral_cache.get(key=cache_key)\n\n\ndef _cache_workflow_specification_in_ephemeral_cache(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    specification: dict,\n    ephemeral_cache: BaseCache,\n    workflow_version_id: Optional[str] = None,\n) -> None:\n    cache_key = _prepare_workflow_response_cache_key(\n        api_key=api_key,\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        workflow_version_id=workflow_version_id,\n    )\n    ephemeral_cache.set(\n        key=cache_key,\n        value=specification,\n        expire=WORKFLOWS_DEFINITION_CACHE_EXPIRY,\n    )\n\n\ndef _prepare_workflow_response_cache_key(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> str:\n    workflow_version_suffix = (\n        f\":workflow_version={workflow_version_id}\" if workflow_version_id else \"\"\n    )\n    if SINGLE_TENANT_WORKFLOW_CACHE:\n        return (\n            f\"workflow_definition:{workspace_id}:{workflow_id}{workflow_version_suffix}\"\n        )\n    cache_seed = f\"{workspace_id}:{api_key or ''}\"\n    cache_fingerprint = hashlib.sha256(\n        cache_seed.encode(\"utf-8\"), usedforsecurity=False\n    ).hexdigest()\n    return f\"workflow_definition:{workspace_id}:{workflow_id}{workflow_version_suffix}:{cache_fingerprint}\"\n\n\n@wrap_roboflow_api_errors()\ndef get_from_url(\n    url: str,\n    json_response: bool = True,\n) -> Union[Response, dict]:\n    return _get_from_url(\n        url=url,\n        json_response=json_response,\n    )\n\n\n@backoff.on_exception(\n    backoff.constant,\n    exception=RetryRequestError,\n    max_tries=TRANSIENT_ROBOFLOW_API_ERRORS_RETRIES,\n    interval=TRANSIENT_ROBOFLOW_API_ERRORS_RETRY_INTERVAL,\n)\ndef _get_from_url(\n    url: str,\n    json_response: bool = True,\n    headers: Optional[dict] = None,\n) -> Union[Response, dict]:\n    full_url = wrap_url(url)\n    with start_span(\n        \"roboflow_api.http_get\",\n        {\"http.url\": _url_for_safe_logging(full_url)},\n    ):\n        try:\n            response = requests.get(\n                full_url,\n                headers=build_roboflow_api_headers(explicit_headers=headers),\n                timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n                verify=ROBOFLOW_API_VERIFY_SSL,\n            )\n\n        except (ConnectionError, Timeout, requests.exceptions.ConnectionError) as error:\n            if RETRY_CONNECTION_ERRORS_TO_ROBOFLOW_API:\n                raise RetryRequestError(\n                    message=\"Connectivity error\", inner_error=error\n                ) from error\n            raise error\n        try:\n            api_key_safe_raise_for_status(response=response)\n        except Exception as error:\n            if response.status_code in TRANSIENT_ROBOFLOW_API_ERRORS:\n                raise RetryRequestError(\n                    message=str(error), inner_error=error\n                ) from error\n            raise error\n\n        if MD5_VERIFICATION_ENABLED:\n            x_goog_hash = response.headers.get(\"x-goog-hash\")\n            if x_goog_hash is None:\n                logger.warning(\n                    f\"MD5 verification enabled but response missing x-goog-hash header. \"\n                    f\"Request url: {_url_for_safe_logging(full_url)}\"\n                )\n            else:\n                md5_part = None\n                for part in x_goog_hash.split(\",\"):\n                    if part.strip().startswith(\"md5=\"):\n                        md5_part = part.strip()[4:]\n                        break\n                if md5_part is not None:\n                    try:\n                        md5_from_header = base64.b64decode(md5_part)\n                    except binascii.Error as decode_error:\n                        raise RoboflowAPIUnsuccessfulRequestError(\n                            \"Invalid MD5 value in x-goog-hash header: not valid base64\"\n                        ) from decode_error\n                    if md5_from_header != hashlib.md5(response.content).digest():\n                        raise RoboflowAPIUnsuccessfulRequestError(\n                            \"MD5 hash does not match MD5 received from x-goog-hash header\"\n                        )\n                else:\n                    logger.warning(\n                        f\"MD5 verification enabled but x-goog-hash header has no md5= part. \"\n                        f\"Request url: {_url_for_safe_logging(full_url)}\"\n                    )\n\n        if json_response:\n            return response.json()\n        return response\n\n\ndef _test_range_request(url: str, timeout: int = 10) -> bool:\n    \"\"\"Test if server actually honors range requests by making a real range GET request.\n\n    Note: We can't rely on Accept-Ranges header alone because some servers/CDNs\n    advertise range support but return 200 (full file) instead of 206 (partial).\n    \"\"\"\n    try:\n        headers = {\"Range\": \"bytes=0-0\"}\n        response = requests.get(url, headers=headers, stream=True, timeout=timeout)\n        response.close()\n        if response.status_code == 206:\n            return True\n\n        return False\n    except Exception as e:\n        logger.warning(\n            f\"Failed to test range request support: {e}. Falling back to single-threaded download.\"\n        )\n        return False\n\n\ndef stream_url_to_cache(\n    url: str,\n    filename: str,\n    model_id: str,\n) -> None:\n    from inference_models.utils.download import download_files_to_directory\n\n    with start_span(\n        \"roboflow_api.download_artifact\",\n        {\"http.url\": _url_for_safe_logging(url), \"model.id\": model_id},\n    ):\n        initialise_cache(model_id=model_id)\n        cache_dir = get_cache_dir(model_id=model_id)\n        md5_hash = None\n\n        max_threads = 8 if _test_range_request(url) else 1\n\n        try:\n            download_files_to_directory(\n                target_dir=cache_dir,\n                files_specs=[(filename, url, md5_hash)],\n                verbose=True,\n                download_files_without_hash=True,\n                verify_hash_while_download=False,\n                max_threads_per_download=max_threads,\n            )\n        except Exception as e:\n            raise RoboflowAPIUnsuccessfulRequestError(\n                f\"Failed to download {filename}: {str(e)}\"\n            ) from e\n\n\ndef _url_for_safe_logging(url: str) -> str:\n    \"\"\"Return a URL safe to log by stripping the query string (and params/fragment).\n\n    Expects the full URL as used for the request (e.g. already wrapped).\n    Use this when logging request URLs so that sensitive query parameters\n    (e.g. api_key, tokens) are never written to logs.\n    \"\"\"\n    parsed = urllib.parse.urlparse(url)\n    return urllib.parse.urlunparse(\n        (parsed.scheme, parsed.netloc, parsed.path, \"\", \"\", \"\")\n    )\n\n\ndef _add_params_to_url(url: str, params: List[Tuple[str, str]]) -> str:\n    if len(params) == 0:\n        return url\n    params_chunks = [\n        f\"{name}={urllib.parse.quote_plus(value)}\" for name, value in params\n    ]\n    parameters_string = \"&\".join(params_chunks)\n    return f\"{url}?{parameters_string}\"\n\n\n@wrap_roboflow_api_errors()\ndef send_inference_results_to_model_monitoring(\n    api_key: str,\n    workspace_id: WorkspaceID,\n    inference_data: dict,\n):\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/inference-stats\",\n        params=[(\"api_key\", api_key)],\n    )\n    response = requests.post(\n        url=api_url,\n        json=inference_data,\n        headers=build_roboflow_api_headers(),\n        timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n        verify=ROBOFLOW_API_VERIFY_SSL,\n    )\n    api_key_safe_raise_for_status(response=response)\n\n\ndef get_extra_weights_provider_headers(\n    countinference: Optional[bool] = None,\n    service_secret: Optional[str] = None,\n) -> Optional[Dict[str, str]]:\n    headers = {}\n    if GCP_SERVERLESS:\n        headers[ENFORCE_INTERNAL_ARTIFACTS_URLS_HEADER] = \"true\"\n    if ENFORCE_CREDITS_VERIFICATION:\n        skip = (\n            countinference is False\n            and service_secret is not None\n            and service_secret == ROBOFLOW_SERVICE_SECRET\n        )\n        if not skip:\n            headers[ENFORCE_CREDITS_VERIFICATION_HEADER] = \"true\"\n    return build_roboflow_api_headers(explicit_headers=headers)\n\n\ndef build_roboflow_api_headers(\n    explicit_headers: Optional[Dict[str, Union[str, List[str]]]] = None,\n) -> Dict[str, Union[str, List[str]]]:\n    if explicit_headers is None:\n        explicit_headers = {}\n    explicit_headers = {\n        **explicit_headers,\n        ROBOFLOW_INFERENCE_VERSION_HEADER: __version__,\n        ALLOW_CHUNKED_RESPONSE_HEADER: \"true\",\n    }\n    if not ROBOFLOW_API_EXTRA_HEADERS:\n        return explicit_headers\n    try:\n        extra_headers: dict = json.loads(ROBOFLOW_API_EXTRA_HEADERS)\n        if explicit_headers:\n            extra_headers.update(explicit_headers)\n        return extra_headers\n    except ValueError:\n        logger.warning(\"Could not decode ROBOFLOW_API_EXTRA_HEADERS\")\n        return explicit_headers\n\n\ndef post_to_roboflow_api(\n    endpoint: str,\n    api_key: Optional[str],\n    payload: Optional[dict] = None,\n    params: Optional[List[Tuple[str, str]]] = None,\n    http_errors_handlers: Optional[\n        Dict[int, Callable[[Union[requests.exceptions.HTTPError]], None]]\n    ] = None,\n) -> dict:\n    \"\"\"Generic function to make a POST request to the Roboflow API.\n\n    Args:\n        endpoint: API endpoint path\n        api_key: Roboflow API key\n        payload: JSON payload\n        params: Additional URL parameters\n        http_errors_handlers: Optional custom HTTP error handlers by status code\n    \"\"\"\n\n    @wrap_roboflow_api_errors(http_errors_handlers=http_errors_handlers)\n    def _make_request():\n        url_params = []\n        if api_key:\n            url_params.append((\"api_key\", api_key))\n        if params:\n            url_params.extend(params)\n\n        full_url = _add_params_to_url(\n            url=f\"{API_BASE_URL}/{endpoint.strip('/')}\", params=url_params\n        )\n        wrapped_url = wrap_url(full_url)\n\n        headers = build_roboflow_api_headers()\n\n        response = requests.post(\n            url=wrapped_url,\n            json=payload,\n            headers=headers,\n            timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n            verify=ROBOFLOW_API_VERIFY_SSL,\n        )\n        api_key_safe_raise_for_status(response=response)\n        return response.json()\n\n    return _make_request()\n",
    "patch": null
  },
  {
    "trace_id": "5c1ee963-5124-49e8-9563-15a95c0239d3",
    "function_name": "with_route_exceptions",
    "file_path": "inference/core/interfaces/http/error_handlers.py",
    "speedup_x": 5.885736312335115,
    "review_quality": "high",
    "pre_optimization_commit": "71b3048232e5175eccf91d6b484a5dd9199e27aa",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def with_route_exceptions(route):\n    \"\"\"\n    A decorator that wraps a FastAPI route to handle specific exceptions. If an exception\n    is caught, it returns a JSON response with the error message.\n\n    Args:\n        route (Callable): The FastAPI route to be wrapped.\n\n    Returns:\n        Callable: The wrapped route.\n    \"\"\"\n\n    @wraps(route)\n    def wrapped_route(*args, **kwargs):\n        try:\n            return route(*args, **kwargs)\n        except ContentTypeInvalid as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Invalid Content-Type header provided with request.\"\n                },\n            )\n        except ContentTypeMissing as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\"message\": \"Content-Type header not provided with request.\"},\n            )\n        except InputImageLoadError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": f\"Could not load input image. Cause: {error.get_public_error_details()}\"\n                },\n            )\n        except ModelInputError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": f\"Error with model input. Cause: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except InvalidModelIDError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\"message\": \"Invalid Model ID sent in request.\"},\n            )\n        except InvalidMaskDecodeArgument as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Invalid mask decode argument sent. tradeoff_factor must be in [0.0, 1.0], \"\n                    \"mask_decode_mode: must be one of ['accurate', 'fast', 'tradeoff']\"\n                },\n            )\n        except MissingApiKeyError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Required Roboflow API key is missing. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except (\n            WorkflowSyntaxError,\n            InvalidReferenceTargetError,\n            ExecutionGraphStructureError,\n            StepInputDimensionalityError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=error.blocks_errors,\n            )\n            resp = JSONResponse(status_code=400, content=content.model_dump())\n        except (\n            WorkflowDefinitionError,\n            ReferenceTypeError,\n            RuntimeInputError,\n            InvalidInputTypeError,\n            OperationTypeNotRecognisedError,\n            DynamicBlockError,\n            WorkflowExecutionEngineVersionError,\n            NotSupportedExecutionEngineError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"context\": error.context,\n                    \"inner_error_type\": error.inner_error_type,\n                    \"inner_error_message\": str(error.inner_error),\n                },\n            )\n        except (\n            ProcessesManagerInvalidPayload,\n            MalformedPayloadError,\n            MessageToBigError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except (\n            RoboflowAPINotAuthorizedError,\n            ProcessesManagerAuthorisationError,\n            UnauthorizedModelAccessError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=401,\n                content={\n                    \"message\": \"Unauthorized access to roboflow API - check API key and make sure the key is valid for \"\n                    \"workspace you use. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except RoboflowAPIForbiddenError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=403,\n                content={\n                    \"message\": \"Unauthorized access to roboflow API - check API key and make sure the key is valid and \"\n                    \"have required scopes. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except (RoboflowAPINotNotFoundError, ModelNotFoundError) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=404,\n                content={\n                    \"message\": \"Requested Roboflow resource not found. Make sure that workspace, project or model \"\n                    \"you referred in request exists.\"\n                },\n            )\n        except ProcessesManagerNotFoundError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=404,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except ModelPackageNegotiationError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Could not negotiate model package - {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except (\n            InvalidEnvironmentVariableError,\n            MissingServiceSecretError,\n            ServiceConfigurationError,\n            EnvironmentConfigurationError,\n            InvalidEnvVariable,\n            JetsonTypeResolutionError,\n            MissingDependencyError,\n            InvalidParameterError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500, content={\"message\": \"Service misconfiguration.\"}\n            )\n        except (\n            PreProcessingError,\n            PostProcessingError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": \"Model configuration related to pre- or post-processing is invalid.\"\n                },\n            )\n        except ModelArtefactError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500, content={\"message\": \"Model package is broken.\"}\n            )\n        except ModelLoadingError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Model loading failed: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except (UntrustedFileError, FileHashSumMissmatch) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Issue with model package file: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except ModelRetrievalError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Could not retrieve model {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except OnnxProviderNotAvailable as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=501,\n                content={\n                    \"message\": \"Could not find requested ONNX Runtime Provider. Check that you are using \"\n                    \"the correct docker image on a supported device.\"\n                },\n            )\n        except (\n            MalformedRoboflowAPIResponseError,\n            RoboflowAPIUnsuccessfulRequestError,\n            WorkspaceLoadError,\n            MalformedWorkflowResponseError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=502,\n                content={\"message\": \"Internal error. Request to Roboflow API failed.\"},\n            )\n        except InferenceModelNotFound as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\"message\": \"Model is temporarily not ready - retry request.\"},\n                headers={\"Retry-After\": \"1\"},\n            )\n        except RoboflowAPIConnectionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\n                    \"message\": \"Internal error. Could not connect to Roboflow API.\"\n                },\n            )\n        except ModelManagerLockAcquisitionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\n                    \"message\": \"Could not acquire model manager lock due to other request performing \"\n                    \"blocking operation. Try again....\"\n                },\n                headers={\"Retry-After\": \"1\"},\n            )\n        except RoboflowAPITimeoutError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=504,\n                content={\n                    \"message\": \"Timeout when attempting to connect to Roboflow API.\"\n                },\n            )\n        except ClientCausedStepExecutionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=error.block_id,\n                    ),\n                ],\n            )\n            resp = JSONResponse(\n                status_code=error.status_code,\n                content=content.model_dump(),\n            )\n        except StepExecutionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=error.block_id,\n                        block_type=error.block_type,\n                    ),\n                ],\n            )\n            resp = JSONResponse(\n                status_code=500,\n                content=content.model_dump(),\n            )\n        except WorkflowError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"context\": error.context,\n                    \"inner_error_type\": error.inner_error_type,\n                    \"inner_error_message\": str(error.inner_error),\n                },\n            )\n        except (\n            ProcessesManagerClientError,\n            CommunicationProtocolError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except WebRTCConfigurationError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": str(error),\n                    \"error_type\": \"WebRTCConfigurationError\",\n                },\n            )\n        except CreditsExceededError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=402,\n                content={\n                    \"message\": \"Not enough credits to perform this request.\",\n                    \"error_type\": \"CreditsExceededError\",\n                },\n            )\n        except WorkspaceStreamQuotaError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=429,\n                content={\n                    \"message\": str(error),\n                    \"error_type\": \"WorkspaceStreamQuotaError\",\n                },\n            )\n        except Exception as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(status_code=500, content={\"message\": \"Internal error.\"})\n        return resp\n\n    return wrapped_route\n",
    "optimized_function_code": "from functools import wraps\n\nfrom inference.core import logger\nfrom inference.core.entities.responses.workflows import WorkflowErrorResponse\nfrom inference.core.exceptions import (ContentTypeInvalid, ContentTypeMissing,\n                                       CreditsExceededError,\n                                       InferenceModelNotFound,\n                                       InputImageLoadError,\n                                       InvalidEnvironmentVariableError,\n                                       InvalidMaskDecodeArgument,\n                                       InvalidModelIDError,\n                                       MalformedRoboflowAPIResponseError,\n                                       MalformedWorkflowResponseError,\n                                       MissingApiKeyError,\n                                       MissingServiceSecretError,\n                                       ModelArtefactError,\n                                       ModelManagerLockAcquisitionError,\n                                       OnnxProviderNotAvailable,\n                                       PostProcessingError, PreProcessingError,\n                                       RoboflowAPIConnectionError,\n                                       RoboflowAPIForbiddenError,\n                                       RoboflowAPINotAuthorizedError,\n                                       RoboflowAPINotNotFoundError,\n                                       RoboflowAPITimeoutError,\n                                       RoboflowAPIUnsuccessfulRequestError,\n                                       ServiceConfigurationError,\n                                       WebRTCConfigurationError,\n                                       WorkspaceLoadError,\n                                       WorkspaceStreamQuotaError)\nfrom inference.core.interfaces.stream_manager.api.errors import (\n    ProcessesManagerAuthorisationError, ProcessesManagerClientError,\n    ProcessesManagerInvalidPayload, ProcessesManagerNotFoundError)\nfrom inference.core.interfaces.stream_manager.manager_app.errors import (\n    CommunicationProtocolError, MalformedPayloadError, MessageToBigError)\nfrom inference.core.workflows.core_steps.common.query_language.errors import (\n    InvalidInputTypeError, OperationTypeNotRecognisedError)\nfrom inference.core.workflows.errors import (\n    ClientCausedStepExecutionError, DynamicBlockError,\n    ExecutionGraphStructureError, InvalidReferenceTargetError,\n    NotSupportedExecutionEngineError, ReferenceTypeError, RuntimeInputError,\n    StepExecutionError, StepInputDimensionalityError, WorkflowBlockError,\n    WorkflowDefinitionError, WorkflowError,\n    WorkflowExecutionEngineVersionError, WorkflowSyntaxError)\nfrom inference_models.errors import (EnvironmentConfigurationError,\n                                     FileHashSumMissmatch, InvalidEnvVariable,\n                                     InvalidParameterError,\n                                     JetsonTypeResolutionError,\n                                     MissingDependencyError, ModelInputError,\n                                     ModelLoadingError, ModelNotFoundError,\n                                     ModelPackageNegotiationError,\n                                     ModelRetrievalError,\n                                     UnauthorizedModelAccessError,\n                                     UntrustedFileError)\nfrom starlette.responses import JSONResponse\n\n\ndef with_route_exceptions(route):\n    \"\"\"\n    A decorator that wraps a FastAPI route to handle specific exceptions. If an exception\n    is caught, it returns a JSON response with the error message.\n\n    Args:\n        route (Callable): The FastAPI route to be wrapped.\n\n    Returns:\n        Callable: The wrapped route.\n    \"\"\"\n    def wrapped_route(*args, **kwargs):\n        try:\n            return route(*args, **kwargs)\n        except ContentTypeInvalid as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Invalid Content-Type header provided with request.\"\n                },\n            )\n        except ContentTypeMissing as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=400,\n                content={\"message\": \"Content-Type header not provided with request.\"},\n            )\n        except InputImageLoadError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": f\"Could not load input image. Cause: {error.get_public_error_details()}\"\n                },\n            )\n        except ModelInputError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": f\"Error with model input. Cause: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except InvalidModelIDError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=400,\n                content={\"message\": \"Invalid Model ID sent in request.\"},\n            )\n        except InvalidMaskDecodeArgument as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Invalid mask decode argument sent. tradeoff_factor must be in [0.0, 1.0], \"\n                    \"mask_decode_mode: must be one of ['accurate', 'fast', 'tradeoff']\"\n                },\n            )\n        except MissingApiKeyError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Required Roboflow API key is missing. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except (\n            WorkflowSyntaxError,\n            InvalidReferenceTargetError,\n            ExecutionGraphStructureError,\n            StepInputDimensionalityError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=error.blocks_errors,\n            )\n            return JSONResponse(status_code=400, content=content.model_dump())\n        except (\n            WorkflowDefinitionError,\n            ReferenceTypeError,\n            RuntimeInputError,\n            InvalidInputTypeError,\n            OperationTypeNotRecognisedError,\n            DynamicBlockError,\n            WorkflowExecutionEngineVersionError,\n            NotSupportedExecutionEngineError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"context\": error.context,\n                    \"inner_error_type\": error.inner_error_type,\n                    \"inner_error_message\": str(error.inner_error),\n                },\n            )\n        except (\n            ProcessesManagerInvalidPayload,\n            MalformedPayloadError,\n            MessageToBigError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except (\n            RoboflowAPINotAuthorizedError,\n            ProcessesManagerAuthorisationError,\n            UnauthorizedModelAccessError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=401,\n                content={\n                    \"message\": \"Unauthorized access to roboflow API - check API key and make sure the key is valid for \"\n                    \"workspace you use. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except RoboflowAPIForbiddenError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=403,\n                content={\n                    \"message\": \"Unauthorized access to roboflow API - check API key and make sure the key is valid and \"\n                    \"have required scopes. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except (RoboflowAPINotNotFoundError, ModelNotFoundError) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=404,\n                content={\n                    \"message\": \"Requested Roboflow resource not found. Make sure that workspace, project or model \"\n                    \"you referred in request exists.\"\n                },\n            )\n        except ProcessesManagerNotFoundError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=404,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except ModelPackageNegotiationError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Could not negotiate model package - {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except (\n            InvalidEnvironmentVariableError,\n            MissingServiceSecretError,\n            ServiceConfigurationError,\n            EnvironmentConfigurationError,\n            InvalidEnvVariable,\n            JetsonTypeResolutionError,\n            MissingDependencyError,\n            InvalidParameterError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=500, content={\"message\": \"Service misconfiguration.\"}\n            )\n        except (\n            PreProcessingError,\n            PostProcessingError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": \"Model configuration related to pre- or post-processing is invalid.\"\n                },\n            )\n        except ModelArtefactError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=500, content={\"message\": \"Model package is broken.\"}\n            )\n        except ModelLoadingError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Model loading failed: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except (UntrustedFileError, FileHashSumMissmatch) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Issue with model package file: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except ModelRetrievalError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Could not retrieve model {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except OnnxProviderNotAvailable as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=501,\n                content={\n                    \"message\": \"Could not find requested ONNX Runtime Provider. Check that you are using \"\n                    \"the correct docker image on a supported device.\"\n                },\n            )\n        except (\n            MalformedRoboflowAPIResponseError,\n            RoboflowAPIUnsuccessfulRequestError,\n            WorkspaceLoadError,\n            MalformedWorkflowResponseError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=502,\n                content={\"message\": \"Internal error. Request to Roboflow API failed.\"},\n            )\n        except InferenceModelNotFound as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=503,\n                content={\"message\": \"Model is temporarily not ready - retry request.\"},\n                headers={\"Retry-After\": \"1\"},\n            )\n        except RoboflowAPIConnectionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=503,\n                content={\n                    \"message\": \"Internal error. Could not connect to Roboflow API.\"\n                },\n            )\n        except ModelManagerLockAcquisitionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=503,\n                content={\n                    \"message\": \"Could not acquire model manager lock due to other request performing \"\n                    \"blocking operation. Try again....\"\n                },\n                headers={\"Retry-After\": \"1\"},\n            )\n        except RoboflowAPITimeoutError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=504,\n                content={\n                    \"message\": \"Timeout when attempting to connect to Roboflow API.\"\n                },\n            )\n        except ClientCausedStepExecutionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=error.block_id,\n                    ),\n                ],\n            )\n            return JSONResponse(\n                status_code=error.status_code,\n                content=content.model_dump(),\n            )\n        except StepExecutionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=error.block_id,\n                        block_type=error.block_type,\n                    ),\n                ],\n            )\n            return JSONResponse(\n                status_code=500,\n                content=content.model_dump(),\n            )\n        except WorkflowError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"context\": error.context,\n                    \"inner_error_type\": error.inner_error_type,\n                    \"inner_error_message\": str(error.inner_error),\n                },\n            )\n        except (\n            ProcessesManagerClientError,\n            CommunicationProtocolError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except WebRTCConfigurationError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": str(error),\n                    \"error_type\": \"WebRTCConfigurationError\",\n                },\n            )\n        except CreditsExceededError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=402,\n                content={\n                    \"message\": \"Not enough credits to perform this request.\",\n                    \"error_type\": \"CreditsExceededError\",\n                },\n            )\n        except WorkspaceStreamQuotaError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=429,\n                content={\n                    \"message\": str(error),\n                    \"error_type\": \"WorkspaceStreamQuotaError\",\n                },\n            )\n        except Exception as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(status_code=500, content={\"message\": \"Internal error.\"})\n\n    return wrapped_route",
    "optimized_raw_markdown": "```python:inference/core/interfaces/http/error_handlers.py\nfrom functools import wraps\n\nfrom inference.core import logger\nfrom inference.core.entities.responses.workflows import WorkflowErrorResponse\nfrom inference.core.exceptions import (ContentTypeInvalid, ContentTypeMissing,\n                                       CreditsExceededError,\n                                       InferenceModelNotFound,\n                                       InputImageLoadError,\n                                       InvalidEnvironmentVariableError,\n                                       InvalidMaskDecodeArgument,\n                                       InvalidModelIDError,\n                                       MalformedRoboflowAPIResponseError,\n                                       MalformedWorkflowResponseError,\n                                       MissingApiKeyError,\n                                       MissingServiceSecretError,\n                                       ModelArtefactError,\n                                       ModelManagerLockAcquisitionError,\n                                       OnnxProviderNotAvailable,\n                                       PostProcessingError, PreProcessingError,\n                                       RoboflowAPIConnectionError,\n                                       RoboflowAPIForbiddenError,\n                                       RoboflowAPINotAuthorizedError,\n                                       RoboflowAPINotNotFoundError,\n                                       RoboflowAPITimeoutError,\n                                       RoboflowAPIUnsuccessfulRequestError,\n                                       ServiceConfigurationError,\n                                       WebRTCConfigurationError,\n                                       WorkspaceLoadError,\n                                       WorkspaceStreamQuotaError)\nfrom inference.core.interfaces.stream_manager.api.errors import (\n    ProcessesManagerAuthorisationError, ProcessesManagerClientError,\n    ProcessesManagerInvalidPayload, ProcessesManagerNotFoundError)\nfrom inference.core.interfaces.stream_manager.manager_app.errors import (\n    CommunicationProtocolError, MalformedPayloadError, MessageToBigError)\nfrom inference.core.workflows.core_steps.common.query_language.errors import (\n    InvalidInputTypeError, OperationTypeNotRecognisedError)\nfrom inference.core.workflows.errors import (\n    ClientCausedStepExecutionError, DynamicBlockError,\n    ExecutionGraphStructureError, InvalidReferenceTargetError,\n    NotSupportedExecutionEngineError, ReferenceTypeError, RuntimeInputError,\n    StepExecutionError, StepInputDimensionalityError, WorkflowBlockError,\n    WorkflowDefinitionError, WorkflowError,\n    WorkflowExecutionEngineVersionError, WorkflowSyntaxError)\nfrom inference_models.errors import (EnvironmentConfigurationError,\n                                     FileHashSumMissmatch, InvalidEnvVariable,\n                                     InvalidParameterError,\n                                     JetsonTypeResolutionError,\n                                     MissingDependencyError, ModelInputError,\n                                     ModelLoadingError, ModelNotFoundError,\n                                     ModelPackageNegotiationError,\n                                     ModelRetrievalError,\n                                     UnauthorizedModelAccessError,\n                                     UntrustedFileError)\nfrom starlette.responses import JSONResponse\n\n\ndef with_route_exceptions(route):\n    \"\"\"\n    A decorator that wraps a FastAPI route to handle specific exceptions. If an exception\n    is caught, it returns a JSON response with the error message.\n\n    Args:\n        route (Callable): The FastAPI route to be wrapped.\n\n    Returns:\n        Callable: The wrapped route.\n    \"\"\"\n    def wrapped_route(*args, **kwargs):\n        try:\n            return route(*args, **kwargs)\n        except ContentTypeInvalid as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Invalid Content-Type header provided with request.\"\n                },\n            )\n        except ContentTypeMissing as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=400,\n                content={\"message\": \"Content-Type header not provided with request.\"},\n            )\n        except InputImageLoadError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": f\"Could not load input image. Cause: {error.get_public_error_details()}\"\n                },\n            )\n        except ModelInputError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": f\"Error with model input. Cause: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except InvalidModelIDError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=400,\n                content={\"message\": \"Invalid Model ID sent in request.\"},\n            )\n        except InvalidMaskDecodeArgument as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Invalid mask decode argument sent. tradeoff_factor must be in [0.0, 1.0], \"\n                    \"mask_decode_mode: must be one of ['accurate', 'fast', 'tradeoff']\"\n                },\n            )\n        except MissingApiKeyError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Required Roboflow API key is missing. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except (\n            WorkflowSyntaxError,\n            InvalidReferenceTargetError,\n            ExecutionGraphStructureError,\n            StepInputDimensionalityError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=error.blocks_errors,\n            )\n            return JSONResponse(status_code=400, content=content.model_dump())\n        except (\n            WorkflowDefinitionError,\n            ReferenceTypeError,\n            RuntimeInputError,\n            InvalidInputTypeError,\n            OperationTypeNotRecognisedError,\n            DynamicBlockError,\n            WorkflowExecutionEngineVersionError,\n            NotSupportedExecutionEngineError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"context\": error.context,\n                    \"inner_error_type\": error.inner_error_type,\n                    \"inner_error_message\": str(error.inner_error),\n                },\n            )\n        except (\n            ProcessesManagerInvalidPayload,\n            MalformedPayloadError,\n            MessageToBigError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except (\n            RoboflowAPINotAuthorizedError,\n            ProcessesManagerAuthorisationError,\n            UnauthorizedModelAccessError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=401,\n                content={\n                    \"message\": \"Unauthorized access to roboflow API - check API key and make sure the key is valid for \"\n                    \"workspace you use. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except RoboflowAPIForbiddenError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=403,\n                content={\n                    \"message\": \"Unauthorized access to roboflow API - check API key and make sure the key is valid and \"\n                    \"have required scopes. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except (RoboflowAPINotNotFoundError, ModelNotFoundError) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=404,\n                content={\n                    \"message\": \"Requested Roboflow resource not found. Make sure that workspace, project or model \"\n                    \"you referred in request exists.\"\n                },\n            )\n        except ProcessesManagerNotFoundError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=404,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except ModelPackageNegotiationError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Could not negotiate model package - {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except (\n            InvalidEnvironmentVariableError,\n            MissingServiceSecretError,\n            ServiceConfigurationError,\n            EnvironmentConfigurationError,\n            InvalidEnvVariable,\n            JetsonTypeResolutionError,\n            MissingDependencyError,\n            InvalidParameterError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=500, content={\"message\": \"Service misconfiguration.\"}\n            )\n        except (\n            PreProcessingError,\n            PostProcessingError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": \"Model configuration related to pre- or post-processing is invalid.\"\n                },\n            )\n        except ModelArtefactError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=500, content={\"message\": \"Model package is broken.\"}\n            )\n        except ModelLoadingError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Model loading failed: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except (UntrustedFileError, FileHashSumMissmatch) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Issue with model package file: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except ModelRetrievalError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Could not retrieve model {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except OnnxProviderNotAvailable as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=501,\n                content={\n                    \"message\": \"Could not find requested ONNX Runtime Provider. Check that you are using \"\n                    \"the correct docker image on a supported device.\"\n                },\n            )\n        except (\n            MalformedRoboflowAPIResponseError,\n            RoboflowAPIUnsuccessfulRequestError,\n            WorkspaceLoadError,\n            MalformedWorkflowResponseError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=502,\n                content={\"message\": \"Internal error. Request to Roboflow API failed.\"},\n            )\n        except InferenceModelNotFound as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=503,\n                content={\"message\": \"Model is temporarily not ready - retry request.\"},\n                headers={\"Retry-After\": \"1\"},\n            )\n        except RoboflowAPIConnectionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=503,\n                content={\n                    \"message\": \"Internal error. Could not connect to Roboflow API.\"\n                },\n            )\n        except ModelManagerLockAcquisitionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=503,\n                content={\n                    \"message\": \"Could not acquire model manager lock due to other request performing \"\n                    \"blocking operation. Try again....\"\n                },\n                headers={\"Retry-After\": \"1\"},\n            )\n        except RoboflowAPITimeoutError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=504,\n                content={\n                    \"message\": \"Timeout when attempting to connect to Roboflow API.\"\n                },\n            )\n        except ClientCausedStepExecutionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=error.block_id,\n                    ),\n                ],\n            )\n            return JSONResponse(\n                status_code=error.status_code,\n                content=content.model_dump(),\n            )\n        except StepExecutionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=error.block_id,\n                        block_type=error.block_type,\n                    ),\n                ],\n            )\n            return JSONResponse(\n                status_code=500,\n                content=content.model_dump(),\n            )\n        except WorkflowError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"context\": error.context,\n                    \"inner_error_type\": error.inner_error_type,\n                    \"inner_error_message\": str(error.inner_error),\n                },\n            )\n        except (\n            ProcessesManagerClientError,\n            CommunicationProtocolError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except WebRTCConfigurationError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": str(error),\n                    \"error_type\": \"WebRTCConfigurationError\",\n                },\n            )\n        except CreditsExceededError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=402,\n                content={\n                    \"message\": \"Not enough credits to perform this request.\",\n                    \"error_type\": \"CreditsExceededError\",\n                },\n            )\n        except WorkspaceStreamQuotaError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=429,\n                content={\n                    \"message\": str(error),\n                    \"error_type\": \"WorkspaceStreamQuotaError\",\n                },\n            )\n        except Exception as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(status_code=500, content={\"message\": \"Internal error.\"})\n\n    return wrapped_route\n```",
    "optimized_function_only": "def with_route_exceptions(route):\n    \"\"\"\n    A decorator that wraps a FastAPI route to handle specific exceptions. If an exception\n    is caught, it returns a JSON response with the error message.\n\n    Args:\n        route (Callable): The FastAPI route to be wrapped.\n\n    Returns:\n        Callable: The wrapped route.\n    \"\"\"\n    def wrapped_route(*args, **kwargs):\n        try:\n            return route(*args, **kwargs)\n        except ContentTypeInvalid as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Invalid Content-Type header provided with request.\"\n                },\n            )\n        except ContentTypeMissing as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=400,\n                content={\"message\": \"Content-Type header not provided with request.\"},\n            )\n        except InputImageLoadError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": f\"Could not load input image. Cause: {error.get_public_error_details()}\"\n                },\n            )\n        except ModelInputError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": f\"Error with model input. Cause: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except InvalidModelIDError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=400,\n                content={\"message\": \"Invalid Model ID sent in request.\"},\n            )\n        except InvalidMaskDecodeArgument as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Invalid mask decode argument sent. tradeoff_factor must be in [0.0, 1.0], \"\n                    \"mask_decode_mode: must be one of ['accurate', 'fast', 'tradeoff']\"\n                },\n            )\n        except MissingApiKeyError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Required Roboflow API key is missing. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except (\n            WorkflowSyntaxError,\n            InvalidReferenceTargetError,\n            ExecutionGraphStructureError,\n            StepInputDimensionalityError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=error.blocks_errors,\n            )\n            return JSONResponse(status_code=400, content=content.model_dump())\n        except (\n            WorkflowDefinitionError,\n            ReferenceTypeError,\n            RuntimeInputError,\n            InvalidInputTypeError,\n            OperationTypeNotRecognisedError,\n            DynamicBlockError,\n            WorkflowExecutionEngineVersionError,\n            NotSupportedExecutionEngineError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"context\": error.context,\n                    \"inner_error_type\": error.inner_error_type,\n                    \"inner_error_message\": str(error.inner_error),\n                },\n            )\n        except (\n            ProcessesManagerInvalidPayload,\n            MalformedPayloadError,\n            MessageToBigError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except (\n            RoboflowAPINotAuthorizedError,\n            ProcessesManagerAuthorisationError,\n            UnauthorizedModelAccessError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=401,\n                content={\n                    \"message\": \"Unauthorized access to roboflow API - check API key and make sure the key is valid for \"\n                    \"workspace you use. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except RoboflowAPIForbiddenError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=403,\n                content={\n                    \"message\": \"Unauthorized access to roboflow API - check API key and make sure the key is valid and \"\n                    \"have required scopes. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except (RoboflowAPINotNotFoundError, ModelNotFoundError) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=404,\n                content={\n                    \"message\": \"Requested Roboflow resource not found. Make sure that workspace, project or model \"\n                    \"you referred in request exists.\"\n                },\n            )\n        except ProcessesManagerNotFoundError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=404,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except ModelPackageNegotiationError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Could not negotiate model package - {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except (\n            InvalidEnvironmentVariableError,\n            MissingServiceSecretError,\n            ServiceConfigurationError,\n            EnvironmentConfigurationError,\n            InvalidEnvVariable,\n            JetsonTypeResolutionError,\n            MissingDependencyError,\n            InvalidParameterError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=500, content={\"message\": \"Service misconfiguration.\"}\n            )\n        except (\n            PreProcessingError,\n            PostProcessingError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": \"Model configuration related to pre- or post-processing is invalid.\"\n                },\n            )\n        except ModelArtefactError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=500, content={\"message\": \"Model package is broken.\"}\n            )\n        except ModelLoadingError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Model loading failed: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except (UntrustedFileError, FileHashSumMissmatch) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Issue with model package file: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except ModelRetrievalError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Could not retrieve model {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except OnnxProviderNotAvailable as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=501,\n                content={\n                    \"message\": \"Could not find requested ONNX Runtime Provider. Check that you are using \"\n                    \"the correct docker image on a supported device.\"\n                },\n            )\n        except (\n            MalformedRoboflowAPIResponseError,\n            RoboflowAPIUnsuccessfulRequestError,\n            WorkspaceLoadError,\n            MalformedWorkflowResponseError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=502,\n                content={\"message\": \"Internal error. Request to Roboflow API failed.\"},\n            )\n        except InferenceModelNotFound as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=503,\n                content={\"message\": \"Model is temporarily not ready - retry request.\"},\n                headers={\"Retry-After\": \"1\"},\n            )\n        except RoboflowAPIConnectionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=503,\n                content={\n                    \"message\": \"Internal error. Could not connect to Roboflow API.\"\n                },\n            )\n        except ModelManagerLockAcquisitionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=503,\n                content={\n                    \"message\": \"Could not acquire model manager lock due to other request performing \"\n                    \"blocking operation. Try again....\"\n                },\n                headers={\"Retry-After\": \"1\"},\n            )\n        except RoboflowAPITimeoutError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=504,\n                content={\n                    \"message\": \"Timeout when attempting to connect to Roboflow API.\"\n                },\n            )\n        except ClientCausedStepExecutionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=error.block_id,\n                    ),\n                ],\n            )\n            return JSONResponse(\n                status_code=error.status_code,\n                content=content.model_dump(),\n            )\n        except StepExecutionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=error.block_id,\n                        block_type=error.block_type,\n                    ),\n                ],\n            )\n            return JSONResponse(\n                status_code=500,\n                content=content.model_dump(),\n            )\n        except WorkflowError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"context\": error.context,\n                    \"inner_error_type\": error.inner_error_type,\n                    \"inner_error_message\": str(error.inner_error),\n                },\n            )\n        except (\n            ProcessesManagerClientError,\n            CommunicationProtocolError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except WebRTCConfigurationError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": str(error),\n                    \"error_type\": \"WebRTCConfigurationError\",\n                },\n            )\n        except CreditsExceededError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=402,\n                content={\n                    \"message\": \"Not enough credits to perform this request.\",\n                    \"error_type\": \"CreditsExceededError\",\n                },\n            )\n        except WorkspaceStreamQuotaError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(\n                status_code=429,\n                content={\n                    \"message\": str(error),\n                    \"error_type\": \"WorkspaceStreamQuotaError\",\n                },\n            )\n        except Exception as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            return JSONResponse(status_code=500, content={\"message\": \"Internal error.\"})\n\n    return wrapped_route",
    "original_file_content": "from functools import wraps\n\nfrom starlette.responses import JSONResponse\n\nfrom inference.core import logger\nfrom inference.core.entities.responses.workflows import WorkflowErrorResponse\nfrom inference.core.exceptions import (\n    ContentTypeInvalid,\n    ContentTypeMissing,\n    CreditsExceededError,\n    InferenceModelNotFound,\n    InputImageLoadError,\n    InvalidEnvironmentVariableError,\n    InvalidMaskDecodeArgument,\n    InvalidModelIDError,\n    MalformedRoboflowAPIResponseError,\n    MalformedWorkflowResponseError,\n    MissingApiKeyError,\n    MissingServiceSecretError,\n    ModelArtefactError,\n    ModelManagerLockAcquisitionError,\n    OnnxProviderNotAvailable,\n    PostProcessingError,\n    PreProcessingError,\n    RoboflowAPIConnectionError,\n    RoboflowAPIForbiddenError,\n    RoboflowAPINotAuthorizedError,\n    RoboflowAPINotNotFoundError,\n    RoboflowAPITimeoutError,\n    RoboflowAPIUnsuccessfulRequestError,\n    ServiceConfigurationError,\n    WebRTCConfigurationError,\n    WorkspaceLoadError,\n    WorkspaceStreamQuotaError,\n)\nfrom inference.core.interfaces.stream_manager.api.errors import (\n    ProcessesManagerAuthorisationError,\n    ProcessesManagerClientError,\n    ProcessesManagerInvalidPayload,\n    ProcessesManagerNotFoundError,\n)\nfrom inference.core.interfaces.stream_manager.manager_app.errors import (\n    CommunicationProtocolError,\n    MalformedPayloadError,\n    MessageToBigError,\n)\nfrom inference.core.workflows.core_steps.common.query_language.errors import (\n    InvalidInputTypeError,\n    OperationTypeNotRecognisedError,\n)\nfrom inference.core.workflows.errors import (\n    ClientCausedStepExecutionError,\n    DynamicBlockError,\n    ExecutionGraphStructureError,\n    InvalidReferenceTargetError,\n    NotSupportedExecutionEngineError,\n    ReferenceTypeError,\n    RuntimeInputError,\n    StepExecutionError,\n    StepInputDimensionalityError,\n    WorkflowBlockError,\n    WorkflowDefinitionError,\n    WorkflowError,\n    WorkflowExecutionEngineVersionError,\n    WorkflowSyntaxError,\n)\nfrom inference_models.errors import (\n    EnvironmentConfigurationError,\n    FileHashSumMissmatch,\n    InvalidEnvVariable,\n    InvalidParameterError,\n    JetsonTypeResolutionError,\n    MissingDependencyError,\n    ModelInputError,\n    ModelLoadingError,\n    ModelNotFoundError,\n    ModelPackageNegotiationError,\n    ModelRetrievalError,\n    UnauthorizedModelAccessError,\n    UntrustedFileError,\n)\n\n\ndef with_route_exceptions(route):\n    \"\"\"\n    A decorator that wraps a FastAPI route to handle specific exceptions. If an exception\n    is caught, it returns a JSON response with the error message.\n\n    Args:\n        route (Callable): The FastAPI route to be wrapped.\n\n    Returns:\n        Callable: The wrapped route.\n    \"\"\"\n\n    @wraps(route)\n    def wrapped_route(*args, **kwargs):\n        try:\n            return route(*args, **kwargs)\n        except ContentTypeInvalid as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Invalid Content-Type header provided with request.\"\n                },\n            )\n        except ContentTypeMissing as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\"message\": \"Content-Type header not provided with request.\"},\n            )\n        except InputImageLoadError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": f\"Could not load input image. Cause: {error.get_public_error_details()}\"\n                },\n            )\n        except ModelInputError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": f\"Error with model input. Cause: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except InvalidModelIDError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\"message\": \"Invalid Model ID sent in request.\"},\n            )\n        except InvalidMaskDecodeArgument as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Invalid mask decode argument sent. tradeoff_factor must be in [0.0, 1.0], \"\n                    \"mask_decode_mode: must be one of ['accurate', 'fast', 'tradeoff']\"\n                },\n            )\n        except MissingApiKeyError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Required Roboflow API key is missing. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except (\n            WorkflowSyntaxError,\n            InvalidReferenceTargetError,\n            ExecutionGraphStructureError,\n            StepInputDimensionalityError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=error.blocks_errors,\n            )\n            resp = JSONResponse(status_code=400, content=content.model_dump())\n        except (\n            WorkflowDefinitionError,\n            ReferenceTypeError,\n            RuntimeInputError,\n            InvalidInputTypeError,\n            OperationTypeNotRecognisedError,\n            DynamicBlockError,\n            WorkflowExecutionEngineVersionError,\n            NotSupportedExecutionEngineError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"context\": error.context,\n                    \"inner_error_type\": error.inner_error_type,\n                    \"inner_error_message\": str(error.inner_error),\n                },\n            )\n        except (\n            ProcessesManagerInvalidPayload,\n            MalformedPayloadError,\n            MessageToBigError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except (\n            RoboflowAPINotAuthorizedError,\n            ProcessesManagerAuthorisationError,\n            UnauthorizedModelAccessError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=401,\n                content={\n                    \"message\": \"Unauthorized access to roboflow API - check API key and make sure the key is valid for \"\n                    \"workspace you use. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except RoboflowAPIForbiddenError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=403,\n                content={\n                    \"message\": \"Unauthorized access to roboflow API - check API key and make sure the key is valid and \"\n                    \"have required scopes. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except (RoboflowAPINotNotFoundError, ModelNotFoundError) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=404,\n                content={\n                    \"message\": \"Requested Roboflow resource not found. Make sure that workspace, project or model \"\n                    \"you referred in request exists.\"\n                },\n            )\n        except ProcessesManagerNotFoundError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=404,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except ModelPackageNegotiationError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Could not negotiate model package - {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except (\n            InvalidEnvironmentVariableError,\n            MissingServiceSecretError,\n            ServiceConfigurationError,\n            EnvironmentConfigurationError,\n            InvalidEnvVariable,\n            JetsonTypeResolutionError,\n            MissingDependencyError,\n            InvalidParameterError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500, content={\"message\": \"Service misconfiguration.\"}\n            )\n        except (\n            PreProcessingError,\n            PostProcessingError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": \"Model configuration related to pre- or post-processing is invalid.\"\n                },\n            )\n        except ModelArtefactError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500, content={\"message\": \"Model package is broken.\"}\n            )\n        except ModelLoadingError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Model loading failed: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except (UntrustedFileError, FileHashSumMissmatch) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Issue with model package file: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except ModelRetrievalError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Could not retrieve model {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except OnnxProviderNotAvailable as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=501,\n                content={\n                    \"message\": \"Could not find requested ONNX Runtime Provider. Check that you are using \"\n                    \"the correct docker image on a supported device.\"\n                },\n            )\n        except (\n            MalformedRoboflowAPIResponseError,\n            RoboflowAPIUnsuccessfulRequestError,\n            WorkspaceLoadError,\n            MalformedWorkflowResponseError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=502,\n                content={\"message\": \"Internal error. Request to Roboflow API failed.\"},\n            )\n        except InferenceModelNotFound as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\"message\": \"Model is temporarily not ready - retry request.\"},\n                headers={\"Retry-After\": \"1\"},\n            )\n        except RoboflowAPIConnectionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\n                    \"message\": \"Internal error. Could not connect to Roboflow API.\"\n                },\n            )\n        except ModelManagerLockAcquisitionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\n                    \"message\": \"Could not acquire model manager lock due to other request performing \"\n                    \"blocking operation. Try again....\"\n                },\n                headers={\"Retry-After\": \"1\"},\n            )\n        except RoboflowAPITimeoutError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=504,\n                content={\n                    \"message\": \"Timeout when attempting to connect to Roboflow API.\"\n                },\n            )\n        except ClientCausedStepExecutionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=error.block_id,\n                    ),\n                ],\n            )\n            resp = JSONResponse(\n                status_code=error.status_code,\n                content=content.model_dump(),\n            )\n        except StepExecutionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=error.block_id,\n                        block_type=error.block_type,\n                    ),\n                ],\n            )\n            resp = JSONResponse(\n                status_code=500,\n                content=content.model_dump(),\n            )\n        except WorkflowError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"context\": error.context,\n                    \"inner_error_type\": error.inner_error_type,\n                    \"inner_error_message\": str(error.inner_error),\n                },\n            )\n        except (\n            ProcessesManagerClientError,\n            CommunicationProtocolError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except WebRTCConfigurationError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": str(error),\n                    \"error_type\": \"WebRTCConfigurationError\",\n                },\n            )\n        except CreditsExceededError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=402,\n                content={\n                    \"message\": \"Not enough credits to perform this request.\",\n                    \"error_type\": \"CreditsExceededError\",\n                },\n            )\n        except WorkspaceStreamQuotaError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=429,\n                content={\n                    \"message\": str(error),\n                    \"error_type\": \"WorkspaceStreamQuotaError\",\n                },\n            )\n        except Exception as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(status_code=500, content={\"message\": \"Internal error.\"})\n        return resp\n\n    return wrapped_route\n\n\ndef with_route_exceptions_async(route):\n    \"\"\"\n    A decorator that wraps a FastAPI route to handle specific exceptions. If an exception\n    is caught, it returns a JSON response with the error message.\n\n    Args:\n        route (Callable): The FastAPI route to be wrapped.\n\n    Returns:\n        Callable: The wrapped route.\n    \"\"\"\n\n    @wraps(route)\n    async def wrapped_route(*args, **kwargs):\n        try:\n            return await route(*args, **kwargs)\n        except ContentTypeInvalid as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Invalid Content-Type header provided with request.\"\n                },\n            )\n        except ContentTypeMissing as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\"message\": \"Content-Type header not provided with request.\"},\n            )\n        except InputImageLoadError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": f\"Could not load input image. Cause: {error.get_public_error_details()}\"\n                },\n            )\n        except ModelInputError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": f\"Error with model input. Cause: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except InvalidModelIDError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\"message\": \"Invalid Model ID sent in request.\"},\n            )\n        except InvalidMaskDecodeArgument as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Invalid mask decode argument sent. tradeoff_factor must be in [0.0, 1.0], \"\n                    \"mask_decode_mode: must be one of ['accurate', 'fast', 'tradeoff']\"\n                },\n            )\n        except MissingApiKeyError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Required Roboflow API key is missing. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except (\n            WorkflowSyntaxError,\n            InvalidReferenceTargetError,\n            ExecutionGraphStructureError,\n            StepInputDimensionalityError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=error.blocks_errors,\n            )\n            resp = JSONResponse(status_code=400, content=content.model_dump())\n        except (\n            WorkflowDefinitionError,\n            ReferenceTypeError,\n            RuntimeInputError,\n            InvalidInputTypeError,\n            OperationTypeNotRecognisedError,\n            DynamicBlockError,\n            WorkflowExecutionEngineVersionError,\n            NotSupportedExecutionEngineError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"context\": error.context,\n                    \"inner_error_type\": error.inner_error_type,\n                    \"inner_error_message\": str(error.inner_error),\n                },\n            )\n        except (\n            ProcessesManagerInvalidPayload,\n            MalformedPayloadError,\n            MessageToBigError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except (\n            RoboflowAPINotAuthorizedError,\n            ProcessesManagerAuthorisationError,\n            UnauthorizedModelAccessError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=401,\n                content={\n                    \"message\": \"Unauthorized access to roboflow API - check API key and make sure the key is valid for \"\n                    \"workspace you use. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except RoboflowAPIForbiddenError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=403,\n                content={\n                    \"message\": \"Unauthorized access to roboflow API - check API key and make sure the key is valid and \"\n                    \"have required scopes. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except (RoboflowAPINotNotFoundError, ModelNotFoundError) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=404,\n                content={\n                    \"message\": \"Requested Roboflow resource not found. Make sure that workspace, project or model \"\n                    \"you referred in request exists.\"\n                },\n            )\n        except ProcessesManagerNotFoundError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=404,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except ModelPackageNegotiationError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Could not negotiate model package - {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except (\n            InvalidEnvironmentVariableError,\n            MissingServiceSecretError,\n            ServiceConfigurationError,\n            EnvironmentConfigurationError,\n            InvalidEnvVariable,\n            JetsonTypeResolutionError,\n            MissingDependencyError,\n            InvalidParameterError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500, content={\"message\": \"Service misconfiguration.\"}\n            )\n        except (\n            PreProcessingError,\n            PostProcessingError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": \"Model configuration related to pre- or post-processing is invalid.\"\n                },\n            )\n        except ModelArtefactError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500, content={\"message\": \"Model package is broken.\"}\n            )\n        except ModelLoadingError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Model loading failed: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except (UntrustedFileError, FileHashSumMissmatch) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Issue with model package file: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except ModelRetrievalError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Could not retrieve model {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except OnnxProviderNotAvailable as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=501,\n                content={\n                    \"message\": \"Could not find requested ONNX Runtime Provider. Check that you are using \"\n                    \"the correct docker image on a supported device.\"\n                },\n            )\n        except (\n            MalformedRoboflowAPIResponseError,\n            RoboflowAPIUnsuccessfulRequestError,\n            WorkspaceLoadError,\n            MalformedWorkflowResponseError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=502,\n                content={\"message\": \"Internal error. Request to Roboflow API failed.\"},\n            )\n        except InferenceModelNotFound as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\"message\": \"Model is temporarily not ready - retry request.\"},\n                headers={\"Retry-After\": \"1\"},\n            )\n        except RoboflowAPIConnectionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\n                    \"message\": \"Internal error. Could not connect to Roboflow API.\"\n                },\n            )\n        except ModelManagerLockAcquisitionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\n                    \"message\": \"Could not acquire model manager lock due to other request performing \"\n                    \"blocking operation. Try again....\"\n                },\n                headers={\"Retry-After\": \"1\"},\n            )\n        except RoboflowAPITimeoutError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=504,\n                content={\n                    \"message\": \"Timeout when attempting to connect to Roboflow API.\"\n                },\n            )\n        except ClientCausedStepExecutionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=error.block_id,\n                    ),\n                ],\n            )\n            resp = JSONResponse(\n                status_code=error.status_code,\n                content=content.model_dump(),\n            )\n        except StepExecutionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=error.block_id,\n                        block_type=error.block_type,\n                    ),\n                ],\n            )\n            resp = JSONResponse(\n                status_code=500,\n                content=content.model_dump(),\n            )\n        except WorkflowError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"context\": error.context,\n                    \"inner_error_type\": error.inner_error_type,\n                    \"inner_error_message\": str(error.inner_error),\n                },\n            )\n        except (\n            ProcessesManagerClientError,\n            CommunicationProtocolError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except WebRTCConfigurationError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": str(error),\n                    \"error_type\": \"WebRTCConfigurationError\",\n                },\n            )\n        except CreditsExceededError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=402,\n                content={\n                    \"message\": \"Not enough credits to perform this request.\",\n                    \"error_type\": \"CreditsExceededError\",\n                },\n            )\n        except WorkspaceStreamQuotaError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=429,\n                content={\n                    \"message\": str(error),\n                    \"error_type\": \"WorkspaceStreamQuotaError\",\n                },\n            )\n        except Exception as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(status_code=500, content={\"message\": \"Internal error.\"})\n        return resp\n\n    return wrapped_route\n",
    "patch": null
  },
  {
    "trace_id": "44c6baa3-2462-47d9-80c6-e208bf81f594",
    "function_name": "_ForceTraceRootSampler.get_description",
    "file_path": "inference/core/telemetry.py",
    "speedup_x": 1.0299888791734935,
    "review_quality": "high",
    "pre_optimization_commit": "3d23a0e028b2aba8cea9eaf037e6ebccad8cac97",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def get_description(self) -> str:\n        return f\"ForceTraceRootSampler({self._delegate.get_description()})\"\n",
    "optimized_function_code": "from typing import Any\n\n\nclass _ForceTraceRootSampler:\n\n    def __init__(self, delegate: Any) -> None:\n        self._delegate = delegate\n\n        self._cached_description = f\"ForceTraceRootSampler({delegate.get_description()})\"\n\n    def get_description(self) -> str:\n        return self._cached_description",
    "optimized_raw_markdown": "```python:inference/core/telemetry.py\nfrom typing import Any\n\n\nclass _ForceTraceRootSampler:\n\n    def __init__(self, delegate: Any) -> None:\n        self._delegate = delegate\n\n        self._cached_description = f\"ForceTraceRootSampler({delegate.get_description()})\"\n\n    def get_description(self) -> str:\n        return self._cached_description\n```",
    "optimized_function_only": "    def get_description(self) -> str:\n        return self._cached_description",
    "original_file_content": "\"\"\"OpenTelemetry tracing setup and helpers for the inference server.\n\nAll public helpers are safe to import and call even when opentelemetry is not\ninstalled \u2014 they degrade to noops.  Business-logic code should never need to\ncheck whether OTel is available.\n\nUsage::\n\n    from inference.core.telemetry import (\n        start_span, record_error, set_span_attribute,\n    )\n\n    with start_span(\"model.infer\", {\"model.id\": model_id}):\n        result = do_inference(...)\n        set_span_attribute(\"model.load_time_seconds\", elapsed)\n\n    record_error(error)\n\"\"\"\n\nimport contextvars\nimport logging\nfrom contextlib import contextmanager\nfrom typing import Any, Dict, Optional, Sequence\n\nlogger = logging.getLogger(\"inference\")\n\n# ---------------------------------------------------------------------------\n# Graceful opentelemetry imports \u2014 everything below is noop when not installed\n# ---------------------------------------------------------------------------\ntry:\n    from opentelemetry import trace\n    from opentelemetry.propagate import inject as _otel_inject\n    from opentelemetry.propagate import set_global_textmap\n    from opentelemetry.propagators.composite import CompositePropagator\n    from opentelemetry.trace import StatusCode\n    from opentelemetry.trace.propagation.tracecontext import (\n        TraceContextTextMapPropagator,\n    )\n\n    _OTEL_AVAILABLE = True\nexcept ImportError:\n    _OTEL_AVAILABLE = False\n\n_tracer = None\n_provider = None\n_meter_provider = None\n_metrics: Optional[Dict[str, Any]] = None\n\n# Header name for forcing a trace on a specific request.\nFORCE_TRACE_HEADER = b\"x-force-trace\"\n\n# ContextVar set by _ForceTraceASGIMiddleware, read by _ForceTraceRootSampler.\n# Per-request isolation is automatic in ASGI (each request runs in its own task).\n_force_trace_flag: contextvars.ContextVar[bool] = contextvars.ContextVar(\n    \"_force_trace_flag\", default=False\n)\n\n\n# ---------------------------------------------------------------------------\n# Public helpers \u2014 always safe to call\n# ---------------------------------------------------------------------------\n\n\n@contextmanager\ndef start_span(name: str, attributes: Optional[Dict[str, Any]] = None):\n    \"\"\"Start a new span as a child of the current context.\n\n    Yields the span (or None when OTel is not available).\n    \"\"\"\n    if not _OTEL_AVAILABLE:\n        yield None\n        return\n    tracer = _get_tracer()\n    with tracer.start_as_current_span(name, attributes=attributes) as span:\n        yield span\n\n\ndef record_error(error: Exception) -> None:\n    \"\"\"Record an exception on the current active span and set ERROR status.\n\n    Safe to call when OTel is not installed or there is no active span.\n    \"\"\"\n    if not _OTEL_AVAILABLE:\n        return\n    span = trace.get_current_span()\n    if span and span.is_recording():\n        span.record_exception(error)\n        span.set_status(StatusCode.ERROR, str(error))\n\n\ndef get_trace_id() -> Optional[str]:\n    \"\"\"Return the current trace ID as a hex string, or None.\"\"\"\n    if not _OTEL_AVAILABLE:\n        return None\n    span = trace.get_current_span()\n    ctx = span.get_span_context()\n    if ctx and ctx.trace_id:\n        return format(ctx.trace_id, \"032x\")\n    return None\n\n\ndef set_span_attribute(key: str, value: Any) -> None:\n    \"\"\"Set an attribute on the current active span.\n\n    Noop when OTel is unavailable or there is no recording span.\n    Callers never need to check for None spans.\n    \"\"\"\n    if not _OTEL_AVAILABLE:\n        return\n    span = trace.get_current_span()\n    if span and span.is_recording():\n        span.set_attribute(key, value)\n\n\ndef capture_context() -> Any:\n    \"\"\"Capture the current OTel context for propagation to another thread.\n\n    Returns an opaque token (or None). Pass to attach_context() in the target thread.\n    \"\"\"\n    if not _OTEL_AVAILABLE:\n        return None\n    from opentelemetry import context\n\n    return context.get_current()\n\n\ndef attach_context(ctx: Any) -> Any:\n    \"\"\"Attach a previously captured OTel context in the current thread.\n\n    Returns a token that MUST be passed to detach_context() when done.\n    \"\"\"\n    if ctx is None or not _OTEL_AVAILABLE:\n        return None\n    from opentelemetry import context\n\n    return context.attach(ctx)\n\n\ndef detach_context(token: Any) -> None:\n    \"\"\"Detach a previously attached context. Must be called in a finally block.\"\"\"\n    if token is None or not _OTEL_AVAILABLE:\n        return\n    from opentelemetry import context\n\n    context.detach(token)\n\n\ndef inject_trace_context(headers: dict) -> dict:\n    \"\"\"Inject W3C traceparent/tracestate into *headers* dict and return it.\n\n    Safe to call when OTel is not installed (returns headers unchanged).\n    \"\"\"\n    if not _OTEL_AVAILABLE:\n        return headers\n    if headers is None:\n        headers = {}\n    _otel_inject(headers)\n    return headers\n\n\ndef trace_context_log_processor(\n    logger_instance: Any, method_name: str, event_dict: Dict[str, Any]\n) -> Dict[str, Any]:\n    \"\"\"Structlog processor that injects trace_id and span_id into log entries.\"\"\"\n    if not _OTEL_AVAILABLE:\n        return event_dict\n    span = trace.get_current_span()\n    ctx = span.get_span_context()\n    if ctx and ctx.trace_id:\n        event_dict[\"trace_id\"] = format(ctx.trace_id, \"032x\")\n        event_dict[\"span_id\"] = format(ctx.span_id, \"016x\")\n    return event_dict\n\n\n# ---------------------------------------------------------------------------\n# Metrics helpers \u2014 always safe to call\n# ---------------------------------------------------------------------------\n\n\ndef record_model_loaded(model_id: str, load_time: float) -> None:\n    \"\"\"Record a model load event: increment counters and record load duration.\"\"\"\n    if _metrics is None:\n        return\n    _metrics[\"models_loaded\"].add(1)\n    _metrics[\"model_loads\"].add(1, {\"model.id\": model_id})\n    _metrics[\"model_load_duration\"].record(load_time, {\"model.id\": model_id})\n\n\ndef record_model_unloaded(model_id: str) -> None:\n    \"\"\"Record a model unload event.\"\"\"\n    if _metrics is None:\n        return\n    _metrics[\"models_loaded\"].add(-1)\n    _metrics[\"model_unloads\"].add(1, {\"model.id\": model_id})\n\n\ndef record_inference(model_id: str, duration: float) -> None:\n    \"\"\"Record an inference execution.\"\"\"\n    if _metrics is None:\n        return\n    _metrics[\"model_infer_count\"].add(1, {\"model.id\": model_id})\n    _metrics[\"model_infer_duration\"].record(duration, {\"model.id\": model_id})\n\n\ndef record_api_call(function_name: str, duration: float) -> None:\n    \"\"\"Record a Roboflow API call duration.\"\"\"\n    if _metrics is None:\n        return\n    _metrics[\"api_call_duration\"].record(\n        duration, {\"roboflow_api.function\": function_name}\n    )\n\n\ndef record_error_metric(error_type: str) -> None:\n    \"\"\"Increment the error counter by error type.\"\"\"\n    if _metrics is None:\n        return\n    _metrics[\"errors\"].add(1, {\"error.type\": error_type})\n\n\n# ---------------------------------------------------------------------------\n# Force-trace ASGI middleware + custom sampler\n# ---------------------------------------------------------------------------\n\n\nclass _ForceTraceASGIMiddleware:\n    \"\"\"Lightweight ASGI middleware that detects X-Force-Trace header.\n\n    Must wrap the app OUTSIDE the OTel instrumentor so the ContextVar is set\n    before the instrumentor's should_sample() call.  We achieve this by adding\n    it via app.add_middleware() AFTER FastAPIInstrumentor.instrument_app() \u2014\n    Starlette builds the middleware stack so the last-added middleware is\n    outermost.\n    \"\"\"\n\n    def __init__(self, app: Any) -> None:\n        self.app = app\n\n    async def __call__(self, scope: dict, receive: Any, send: Any) -> None:\n        if scope[\"type\"] == \"http\":\n            for header_name, header_value in scope.get(\"headers\", []):\n                if header_name == FORCE_TRACE_HEADER:\n                    if header_value.lower() == b\"true\":\n                        _force_trace_flag.set(True)\n                    break\n        try:\n            await self.app(scope, receive, send)\n        finally:\n            _force_trace_flag.set(False)\n\n\nclass _TraceIdResponseMiddleware:\n    \"\"\"Raw ASGI middleware that injects X-Trace-Id into response headers.\n\n    Must sit INSIDE the OTel instrumentor in the middleware stack so the span\n    context is available when the response is sent.  Added via\n    app.add_middleware() BEFORE FastAPIInstrumentor.instrument_app() \u2014\n    Starlette builds the stack so earlier-added middleware is innermost.\n\n    We use a raw ASGI middleware (not BaseHTTPMiddleware) because Starlette's\n    BaseHTTPMiddleware runs call_next in a separate task, which breaks\n    ContextVar propagation \u2014 get_trace_id() would return None.\n    \"\"\"\n\n    def __init__(self, app: Any) -> None:\n        self.app = app\n\n    async def __call__(self, scope: dict, receive: Any, send: Any) -> None:\n        if scope[\"type\"] != \"http\":\n            await self.app(scope, receive, send)\n            return\n\n        async def send_with_trace_id(message: dict) -> None:\n            if message[\"type\"] == \"http.response.start\":\n                trace_id = get_trace_id()\n                if trace_id:\n                    from inference.core.constants import TRACE_ID_HEADER\n\n                    headers = list(message.get(\"headers\", []))\n                    headers.append(\n                        (TRACE_ID_HEADER.lower().encode(), trace_id.encode())\n                    )\n                    message = {**message, \"headers\": headers}\n            await send(message)\n\n        await self.app(scope, receive, send_with_trace_id)\n\n\nclass _ForceTraceRootSampler:\n    \"\"\"Custom root sampler that force-samples when X-Force-Trace is set.\n\n    Used as the ``root`` argument to ParentBased:\n      - Parent exists  -> ParentBased honours the parent's decision (not us)\n      - No parent, X-Force-Trace: true -> always sample\n      - No parent, no header -> delegate to the ratio-based sampler\n    \"\"\"\n\n    def __init__(self, delegate: Any) -> None:\n        self._delegate = delegate\n\n    def should_sample(\n        self,\n        parent_context: Any,\n        trace_id: int,\n        name: str,\n        kind: Any = None,\n        attributes: Any = None,\n        links: Optional[Sequence[Any]] = None,\n        trace_state: Any = None,\n    ) -> Any:\n        if _force_trace_flag.get(False):\n            from opentelemetry.sdk.trace.sampling import Decision, SamplingResult\n\n            return SamplingResult(\n                decision=Decision.RECORD_AND_SAMPLE,\n                attributes={\"sampling.forced\": True},\n                trace_state=trace_state,\n            )\n        return self._delegate.should_sample(\n            parent_context, trace_id, name, kind, attributes, links, trace_state\n        )\n\n    def get_description(self) -> str:\n        return f\"ForceTraceRootSampler({self._delegate.get_description()})\"\n\n\n# ---------------------------------------------------------------------------\n# Setup / shutdown \u2014 called only when OTEL_TRACING_ENABLED is True\n# ---------------------------------------------------------------------------\n\n\ndef setup_telemetry(app: Any) -> None:\n    \"\"\"Initialize OTel TracerProvider, MeterProvider, and instrument the FastAPI app.\n\n    Must be called before any middleware is added so the FastAPI instrumentor\n    wraps at the outermost ASGI layer.\n    \"\"\"\n    global _provider, _tracer, _meter_provider, _metrics\n\n    from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import (\n        OTLPSpanExporter as GRPCExporter,\n    )\n    from opentelemetry.exporter.otlp.proto.http.trace_exporter import (\n        OTLPSpanExporter as HTTPExporter,\n    )\n    from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor\n    from opentelemetry.sdk.resources import Resource\n    from opentelemetry.sdk.trace import TracerProvider\n    from opentelemetry.sdk.trace.export import BatchSpanProcessor\n    from opentelemetry.sdk.trace.sampling import (\n        ALWAYS_OFF,\n        ALWAYS_ON,\n        ParentBased,\n        TraceIdRatioBased,\n    )\n\n    from inference.core.env import (\n        OTEL_EXPORTER_ENDPOINT,\n        OTEL_EXPORTER_PROTOCOL,\n        OTEL_METRIC_EXPORT_INTERVAL_MS,\n        OTEL_METRIC_EXPORTER_ENDPOINT,\n        OTEL_METRICS_ENABLED,\n        OTEL_SAMPLING_RATE,\n        OTEL_SERVICE_NAME,\n        OTEL_TRACE_EXPORT_INTERVAL_MS,\n    )\n\n    # W3C TraceContext propagator \u2014 always set so extract/inject are safe\n    set_global_textmap(CompositePropagator([TraceContextTextMapPropagator()]))\n\n    # Build root sampler with force-trace override\n    if OTEL_SAMPLING_RATE <= 0:\n        root_sampler = ALWAYS_OFF\n    elif OTEL_SAMPLING_RATE >= 1.0:\n        root_sampler = ALWAYS_ON\n    else:\n        root_sampler = TraceIdRatioBased(OTEL_SAMPLING_RATE)\n\n    # ParentBased: child spans honour parent decision, root spans use our\n    # custom sampler that checks for X-Force-Trace before falling back to\n    # the ratio-based sampler.\n    sampler = ParentBased(root=_ForceTraceRootSampler(root_sampler))\n\n    from inference.core.devices.utils import GLOBAL_INFERENCE_SERVER_ID\n\n    resource = Resource.create(\n        {\n            \"service.name\": OTEL_SERVICE_NAME,\n            \"service.instance.id\": GLOBAL_INFERENCE_SERVER_ID,\n        }\n    )\n\n    if OTEL_EXPORTER_PROTOCOL == \"http\":\n        exporter = HTTPExporter(\n            endpoint=f\"http://{OTEL_EXPORTER_ENDPOINT}/v1/traces\",\n        )\n    else:\n        exporter = GRPCExporter(\n            endpoint=OTEL_EXPORTER_ENDPOINT,\n            insecure=True,\n        )\n\n    _provider = TracerProvider(resource=resource, sampler=sampler)\n    _provider.add_span_processor(\n        BatchSpanProcessor(\n            exporter, schedule_delay_millis=OTEL_TRACE_EXPORT_INTERVAL_MS\n        )\n    )\n    trace.set_tracer_provider(_provider)\n\n    _tracer = trace.get_tracer(\"inference\")\n\n    # --- Metrics ---\n    if OTEL_METRICS_ENABLED:\n        from opentelemetry import metrics as otel_metrics\n        from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import (\n            OTLPMetricExporter as GRPCMetricExporter,\n        )\n        from opentelemetry.exporter.otlp.proto.http.metric_exporter import (\n            OTLPMetricExporter as HTTPMetricExporter,\n        )\n        from opentelemetry.sdk.metrics import MeterProvider\n        from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader\n\n        metric_endpoint = OTEL_METRIC_EXPORTER_ENDPOINT or OTEL_EXPORTER_ENDPOINT\n        if OTEL_EXPORTER_PROTOCOL == \"http\":\n            metric_exporter = HTTPMetricExporter(\n                endpoint=f\"http://{metric_endpoint}/v1/metrics\",\n            )\n        else:\n            metric_exporter = GRPCMetricExporter(\n                endpoint=metric_endpoint,\n                insecure=True,\n            )\n\n        metric_reader = PeriodicExportingMetricReader(\n            metric_exporter, export_interval_millis=OTEL_METRIC_EXPORT_INTERVAL_MS\n        )\n        _meter_provider = MeterProvider(\n            resource=resource, metric_readers=[metric_reader]\n        )\n        otel_metrics.set_meter_provider(_meter_provider)\n\n        meter = _meter_provider.get_meter(\"inference\")\n        _metrics = {\n            \"models_loaded\": meter.create_up_down_counter(\n                \"inference.models.loaded\",\n                description=\"Number of models currently loaded\",\n            ),\n            \"model_loads\": meter.create_counter(\n                \"inference.model.loads\",\n                description=\"Total model loads (cold starts)\",\n            ),\n            \"model_unloads\": meter.create_counter(\n                \"inference.model.unloads\",\n                description=\"Total model unloads\",\n            ),\n            \"model_load_duration\": meter.create_histogram(\n                \"inference.model.load.duration\",\n                unit=\"s\",\n                description=\"Model load time in seconds\",\n            ),\n            \"model_infer_count\": meter.create_counter(\n                \"inference.model.infer.count\",\n                description=\"Total inference requests\",\n            ),\n            \"model_infer_duration\": meter.create_histogram(\n                \"inference.model.infer.duration\",\n                unit=\"s\",\n                description=\"Inference latency in seconds\",\n            ),\n            \"api_call_duration\": meter.create_histogram(\n                \"inference.roboflow_api.duration\",\n                unit=\"s\",\n                description=\"Roboflow API call latency in seconds\",\n            ),\n            \"errors\": meter.create_counter(\n                \"inference.errors\",\n                description=\"Total errors by type\",\n            ),\n        }\n        _install_export_error_filter(\"opentelemetry.sdk.metrics._internal.export\")\n\n    # Replace noisy connection-refused tracebacks with a single-line warning.\n    _install_export_error_filter(\"opentelemetry.sdk.trace.export\")\n\n    # Add trace-ID response middleware BEFORE the instrumentor so it sits\n    # INSIDE the OTel span context (earlier-added = innermost in Starlette).\n    app.add_middleware(_TraceIdResponseMiddleware)\n\n    # Auto-instrument FastAPI: creates server spans, extracts traceparent\n    FastAPIInstrumentor.instrument_app(app)\n\n    # Auto-instrument outgoing requests: creates http.client spans, injects traceparent\n    from opentelemetry.instrumentation.requests import RequestsInstrumentor\n\n    RequestsInstrumentor().instrument()\n\n    # Add force-trace middleware AFTER the instrumentor so it wraps outermost.\n    # Starlette builds middleware last-added = outermost, so this runs BEFORE\n    # the instrumentor's ASGI middleware, ensuring the ContextVar is set\n    # before should_sample() is called.\n    app.add_middleware(_ForceTraceASGIMiddleware)\n\n    logger.info(\n        \"OpenTelemetry tracing enabled (service=%s, endpoint=%s, protocol=%s, sampling_rate=%s)\",\n        OTEL_SERVICE_NAME,\n        OTEL_EXPORTER_ENDPOINT,\n        OTEL_EXPORTER_PROTOCOL,\n        OTEL_SAMPLING_RATE,\n    )\n\n\ndef shutdown_telemetry() -> None:\n    \"\"\"Flush pending spans/metrics and shut down providers.\"\"\"\n    if _provider is not None and hasattr(_provider, \"shutdown\"):\n        _provider.shutdown()\n    if _meter_provider is not None and hasattr(_meter_provider, \"shutdown\"):\n        _meter_provider.shutdown()\n\n\ndef _get_tracer():\n    global _tracer\n    if _tracer is None and _OTEL_AVAILABLE:\n        _tracer = trace.get_tracer(\"inference\")\n    return _tracer\n\n\nclass _ExportErrorFilter(logging.Filter):\n    \"\"\"Replace noisy OTel export tracebacks with a single-line warning.\n\n    The OTel SDK logs full connection-refused tracebacks every export cycle\n    when the collector is down. This filter catches those ERROR-level records,\n    logs a clean warning once, and suppresses duplicates.\n    \"\"\"\n\n    def __init__(self):\n        super().__init__()\n        self._warned = False\n\n    def filter(self, record: logging.LogRecord) -> bool:\n        if record.levelno >= logging.ERROR:\n            if not self._warned:\n                logger.warning(\n                    \"OTel exporter cannot reach collector \u2014 traces/metrics will be dropped \"\n                    \"until the collector is available.\"\n                )\n                self._warned = True\n            return False  # suppress the original noisy traceback\n        # Reset warning flag when exports succeed again (logged at DEBUG/INFO)\n        if self._warned and record.levelno <= logging.INFO:\n            self._warned = False\n        return True\n\n\ndef _install_export_error_filter(logger_name: str) -> None:\n    \"\"\"Attach the export error filter to an OTel SDK logger.\"\"\"\n    otel_logger = logging.getLogger(logger_name)\n    otel_logger.addFilter(_ExportErrorFilter())\n",
    "patch": null
  },
  {
    "trace_id": "8a3b97f7-1814-4488-834f-190e6ca93477",
    "function_name": "record_inference",
    "file_path": "inference/core/telemetry.py",
    "speedup_x": 0.21565895329182055,
    "review_quality": "high",
    "pre_optimization_commit": "3d23a0e028b2aba8cea9eaf037e6ebccad8cac97",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def record_inference(model_id: str, duration: float) -> None:\n    \"\"\"Record an inference execution.\"\"\"\n    if _metrics is None:\n        return\n    _metrics[\"model_infer_count\"].add(1, {\"model.id\": model_id})\n    _metrics[\"model_infer_duration\"].record(duration, {\"model.id\": model_id})\n",
    "optimized_function_code": "from typing import Any, Dict, Optional\n\n_metrics: Optional[Dict[str, Any]] = None\n\n_cached_metrics_methods: Optional[tuple] = None\n\n\ndef record_inference(model_id: str, duration: float) -> None:\n    \"\"\"Record an inference execution.\"\"\"\n    if _metrics is None:\n        return\n    \n    _cache = _cached_metrics_methods\n    if _cache is None or _cache[0] is not _metrics:\n        count_metric = _metrics[\"model_infer_count\"]\n        duration_metric = _metrics[\"model_infer_duration\"]\n        _cache = (_metrics, count_metric.add, duration_metric.record)\n        globals()[\"_cached_metrics_methods\"] = _cache\n    \n    _cache[1](1, {\"model.id\": model_id})\n    _cache[2](duration, {\"model.id\": model_id})",
    "optimized_raw_markdown": "```python:inference/core/telemetry.py\nfrom typing import Any, Dict, Optional\n\n_metrics: Optional[Dict[str, Any]] = None\n\n_cached_metrics_methods: Optional[tuple] = None\n\n\ndef record_inference(model_id: str, duration: float) -> None:\n    \"\"\"Record an inference execution.\"\"\"\n    if _metrics is None:\n        return\n    \n    _cache = _cached_metrics_methods\n    if _cache is None or _cache[0] is not _metrics:\n        count_metric = _metrics[\"model_infer_count\"]\n        duration_metric = _metrics[\"model_infer_duration\"]\n        _cache = (_metrics, count_metric.add, duration_metric.record)\n        globals()[\"_cached_metrics_methods\"] = _cache\n    \n    _cache[1](1, {\"model.id\": model_id})\n    _cache[2](duration, {\"model.id\": model_id})\n```",
    "optimized_function_only": "def record_inference(model_id: str, duration: float) -> None:\n    \"\"\"Record an inference execution.\"\"\"\n    if _metrics is None:\n        return\n    \n    _cache = _cached_metrics_methods\n    if _cache is None or _cache[0] is not _metrics:\n        count_metric = _metrics[\"model_infer_count\"]\n        duration_metric = _metrics[\"model_infer_duration\"]\n        _cache = (_metrics, count_metric.add, duration_metric.record)\n        globals()[\"_cached_metrics_methods\"] = _cache\n    \n    _cache[1](1, {\"model.id\": model_id})\n    _cache[2](duration, {\"model.id\": model_id})",
    "original_file_content": "\"\"\"OpenTelemetry tracing setup and helpers for the inference server.\n\nAll public helpers are safe to import and call even when opentelemetry is not\ninstalled \u2014 they degrade to noops.  Business-logic code should never need to\ncheck whether OTel is available.\n\nUsage::\n\n    from inference.core.telemetry import (\n        start_span, record_error, set_span_attribute,\n    )\n\n    with start_span(\"model.infer\", {\"model.id\": model_id}):\n        result = do_inference(...)\n        set_span_attribute(\"model.load_time_seconds\", elapsed)\n\n    record_error(error)\n\"\"\"\n\nimport contextvars\nimport logging\nfrom contextlib import contextmanager\nfrom typing import Any, Dict, Optional, Sequence\n\nlogger = logging.getLogger(\"inference\")\n\n# ---------------------------------------------------------------------------\n# Graceful opentelemetry imports \u2014 everything below is noop when not installed\n# ---------------------------------------------------------------------------\ntry:\n    from opentelemetry import trace\n    from opentelemetry.propagate import inject as _otel_inject\n    from opentelemetry.propagate import set_global_textmap\n    from opentelemetry.propagators.composite import CompositePropagator\n    from opentelemetry.trace import StatusCode\n    from opentelemetry.trace.propagation.tracecontext import (\n        TraceContextTextMapPropagator,\n    )\n\n    _OTEL_AVAILABLE = True\nexcept ImportError:\n    _OTEL_AVAILABLE = False\n\n_tracer = None\n_provider = None\n_meter_provider = None\n_metrics: Optional[Dict[str, Any]] = None\n\n# Header name for forcing a trace on a specific request.\nFORCE_TRACE_HEADER = b\"x-force-trace\"\n\n# ContextVar set by _ForceTraceASGIMiddleware, read by _ForceTraceRootSampler.\n# Per-request isolation is automatic in ASGI (each request runs in its own task).\n_force_trace_flag: contextvars.ContextVar[bool] = contextvars.ContextVar(\n    \"_force_trace_flag\", default=False\n)\n\n\n# ---------------------------------------------------------------------------\n# Public helpers \u2014 always safe to call\n# ---------------------------------------------------------------------------\n\n\n@contextmanager\ndef start_span(name: str, attributes: Optional[Dict[str, Any]] = None):\n    \"\"\"Start a new span as a child of the current context.\n\n    Yields the span (or None when OTel is not available).\n    \"\"\"\n    if not _OTEL_AVAILABLE:\n        yield None\n        return\n    tracer = _get_tracer()\n    with tracer.start_as_current_span(name, attributes=attributes) as span:\n        yield span\n\n\ndef record_error(error: Exception) -> None:\n    \"\"\"Record an exception on the current active span and set ERROR status.\n\n    Safe to call when OTel is not installed or there is no active span.\n    \"\"\"\n    if not _OTEL_AVAILABLE:\n        return\n    span = trace.get_current_span()\n    if span and span.is_recording():\n        span.record_exception(error)\n        span.set_status(StatusCode.ERROR, str(error))\n\n\ndef get_trace_id() -> Optional[str]:\n    \"\"\"Return the current trace ID as a hex string, or None.\"\"\"\n    if not _OTEL_AVAILABLE:\n        return None\n    span = trace.get_current_span()\n    ctx = span.get_span_context()\n    if ctx and ctx.trace_id:\n        return format(ctx.trace_id, \"032x\")\n    return None\n\n\ndef set_span_attribute(key: str, value: Any) -> None:\n    \"\"\"Set an attribute on the current active span.\n\n    Noop when OTel is unavailable or there is no recording span.\n    Callers never need to check for None spans.\n    \"\"\"\n    if not _OTEL_AVAILABLE:\n        return\n    span = trace.get_current_span()\n    if span and span.is_recording():\n        span.set_attribute(key, value)\n\n\ndef capture_context() -> Any:\n    \"\"\"Capture the current OTel context for propagation to another thread.\n\n    Returns an opaque token (or None). Pass to attach_context() in the target thread.\n    \"\"\"\n    if not _OTEL_AVAILABLE:\n        return None\n    from opentelemetry import context\n\n    return context.get_current()\n\n\ndef attach_context(ctx: Any) -> Any:\n    \"\"\"Attach a previously captured OTel context in the current thread.\n\n    Returns a token that MUST be passed to detach_context() when done.\n    \"\"\"\n    if ctx is None or not _OTEL_AVAILABLE:\n        return None\n    from opentelemetry import context\n\n    return context.attach(ctx)\n\n\ndef detach_context(token: Any) -> None:\n    \"\"\"Detach a previously attached context. Must be called in a finally block.\"\"\"\n    if token is None or not _OTEL_AVAILABLE:\n        return\n    from opentelemetry import context\n\n    context.detach(token)\n\n\ndef inject_trace_context(headers: dict) -> dict:\n    \"\"\"Inject W3C traceparent/tracestate into *headers* dict and return it.\n\n    Safe to call when OTel is not installed (returns headers unchanged).\n    \"\"\"\n    if not _OTEL_AVAILABLE:\n        return headers\n    if headers is None:\n        headers = {}\n    _otel_inject(headers)\n    return headers\n\n\ndef trace_context_log_processor(\n    logger_instance: Any, method_name: str, event_dict: Dict[str, Any]\n) -> Dict[str, Any]:\n    \"\"\"Structlog processor that injects trace_id and span_id into log entries.\"\"\"\n    if not _OTEL_AVAILABLE:\n        return event_dict\n    span = trace.get_current_span()\n    ctx = span.get_span_context()\n    if ctx and ctx.trace_id:\n        event_dict[\"trace_id\"] = format(ctx.trace_id, \"032x\")\n        event_dict[\"span_id\"] = format(ctx.span_id, \"016x\")\n    return event_dict\n\n\n# ---------------------------------------------------------------------------\n# Metrics helpers \u2014 always safe to call\n# ---------------------------------------------------------------------------\n\n\ndef record_model_loaded(model_id: str, load_time: float) -> None:\n    \"\"\"Record a model load event: increment counters and record load duration.\"\"\"\n    if _metrics is None:\n        return\n    _metrics[\"models_loaded\"].add(1)\n    _metrics[\"model_loads\"].add(1, {\"model.id\": model_id})\n    _metrics[\"model_load_duration\"].record(load_time, {\"model.id\": model_id})\n\n\ndef record_model_unloaded(model_id: str) -> None:\n    \"\"\"Record a model unload event.\"\"\"\n    if _metrics is None:\n        return\n    _metrics[\"models_loaded\"].add(-1)\n    _metrics[\"model_unloads\"].add(1, {\"model.id\": model_id})\n\n\ndef record_inference(model_id: str, duration: float) -> None:\n    \"\"\"Record an inference execution.\"\"\"\n    if _metrics is None:\n        return\n    _metrics[\"model_infer_count\"].add(1, {\"model.id\": model_id})\n    _metrics[\"model_infer_duration\"].record(duration, {\"model.id\": model_id})\n\n\ndef record_api_call(function_name: str, duration: float) -> None:\n    \"\"\"Record a Roboflow API call duration.\"\"\"\n    if _metrics is None:\n        return\n    _metrics[\"api_call_duration\"].record(\n        duration, {\"roboflow_api.function\": function_name}\n    )\n\n\ndef record_error_metric(error_type: str) -> None:\n    \"\"\"Increment the error counter by error type.\"\"\"\n    if _metrics is None:\n        return\n    _metrics[\"errors\"].add(1, {\"error.type\": error_type})\n\n\n# ---------------------------------------------------------------------------\n# Force-trace ASGI middleware + custom sampler\n# ---------------------------------------------------------------------------\n\n\nclass _ForceTraceASGIMiddleware:\n    \"\"\"Lightweight ASGI middleware that detects X-Force-Trace header.\n\n    Must wrap the app OUTSIDE the OTel instrumentor so the ContextVar is set\n    before the instrumentor's should_sample() call.  We achieve this by adding\n    it via app.add_middleware() AFTER FastAPIInstrumentor.instrument_app() \u2014\n    Starlette builds the middleware stack so the last-added middleware is\n    outermost.\n    \"\"\"\n\n    def __init__(self, app: Any) -> None:\n        self.app = app\n\n    async def __call__(self, scope: dict, receive: Any, send: Any) -> None:\n        if scope[\"type\"] == \"http\":\n            for header_name, header_value in scope.get(\"headers\", []):\n                if header_name == FORCE_TRACE_HEADER:\n                    if header_value.lower() == b\"true\":\n                        _force_trace_flag.set(True)\n                    break\n        try:\n            await self.app(scope, receive, send)\n        finally:\n            _force_trace_flag.set(False)\n\n\nclass _TraceIdResponseMiddleware:\n    \"\"\"Raw ASGI middleware that injects X-Trace-Id into response headers.\n\n    Must sit INSIDE the OTel instrumentor in the middleware stack so the span\n    context is available when the response is sent.  Added via\n    app.add_middleware() BEFORE FastAPIInstrumentor.instrument_app() \u2014\n    Starlette builds the stack so earlier-added middleware is innermost.\n\n    We use a raw ASGI middleware (not BaseHTTPMiddleware) because Starlette's\n    BaseHTTPMiddleware runs call_next in a separate task, which breaks\n    ContextVar propagation \u2014 get_trace_id() would return None.\n    \"\"\"\n\n    def __init__(self, app: Any) -> None:\n        self.app = app\n\n    async def __call__(self, scope: dict, receive: Any, send: Any) -> None:\n        if scope[\"type\"] != \"http\":\n            await self.app(scope, receive, send)\n            return\n\n        async def send_with_trace_id(message: dict) -> None:\n            if message[\"type\"] == \"http.response.start\":\n                trace_id = get_trace_id()\n                if trace_id:\n                    from inference.core.constants import TRACE_ID_HEADER\n\n                    headers = list(message.get(\"headers\", []))\n                    headers.append(\n                        (TRACE_ID_HEADER.lower().encode(), trace_id.encode())\n                    )\n                    message = {**message, \"headers\": headers}\n            await send(message)\n\n        await self.app(scope, receive, send_with_trace_id)\n\n\nclass _ForceTraceRootSampler:\n    \"\"\"Custom root sampler that force-samples when X-Force-Trace is set.\n\n    Used as the ``root`` argument to ParentBased:\n      - Parent exists  -> ParentBased honours the parent's decision (not us)\n      - No parent, X-Force-Trace: true -> always sample\n      - No parent, no header -> delegate to the ratio-based sampler\n    \"\"\"\n\n    def __init__(self, delegate: Any) -> None:\n        self._delegate = delegate\n\n    def should_sample(\n        self,\n        parent_context: Any,\n        trace_id: int,\n        name: str,\n        kind: Any = None,\n        attributes: Any = None,\n        links: Optional[Sequence[Any]] = None,\n        trace_state: Any = None,\n    ) -> Any:\n        if _force_trace_flag.get(False):\n            from opentelemetry.sdk.trace.sampling import Decision, SamplingResult\n\n            return SamplingResult(\n                decision=Decision.RECORD_AND_SAMPLE,\n                attributes={\"sampling.forced\": True},\n                trace_state=trace_state,\n            )\n        return self._delegate.should_sample(\n            parent_context, trace_id, name, kind, attributes, links, trace_state\n        )\n\n    def get_description(self) -> str:\n        return f\"ForceTraceRootSampler({self._delegate.get_description()})\"\n\n\n# ---------------------------------------------------------------------------\n# Setup / shutdown \u2014 called only when OTEL_TRACING_ENABLED is True\n# ---------------------------------------------------------------------------\n\n\ndef setup_telemetry(app: Any) -> None:\n    \"\"\"Initialize OTel TracerProvider, MeterProvider, and instrument the FastAPI app.\n\n    Must be called before any middleware is added so the FastAPI instrumentor\n    wraps at the outermost ASGI layer.\n    \"\"\"\n    global _provider, _tracer, _meter_provider, _metrics\n\n    from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import (\n        OTLPSpanExporter as GRPCExporter,\n    )\n    from opentelemetry.exporter.otlp.proto.http.trace_exporter import (\n        OTLPSpanExporter as HTTPExporter,\n    )\n    from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor\n    from opentelemetry.sdk.resources import Resource\n    from opentelemetry.sdk.trace import TracerProvider\n    from opentelemetry.sdk.trace.export import BatchSpanProcessor\n    from opentelemetry.sdk.trace.sampling import (\n        ALWAYS_OFF,\n        ALWAYS_ON,\n        ParentBased,\n        TraceIdRatioBased,\n    )\n\n    from inference.core.env import (\n        OTEL_EXPORTER_ENDPOINT,\n        OTEL_EXPORTER_PROTOCOL,\n        OTEL_METRIC_EXPORT_INTERVAL_MS,\n        OTEL_METRIC_EXPORTER_ENDPOINT,\n        OTEL_METRICS_ENABLED,\n        OTEL_SAMPLING_RATE,\n        OTEL_SERVICE_NAME,\n        OTEL_TRACE_EXPORT_INTERVAL_MS,\n    )\n\n    # W3C TraceContext propagator \u2014 always set so extract/inject are safe\n    set_global_textmap(CompositePropagator([TraceContextTextMapPropagator()]))\n\n    # Build root sampler with force-trace override\n    if OTEL_SAMPLING_RATE <= 0:\n        root_sampler = ALWAYS_OFF\n    elif OTEL_SAMPLING_RATE >= 1.0:\n        root_sampler = ALWAYS_ON\n    else:\n        root_sampler = TraceIdRatioBased(OTEL_SAMPLING_RATE)\n\n    # ParentBased: child spans honour parent decision, root spans use our\n    # custom sampler that checks for X-Force-Trace before falling back to\n    # the ratio-based sampler.\n    sampler = ParentBased(root=_ForceTraceRootSampler(root_sampler))\n\n    from inference.core.devices.utils import GLOBAL_INFERENCE_SERVER_ID\n\n    resource = Resource.create(\n        {\n            \"service.name\": OTEL_SERVICE_NAME,\n            \"service.instance.id\": GLOBAL_INFERENCE_SERVER_ID,\n        }\n    )\n\n    if OTEL_EXPORTER_PROTOCOL == \"http\":\n        exporter = HTTPExporter(\n            endpoint=f\"http://{OTEL_EXPORTER_ENDPOINT}/v1/traces\",\n        )\n    else:\n        exporter = GRPCExporter(\n            endpoint=OTEL_EXPORTER_ENDPOINT,\n            insecure=True,\n        )\n\n    _provider = TracerProvider(resource=resource, sampler=sampler)\n    _provider.add_span_processor(\n        BatchSpanProcessor(\n            exporter, schedule_delay_millis=OTEL_TRACE_EXPORT_INTERVAL_MS\n        )\n    )\n    trace.set_tracer_provider(_provider)\n\n    _tracer = trace.get_tracer(\"inference\")\n\n    # --- Metrics ---\n    if OTEL_METRICS_ENABLED:\n        from opentelemetry import metrics as otel_metrics\n        from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import (\n            OTLPMetricExporter as GRPCMetricExporter,\n        )\n        from opentelemetry.exporter.otlp.proto.http.metric_exporter import (\n            OTLPMetricExporter as HTTPMetricExporter,\n        )\n        from opentelemetry.sdk.metrics import MeterProvider\n        from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader\n\n        metric_endpoint = OTEL_METRIC_EXPORTER_ENDPOINT or OTEL_EXPORTER_ENDPOINT\n        if OTEL_EXPORTER_PROTOCOL == \"http\":\n            metric_exporter = HTTPMetricExporter(\n                endpoint=f\"http://{metric_endpoint}/v1/metrics\",\n            )\n        else:\n            metric_exporter = GRPCMetricExporter(\n                endpoint=metric_endpoint,\n                insecure=True,\n            )\n\n        metric_reader = PeriodicExportingMetricReader(\n            metric_exporter, export_interval_millis=OTEL_METRIC_EXPORT_INTERVAL_MS\n        )\n        _meter_provider = MeterProvider(\n            resource=resource, metric_readers=[metric_reader]\n        )\n        otel_metrics.set_meter_provider(_meter_provider)\n\n        meter = _meter_provider.get_meter(\"inference\")\n        _metrics = {\n            \"models_loaded\": meter.create_up_down_counter(\n                \"inference.models.loaded\",\n                description=\"Number of models currently loaded\",\n            ),\n            \"model_loads\": meter.create_counter(\n                \"inference.model.loads\",\n                description=\"Total model loads (cold starts)\",\n            ),\n            \"model_unloads\": meter.create_counter(\n                \"inference.model.unloads\",\n                description=\"Total model unloads\",\n            ),\n            \"model_load_duration\": meter.create_histogram(\n                \"inference.model.load.duration\",\n                unit=\"s\",\n                description=\"Model load time in seconds\",\n            ),\n            \"model_infer_count\": meter.create_counter(\n                \"inference.model.infer.count\",\n                description=\"Total inference requests\",\n            ),\n            \"model_infer_duration\": meter.create_histogram(\n                \"inference.model.infer.duration\",\n                unit=\"s\",\n                description=\"Inference latency in seconds\",\n            ),\n            \"api_call_duration\": meter.create_histogram(\n                \"inference.roboflow_api.duration\",\n                unit=\"s\",\n                description=\"Roboflow API call latency in seconds\",\n            ),\n            \"errors\": meter.create_counter(\n                \"inference.errors\",\n                description=\"Total errors by type\",\n            ),\n        }\n        _install_export_error_filter(\"opentelemetry.sdk.metrics._internal.export\")\n\n    # Replace noisy connection-refused tracebacks with a single-line warning.\n    _install_export_error_filter(\"opentelemetry.sdk.trace.export\")\n\n    # Add trace-ID response middleware BEFORE the instrumentor so it sits\n    # INSIDE the OTel span context (earlier-added = innermost in Starlette).\n    app.add_middleware(_TraceIdResponseMiddleware)\n\n    # Auto-instrument FastAPI: creates server spans, extracts traceparent\n    FastAPIInstrumentor.instrument_app(app)\n\n    # Auto-instrument outgoing requests: creates http.client spans, injects traceparent\n    from opentelemetry.instrumentation.requests import RequestsInstrumentor\n\n    RequestsInstrumentor().instrument()\n\n    # Add force-trace middleware AFTER the instrumentor so it wraps outermost.\n    # Starlette builds middleware last-added = outermost, so this runs BEFORE\n    # the instrumentor's ASGI middleware, ensuring the ContextVar is set\n    # before should_sample() is called.\n    app.add_middleware(_ForceTraceASGIMiddleware)\n\n    logger.info(\n        \"OpenTelemetry tracing enabled (service=%s, endpoint=%s, protocol=%s, sampling_rate=%s)\",\n        OTEL_SERVICE_NAME,\n        OTEL_EXPORTER_ENDPOINT,\n        OTEL_EXPORTER_PROTOCOL,\n        OTEL_SAMPLING_RATE,\n    )\n\n\ndef shutdown_telemetry() -> None:\n    \"\"\"Flush pending spans/metrics and shut down providers.\"\"\"\n    if _provider is not None and hasattr(_provider, \"shutdown\"):\n        _provider.shutdown()\n    if _meter_provider is not None and hasattr(_meter_provider, \"shutdown\"):\n        _meter_provider.shutdown()\n\n\ndef _get_tracer():\n    global _tracer\n    if _tracer is None and _OTEL_AVAILABLE:\n        _tracer = trace.get_tracer(\"inference\")\n    return _tracer\n\n\nclass _ExportErrorFilter(logging.Filter):\n    \"\"\"Replace noisy OTel export tracebacks with a single-line warning.\n\n    The OTel SDK logs full connection-refused tracebacks every export cycle\n    when the collector is down. This filter catches those ERROR-level records,\n    logs a clean warning once, and suppresses duplicates.\n    \"\"\"\n\n    def __init__(self):\n        super().__init__()\n        self._warned = False\n\n    def filter(self, record: logging.LogRecord) -> bool:\n        if record.levelno >= logging.ERROR:\n            if not self._warned:\n                logger.warning(\n                    \"OTel exporter cannot reach collector \u2014 traces/metrics will be dropped \"\n                    \"until the collector is available.\"\n                )\n                self._warned = True\n            return False  # suppress the original noisy traceback\n        # Reset warning flag when exports succeed again (logged at DEBUG/INFO)\n        if self._warned and record.levelno <= logging.INFO:\n            self._warned = False\n        return True\n\n\ndef _install_export_error_filter(logger_name: str) -> None:\n    \"\"\"Attach the export error filter to an OTel SDK logger.\"\"\"\n    otel_logger = logging.getLogger(logger_name)\n    otel_logger.addFilter(_ExportErrorFilter())\n",
    "patch": null
  },
  {
    "trace_id": "79b061b7-947c-4157-9cfc-d10e7834a2ee",
    "function_name": "ByteTrackManifest.describe_outputs",
    "file_path": "inference/core/workflows/core_steps/trackers/bytetrack/v1.py",
    "speedup_x": 16.55902700156185,
    "review_quality": "high",
    "pre_optimization_commit": "e450f9a7e8851dc08333f7482154a8d1fc688955",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def describe_outputs(cls) -> List[OutputDefinition]:\n        return tracker_describe_outputs()\n",
    "optimized_function_code": "from typing import List\n\nfrom inference.core.workflows.execution_engine.entities.base import \\\n    OutputDefinition\nfrom inference.core.workflows.execution_engine.entities.types import \\\n    OBJECT_DETECTION_PREDICTION_KIND\n\nOUTPUT_KEY: str = \"tracked_detections\"\n\n\n\n_cached_outputs = None\n\n\ndef tracker_describe_outputs() -> List[OutputDefinition]:\n    \"\"\"Output definitions shared by all tracker blocks.\"\"\"\n    global _cached_outputs\n    if _cached_outputs is None:\n        _cached_outputs = [\n            OutputDefinition(name=OUTPUT_KEY, kind=[OBJECT_DETECTION_PREDICTION_KIND]),\n            OutputDefinition(name=\"new_instances\", kind=[OBJECT_DETECTION_PREDICTION_KIND]),\n            OutputDefinition(\n                name=\"already_seen_instances\",\n                kind=[OBJECT_DETECTION_PREDICTION_KIND],\n            ),\n        ]\n    return _cached_outputs",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/trackers/_base.py\nfrom typing import List\n\nfrom inference.core.workflows.execution_engine.entities.base import \\\n    OutputDefinition\nfrom inference.core.workflows.execution_engine.entities.types import \\\n    OBJECT_DETECTION_PREDICTION_KIND\n\nOUTPUT_KEY: str = \"tracked_detections\"\n\n\n\n_cached_outputs = None\n\n\ndef tracker_describe_outputs() -> List[OutputDefinition]:\n    \"\"\"Output definitions shared by all tracker blocks.\"\"\"\n    global _cached_outputs\n    if _cached_outputs is None:\n        _cached_outputs = [\n            OutputDefinition(name=OUTPUT_KEY, kind=[OBJECT_DETECTION_PREDICTION_KIND]),\n            OutputDefinition(name=\"new_instances\", kind=[OBJECT_DETECTION_PREDICTION_KIND]),\n            OutputDefinition(\n                name=\"already_seen_instances\",\n                kind=[OBJECT_DETECTION_PREDICTION_KIND],\n            ),\n        ]\n    return _cached_outputs\n```",
    "optimized_function_only": null,
    "original_file_content": "from typing import Any, List, Literal, Optional, Type, Union\n\nimport supervision as sv\nfrom pydantic import ConfigDict, Field\nfrom trackers import ByteTrackTracker\n\nfrom inference.core.workflows.core_steps.trackers._base import (\n    TrackerBlockBase,\n    tracker_describe_outputs,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    FLOAT_ZERO_TO_ONE_KIND,\n    IMAGE_KIND,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    INTEGER_KIND,\n    KEYPOINT_DETECTION_PREDICTION_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import BlockResult, WorkflowBlockManifest\n\nDEFAULT_LOST_TRACK_BUFFER = 30\nDEFAULT_TRACK_ACTIVATION_THRESHOLD = 0.7\nDEFAULT_MINIMUM_CONSECUTIVE_FRAMES = 2\nDEFAULT_MINIMUM_IOU_THRESHOLD = 0.1\nDEFAULT_HIGH_CONF_DET_THRESHOLD = 0.6\nDEFAULT_INSTANCES_CACHE_SIZE = 16384\n\nSHORT_DESCRIPTION = \"Tracks objects across frames. Best for most scenes.\"\nLONG_DESCRIPTION = \"\"\"\nTrack objects across video frames using the **ByteTrack** algorithm from the\nroboflow/trackers package.\n\nByteTrack splits detections into high- and low-confidence pools and runs two\nrounds of IoU-based association.  The first round matches high-confidence\ndetections to existing tracks; the second recovers weak detections that overlap\nunmatched tracks.  This makes ByteTrack particularly effective in **dense\nenvironments** where objects are frequently partially occluded and detector\nconfidence fluctuates.\n\n**When to use ByteTrack:**\n- General-purpose tracking across diverse scenes.\n- Dense or crowded environments with partial occlusions.\n- Sports tracking and fast-moving objects (highest benchmark scores on SportsMOT).\n- When your detector produces a mix of high- and low-confidence detections that\n  you want to retain.\n\n**When to consider alternatives:**\n- For maximum simplicity and speed with a strong detector, use **SORT**.\n- For scenes with heavy occlusion and non-linear motion, use **OC-SORT**.\n\nOutputs three detection sets:\n- **tracked_detections**: All confirmed tracked detections with assigned track IDs.\n- **new_instances**: Detections whose track ID appears for the first time.\n- **already_seen_instances**: Detections whose track ID has been seen in a prior frame.\n\nThe block maintains separate tracker state and instance cache per `video_identifier`,\nenabling multi-stream tracking within a single workflow.\n\"\"\"\n\n\nclass ByteTrackManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"ByteTrack Tracker\",\n            \"version\": \"v1\",\n            \"short_description\": SHORT_DESCRIPTION,\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"transformation\",\n            \"ui_manifest\": {\n                \"section\": \"video\",\n                \"icon\": \"far fa-location-crosshairs\",\n                \"blockPriority\": 0,\n                \"trackers\": True,\n            },\n        },\n        protected_namespaces=(),\n    )\n    type: Literal[\"roboflow_core/trackers_bytetrack@v1\"]\n    image: Selector(kind=[IMAGE_KIND]) = Field(\n        description=\"Input image with embedded video metadata (fps and video_identifier). \"\n        \"Used to initialise and retrieve per-video tracker state.\",\n    )\n    detections: Selector(\n        kind=[\n            OBJECT_DETECTION_PREDICTION_KIND,\n            KEYPOINT_DETECTION_PREDICTION_KIND,\n            INSTANCE_SEGMENTATION_PREDICTION_KIND,\n        ]\n    ) = Field(\n        description=\"Detection predictions for the current frame to track.\",\n        examples=[\"$steps.object_detection_model.predictions\"],\n    )\n    minimum_iou_threshold: Union[\n        Optional[float], Selector(kind=[FLOAT_ZERO_TO_ONE_KIND])\n    ] = Field(\n        default=DEFAULT_MINIMUM_IOU_THRESHOLD,\n        description=\"Minimum IoU required to associate a detection with an existing track. \"\n        f\"Default: {DEFAULT_MINIMUM_IOU_THRESHOLD}.\",\n        examples=[DEFAULT_MINIMUM_IOU_THRESHOLD, \"$inputs.minimum_iou_threshold\"],\n        json_schema_extra={\n            \"always_visible\": True,\n        },\n    )\n    minimum_consecutive_frames: Union[Optional[int], Selector(kind=[INTEGER_KIND])] = (\n        Field(\n            default=DEFAULT_MINIMUM_CONSECUTIVE_FRAMES,\n            description=\"Number of consecutive frames a track must be matched before it is \"\n            f\"emitted as a confirmed track (tracker_id != -1). Default: {DEFAULT_MINIMUM_CONSECUTIVE_FRAMES}.\",\n            examples=[\n                DEFAULT_MINIMUM_CONSECUTIVE_FRAMES,\n                \"$inputs.minimum_consecutive_frames\",\n            ],\n            json_schema_extra={\n                \"always_visible\": True,\n            },\n        )\n    )\n    lost_track_buffer: Union[Optional[int], Selector(kind=[INTEGER_KIND])] = Field(\n        default=DEFAULT_LOST_TRACK_BUFFER,\n        description=\"Number of frames to keep a track alive after it loses its matched \"\n        f\"detection. Higher values improve occlusion recovery. Default: {DEFAULT_LOST_TRACK_BUFFER}.\",\n        examples=[DEFAULT_LOST_TRACK_BUFFER, \"$inputs.lost_track_buffer\"],\n        json_schema_extra={\n            \"always_visible\": True,\n        },\n    )\n    track_activation_threshold: Union[\n        Optional[float], Selector(kind=[FLOAT_ZERO_TO_ONE_KIND])\n    ] = Field(\n        default=DEFAULT_TRACK_ACTIVATION_THRESHOLD,\n        description=\"Minimum detection confidence required to spawn a new track. \"\n        f\"Detections below this threshold are not used to create new tracks. Default: {DEFAULT_TRACK_ACTIVATION_THRESHOLD}.\",\n        examples=[\n            DEFAULT_TRACK_ACTIVATION_THRESHOLD,\n            \"$inputs.track_activation_threshold\",\n        ],\n    )\n    high_conf_det_threshold: Union[\n        Optional[float], Selector(kind=[FLOAT_ZERO_TO_ONE_KIND])\n    ] = Field(\n        default=DEFAULT_HIGH_CONF_DET_THRESHOLD,\n        description=\"Confidence threshold for high-confidence detections used in \"\n        f\"association. Default: {DEFAULT_HIGH_CONF_DET_THRESHOLD}.\",\n        examples=[DEFAULT_HIGH_CONF_DET_THRESHOLD, \"$inputs.high_conf_det_threshold\"],\n    )\n    instances_cache_size: int = Field(\n        default=DEFAULT_INSTANCES_CACHE_SIZE,\n        description=\"Maximum number of track IDs retained in the instance cache for \"\n        f\"new/already-seen categorisation. Uses FIFO eviction. Default: {DEFAULT_INSTANCES_CACHE_SIZE}.\",\n    )\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return tracker_describe_outputs()\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass ByteTrackBlockV1(TrackerBlockBase):\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return ByteTrackManifest\n\n    def _create_tracker(self, fps: int, **kwargs: Any) -> Any:\n        return ByteTrackTracker(\n            lost_track_buffer=kwargs[\"lost_track_buffer\"],\n            frame_rate=fps,\n            track_activation_threshold=kwargs[\"track_activation_threshold\"],\n            minimum_consecutive_frames=kwargs[\"minimum_consecutive_frames\"],\n            minimum_iou_threshold=kwargs[\"minimum_iou_threshold\"],\n            high_conf_det_threshold=kwargs[\"high_conf_det_threshold\"],\n        )\n\n    def run(\n        self,\n        image: WorkflowImageData,\n        detections: sv.Detections,\n        lost_track_buffer: int = DEFAULT_LOST_TRACK_BUFFER,\n        minimum_iou_threshold: float = DEFAULT_MINIMUM_IOU_THRESHOLD,\n        minimum_consecutive_frames: int = DEFAULT_MINIMUM_CONSECUTIVE_FRAMES,\n        instances_cache_size: int = DEFAULT_INSTANCES_CACHE_SIZE,\n        track_activation_threshold: float = DEFAULT_TRACK_ACTIVATION_THRESHOLD,\n        high_conf_det_threshold: float = DEFAULT_HIGH_CONF_DET_THRESHOLD,\n    ) -> BlockResult:\n        return self._run_tracker(\n            image=image,\n            detections=detections,\n            instances_cache_size=instances_cache_size,\n            lost_track_buffer=lost_track_buffer,\n            minimum_iou_threshold=minimum_iou_threshold,\n            minimum_consecutive_frames=minimum_consecutive_frames,\n            track_activation_threshold=track_activation_threshold,\n            high_conf_det_threshold=high_conf_det_threshold,\n        )\n",
    "patch": null
  },
  {
    "trace_id": "71ecf111-ef2d-481f-9c46-1e1fe38f85c8",
    "function_name": "SORTBlockV1.run",
    "file_path": "inference/core/workflows/core_steps/trackers/sort/v1.py",
    "speedup_x": 1.0651544389083694,
    "review_quality": "high",
    "pre_optimization_commit": "HEAD",
    "resolution_method": "db_code_only",
    "source": "db_features",
    "original_function_code": "    def run(\n        self,\n        image: WorkflowImageData,\n        detections: sv.Detections,\n        lost_track_buffer: int = 30,\n        minimum_iou_threshold: float = 0.3,\n        minimum_consecutive_frames: int = 3,\n        instances_cache_size: int = 16384,\n        track_activation_threshold: float = 0.25,\n    ) -> BlockResult:\n        return self._run_tracker(\n            image=image,\n            detections=detections,\n            instances_cache_size=instances_cache_size,\n            lost_track_buffer=lost_track_buffer,\n            minimum_iou_threshold=minimum_iou_threshold,\n            minimum_consecutive_frames=minimum_consecutive_frames,\n            track_activation_threshold=track_activation_threshold,\n        )",
    "optimized_function_code": "import supervision as sv\nfrom collections import deque\nfrom inference.core import logger\nfrom inference.core.workflows.execution_engine.entities.base import WorkflowImageData\nfrom inference.core.workflows.prototypes.block import BlockResult, WorkflowBlock\nfrom typing import Any, Dict\n\nOUTPUT_KEY: str = \"tracked_detections\"\n\n\nclass InstanceCache:\n    \"\"\"FIFO cache that tracks which object track IDs have been seen before.\n\n    Used to categorize tracked detections as new (first appearance) or\n    already seen (reappearance) across video frames.\n    \"\"\"\n\n    def __init__(self, size: int):\n        size = max(1, size)\n        self._cache_inserts_track = deque(maxlen=size)\n        self._cache = set()\n\n    def record_instance(self, tracker_id: int) -> bool:\n        \"\"\"Record a tracker ID and return whether it was previously seen.\n\n        Returns:\n            True if the tracker_id was already in the cache (seen before),\n            False if this is its first appearance.\n        \"\"\"\n        in_cache = tracker_id in self._cache\n        if not in_cache:\n            self._cache_new_tracker_id(tracker_id=tracker_id)\n        return in_cache\n\n    def _cache_new_tracker_id(self, tracker_id: int) -> None:\n        while len(self._cache) >= self._cache_inserts_track.maxlen:\n            to_drop = self._cache_inserts_track.popleft()\n            self._cache.remove(to_drop)\n        self._cache_inserts_track.append(tracker_id)\n        self._cache.add(tracker_id)\n\n\nclass TrackerBlockBase(WorkflowBlock):\n\n    def __init__(self) -> None:\n        self._trackers: Dict[str, Any] = {}\n        self._per_video_cache: Dict[str, InstanceCache] = {}\n\n    def _run_tracker(\n        self,\n        image: WorkflowImageData,\n        detections: sv.Detections,\n        instances_cache_size: int = 16384,\n        **tracker_kwargs: Any,\n    ) -> BlockResult:\n        metadata = image.video_metadata\n        fps = metadata.fps\n        if not fps:\n            fps = 30\n            logger.warning(\n                f\"fps not available in VideoMetadata for {self.__class__.__name__}, \"\n                \"defaulting to 30 fps for tracker initialisation\"\n            )\n        video_id = metadata.video_identifier\n\n        if video_id not in self._trackers:\n            self._trackers[video_id] = self._create_tracker(fps=fps, **tracker_kwargs)\n\n        tracker = self._trackers[video_id]\n        if isinstance(detections, sv.Detections):\n            merged = detections\n        else:\n            merged = sv.Detections.merge(detections[i] for i in range(len(detections)))\n        tracked_detections = tracker.update(merged)\n\n        # Filter out immature / unmatched tracks (tracker_id == -1)\n        if tracked_detections.tracker_id is not None and len(tracked_detections) > 0:\n            valid_mask = tracked_detections.tracker_id != -1\n            tracked_detections = tracked_detections[valid_mask]\n\n        if video_id not in self._per_video_cache:\n            self._per_video_cache[video_id] = InstanceCache(size=instances_cache_size)\n        cache = self._per_video_cache[video_id]\n\n        not_seen_mask, seen_mask = [], []\n        for tracker_id in tracked_detections.tracker_id.tolist():\n            already_seen = cache.record_instance(tracker_id=tracker_id)\n            not_seen_mask.append(not already_seen)\n            seen_mask.append(already_seen)\n\n        return {\n            OUTPUT_KEY: tracked_detections,\n            \"new_instances\": tracked_detections[not_seen_mask],\n            \"already_seen_instances\": tracked_detections[seen_mask],\n        }",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/trackers/_base.py\nimport supervision as sv\nfrom collections import deque\nfrom inference.core import logger\nfrom inference.core.workflows.execution_engine.entities.base import WorkflowImageData\nfrom inference.core.workflows.prototypes.block import BlockResult, WorkflowBlock\nfrom typing import Any, Dict\n\nOUTPUT_KEY: str = \"tracked_detections\"\n\n\nclass InstanceCache:\n    \"\"\"FIFO cache that tracks which object track IDs have been seen before.\n\n    Used to categorize tracked detections as new (first appearance) or\n    already seen (reappearance) across video frames.\n    \"\"\"\n\n    def __init__(self, size: int):\n        size = max(1, size)\n        self._cache_inserts_track = deque(maxlen=size)\n        self._cache = set()\n\n    def record_instance(self, tracker_id: int) -> bool:\n        \"\"\"Record a tracker ID and return whether it was previously seen.\n\n        Returns:\n            True if the tracker_id was already in the cache (seen before),\n            False if this is its first appearance.\n        \"\"\"\n        in_cache = tracker_id in self._cache\n        if not in_cache:\n            self._cache_new_tracker_id(tracker_id=tracker_id)\n        return in_cache\n\n    def _cache_new_tracker_id(self, tracker_id: int) -> None:\n        while len(self._cache) >= self._cache_inserts_track.maxlen:\n            to_drop = self._cache_inserts_track.popleft()\n            self._cache.remove(to_drop)\n        self._cache_inserts_track.append(tracker_id)\n        self._cache.add(tracker_id)\n\n\nclass TrackerBlockBase(WorkflowBlock):\n\n    def __init__(self) -> None:\n        self._trackers: Dict[str, Any] = {}\n        self._per_video_cache: Dict[str, InstanceCache] = {}\n\n    def _run_tracker(\n        self,\n        image: WorkflowImageData,\n        detections: sv.Detections,\n        instances_cache_size: int = 16384,\n        **tracker_kwargs: Any,\n    ) -> BlockResult:\n        metadata = image.video_metadata\n        fps = metadata.fps\n        if not fps:\n            fps = 30\n            logger.warning(\n                f\"fps not available in VideoMetadata for {self.__class__.__name__}, \"\n                \"defaulting to 30 fps for tracker initialisation\"\n            )\n        video_id = metadata.video_identifier\n\n        if video_id not in self._trackers:\n            self._trackers[video_id] = self._create_tracker(fps=fps, **tracker_kwargs)\n\n        tracker = self._trackers[video_id]\n        if isinstance(detections, sv.Detections):\n            merged = detections\n        else:\n            merged = sv.Detections.merge(detections[i] for i in range(len(detections)))\n        tracked_detections = tracker.update(merged)\n\n        # Filter out immature / unmatched tracks (tracker_id == -1)\n        if tracked_detections.tracker_id is not None and len(tracked_detections) > 0:\n            valid_mask = tracked_detections.tracker_id != -1\n            tracked_detections = tracked_detections[valid_mask]\n\n        if video_id not in self._per_video_cache:\n            self._per_video_cache[video_id] = InstanceCache(size=instances_cache_size)\n        cache = self._per_video_cache[video_id]\n\n        not_seen_mask, seen_mask = [], []\n        for tracker_id in tracked_detections.tracker_id.tolist():\n            already_seen = cache.record_instance(tracker_id=tracker_id)\n            not_seen_mask.append(not already_seen)\n            seen_mask.append(already_seen)\n\n        return {\n            OUTPUT_KEY: tracked_detections,\n            \"new_instances\": tracked_detections[not_seen_mask],\n            \"already_seen_instances\": tracked_detections[seen_mask],\n        }\n```",
    "optimized_function_only": null,
    "original_file_content": "import supervision as sv\nfrom inference.core.workflows.core_steps.trackers._base import TrackerBlockBase\nfrom inference.core.workflows.execution_engine.entities.base import WorkflowImageData\nfrom inference.core.workflows.prototypes.block import BlockResult\n\nclass SORTBlockV1(TrackerBlockBase):\n\n    def run(\n        self,\n        image: WorkflowImageData,\n        detections: sv.Detections,\n        lost_track_buffer: int = 30,\n        minimum_iou_threshold: float = 0.3,\n        minimum_consecutive_frames: int = 3,\n        instances_cache_size: int = 16384,\n        track_activation_threshold: float = 0.25,\n    ) -> BlockResult:\n        return self._run_tracker(\n            image=image,\n            detections=detections,\n            instances_cache_size=instances_cache_size,\n            lost_track_buffer=lost_track_buffer,\n            minimum_iou_threshold=minimum_iou_threshold,\n            minimum_consecutive_frames=minimum_consecutive_frames,\n            track_activation_threshold=track_activation_threshold,\n        )",
    "patch": null
  },
  {
    "trace_id": "e0b0f41e-67e9-466d-be0b-33967c943ee4",
    "function_name": "InstanceCache.record_instance",
    "file_path": "inference/core/workflows/core_steps/trackers/_base.py",
    "speedup_x": 0.13747348974936976,
    "review_quality": "high",
    "pre_optimization_commit": "e450f9a7e8851dc08333f7482154a8d1fc688955",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def record_instance(self, tracker_id: int) -> bool:\n        \"\"\"Record a tracker ID and return whether it was previously seen.\n\n        Returns:\n            True if the tracker_id was already in the cache (seen before),\n            False if this is its first appearance.\n        \"\"\"\n        in_cache = tracker_id in self._cache\n        if not in_cache:\n            self._cache_new_tracker_id(tracker_id=tracker_id)\n        return in_cache\n",
    "optimized_function_code": "from collections import deque\n\n\nclass InstanceCache:\n\n    def __init__(self, size: int):\n        size = max(1, size)\n        self._cache_inserts_track = deque(maxlen=size)\n        self._cache = set()\n\n    def record_instance(self, tracker_id: int) -> bool:\n        \"\"\"Record a tracker ID and return whether it was previously seen.\n\n        Returns:\n            True if the tracker_id was already in the cache (seen before),\n            False if this is its first appearance.\n        \"\"\"\n        in_cache = tracker_id in self._cache\n        if not in_cache:\n            if len(self._cache) >= self._cache_inserts_track.maxlen:\n                to_drop = self._cache_inserts_track.popleft()\n                self._cache.remove(to_drop)\n            self._cache_inserts_track.append(tracker_id)\n            self._cache.add(tracker_id)\n        return in_cache",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/trackers/_base.py\nfrom collections import deque\n\n\nclass InstanceCache:\n\n    def __init__(self, size: int):\n        size = max(1, size)\n        self._cache_inserts_track = deque(maxlen=size)\n        self._cache = set()\n\n    def record_instance(self, tracker_id: int) -> bool:\n        \"\"\"Record a tracker ID and return whether it was previously seen.\n\n        Returns:\n            True if the tracker_id was already in the cache (seen before),\n            False if this is its first appearance.\n        \"\"\"\n        in_cache = tracker_id in self._cache\n        if not in_cache:\n            if len(self._cache) >= self._cache_inserts_track.maxlen:\n                to_drop = self._cache_inserts_track.popleft()\n                self._cache.remove(to_drop)\n            self._cache_inserts_track.append(tracker_id)\n            self._cache.add(tracker_id)\n        return in_cache\n```",
    "optimized_function_only": "    def record_instance(self, tracker_id: int) -> bool:\n        \"\"\"Record a tracker ID and return whether it was previously seen.\n\n        Returns:\n            True if the tracker_id was already in the cache (seen before),\n            False if this is its first appearance.\n        \"\"\"\n        in_cache = tracker_id in self._cache\n        if not in_cache:\n            if len(self._cache) >= self._cache_inserts_track.maxlen:\n                to_drop = self._cache_inserts_track.popleft()\n                self._cache.remove(to_drop)\n            self._cache_inserts_track.append(tracker_id)\n            self._cache.add(tracker_id)\n        return in_cache",
    "original_file_content": "\"\"\"Shared base classes for tracker workflow blocks.\n\nEach concrete tracker block (ByteTrack, SORT, OC-SORT) inherits from\n``TrackerBlockBase`` and only needs to implement ``_create_tracker`` and\n``get_manifest``.\n\"\"\"\n\nfrom abc import abstractmethod\nfrom collections import deque\nfrom typing import Any, Dict, List, Optional, Type\n\nimport supervision as sv\n\nfrom inference.core import logger\nfrom inference.core.workflows.execution_engine.entities.base import (\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    OBJECT_DETECTION_PREDICTION_KIND,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nOUTPUT_KEY: str = \"tracked_detections\"\n\n\nclass InstanceCache:\n    \"\"\"FIFO cache that tracks which object track IDs have been seen before.\n\n    Used to categorize tracked detections as new (first appearance) or\n    already seen (reappearance) across video frames.\n    \"\"\"\n\n    def __init__(self, size: int):\n        size = max(1, size)\n        self._cache_inserts_track = deque(maxlen=size)\n        self._cache = set()\n\n    def record_instance(self, tracker_id: int) -> bool:\n        \"\"\"Record a tracker ID and return whether it was previously seen.\n\n        Returns:\n            True if the tracker_id was already in the cache (seen before),\n            False if this is its first appearance.\n        \"\"\"\n        in_cache = tracker_id in self._cache\n        if not in_cache:\n            self._cache_new_tracker_id(tracker_id=tracker_id)\n        return in_cache\n\n    def _cache_new_tracker_id(self, tracker_id: int) -> None:\n        while len(self._cache) >= self._cache_inserts_track.maxlen:\n            to_drop = self._cache_inserts_track.popleft()\n            self._cache.remove(to_drop)\n        self._cache_inserts_track.append(tracker_id)\n        self._cache.add(tracker_id)\n\n\nclass TrackerBlockBase(WorkflowBlock):\n    \"\"\"Common run-loop shared by every tracker block.\n\n    Sub-classes only need to override ``_create_tracker`` and ``get_manifest``.\n    \"\"\"\n\n    def __init__(self) -> None:\n        self._trackers: Dict[str, Any] = {}\n        self._per_video_cache: Dict[str, InstanceCache] = {}\n\n    @classmethod\n    @abstractmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]: ...\n\n    @abstractmethod\n    def _create_tracker(self, fps: int, **kwargs: Any) -> Any:\n        \"\"\"Instantiate the concrete tracker with algorithm-specific params.\"\"\"\n        ...\n\n    def _run_tracker(\n        self,\n        image: WorkflowImageData,\n        detections: sv.Detections,\n        instances_cache_size: int,\n        **tracker_kwargs: Any,\n    ) -> BlockResult:\n        \"\"\"Run one frame through the tracker.\n\n        Note: tracker parameters (``tracker_kwargs``) are only used when the\n        tracker is **first created** for a given ``video_identifier``.\n        Changing parameter values on subsequent frames has no effect because\n        the tracker instance is cached for the lifetime of the video stream.\n        \"\"\"\n        metadata = image.video_metadata\n        fps = metadata.fps\n        if not fps:\n            fps = 30\n            logger.warning(\n                f\"fps not available in VideoMetadata for {self.__class__.__name__}, \"\n                \"defaulting to 30 fps for tracker initialisation\"\n            )\n        video_id = metadata.video_identifier\n\n        if video_id not in self._trackers:\n            self._trackers[video_id] = self._create_tracker(fps=fps, **tracker_kwargs)\n\n        tracker = self._trackers[video_id]\n        tracked_detections = tracker.update(detections)\n\n        # Filter out immature / unmatched tracks (tracker_id == -1)\n        if tracked_detections.tracker_id is not None and len(tracked_detections) > 0:\n            valid_mask = tracked_detections.tracker_id != -1\n            tracked_detections = tracked_detections[valid_mask]\n\n        if video_id not in self._per_video_cache:\n            self._per_video_cache[video_id] = InstanceCache(size=instances_cache_size)\n        cache = self._per_video_cache[video_id]\n\n        not_seen_mask, seen_mask = [], []\n        for tracker_id in tracked_detections.tracker_id.tolist():\n            already_seen = cache.record_instance(tracker_id=tracker_id)\n            not_seen_mask.append(not already_seen)\n            seen_mask.append(already_seen)\n\n        return {\n            OUTPUT_KEY: tracked_detections,\n            \"new_instances\": tracked_detections[not_seen_mask],\n            \"already_seen_instances\": tracked_detections[seen_mask],\n        }\n\n\ndef tracker_describe_outputs() -> List[OutputDefinition]:\n    \"\"\"Output definitions shared by all tracker blocks.\"\"\"\n    return [\n        OutputDefinition(name=OUTPUT_KEY, kind=[OBJECT_DETECTION_PREDICTION_KIND]),\n        OutputDefinition(name=\"new_instances\", kind=[OBJECT_DETECTION_PREDICTION_KIND]),\n        OutputDefinition(\n            name=\"already_seen_instances\",\n            kind=[OBJECT_DETECTION_PREDICTION_KIND],\n        ),\n    ]\n",
    "patch": null
  },
  {
    "trace_id": "fe604e77-00aa-41bd-b347-08581321b2de",
    "function_name": "SORTManifest.describe_outputs",
    "file_path": "inference/core/workflows/core_steps/trackers/sort/v1.py",
    "speedup_x": 16.15681975348376,
    "review_quality": "high",
    "pre_optimization_commit": "e450f9a7e8851dc08333f7482154a8d1fc688955",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def describe_outputs(cls) -> List[OutputDefinition]:\n        return tracker_describe_outputs()\n",
    "optimized_function_code": "from functools import lru_cache\nfrom inference.core.workflows.execution_engine.entities.base import OutputDefinition\nfrom inference.core.workflows.execution_engine.entities.types import OBJECT_DETECTION_PREDICTION_KIND\nfrom typing import List\n\nOUTPUT_KEY: str = \"tracked_detections\"\n\n\n@lru_cache(maxsize=1)\ndef tracker_describe_outputs() -> List[OutputDefinition]:\n    \"\"\"Output definitions shared by all tracker blocks.\"\"\"\n    return [\n        OutputDefinition(name=OUTPUT_KEY, kind=[OBJECT_DETECTION_PREDICTION_KIND]),\n        OutputDefinition(name=\"new_instances\", kind=[OBJECT_DETECTION_PREDICTION_KIND]),\n        OutputDefinition(\n            name=\"already_seen_instances\",\n            kind=[OBJECT_DETECTION_PREDICTION_KIND],\n        ),\n    ]",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/trackers/_base.py\nfrom functools import lru_cache\nfrom inference.core.workflows.execution_engine.entities.base import OutputDefinition\nfrom inference.core.workflows.execution_engine.entities.types import OBJECT_DETECTION_PREDICTION_KIND\nfrom typing import List\n\nOUTPUT_KEY: str = \"tracked_detections\"\n\n\n@lru_cache(maxsize=1)\ndef tracker_describe_outputs() -> List[OutputDefinition]:\n    \"\"\"Output definitions shared by all tracker blocks.\"\"\"\n    return [\n        OutputDefinition(name=OUTPUT_KEY, kind=[OBJECT_DETECTION_PREDICTION_KIND]),\n        OutputDefinition(name=\"new_instances\", kind=[OBJECT_DETECTION_PREDICTION_KIND]),\n        OutputDefinition(\n            name=\"already_seen_instances\",\n            kind=[OBJECT_DETECTION_PREDICTION_KIND],\n        ),\n    ]\n```",
    "optimized_function_only": null,
    "original_file_content": "from typing import Any, List, Literal, Optional, Type, Union\n\nimport supervision as sv\nfrom pydantic import ConfigDict, Field\nfrom trackers import SORTTracker\n\nfrom inference.core.workflows.core_steps.trackers._base import (\n    TrackerBlockBase,\n    tracker_describe_outputs,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    FLOAT_ZERO_TO_ONE_KIND,\n    IMAGE_KIND,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    INTEGER_KIND,\n    KEYPOINT_DETECTION_PREDICTION_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import BlockResult, WorkflowBlockManifest\n\nDEFAULT_LOST_TRACK_BUFFER = 30\nDEFAULT_TRACK_ACTIVATION_THRESHOLD = 0.25\nDEFAULT_MINIMUM_CONSECUTIVE_FRAMES = 3\nDEFAULT_MINIMUM_IOU_THRESHOLD = 0.3\nDEFAULT_INSTANCES_CACHE_SIZE = 16384\n\nSHORT_DESCRIPTION = (\n    \"Fast, lightweight object tracking. Works best when objects are clearly visible.\"\n)\nLONG_DESCRIPTION = \"\"\"\nTrack objects across video frames using the **SORT** algorithm from the\nroboflow/trackers package.\n\nSORT pairs a Kalman filter motion model with single-stage IoU-based Hungarian\nassignment.  It has the fewest parameters and lowest overhead, processing\nhundreds of frames per second.  However, it lacks re-identification and\nocclusion-recovery mechanisms, so tracks may fragment or switch IDs when objects\nare temporarily hidden.\n\n**When to use SORT:**\n- Controlled environments with reliable, high-confidence detections.\n- Real-time pipelines where maximum throughput is critical.\n- Simple scenes with minimal occlusion and predictable linear motion.\n\n**When to consider alternatives:**\n- If you see fragmented tracks or missed weak detections, try **ByteTrack**.\n- If objects undergo heavy occlusion or non-linear motion, try **OC-SORT**.\n\nOutputs three detection sets:\n- **tracked_detections**: All confirmed tracked detections with assigned track IDs.\n- **new_instances**: Detections whose track ID appears for the first time.\n- **already_seen_instances**: Detections whose track ID has been seen in a prior frame.\n\nThe block maintains separate tracker state and instance cache per `video_identifier`,\nenabling multi-stream tracking within a single workflow.\n\"\"\"\n\n\nclass SORTManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"SORT Tracker\",\n            \"version\": \"v1\",\n            \"short_description\": SHORT_DESCRIPTION,\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"transformation\",\n            \"ui_manifest\": {\n                \"section\": \"video\",\n                \"icon\": \"far fa-location-crosshairs\",\n                \"blockPriority\": 0,\n                \"trackers\": True,\n            },\n        },\n        protected_namespaces=(),\n    )\n    type: Literal[\"roboflow_core/trackers_sort@v1\"]\n    image: Selector(kind=[IMAGE_KIND]) = Field(\n        description=\"Input image with embedded video metadata (fps and video_identifier). \"\n        \"Used to initialise and retrieve per-video tracker state.\",\n    )\n    detections: Selector(\n        kind=[\n            OBJECT_DETECTION_PREDICTION_KIND,\n            KEYPOINT_DETECTION_PREDICTION_KIND,\n            INSTANCE_SEGMENTATION_PREDICTION_KIND,\n        ]\n    ) = Field(\n        description=\"Detection predictions for the current frame to track.\",\n        examples=[\"$steps.object_detection_model.predictions\"],\n    )\n    minimum_iou_threshold: Union[\n        Optional[float], Selector(kind=[FLOAT_ZERO_TO_ONE_KIND])\n    ] = Field(\n        default=DEFAULT_MINIMUM_IOU_THRESHOLD,\n        description=\"Minimum IoU required to associate a detection with an existing track. \"\n        f\"Default: {DEFAULT_MINIMUM_IOU_THRESHOLD}.\",\n        examples=[DEFAULT_MINIMUM_IOU_THRESHOLD, \"$inputs.minimum_iou_threshold\"],\n        json_schema_extra={\n            \"always_visible\": True,\n        },\n    )\n    minimum_consecutive_frames: Union[Optional[int], Selector(kind=[INTEGER_KIND])] = (\n        Field(\n            default=DEFAULT_MINIMUM_CONSECUTIVE_FRAMES,\n            description=\"Number of consecutive frames a track must be matched before it is \"\n            f\"emitted as a confirmed track (tracker_id != -1). Default: {DEFAULT_MINIMUM_CONSECUTIVE_FRAMES}.\",\n            examples=[\n                DEFAULT_MINIMUM_CONSECUTIVE_FRAMES,\n                \"$inputs.minimum_consecutive_frames\",\n            ],\n            json_schema_extra={\n                \"always_visible\": True,\n            },\n        )\n    )\n    lost_track_buffer: Union[Optional[int], Selector(kind=[INTEGER_KIND])] = Field(\n        default=DEFAULT_LOST_TRACK_BUFFER,\n        description=\"Number of frames to keep a track alive after it loses its matched \"\n        f\"detection. Higher values improve occlusion recovery. Default: {DEFAULT_LOST_TRACK_BUFFER}.\",\n        examples=[DEFAULT_LOST_TRACK_BUFFER, \"$inputs.lost_track_buffer\"],\n        json_schema_extra={\n            \"always_visible\": True,\n        },\n    )\n    track_activation_threshold: Union[\n        Optional[float], Selector(kind=[FLOAT_ZERO_TO_ONE_KIND])\n    ] = Field(\n        default=DEFAULT_TRACK_ACTIVATION_THRESHOLD,\n        description=\"Minimum detection confidence required to spawn a new track. \"\n        f\"Detections below this threshold are not used to create new tracks. Default: {DEFAULT_TRACK_ACTIVATION_THRESHOLD}.\",\n        examples=[\n            DEFAULT_TRACK_ACTIVATION_THRESHOLD,\n            \"$inputs.track_activation_threshold\",\n        ],\n    )\n    instances_cache_size: int = Field(\n        default=DEFAULT_INSTANCES_CACHE_SIZE,\n        description=\"Maximum number of track IDs retained in the instance cache for \"\n        f\"new/already-seen categorisation. Uses FIFO eviction. Default: {DEFAULT_INSTANCES_CACHE_SIZE}.\",\n    )\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return tracker_describe_outputs()\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass SORTBlockV1(TrackerBlockBase):\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return SORTManifest\n\n    def _create_tracker(self, fps: int, **kwargs: Any) -> Any:\n        return SORTTracker(\n            lost_track_buffer=kwargs[\"lost_track_buffer\"],\n            frame_rate=fps,\n            track_activation_threshold=kwargs[\"track_activation_threshold\"],\n            minimum_consecutive_frames=kwargs[\"minimum_consecutive_frames\"],\n            minimum_iou_threshold=kwargs[\"minimum_iou_threshold\"],\n        )\n\n    def run(\n        self,\n        image: WorkflowImageData,\n        detections: sv.Detections,\n        lost_track_buffer: int = DEFAULT_LOST_TRACK_BUFFER,\n        minimum_iou_threshold: float = DEFAULT_MINIMUM_IOU_THRESHOLD,\n        minimum_consecutive_frames: int = DEFAULT_MINIMUM_CONSECUTIVE_FRAMES,\n        instances_cache_size: int = DEFAULT_INSTANCES_CACHE_SIZE,\n        track_activation_threshold: float = DEFAULT_TRACK_ACTIVATION_THRESHOLD,\n    ) -> BlockResult:\n        return self._run_tracker(\n            image=image,\n            detections=detections,\n            instances_cache_size=instances_cache_size,\n            lost_track_buffer=lost_track_buffer,\n            minimum_iou_threshold=minimum_iou_threshold,\n            minimum_consecutive_frames=minimum_consecutive_frames,\n            track_activation_threshold=track_activation_threshold,\n        )\n",
    "patch": null
  },
  {
    "trace_id": "92fe0f54-daaf-448f-b57e-92162e2b8620",
    "function_name": "OCSORTBlockV1.run",
    "file_path": "inference/core/workflows/core_steps/trackers/ocsort/v1.py",
    "speedup_x": 0.5975505904472258,
    "review_quality": "high",
    "pre_optimization_commit": "HEAD",
    "resolution_method": "db_code_only",
    "source": "db_features",
    "original_function_code": "    def run(\n        self,\n        image: WorkflowImageData,\n        detections: sv.Detections,\n        lost_track_buffer: int = 30,\n        minimum_iou_threshold: float = 0.1,\n        minimum_consecutive_frames: int = 2,\n        instances_cache_size: int = 16384,\n        high_conf_det_threshold: float = 0.6,\n        direction_consistency_weight: float = 0.2,\n        delta_t: int = 3,\n    ) -> BlockResult:\n        return self._run_tracker(\n            image=image,\n            detections=detections,\n            instances_cache_size=instances_cache_size,\n            lost_track_buffer=lost_track_buffer,\n            minimum_iou_threshold=minimum_iou_threshold,\n            minimum_consecutive_frames=minimum_consecutive_frames,\n            high_conf_det_threshold=high_conf_det_threshold,\n            direction_consistency_weight=direction_consistency_weight,\n            delta_t=delta_t,\n        )",
    "optimized_function_code": "import supervision as sv\nfrom inference.core import logger\nfrom inference.core.workflows.core_steps.trackers._utils import InstanceCache\nfrom inference.core.workflows.execution_engine.entities.base import WorkflowImageData\nfrom inference.core.workflows.prototypes.block import BlockResult, WorkflowBlock\nfrom typing import Any, Dict\n\nOUTPUT_KEY: str = \"tracked_detections\"\n\n\nclass TrackerBlockBase(WorkflowBlock):\n\n    def __init__(self) -> None:\n        self._trackers: Dict[str, Any] = {}\n        self._per_video_cache: Dict[str, InstanceCache] = {}\n\n    def _run_tracker(\n        self,\n        image: WorkflowImageData,\n        detections: sv.Detections,\n        instances_cache_size: int = 16384,\n        **tracker_kwargs: Any,\n    ) -> BlockResult:\n        metadata = image.video_metadata\n        fps = metadata.fps\n        if not fps:\n            fps = 30\n            logger.warning(\n                f\"fps not available in VideoMetadata for {self.__class__.__name__}, \"\n                \"defaulting to 30 fps for tracker initialisation\"\n            )\n        video_id = metadata.video_identifier\n\n        if video_id not in self._trackers:\n            self._trackers[video_id] = self._create_tracker(fps=fps, **tracker_kwargs)\n\n        tracker = self._trackers[video_id]\n\n        if isinstance(detections, sv.Detections):\n            merged = detections\n        else:\n            merged = sv.Detections.merge(detections)\n\n        tracked_detections = tracker.update(merged)\n\n        # Filter out immature / unmatched tracks (tracker_id == -1)\n        if tracked_detections.tracker_id is not None and len(tracked_detections) > 0:\n            valid_mask = tracked_detections.tracker_id != -1\n            tracked_detections = tracked_detections[valid_mask]\n\n        if video_id not in self._per_video_cache:\n            self._per_video_cache[video_id] = InstanceCache(size=instances_cache_size)\n        cache = self._per_video_cache[video_id]\n\n        not_seen_mask, seen_mask = [], []\n        for tracker_id in tracked_detections.tracker_id:\n            already_seen = cache.record_instance(tracker_id=tracker_id)\n            not_seen_mask.append(not already_seen)\n            seen_mask.append(already_seen)\n\n\n        return {\n            OUTPUT_KEY: tracked_detections,\n            \"new_instances\": tracked_detections[not_seen_mask],\n            \"already_seen_instances\": tracked_detections[seen_mask],\n        }",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/trackers/_base.py\nimport supervision as sv\nfrom inference.core import logger\nfrom inference.core.workflows.core_steps.trackers._utils import InstanceCache\nfrom inference.core.workflows.execution_engine.entities.base import WorkflowImageData\nfrom inference.core.workflows.prototypes.block import BlockResult, WorkflowBlock\nfrom typing import Any, Dict\n\nOUTPUT_KEY: str = \"tracked_detections\"\n\n\nclass TrackerBlockBase(WorkflowBlock):\n\n    def __init__(self) -> None:\n        self._trackers: Dict[str, Any] = {}\n        self._per_video_cache: Dict[str, InstanceCache] = {}\n\n    def _run_tracker(\n        self,\n        image: WorkflowImageData,\n        detections: sv.Detections,\n        instances_cache_size: int = 16384,\n        **tracker_kwargs: Any,\n    ) -> BlockResult:\n        metadata = image.video_metadata\n        fps = metadata.fps\n        if not fps:\n            fps = 30\n            logger.warning(\n                f\"fps not available in VideoMetadata for {self.__class__.__name__}, \"\n                \"defaulting to 30 fps for tracker initialisation\"\n            )\n        video_id = metadata.video_identifier\n\n        if video_id not in self._trackers:\n            self._trackers[video_id] = self._create_tracker(fps=fps, **tracker_kwargs)\n\n        tracker = self._trackers[video_id]\n\n        if isinstance(detections, sv.Detections):\n            merged = detections\n        else:\n            merged = sv.Detections.merge(detections)\n\n        tracked_detections = tracker.update(merged)\n\n        # Filter out immature / unmatched tracks (tracker_id == -1)\n        if tracked_detections.tracker_id is not None and len(tracked_detections) > 0:\n            valid_mask = tracked_detections.tracker_id != -1\n            tracked_detections = tracked_detections[valid_mask]\n\n        if video_id not in self._per_video_cache:\n            self._per_video_cache[video_id] = InstanceCache(size=instances_cache_size)\n        cache = self._per_video_cache[video_id]\n\n        not_seen_mask, seen_mask = [], []\n        for tracker_id in tracked_detections.tracker_id:\n            already_seen = cache.record_instance(tracker_id=tracker_id)\n            not_seen_mask.append(not already_seen)\n            seen_mask.append(already_seen)\n\n\n        return {\n            OUTPUT_KEY: tracked_detections,\n            \"new_instances\": tracked_detections[not_seen_mask],\n            \"already_seen_instances\": tracked_detections[seen_mask],\n        }\n```",
    "optimized_function_only": null,
    "original_file_content": "import supervision as sv\nfrom inference.core.workflows.core_steps.trackers._base import TrackerBlockBase\nfrom inference.core.workflows.execution_engine.entities.base import WorkflowImageData\nfrom inference.core.workflows.prototypes.block import BlockResult\n\nclass OCSORTBlockV1(TrackerBlockBase):\n\n    def run(\n        self,\n        image: WorkflowImageData,\n        detections: sv.Detections,\n        lost_track_buffer: int = 30,\n        minimum_iou_threshold: float = 0.1,\n        minimum_consecutive_frames: int = 2,\n        instances_cache_size: int = 16384,\n        high_conf_det_threshold: float = 0.6,\n        direction_consistency_weight: float = 0.2,\n        delta_t: int = 3,\n    ) -> BlockResult:\n        return self._run_tracker(\n            image=image,\n            detections=detections,\n            instances_cache_size=instances_cache_size,\n            lost_track_buffer=lost_track_buffer,\n            minimum_iou_threshold=minimum_iou_threshold,\n            minimum_consecutive_frames=minimum_consecutive_frames,\n            high_conf_det_threshold=high_conf_det_threshold,\n            direction_consistency_weight=direction_consistency_weight,\n            delta_t=delta_t,\n        )",
    "patch": null
  },
  {
    "trace_id": "1f498919-21c8-490f-be83-843e30ef2a1f",
    "function_name": "ByteTrackManifest.describe_outputs",
    "file_path": "inference/core/workflows/core_steps/transformations/byte_tracker/v1.py",
    "speedup_x": 15.664097790519047,
    "review_quality": "high",
    "pre_optimization_commit": "HEAD",
    "resolution_method": "db_code_only",
    "source": "db_features",
    "original_function_code": "    def describe_outputs(cls) -> List[OutputDefinition]:\n        return tracker_describe_outputs()",
    "optimized_function_code": "from functools import lru_cache\nfrom typing import List\n\nfrom inference.core.workflows.execution_engine.entities.base import \\\n    OutputDefinition\nfrom inference.core.workflows.execution_engine.entities.types import \\\n    OBJECT_DETECTION_PREDICTION_KIND\n\nOUTPUT_KEY: str = \"tracked_detections\"\n\n\n\n\n@lru_cache(maxsize=1)\ndef tracker_describe_outputs() -> List[OutputDefinition]:\n    \"\"\"Output definitions shared by all tracker blocks.\"\"\"\n    return [\n        OutputDefinition(name=OUTPUT_KEY, kind=[OBJECT_DETECTION_PREDICTION_KIND]),\n        OutputDefinition(name=\"new_instances\", kind=[OBJECT_DETECTION_PREDICTION_KIND]),\n        OutputDefinition(\n            name=\"already_seen_instances\",\n            kind=[OBJECT_DETECTION_PREDICTION_KIND],\n        ),\n    ]",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/trackers/_base.py\nfrom functools import lru_cache\nfrom typing import List\n\nfrom inference.core.workflows.execution_engine.entities.base import \\\n    OutputDefinition\nfrom inference.core.workflows.execution_engine.entities.types import \\\n    OBJECT_DETECTION_PREDICTION_KIND\n\nOUTPUT_KEY: str = \"tracked_detections\"\n\n\n\n\n@lru_cache(maxsize=1)\ndef tracker_describe_outputs() -> List[OutputDefinition]:\n    \"\"\"Output definitions shared by all tracker blocks.\"\"\"\n    return [\n        OutputDefinition(name=OUTPUT_KEY, kind=[OBJECT_DETECTION_PREDICTION_KIND]),\n        OutputDefinition(name=\"new_instances\", kind=[OBJECT_DETECTION_PREDICTION_KIND]),\n        OutputDefinition(\n            name=\"already_seen_instances\",\n            kind=[OBJECT_DETECTION_PREDICTION_KIND],\n        ),\n    ]\n```",
    "optimized_function_only": null,
    "original_file_content": "from inference.core.workflows.core_steps.trackers._base import tracker_describe_outputs\nfrom inference.core.workflows.execution_engine.entities.base import OutputDefinition\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\nfrom typing import List\n\nSHORT_DESCRIPTION = \"Track objects across video frames using ByteTrack.\"\nLONG_DESCRIPTION = \"\"\"\nTrack objects across video frames using the **ByteTrack** algorithm from the\nroboflow/trackers package.\n\nByteTrack uses two-stage association with high- and low-confidence detection\npools.  It is robust in crowded scenes and during occlusions.\n\nOutputs three detection sets:\n- **tracked_detections**: All confirmed tracked detections with assigned track IDs.\n- **new_instances**: Detections whose track ID appears for the first time.\n- **already_seen_instances**: Detections whose track ID has been seen in a prior frame.\n\nThe block maintains separate tracker state and instance cache per `video_identifier`,\nenabling multi-stream tracking within a single workflow.\n\"\"\"\n\n\nclass ByteTrackManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return tracker_describe_outputs()",
    "patch": null
  },
  {
    "trace_id": "8f7f2378-7585-4973-8fb0-137aa8f32bc2",
    "function_name": "InferenceModelsGLMOCRAdapter.postprocess",
    "file_path": "inference/models/glm_ocr/glm_ocr_inference_models.py",
    "speedup_x": 0.19267289373923105,
    "review_quality": "medium",
    "pre_optimization_commit": "2fcfa233d55edf579db58933ca9bac1b86d85fe6",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def postprocess(\n        self,\n        predictions: torch.Tensor,\n        preprocess_return_metadata: PreprocessReturnMetadata,\n        **kwargs,\n    ) -> List[LMMInferenceResponse]:\n        result = self._model.post_process_generation(\n            predictions,\n            **kwargs,\n        )[0]\n        return [\n            LMMInferenceResponse(\n                response=result,\n                image=InferenceResponseImage(\n                    width=preprocess_return_metadata[\"image_dims\"][0],\n                    height=preprocess_return_metadata[\"image_dims\"][1],\n                ),\n            )\n        ]\n",
    "optimized_function_code": "from typing import List\n\nimport torch\nfrom inference.core.entities.responses import (InferenceResponseImage,\n                                               LMMInferenceResponse)\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES, API_KEY,\n    DISABLED_INFERENCE_MODELS_BACKENDS, VALID_INFERENCE_MODELS_BACKENDS)\nfrom inference.core.models.base import Model\nfrom inference.core.models.types import PreprocessReturnMetadata\nfrom inference.core.roboflow_api import get_extra_weights_provider_headers\nfrom inference_models import AutoModel\nfrom inference_models.models.glm_ocr.glm_ocr_hf import GlmOcrHF\n\n\nclass InferenceModelsGLMOCRAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n\n        self.task_type = \"lmm\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n        backend = list(\n            VALID_INFERENCE_MODELS_BACKENDS.difference(\n                DISABLED_INFERENCE_MODELS_BACKENDS\n            )\n        )\n        self._model: GlmOcrHF = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            backend=backend,\n            **kwargs,\n        )\n\n    def postprocess(\n        self,\n        predictions: torch.Tensor,\n        preprocess_return_metadata: PreprocessReturnMetadata,\n        **kwargs,\n    ) -> List[LMMInferenceResponse]:\n        result = self._model.post_process_generation(\n            predictions,\n            **kwargs,\n        )[0]\n        # Localize image dims to avoid repeated dict lookups\n        image_dims = preprocess_return_metadata[\"image_dims\"]\n        # Use pydantic v2 model_construct to create instances without validation overhead\n        image_obj = InferenceResponseImage.model_construct(\n            width=image_dims[0],\n            height=image_dims[1],\n        )\n        response_obj = LMMInferenceResponse.model_construct(\n            response=result,\n            image=image_obj,\n        )\n        return [response_obj]",
    "optimized_raw_markdown": "```python:inference/models/glm_ocr/glm_ocr_inference_models.py\nfrom typing import List\n\nimport torch\nfrom inference.core.entities.responses import (InferenceResponseImage,\n                                               LMMInferenceResponse)\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES, API_KEY,\n    DISABLED_INFERENCE_MODELS_BACKENDS, VALID_INFERENCE_MODELS_BACKENDS)\nfrom inference.core.models.base import Model\nfrom inference.core.models.types import PreprocessReturnMetadata\nfrom inference.core.roboflow_api import get_extra_weights_provider_headers\nfrom inference_models import AutoModel\nfrom inference_models.models.glm_ocr.glm_ocr_hf import GlmOcrHF\n\n\nclass InferenceModelsGLMOCRAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n\n        self.task_type = \"lmm\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n        backend = list(\n            VALID_INFERENCE_MODELS_BACKENDS.difference(\n                DISABLED_INFERENCE_MODELS_BACKENDS\n            )\n        )\n        self._model: GlmOcrHF = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            backend=backend,\n            **kwargs,\n        )\n\n    def postprocess(\n        self,\n        predictions: torch.Tensor,\n        preprocess_return_metadata: PreprocessReturnMetadata,\n        **kwargs,\n    ) -> List[LMMInferenceResponse]:\n        result = self._model.post_process_generation(\n            predictions,\n            **kwargs,\n        )[0]\n        # Localize image dims to avoid repeated dict lookups\n        image_dims = preprocess_return_metadata[\"image_dims\"]\n        # Use pydantic v2 model_construct to create instances without validation overhead\n        image_obj = InferenceResponseImage.model_construct(\n            width=image_dims[0],\n            height=image_dims[1],\n        )\n        response_obj = LMMInferenceResponse.model_construct(\n            response=result,\n            image=image_obj,\n        )\n        return [response_obj]\n```",
    "optimized_function_only": "    def postprocess(\n        self,\n        predictions: torch.Tensor,\n        preprocess_return_metadata: PreprocessReturnMetadata,\n        **kwargs,\n    ) -> List[LMMInferenceResponse]:\n        result = self._model.post_process_generation(\n            predictions,\n            **kwargs,\n        )[0]\n        # Localize image dims to avoid repeated dict lookups\n        image_dims = preprocess_return_metadata[\"image_dims\"]\n        # Use pydantic v2 model_construct to create instances without validation overhead\n        image_obj = InferenceResponseImage.model_construct(\n            width=image_dims[0],\n            height=image_dims[1],\n        )\n        response_obj = LMMInferenceResponse.model_construct(\n            response=result,\n            image=image_obj,\n        )\n        return [response_obj]",
    "original_file_content": "from typing import Any, List, Optional\n\nimport torch\n\nfrom inference.core.entities.responses import (\n    InferenceResponseImage,\n    LMMInferenceResponse,\n)\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n    API_KEY,\n    DISABLED_INFERENCE_MODELS_BACKENDS,\n    VALID_INFERENCE_MODELS_BACKENDS,\n)\nfrom inference.core.models.base import Model\nfrom inference.core.models.types import PreprocessReturnMetadata\nfrom inference.core.roboflow_api import get_extra_weights_provider_headers\nfrom inference.core.utils.image_utils import load_image_bgr\nfrom inference_models import AutoModel\nfrom inference_models.models.glm_ocr.glm_ocr_hf import GlmOcrHF\n\n\nclass InferenceModelsGLMOCRAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n\n        self.task_type = \"lmm\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n        backend = list(\n            VALID_INFERENCE_MODELS_BACKENDS.difference(\n                DISABLED_INFERENCE_MODELS_BACKENDS\n            )\n        )\n        self._model: GlmOcrHF = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            backend=backend,\n            **kwargs,\n        )\n\n    def preprocess(self, image: Any, prompt: Optional[str] = None, **kwargs):\n        is_batch = isinstance(image, list)\n        if is_batch:\n            raise ValueError(\"This model does not support batched-inference.\")\n        np_image = load_image_bgr(\n            image,\n            disable_preproc_auto_orient=kwargs.get(\n                \"disable_preproc_auto_orient\", False\n            ),\n        )\n        input_shape = PreprocessReturnMetadata({\"image_dims\": np_image.shape[:2][::-1]})\n        return (\n            self._model.pre_process_generation(np_image, prompt, **kwargs),\n            input_shape,\n        )\n\n    def predict(self, inputs, **kwargs) -> torch.Tensor:\n        return self._model.generate(inputs, **kwargs)\n\n    def postprocess(\n        self,\n        predictions: torch.Tensor,\n        preprocess_return_metadata: PreprocessReturnMetadata,\n        **kwargs,\n    ) -> List[LMMInferenceResponse]:\n        result = self._model.post_process_generation(\n            predictions,\n            **kwargs,\n        )[0]\n        return [\n            LMMInferenceResponse(\n                response=result,\n                image=InferenceResponseImage(\n                    width=preprocess_return_metadata[\"image_dims\"][0],\n                    height=preprocess_return_metadata[\"image_dims\"][1],\n                ),\n            )\n        ]\n\n    def clear_cache(self, delete_from_disk: bool = True) -> None:\n        \"\"\"Clears any cache if necessary. TODO: Implement this to delete the cache from the experimental model.\n\n        Args:\n            delete_from_disk (bool, optional): Whether to delete cached files from disk. Defaults to True.\n        \"\"\"\n        pass\n",
    "patch": null
  },
  {
    "trace_id": "94c04fe2-2e76-4631-8302-2c4729ccb11a",
    "function_name": "prepare_operators_descriptions",
    "file_path": "inference/core/workflows/core_steps/common/query_language/introspection/core.py",
    "speedup_x": 14149.746620452424,
    "review_quality": "high",
    "pre_optimization_commit": "aece4fff835fad9d67e1419e0a86528694765a2b",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def prepare_operators_descriptions() -> List[OperatorDescription]:\n    operator_types = [\n        In,\n        StringContains,\n        StringEndsWith,\n        StringStartsWith,\n        NumberLowerEqual,\n        NumberLower,\n        NumberGreaterEqual,\n        NumberGreater,\n        NotEquals,\n        Equals,\n        Exists,\n        DoesNotExist,\n        IsTrue,\n        IsFalse,\n        IsEmpty,\n        IsNotEmpty,\n    ]\n    results = []\n    for operator_type in operator_types:\n        operator_schema = operator_type.model_json_schema()\n        for alias in operator_schema[\"properties\"][\"type\"].get(\"enum\", []):\n            results.append(\n                OperatorDescription(\n                    operator_type=alias,\n                    operands_number=operator_schema[\"operands_number\"],\n                    operands_kinds=operator_schema[\"operands_kinds\"],\n                    description=operator_schema.get(\"description\"),\n                )\n            )\n    return results\n",
    "optimized_function_code": "from typing import List\n\nfrom inference.core.workflows.core_steps.common.query_language.entities.introspection import \\\n    OperatorDescription\nfrom inference.core.workflows.core_steps.common.query_language.entities.operations import (\n    DoesNotExist, Equals, Exists, In, IsEmpty, IsFalse, IsNotEmpty, IsTrue,\n    NotEquals, NumberGreater, NumberGreaterEqual, NumberLower,\n    NumberLowerEqual, StringContains, StringEndsWith, StringStartsWith)\n\n_CACHED_OPERATORS_DESCRIPTIONS = None\n\ndef prepare_operators_descriptions() -> List[OperatorDescription]:\n    global _CACHED_OPERATORS_DESCRIPTIONS\n    \n    if _CACHED_OPERATORS_DESCRIPTIONS is not None:\n        return _CACHED_OPERATORS_DESCRIPTIONS\n    \n    operator_types = [\n        In,\n        StringContains,\n        StringEndsWith,\n        StringStartsWith,\n        NumberLowerEqual,\n        NumberLower,\n        NumberGreaterEqual,\n        NumberGreater,\n        NotEquals,\n        Equals,\n        Exists,\n        DoesNotExist,\n        IsTrue,\n        IsFalse,\n        IsEmpty,\n        IsNotEmpty,\n    ]\n    results = []\n    for operator_type in operator_types:\n        operator_schema = operator_type.model_json_schema()\n        type_enum = operator_schema[\"properties\"][\"type\"].get(\"enum\", [])\n        operands_number = operator_schema[\"operands_number\"]\n        operands_kinds = operator_schema[\"operands_kinds\"]\n        description = operator_schema.get(\"description\")\n        \n        for alias in type_enum:\n            results.append(\n                OperatorDescription(\n                    operator_type=alias,\n                    operands_number=operands_number,\n                    operands_kinds=operands_kinds,\n                    description=description,\n                )\n            )\n    \n    _CACHED_OPERATORS_DESCRIPTIONS = results\n    return results",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/common/query_language/introspection/core.py\nfrom typing import List\n\nfrom inference.core.workflows.core_steps.common.query_language.entities.introspection import \\\n    OperatorDescription\nfrom inference.core.workflows.core_steps.common.query_language.entities.operations import (\n    DoesNotExist, Equals, Exists, In, IsEmpty, IsFalse, IsNotEmpty, IsTrue,\n    NotEquals, NumberGreater, NumberGreaterEqual, NumberLower,\n    NumberLowerEqual, StringContains, StringEndsWith, StringStartsWith)\n\n_CACHED_OPERATORS_DESCRIPTIONS = None\n\ndef prepare_operators_descriptions() -> List[OperatorDescription]:\n    global _CACHED_OPERATORS_DESCRIPTIONS\n    \n    if _CACHED_OPERATORS_DESCRIPTIONS is not None:\n        return _CACHED_OPERATORS_DESCRIPTIONS\n    \n    operator_types = [\n        In,\n        StringContains,\n        StringEndsWith,\n        StringStartsWith,\n        NumberLowerEqual,\n        NumberLower,\n        NumberGreaterEqual,\n        NumberGreater,\n        NotEquals,\n        Equals,\n        Exists,\n        DoesNotExist,\n        IsTrue,\n        IsFalse,\n        IsEmpty,\n        IsNotEmpty,\n    ]\n    results = []\n    for operator_type in operator_types:\n        operator_schema = operator_type.model_json_schema()\n        type_enum = operator_schema[\"properties\"][\"type\"].get(\"enum\", [])\n        operands_number = operator_schema[\"operands_number\"]\n        operands_kinds = operator_schema[\"operands_kinds\"]\n        description = operator_schema.get(\"description\")\n        \n        for alias in type_enum:\n            results.append(\n                OperatorDescription(\n                    operator_type=alias,\n                    operands_number=operands_number,\n                    operands_kinds=operands_kinds,\n                    description=description,\n                )\n            )\n    \n    _CACHED_OPERATORS_DESCRIPTIONS = results\n    return results\n```",
    "optimized_function_only": "def prepare_operators_descriptions() -> List[OperatorDescription]:\n    global _CACHED_OPERATORS_DESCRIPTIONS\n    \n    if _CACHED_OPERATORS_DESCRIPTIONS is not None:\n        return _CACHED_OPERATORS_DESCRIPTIONS\n    \n    operator_types = [\n        In,\n        StringContains,\n        StringEndsWith,\n        StringStartsWith,\n        NumberLowerEqual,\n        NumberLower,\n        NumberGreaterEqual,\n        NumberGreater,\n        NotEquals,\n        Equals,\n        Exists,\n        DoesNotExist,\n        IsTrue,\n        IsFalse,\n        IsEmpty,\n        IsNotEmpty,\n    ]\n    results = []\n    for operator_type in operator_types:\n        operator_schema = operator_type.model_json_schema()\n        type_enum = operator_schema[\"properties\"][\"type\"].get(\"enum\", [])\n        operands_number = operator_schema[\"operands_number\"]\n        operands_kinds = operator_schema[\"operands_kinds\"]\n        description = operator_schema.get(\"description\")\n        \n        for alias in type_enum:\n            results.append(\n                OperatorDescription(\n                    operator_type=alias,\n                    operands_number=operands_number,\n                    operands_kinds=operands_kinds,\n                    description=description,\n                )\n            )\n    \n    _CACHED_OPERATORS_DESCRIPTIONS = results\n    return results",
    "original_file_content": "from typing import List, Optional\n\nfrom inference.core.workflows.core_steps.common.query_language.entities.introspection import (\n    OperationDescription,\n    OperatorDescription,\n)\nfrom inference.core.workflows.core_steps.common.query_language.entities.operations import (\n    DoesNotExist,\n    Equals,\n    Exists,\n    In,\n    IsEmpty,\n    IsFalse,\n    IsNotEmpty,\n    IsTrue,\n    NotEquals,\n    NumberGreater,\n    NumberGreaterEqual,\n    NumberLower,\n    NumberLowerEqual,\n    OperationsChain,\n    StringContains,\n    StringEndsWith,\n    StringStartsWith,\n)\n\n\ndef _ref_to_def_name(\n    schema: dict,\n    ref_key: str = \"$ref\",\n) -> Optional[str]:\n    \"\"\"Extract definition name from a JSON Schema object's $ref (e.g. {'$ref': '#/$defs/Foo'} -> 'Foo').\"\"\"\n    ref = schema.get(ref_key)\n    if ref is None:\n        return None\n\n    return ref.split(\"/\")[-1]\n\n\ndef _get_property_name_options(\n    type_definition: dict,\n    defs: dict,\n) -> Optional[List[str]]:\n    \"\"\"Resolve property_name enum from operation schema when present (e.g. DetectionsProperty).\"\"\"\n    properties = type_definition.get(\"properties\") or {}\n    property_name_schema = properties.get(\"property_name\")\n\n    if not property_name_schema:\n        return None\n\n    ref_name = _ref_to_def_name(property_name_schema)\n    if ref_name is not None:\n        resolved = defs.get(ref_name)\n        if resolved and \"enum\" in resolved:\n            return list(resolved[\"enum\"])\n\n    if \"enum\" in property_name_schema:\n        return list(property_name_schema[\"enum\"])\n\n    return None\n\n\ndef prepare_operations_descriptions() -> List[OperationDescription]:\n    operations_chain_schema = OperationsChain.model_json_schema()\n    defs = operations_chain_schema.get(\"$defs\", {})\n    operation_type_definitions = operations_chain_schema[\"properties\"][\"operations\"][\"items\"][\"oneOf\"]  # fmt: skip\n\n    operation_types = [\n        name\n        for type_definition in operation_type_definitions\n        if (name := _ref_to_def_name(type_definition)) is not None\n    ]\n    type_definitions = [defs[operation_type] for operation_type in operation_types]\n\n    result = []\n    for type_definition in type_definitions:\n        property_name_options = _get_property_name_options(type_definition, defs)\n\n        result.append(\n            OperationDescription(\n                operation_type=type_definition[\"properties\"][\"type\"][\"const\"],\n                compound=type_definition.get(\"compound\", False),\n                input_kind=type_definition[\"input_kind\"],\n                output_kind=type_definition[\"output_kind\"],\n                nested_operation_input_kind=type_definition.get(\n                    \"nested_operation_input_kind\"\n                ),\n                nested_operation_output_kind=type_definition.get(\n                    \"nested_operation_output_kind\"\n                ),\n                property_name_options=property_name_options,\n            )\n        )\n    return result\n\n\ndef prepare_operators_descriptions() -> List[OperatorDescription]:\n    operator_types = [\n        In,\n        StringContains,\n        StringEndsWith,\n        StringStartsWith,\n        NumberLowerEqual,\n        NumberLower,\n        NumberGreaterEqual,\n        NumberGreater,\n        NotEquals,\n        Equals,\n        Exists,\n        DoesNotExist,\n        IsTrue,\n        IsFalse,\n        IsEmpty,\n        IsNotEmpty,\n    ]\n    results = []\n    for operator_type in operator_types:\n        operator_schema = operator_type.model_json_schema()\n        for alias in operator_schema[\"properties\"][\"type\"].get(\"enum\", []):\n            results.append(\n                OperatorDescription(\n                    operator_type=alias,\n                    operands_number=operator_schema[\"operands_number\"],\n                    operands_kinds=operator_schema[\"operands_kinds\"],\n                    description=operator_schema.get(\"description\"),\n                )\n            )\n    return results\n",
    "patch": null
  },
  {
    "trace_id": "5824ca45-b2d1-4990-8e4b-d2c580cf34c9",
    "function_name": "prepare_operations_descriptions",
    "file_path": "inference/core/workflows/core_steps/common/query_language/introspection/core.py",
    "speedup_x": 5.262431985316916,
    "review_quality": "high",
    "pre_optimization_commit": "aece4fff835fad9d67e1419e0a86528694765a2b",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def prepare_operations_descriptions() -> List[OperationDescription]:\n    operations_chain_schema = OperationsChain.model_json_schema()\n    defs = operations_chain_schema.get(\"$defs\", {})\n    operation_type_definitions = operations_chain_schema[\"properties\"][\"operations\"][\"items\"][\"oneOf\"]  # fmt: skip\n\n    operation_types = [\n        name\n        for type_definition in operation_type_definitions\n        if (name := _ref_to_def_name(type_definition)) is not None\n    ]\n    type_definitions = [defs[operation_type] for operation_type in operation_types]\n\n    result = []\n    for type_definition in type_definitions:\n        property_name_options = _get_property_name_options(type_definition, defs)\n\n        result.append(\n            OperationDescription(\n                operation_type=type_definition[\"properties\"][\"type\"][\"const\"],\n                compound=type_definition.get(\"compound\", False),\n                input_kind=type_definition[\"input_kind\"],\n                output_kind=type_definition[\"output_kind\"],\n                nested_operation_input_kind=type_definition.get(\n                    \"nested_operation_input_kind\"\n                ),\n                nested_operation_output_kind=type_definition.get(\n                    \"nested_operation_output_kind\"\n                ),\n                property_name_options=property_name_options,\n            )\n        )\n    return result\n",
    "optimized_function_code": "from inference.core.workflows.core_steps.common.query_language.entities.introspection import OperationDescription\nfrom inference.core.workflows.core_steps.common.query_language.entities.operations import OperationsChain\nfrom typing import List, Optional\nimport functools\n\ndef _ref_to_def_name(\n    schema: dict,\n    ref_key: str = \"$ref\",\n) -> Optional[str]:\n    \"\"\"Extract definition name from a JSON Schema object's $ref (e.g. {'$ref': '#/$defs/Foo'} -> 'Foo').\"\"\"\n    ref = schema.get(ref_key)\n    if ref is None:\n        return None\n\n    return ref.split(\"/\")[-1]\n\n\ndef _get_property_name_options(\n    type_definition: dict,\n    defs: dict,\n) -> Optional[List[str]]:\n    \"\"\"Resolve property_name enum from operation schema when present (e.g. DetectionsProperty).\"\"\"\n    properties = type_definition.get(\"properties\") or {}\n    property_name_schema = properties.get(\"property_name\")\n\n    if not property_name_schema:\n        return None\n\n    ref_name = _ref_to_def_name(property_name_schema)\n    if ref_name is not None:\n        resolved = defs.get(ref_name)\n        if resolved and \"enum\" in resolved:\n            return list(resolved[\"enum\"])\n\n    if \"enum\" in property_name_schema:\n        return list(property_name_schema[\"enum\"])\n\n    return None\n\n\n@functools.lru_cache(maxsize=1)\ndef prepare_operations_descriptions() -> List[OperationDescription]:\n    operations_chain_schema = OperationsChain.model_json_schema()\n    defs = operations_chain_schema.get(\"$defs\", {})\n    operation_type_definitions = operations_chain_schema[\"properties\"][\"operations\"][\"items\"][\"oneOf\"]  # fmt: skip\n\n    operation_types = [\n        name\n        for type_definition in operation_type_definitions\n        if (name := _ref_to_def_name(type_definition)) is not None\n    ]\n    type_definitions = [defs[operation_type] for operation_type in operation_types]\n\n    result = []\n    for type_definition in type_definitions:\n        property_name_options = _get_property_name_options(type_definition, defs)\n\n        result.append(\n            OperationDescription(\n                operation_type=type_definition[\"properties\"][\"type\"][\"const\"],\n                compound=type_definition.get(\"compound\", False),\n                input_kind=type_definition[\"input_kind\"],\n                output_kind=type_definition[\"output_kind\"],\n                nested_operation_input_kind=type_definition.get(\n                    \"nested_operation_input_kind\"\n                ),\n                nested_operation_output_kind=type_definition.get(\n                    \"nested_operation_output_kind\"\n                ),\n                property_name_options=property_name_options,\n            )\n        )\n    return result",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/common/query_language/introspection/core.py\nfrom inference.core.workflows.core_steps.common.query_language.entities.introspection import OperationDescription\nfrom inference.core.workflows.core_steps.common.query_language.entities.operations import OperationsChain\nfrom typing import List, Optional\nimport functools\n\ndef _ref_to_def_name(\n    schema: dict,\n    ref_key: str = \"$ref\",\n) -> Optional[str]:\n    \"\"\"Extract definition name from a JSON Schema object's $ref (e.g. {'$ref': '#/$defs/Foo'} -> 'Foo').\"\"\"\n    ref = schema.get(ref_key)\n    if ref is None:\n        return None\n\n    return ref.split(\"/\")[-1]\n\n\ndef _get_property_name_options(\n    type_definition: dict,\n    defs: dict,\n) -> Optional[List[str]]:\n    \"\"\"Resolve property_name enum from operation schema when present (e.g. DetectionsProperty).\"\"\"\n    properties = type_definition.get(\"properties\") or {}\n    property_name_schema = properties.get(\"property_name\")\n\n    if not property_name_schema:\n        return None\n\n    ref_name = _ref_to_def_name(property_name_schema)\n    if ref_name is not None:\n        resolved = defs.get(ref_name)\n        if resolved and \"enum\" in resolved:\n            return list(resolved[\"enum\"])\n\n    if \"enum\" in property_name_schema:\n        return list(property_name_schema[\"enum\"])\n\n    return None\n\n\n@functools.lru_cache(maxsize=1)\ndef prepare_operations_descriptions() -> List[OperationDescription]:\n    operations_chain_schema = OperationsChain.model_json_schema()\n    defs = operations_chain_schema.get(\"$defs\", {})\n    operation_type_definitions = operations_chain_schema[\"properties\"][\"operations\"][\"items\"][\"oneOf\"]  # fmt: skip\n\n    operation_types = [\n        name\n        for type_definition in operation_type_definitions\n        if (name := _ref_to_def_name(type_definition)) is not None\n    ]\n    type_definitions = [defs[operation_type] for operation_type in operation_types]\n\n    result = []\n    for type_definition in type_definitions:\n        property_name_options = _get_property_name_options(type_definition, defs)\n\n        result.append(\n            OperationDescription(\n                operation_type=type_definition[\"properties\"][\"type\"][\"const\"],\n                compound=type_definition.get(\"compound\", False),\n                input_kind=type_definition[\"input_kind\"],\n                output_kind=type_definition[\"output_kind\"],\n                nested_operation_input_kind=type_definition.get(\n                    \"nested_operation_input_kind\"\n                ),\n                nested_operation_output_kind=type_definition.get(\n                    \"nested_operation_output_kind\"\n                ),\n                property_name_options=property_name_options,\n            )\n        )\n    return result\n```",
    "optimized_function_only": "def prepare_operations_descriptions() -> List[OperationDescription]:\n    operations_chain_schema = OperationsChain.model_json_schema()\n    defs = operations_chain_schema.get(\"$defs\", {})\n    operation_type_definitions = operations_chain_schema[\"properties\"][\"operations\"][\"items\"][\"oneOf\"]  # fmt: skip\n\n    operation_types = [\n        name\n        for type_definition in operation_type_definitions\n        if (name := _ref_to_def_name(type_definition)) is not None\n    ]\n    type_definitions = [defs[operation_type] for operation_type in operation_types]\n\n    result = []\n    for type_definition in type_definitions:\n        property_name_options = _get_property_name_options(type_definition, defs)\n\n        result.append(\n            OperationDescription(\n                operation_type=type_definition[\"properties\"][\"type\"][\"const\"],\n                compound=type_definition.get(\"compound\", False),\n                input_kind=type_definition[\"input_kind\"],\n                output_kind=type_definition[\"output_kind\"],\n                nested_operation_input_kind=type_definition.get(\n                    \"nested_operation_input_kind\"\n                ),\n                nested_operation_output_kind=type_definition.get(\n                    \"nested_operation_output_kind\"\n                ),\n                property_name_options=property_name_options,\n            )\n        )\n    return result",
    "original_file_content": "from typing import List, Optional\n\nfrom inference.core.workflows.core_steps.common.query_language.entities.introspection import (\n    OperationDescription,\n    OperatorDescription,\n)\nfrom inference.core.workflows.core_steps.common.query_language.entities.operations import (\n    DoesNotExist,\n    Equals,\n    Exists,\n    In,\n    IsEmpty,\n    IsFalse,\n    IsNotEmpty,\n    IsTrue,\n    NotEquals,\n    NumberGreater,\n    NumberGreaterEqual,\n    NumberLower,\n    NumberLowerEqual,\n    OperationsChain,\n    StringContains,\n    StringEndsWith,\n    StringStartsWith,\n)\n\n\ndef _ref_to_def_name(\n    schema: dict,\n    ref_key: str = \"$ref\",\n) -> Optional[str]:\n    \"\"\"Extract definition name from a JSON Schema object's $ref (e.g. {'$ref': '#/$defs/Foo'} -> 'Foo').\"\"\"\n    ref = schema.get(ref_key)\n    if ref is None:\n        return None\n\n    return ref.split(\"/\")[-1]\n\n\ndef _get_property_name_options(\n    type_definition: dict,\n    defs: dict,\n) -> Optional[List[str]]:\n    \"\"\"Resolve property_name enum from operation schema when present (e.g. DetectionsProperty).\"\"\"\n    properties = type_definition.get(\"properties\") or {}\n    property_name_schema = properties.get(\"property_name\")\n\n    if not property_name_schema:\n        return None\n\n    ref_name = _ref_to_def_name(property_name_schema)\n    if ref_name is not None:\n        resolved = defs.get(ref_name)\n        if resolved and \"enum\" in resolved:\n            return list(resolved[\"enum\"])\n\n    if \"enum\" in property_name_schema:\n        return list(property_name_schema[\"enum\"])\n\n    return None\n\n\ndef prepare_operations_descriptions() -> List[OperationDescription]:\n    operations_chain_schema = OperationsChain.model_json_schema()\n    defs = operations_chain_schema.get(\"$defs\", {})\n    operation_type_definitions = operations_chain_schema[\"properties\"][\"operations\"][\"items\"][\"oneOf\"]  # fmt: skip\n\n    operation_types = [\n        name\n        for type_definition in operation_type_definitions\n        if (name := _ref_to_def_name(type_definition)) is not None\n    ]\n    type_definitions = [defs[operation_type] for operation_type in operation_types]\n\n    result = []\n    for type_definition in type_definitions:\n        property_name_options = _get_property_name_options(type_definition, defs)\n\n        result.append(\n            OperationDescription(\n                operation_type=type_definition[\"properties\"][\"type\"][\"const\"],\n                compound=type_definition.get(\"compound\", False),\n                input_kind=type_definition[\"input_kind\"],\n                output_kind=type_definition[\"output_kind\"],\n                nested_operation_input_kind=type_definition.get(\n                    \"nested_operation_input_kind\"\n                ),\n                nested_operation_output_kind=type_definition.get(\n                    \"nested_operation_output_kind\"\n                ),\n                property_name_options=property_name_options,\n            )\n        )\n    return result\n\n\ndef prepare_operators_descriptions() -> List[OperatorDescription]:\n    operator_types = [\n        In,\n        StringContains,\n        StringEndsWith,\n        StringStartsWith,\n        NumberLowerEqual,\n        NumberLower,\n        NumberGreaterEqual,\n        NumberGreater,\n        NotEquals,\n        Equals,\n        Exists,\n        DoesNotExist,\n        IsTrue,\n        IsFalse,\n        IsEmpty,\n        IsNotEmpty,\n    ]\n    results = []\n    for operator_type in operator_types:\n        operator_schema = operator_type.model_json_schema()\n        for alias in operator_schema[\"properties\"][\"type\"].get(\"enum\", []):\n            results.append(\n                OperatorDescription(\n                    operator_type=alias,\n                    operands_number=operator_schema[\"operands_number\"],\n                    operands_kinds=operator_schema[\"operands_kinds\"],\n                    description=operator_schema.get(\"description\"),\n                )\n            )\n    return results\n",
    "patch": null
  },
  {
    "trace_id": "e3f568b2-940b-40f9-955a-e8ff8c1aff99",
    "function_name": "_get_property_name_options",
    "file_path": "inference/core/workflows/core_steps/common/query_language/introspection/core.py",
    "speedup_x": 0.515270544551777,
    "review_quality": "high",
    "pre_optimization_commit": "aece4fff835fad9d67e1419e0a86528694765a2b",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def _get_property_name_options(\n    type_definition: dict,\n    defs: dict,\n) -> Optional[List[str]]:\n    \"\"\"Resolve property_name enum from operation schema when present (e.g. DetectionsProperty).\"\"\"\n    properties = type_definition.get(\"properties\") or {}\n    property_name_schema = properties.get(\"property_name\")\n\n    if not property_name_schema:\n        return None\n\n    ref_name = _ref_to_def_name(property_name_schema)\n    if ref_name is not None:\n        resolved = defs.get(ref_name)\n        if resolved and \"enum\" in resolved:\n            return list(resolved[\"enum\"])\n\n    if \"enum\" in property_name_schema:\n        return list(property_name_schema[\"enum\"])\n\n    return None\n",
    "optimized_function_code": "from typing import List, Optional\n\n\ndef _ref_to_def_name(\n    schema: dict,\n    ref_key: str = \"$ref\",\n) -> Optional[str]:\n    \"\"\"Extract definition name from a JSON Schema object's $ref (e.g. {'$ref': '#/$defs/Foo'} -> 'Foo').\"\"\"\n    ref = schema.get(ref_key)\n    if ref is None:\n        return None\n\n    return ref.split(\"/\")[-1]\n\n\ndef _get_property_name_options(\n    type_definition: dict,\n    defs: dict,\n) -> Optional[List[str]]:\n    \"\"\"Resolve property_name enum from operation schema when present (e.g. DetectionsProperty).\"\"\"\n    properties = type_definition.get(\"properties\")\n    if not properties:\n        return None\n    \n    property_name_schema = properties.get(\"property_name\")\n\n    if not property_name_schema:\n        return None\n\n    # Inline _ref_to_def_name to avoid function call overhead\n    ref = property_name_schema.get(\"$ref\")\n    if ref is not None:\n        ref_name = ref.split(\"/\")[-1]\n        resolved = defs.get(ref_name)\n        if resolved:\n            enum = resolved.get(\"enum\")\n            if enum is not None:\n                # Avoid unnecessary list conversion if already a list\n                return enum if isinstance(enum, list) else list(enum)\n\n    enum = property_name_schema.get(\"enum\")\n    if enum is not None:\n        # Avoid unnecessary list conversion if already a list\n        return enum if isinstance(enum, list) else list(enum)\n\n    return None",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/common/query_language/introspection/core.py\nfrom typing import List, Optional\n\n\ndef _ref_to_def_name(\n    schema: dict,\n    ref_key: str = \"$ref\",\n) -> Optional[str]:\n    \"\"\"Extract definition name from a JSON Schema object's $ref (e.g. {'$ref': '#/$defs/Foo'} -> 'Foo').\"\"\"\n    ref = schema.get(ref_key)\n    if ref is None:\n        return None\n\n    return ref.split(\"/\")[-1]\n\n\ndef _get_property_name_options(\n    type_definition: dict,\n    defs: dict,\n) -> Optional[List[str]]:\n    \"\"\"Resolve property_name enum from operation schema when present (e.g. DetectionsProperty).\"\"\"\n    properties = type_definition.get(\"properties\")\n    if not properties:\n        return None\n    \n    property_name_schema = properties.get(\"property_name\")\n\n    if not property_name_schema:\n        return None\n\n    # Inline _ref_to_def_name to avoid function call overhead\n    ref = property_name_schema.get(\"$ref\")\n    if ref is not None:\n        ref_name = ref.split(\"/\")[-1]\n        resolved = defs.get(ref_name)\n        if resolved:\n            enum = resolved.get(\"enum\")\n            if enum is not None:\n                # Avoid unnecessary list conversion if already a list\n                return enum if isinstance(enum, list) else list(enum)\n\n    enum = property_name_schema.get(\"enum\")\n    if enum is not None:\n        # Avoid unnecessary list conversion if already a list\n        return enum if isinstance(enum, list) else list(enum)\n\n    return None\n```",
    "optimized_function_only": "def _get_property_name_options(\n    type_definition: dict,\n    defs: dict,\n) -> Optional[List[str]]:\n    \"\"\"Resolve property_name enum from operation schema when present (e.g. DetectionsProperty).\"\"\"\n    properties = type_definition.get(\"properties\")\n    if not properties:\n        return None\n    \n    property_name_schema = properties.get(\"property_name\")\n\n    if not property_name_schema:\n        return None\n\n    # Inline _ref_to_def_name to avoid function call overhead\n    ref = property_name_schema.get(\"$ref\")\n    if ref is not None:\n        ref_name = ref.split(\"/\")[-1]\n        resolved = defs.get(ref_name)\n        if resolved:\n            enum = resolved.get(\"enum\")\n            if enum is not None:\n                # Avoid unnecessary list conversion if already a list\n                return enum if isinstance(enum, list) else list(enum)\n\n    enum = property_name_schema.get(\"enum\")\n    if enum is not None:\n        # Avoid unnecessary list conversion if already a list\n        return enum if isinstance(enum, list) else list(enum)\n\n    return None",
    "original_file_content": "from typing import List, Optional\n\nfrom inference.core.workflows.core_steps.common.query_language.entities.introspection import (\n    OperationDescription,\n    OperatorDescription,\n)\nfrom inference.core.workflows.core_steps.common.query_language.entities.operations import (\n    DoesNotExist,\n    Equals,\n    Exists,\n    In,\n    IsEmpty,\n    IsFalse,\n    IsNotEmpty,\n    IsTrue,\n    NotEquals,\n    NumberGreater,\n    NumberGreaterEqual,\n    NumberLower,\n    NumberLowerEqual,\n    OperationsChain,\n    StringContains,\n    StringEndsWith,\n    StringStartsWith,\n)\n\n\ndef _ref_to_def_name(\n    schema: dict,\n    ref_key: str = \"$ref\",\n) -> Optional[str]:\n    \"\"\"Extract definition name from a JSON Schema object's $ref (e.g. {'$ref': '#/$defs/Foo'} -> 'Foo').\"\"\"\n    ref = schema.get(ref_key)\n    if ref is None:\n        return None\n\n    return ref.split(\"/\")[-1]\n\n\ndef _get_property_name_options(\n    type_definition: dict,\n    defs: dict,\n) -> Optional[List[str]]:\n    \"\"\"Resolve property_name enum from operation schema when present (e.g. DetectionsProperty).\"\"\"\n    properties = type_definition.get(\"properties\") or {}\n    property_name_schema = properties.get(\"property_name\")\n\n    if not property_name_schema:\n        return None\n\n    ref_name = _ref_to_def_name(property_name_schema)\n    if ref_name is not None:\n        resolved = defs.get(ref_name)\n        if resolved and \"enum\" in resolved:\n            return list(resolved[\"enum\"])\n\n    if \"enum\" in property_name_schema:\n        return list(property_name_schema[\"enum\"])\n\n    return None\n\n\ndef prepare_operations_descriptions() -> List[OperationDescription]:\n    operations_chain_schema = OperationsChain.model_json_schema()\n    defs = operations_chain_schema.get(\"$defs\", {})\n    operation_type_definitions = operations_chain_schema[\"properties\"][\"operations\"][\"items\"][\"oneOf\"]  # fmt: skip\n\n    operation_types = [\n        name\n        for type_definition in operation_type_definitions\n        if (name := _ref_to_def_name(type_definition)) is not None\n    ]\n    type_definitions = [defs[operation_type] for operation_type in operation_types]\n\n    result = []\n    for type_definition in type_definitions:\n        property_name_options = _get_property_name_options(type_definition, defs)\n\n        result.append(\n            OperationDescription(\n                operation_type=type_definition[\"properties\"][\"type\"][\"const\"],\n                compound=type_definition.get(\"compound\", False),\n                input_kind=type_definition[\"input_kind\"],\n                output_kind=type_definition[\"output_kind\"],\n                nested_operation_input_kind=type_definition.get(\n                    \"nested_operation_input_kind\"\n                ),\n                nested_operation_output_kind=type_definition.get(\n                    \"nested_operation_output_kind\"\n                ),\n                property_name_options=property_name_options,\n            )\n        )\n    return result\n\n\ndef prepare_operators_descriptions() -> List[OperatorDescription]:\n    operator_types = [\n        In,\n        StringContains,\n        StringEndsWith,\n        StringStartsWith,\n        NumberLowerEqual,\n        NumberLower,\n        NumberGreaterEqual,\n        NumberGreater,\n        NotEquals,\n        Equals,\n        Exists,\n        DoesNotExist,\n        IsTrue,\n        IsFalse,\n        IsEmpty,\n        IsNotEmpty,\n    ]\n    results = []\n    for operator_type in operator_types:\n        operator_schema = operator_type.model_json_schema()\n        for alias in operator_schema[\"properties\"][\"type\"].get(\"enum\", []):\n            results.append(\n                OperatorDescription(\n                    operator_type=alias,\n                    operands_number=operator_schema[\"operands_number\"],\n                    operands_kinds=operator_schema[\"operands_kinds\"],\n                    description=operator_schema.get(\"description\"),\n                )\n            )\n    return results\n",
    "patch": null
  },
  {
    "trace_id": "0ae79dfb-0c76-4c4e-b97b-ace19c7704df",
    "function_name": "_ref_to_def_name",
    "file_path": "inference/core/workflows/core_steps/common/query_language/introspection/core.py",
    "speedup_x": 0.509847121327117,
    "review_quality": "high",
    "pre_optimization_commit": "aece4fff835fad9d67e1419e0a86528694765a2b",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def _ref_to_def_name(\n    schema: dict,\n    ref_key: str = \"$ref\",\n) -> Optional[str]:\n    \"\"\"Extract definition name from a JSON Schema object's $ref (e.g. {'$ref': '#/$defs/Foo'} -> 'Foo').\"\"\"\n    ref = schema.get(ref_key)\n    if ref is None:\n        return None\n\n    return ref.split(\"/\")[-1]\n",
    "optimized_function_code": "from typing import Optional\n\n\ndef _ref_to_def_name(\n    schema: dict,\n    ref_key: str = \"$ref\",\n) -> Optional[str]:\n    \"\"\"Extract definition name from a JSON Schema object's $ref (e.g. {'$ref': '#/$defs/Foo'} -> 'Foo').\"\"\"\n    ref = schema.get(ref_key)\n    if ref is None:\n        return None\n\n    return ref.rpartition(\"/\")[2]",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/common/query_language/introspection/core.py\nfrom typing import Optional\n\n\ndef _ref_to_def_name(\n    schema: dict,\n    ref_key: str = \"$ref\",\n) -> Optional[str]:\n    \"\"\"Extract definition name from a JSON Schema object's $ref (e.g. {'$ref': '#/$defs/Foo'} -> 'Foo').\"\"\"\n    ref = schema.get(ref_key)\n    if ref is None:\n        return None\n\n    return ref.rpartition(\"/\")[2]\n```",
    "optimized_function_only": "def _ref_to_def_name(\n    schema: dict,\n    ref_key: str = \"$ref\",\n) -> Optional[str]:\n    \"\"\"Extract definition name from a JSON Schema object's $ref (e.g. {'$ref': '#/$defs/Foo'} -> 'Foo').\"\"\"\n    ref = schema.get(ref_key)\n    if ref is None:\n        return None\n\n    return ref.rpartition(\"/\")[2]",
    "original_file_content": "from typing import List, Optional\n\nfrom inference.core.workflows.core_steps.common.query_language.entities.introspection import (\n    OperationDescription,\n    OperatorDescription,\n)\nfrom inference.core.workflows.core_steps.common.query_language.entities.operations import (\n    DoesNotExist,\n    Equals,\n    Exists,\n    In,\n    IsEmpty,\n    IsFalse,\n    IsNotEmpty,\n    IsTrue,\n    NotEquals,\n    NumberGreater,\n    NumberGreaterEqual,\n    NumberLower,\n    NumberLowerEqual,\n    OperationsChain,\n    StringContains,\n    StringEndsWith,\n    StringStartsWith,\n)\n\n\ndef _ref_to_def_name(\n    schema: dict,\n    ref_key: str = \"$ref\",\n) -> Optional[str]:\n    \"\"\"Extract definition name from a JSON Schema object's $ref (e.g. {'$ref': '#/$defs/Foo'} -> 'Foo').\"\"\"\n    ref = schema.get(ref_key)\n    if ref is None:\n        return None\n\n    return ref.split(\"/\")[-1]\n\n\ndef _get_property_name_options(\n    type_definition: dict,\n    defs: dict,\n) -> Optional[List[str]]:\n    \"\"\"Resolve property_name enum from operation schema when present (e.g. DetectionsProperty).\"\"\"\n    properties = type_definition.get(\"properties\") or {}\n    property_name_schema = properties.get(\"property_name\")\n\n    if not property_name_schema:\n        return None\n\n    ref_name = _ref_to_def_name(property_name_schema)\n    if ref_name is not None:\n        resolved = defs.get(ref_name)\n        if resolved and \"enum\" in resolved:\n            return list(resolved[\"enum\"])\n\n    if \"enum\" in property_name_schema:\n        return list(property_name_schema[\"enum\"])\n\n    return None\n\n\ndef prepare_operations_descriptions() -> List[OperationDescription]:\n    operations_chain_schema = OperationsChain.model_json_schema()\n    defs = operations_chain_schema.get(\"$defs\", {})\n    operation_type_definitions = operations_chain_schema[\"properties\"][\"operations\"][\"items\"][\"oneOf\"]  # fmt: skip\n\n    operation_types = [\n        name\n        for type_definition in operation_type_definitions\n        if (name := _ref_to_def_name(type_definition)) is not None\n    ]\n    type_definitions = [defs[operation_type] for operation_type in operation_types]\n\n    result = []\n    for type_definition in type_definitions:\n        property_name_options = _get_property_name_options(type_definition, defs)\n\n        result.append(\n            OperationDescription(\n                operation_type=type_definition[\"properties\"][\"type\"][\"const\"],\n                compound=type_definition.get(\"compound\", False),\n                input_kind=type_definition[\"input_kind\"],\n                output_kind=type_definition[\"output_kind\"],\n                nested_operation_input_kind=type_definition.get(\n                    \"nested_operation_input_kind\"\n                ),\n                nested_operation_output_kind=type_definition.get(\n                    \"nested_operation_output_kind\"\n                ),\n                property_name_options=property_name_options,\n            )\n        )\n    return result\n\n\ndef prepare_operators_descriptions() -> List[OperatorDescription]:\n    operator_types = [\n        In,\n        StringContains,\n        StringEndsWith,\n        StringStartsWith,\n        NumberLowerEqual,\n        NumberLower,\n        NumberGreaterEqual,\n        NumberGreater,\n        NotEquals,\n        Equals,\n        Exists,\n        DoesNotExist,\n        IsTrue,\n        IsFalse,\n        IsEmpty,\n        IsNotEmpty,\n    ]\n    results = []\n    for operator_type in operator_types:\n        operator_schema = operator_type.model_json_schema()\n        for alias in operator_schema[\"properties\"][\"type\"].get(\"enum\", []):\n            results.append(\n                OperatorDescription(\n                    operator_type=alias,\n                    operands_number=operator_schema[\"operands_number\"],\n                    operands_kinds=operator_schema[\"operands_kinds\"],\n                    description=operator_schema.get(\"description\"),\n                )\n            )\n    return results\n",
    "patch": null
  },
  {
    "trace_id": "e707fac9-0172-49c6-8a24-0abfc8cdb6d1",
    "function_name": "deduct_csv_header",
    "file_path": "inference/core/workflows/core_steps/sinks/s3/v1.py",
    "speedup_x": 7.9001437971153425,
    "review_quality": "high",
    "pre_optimization_commit": "639c8e77ab90d6a43f32fe55a355373ae74e0924",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def deduct_csv_header(content: str) -> str:\n    return \"\\n\".join(list(content.split(\"\\n\"))[1:])\n",
    "optimized_function_code": "def deduct_csv_header(content: str) -> str:\n    return content.partition(\"\\n\")[2]",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/sinks/s3/v1.py\ndef deduct_csv_header(content: str) -> str:\n    return content.partition(\"\\n\")[2]\n```",
    "optimized_function_only": "def deduct_csv_header(content: str) -> str:\n    return content.partition(\"\\n\")[2]",
    "original_file_content": "import json\nimport logging\nimport time\nfrom datetime import datetime\nfrom typing import Any, List, Literal, Optional, Type, Union\n\nimport boto3\nfrom botocore.exceptions import BotoCoreError, ClientError\nfrom pydantic import ConfigDict, Field, field_validator\n\nfrom inference.core.workflows.execution_engine.entities.base import OutputDefinition\nfrom inference.core.workflows.execution_engine.entities.types import (\n    BOOLEAN_KIND,\n    SECRET_KIND,\n    STRING_KIND,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nCONTENT_TYPES = {\n    \"csv\": \"text/csv\",\n    \"json\": \"application/json\",\n    \"jsonl\": \"application/x-ndjson\",\n    \"txt\": \"text/plain\",\n}\n\n# Errors that indicate a configuration or auth problem \u2014 retrying will not help.\nNON_RETRYABLE_CLIENT_ERROR_CODES = {\n    \"InvalidAccessKeyId\",\n    \"AccessDenied\",\n    \"NoSuchBucket\",\n    \"InvalidBucketName\",\n    \"SignatureDoesNotMatch\",\n    \"AuthFailure\",\n}\n\nMAX_UPLOAD_RETRIES = 3  # additional attempts after the initial try\nUPLOAD_RETRY_INITIAL_DELAY = 1.0  # seconds; doubles on each subsequent retry\n\nLONG_DESCRIPTION = \"\"\"\nSave workflow data directly to an AWS S3 bucket, supporting CSV, JSON, and text file formats with configurable output modes for aggregating multiple entries into single objects or saving each entry as a separate S3 object.\n\n## How This Block Works\n\nThis block uploads string content from workflow steps to S3 objects. The block:\n\n1. Takes string content (from formatters, predictions, or other string-producing blocks) and S3 configuration as input\n2. Connects to AWS S3 using the provided credentials (or the default AWS credential chain if none are supplied)\n3. Selects the appropriate upload strategy based on `output_mode`:\n   - **Separate Files Mode**: Creates a new S3 object for each input, generating unique keys with timestamps\n   - **Append Log Mode**: Buffers content in memory, uploading a complete object when `max_entries_per_file` is reached or when the block is destroyed\n4. For **separate files mode**: Generates a unique S3 key from the prefix, file name prefix, file type, and a timestamp, then uploads the content directly\n5. For **append log mode**:\n   - Buffers content entries in memory under a single S3 key\n   - Applies format-specific handling for appending:\n     - **CSV**: Removes the header row from subsequent appends (CSV content must include headers on first write)\n     - **JSON**: Converts to JSONL (JSON Lines) format, parsing and re-serializing each JSON document to fit on a single line\n     - **TXT**: Appends content directly with newlines\n   - Tracks entry count and uploads the full buffer as a complete S3 object when `max_entries_per_file` is reached, then starts a fresh buffer with a new key\n   - Uploads any remaining buffered data when the block is destroyed\n6. Returns error status and messages indicating save success or failure\n\nThe block supports two storage strategies: separate files mode creates individual timestamped S3 objects per input (useful for organizing outputs by execution), while append log mode accumulates entries in memory and writes them as complete S3 objects on rotation (useful for time-series logging with controlled upload frequency). S3 key names include timestamps (format: `YYYY_MM_DD_HH_MM_SS_microseconds`) for unique keys and chronological ordering.\n\n## AWS Credentials\n\nCredentials can be supplied in two ways:\n1. **Workflow inputs** \u2014 declare `aws_access_key_id` and `aws_secret_access_key` as workflow inputs of kind `parameter` and connect them to the corresponding fields. This keeps credentials out of the workflow definition and allows them to be supplied at runtime.\n2. **Secrets provider block** \u2014 connect the credential fields to the output of an `Environment Secrets Store` block, which reads values from server-side environment variables without embedding them in the workflow. Note: this is only available on self-hosted `inference` servers and cannot be used on the Roboflow hosted platform.\n\n## S3 Key Structure\n\nThe final S3 key is composed of:\n```\n{s3_prefix}/{file_name_prefix}_{timestamp}.{extension}\n```\nFor example, with `s3_prefix=\"logs/detections\"`, `file_name_prefix=\"run\"`, and `file_type=\"csv\"`:\n```\nlogs/detections/run_2024_10_18_14_09_57_622297.csv\n```\nIf `s3_prefix` is empty, the key starts directly with the file name.\n\n## Note on Append Log Mode\n\nIn append log mode, data is buffered in memory and only uploaded to S3 when:\n- The `max_entries_per_file` limit is reached (object rotation), or\n- The block instance is destroyed at workflow teardown\n\nThis means data may not be immediately visible in S3 after each step execution. Use `separate_files` mode if immediate S3 visibility is required.\n\n## Common Use Cases\n\n- **Cloud Data Logging**: Upload detection results, metrics, or workflow outputs directly to S3 for durable cloud storage and downstream processing\n- **Data Pipeline Integration**: Export formatted CSV or JSONL files to S3 for consumption by data pipelines, analytics tools, or ML training jobs\n- **Batch Result Archival**: Store individual inference results as separate S3 objects organized by timestamp and prefix\n- **Time-Series Collection**: Aggregate workflow outputs into batched JSONL or CSV files in S3 for cost-efficient log storage\n- **Cross-Service Integration**: Write data to S3 to trigger Lambda functions, feed SQS queues, or integrate with other AWS services\n\"\"\"\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"S3 Sink\",\n            \"version\": \"v1\",\n            \"short_description\": \"Upload data to an AWS S3 bucket.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"sink\",\n            \"ui_manifest\": {\n                \"section\": \"data_storage\",\n                \"icon\": \"fal fa-cloud-upload\",\n                \"blockPriority\": 4,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/s3_sink@v1\"]\n    content: Selector(kind=[STRING_KIND]) = Field(\n        description=\"String content to upload to S3. This should be formatted data from other workflow blocks (e.g., CSV content from CSV Formatter, JSON strings, or plain text). The content format should match the specified file_type. For CSV files in append_log mode, content must include header rows on the first write.\",\n        examples=[\"$steps.csv_formatter.csv_content\"],\n    )\n    file_type: Literal[\"csv\", \"json\", \"txt\"] = Field(\n        default=\"csv\",\n        description=\"Type of file to create: 'csv' (CSV format), 'json' (JSON format, or JSONL in append_log mode), or 'txt' (plain text). In append_log mode, JSON files are stored as .jsonl (JSON Lines) format with one JSON object per line.\",\n        examples=[\"csv\"],\n    )\n    output_mode: Literal[\"append_log\", \"separate_files\"] = Field(\n        description=\"Upload strategy: 'append_log' buffers multiple entries and uploads them as a single S3 object when the entry limit is reached (useful for batched logging), or 'separate_files' uploads each input as a new S3 object with a unique timestamp-based key (useful for per-execution outputs).\",\n        examples=[\"append_log\"],\n        json_schema_extra={\n            \"values_metadata\": {\n                \"append_log\": {\n                    \"name\": \"Append Log\",\n                    \"description\": \"Buffers multiple entries and uploads as a single S3 object on rotation\",\n                },\n                \"separate_files\": {\n                    \"name\": \"Separate File\",\n                    \"description\": \"Uploads a new S3 object for each input\",\n                },\n            }\n        },\n    )\n    bucket_name: Union[Selector(kind=[STRING_KIND]), str] = Field(\n        description=\"Name of the target S3 bucket. Can be a static string or a selector resolving to a string at runtime.\",\n        examples=[\"my-inference-results\"],\n    )\n    s3_prefix: Union[Selector(kind=[STRING_KIND]), str] = Field(\n        default=\"\",\n        description=\"S3 key prefix (folder path) where objects will be stored. Trailing slashes are normalized automatically. Combined with file_name_prefix and a timestamp to form the full object key. Example: 'logs/detections' produces keys like 'logs/detections/workflow_output_2024_10_18_14_09_57_622297.csv'.\",\n        examples=[\"logs/detections\"],\n        json_schema_extra={\n            \"always_visible\": True,\n        },\n    )\n    file_name_prefix: Union[Selector(kind=[STRING_KIND]), str] = Field(\n        default=\"workflow_output\",\n        description=\"Prefix used to generate S3 object names. Combined with a timestamp (format: YYYY_MM_DD_HH_MM_SS_microseconds) and file extension to create unique keys like 'workflow_output_2024_10_18_14_09_57_622297.csv'.\",\n        examples=[\"my_output\"],\n        json_schema_extra={\n            \"always_visible\": True,\n        },\n    )\n    max_entries_per_file: Union[int, Selector(kind=[STRING_KIND])] = Field(\n        default=1024,\n        description=\"Maximum number of buffered entries before uploading to S3 and starting a new object in append_log mode. When this limit is reached, the accumulated buffer is uploaded as a complete S3 object and a new buffer starts with a fresh key. Only applies when output_mode is 'append_log'. Must be at least 1.\",\n        examples=[1024],\n        json_schema_extra={\n            \"relevant_for\": {\n                \"output_mode\": {\n                    \"values\": [\"append_log\"],\n                    \"required\": True,\n                },\n            }\n        },\n    )\n    aws_access_key_id: Optional[\n        Union[Selector(kind=[SECRET_KIND, STRING_KIND]), str]\n    ] = Field(\n        default=None,\n        description=\"AWS access key ID for authentication. If not provided, boto3's default credential chain is used (environment variables, ~/.aws/credentials, or IAM role). Recommended: connect this to an Environment Secrets Store block rather than hardcoding.\",\n        examples=[\"$steps.secrets.aws_access_key_id\"],\n    )\n    aws_secret_access_key: Optional[\n        Union[Selector(kind=[SECRET_KIND, STRING_KIND]), str]\n    ] = Field(\n        default=None,\n        description=\"AWS secret access key for authentication. If not provided, boto3's default credential chain is used. Recommended: connect this to an Environment Secrets Store block rather than hardcoding.\",\n        examples=[\"$steps.secrets.aws_secret_access_key\"],\n    )\n    aws_region: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"AWS region where the bucket is located (e.g., 'us-east-1'). If not provided, boto3's default region is used (AWS_DEFAULT_REGION environment variable or ~/.aws/config).\",\n        examples=[\"us-east-1\"],\n    )\n\n    @field_validator(\"max_entries_per_file\")\n    @classmethod\n    def ensure_max_entries_per_file_is_correct(cls, value: Any) -> Any:\n        if isinstance(value, int) and value < 1:\n            raise ValueError(\"`max_entries_per_file` cannot be lower than 1.\")\n        return value\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"error_status\", kind=[BOOLEAN_KIND]),\n            OutputDefinition(name=\"message\", kind=[STRING_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass S3SinkBlockV1(WorkflowBlock):\n\n    def __init__(self):\n        self._buffer: List[str] = []\n        self._entries_in_buffer: int = 0\n        self._current_key: Optional[str] = None\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        content: str,\n        file_type: Literal[\"csv\", \"json\", \"txt\"],\n        output_mode: Literal[\"append_log\", \"separate_files\"],\n        bucket_name: str,\n        s3_prefix: str,\n        file_name_prefix: str,\n        max_entries_per_file: int,\n        aws_access_key_id: Optional[str] = None,\n        aws_secret_access_key: Optional[str] = None,\n        aws_region: Optional[str] = None,\n    ) -> BlockResult:\n        s3_client = create_s3_client(\n            aws_access_key_id=aws_access_key_id,\n            aws_secret_access_key=aws_secret_access_key,\n            aws_region=aws_region,\n        )\n\n        if output_mode == \"separate_files\":\n            return self._upload_separate_file(\n                s3_client=s3_client,\n                content=content,\n                file_type=file_type,\n                bucket_name=bucket_name,\n                s3_prefix=s3_prefix,\n                file_name_prefix=file_name_prefix,\n            )\n        return self._append_to_buffer(\n            s3_client=s3_client,\n            content=content,\n            file_type=file_type,\n            bucket_name=bucket_name,\n            s3_prefix=s3_prefix,\n            file_name_prefix=file_name_prefix,\n            max_entries_per_file=max_entries_per_file,\n        )\n\n    def _upload_separate_file(\n        self,\n        s3_client,\n        content: str,\n        file_type: Literal[\"csv\", \"json\", \"txt\"],\n        bucket_name: str,\n        s3_prefix: str,\n        file_name_prefix: str,\n    ) -> BlockResult:\n        s3_key = generate_s3_key(\n            s3_prefix=s3_prefix,\n            file_name_prefix=file_name_prefix,\n            file_type=file_type,\n        )\n        content_type = CONTENT_TYPES.get(file_type, \"text/plain\")\n        return upload_content_to_s3(\n            s3_client=s3_client,\n            bucket_name=bucket_name,\n            s3_key=s3_key,\n            content=content,\n            content_type=content_type,\n        )\n\n    def _append_to_buffer(\n        self,\n        s3_client,\n        content: str,\n        file_type: Literal[\"csv\", \"json\", \"txt\"],\n        bucket_name: str,\n        s3_prefix: str,\n        file_name_prefix: str,\n        max_entries_per_file: int,\n    ) -> BlockResult:\n        extension = file_type if file_type != \"json\" else \"jsonl\"\n        content_type = CONTENT_TYPES.get(extension, \"text/plain\")\n\n        if file_type == \"json\":\n            try:\n                content = dump_json_inline(content=content)\n            except Exception as error:\n                logging.warning(\n                    f\"Could not process JSON content in append mode: {error}\"\n                )\n                return {\"error_status\": True, \"message\": \"Invalid JSON content\"}\n\n        needs_rotation = (\n            self._current_key is not None\n            and self._entries_in_buffer >= max_entries_per_file\n        )\n        is_first_entry = self._current_key is None\n\n        if needs_rotation or is_first_entry:\n            self._buffer = []\n            self._entries_in_buffer = 0\n            self._current_key = generate_s3_key(\n                s3_prefix=s3_prefix,\n                file_name_prefix=file_name_prefix,\n                file_type=extension,\n            )\n        elif file_type == \"csv\":\n            content = deduct_csv_header(content=content)\n\n        if not content.endswith(\"\\n\"):\n            content = f\"{content}\\n\"\n        self._buffer.append(content)\n        self._entries_in_buffer += 1\n\n        # Always upload the full accumulated buffer so that every run() call\n        # validates credentials and permissions, and errors are surfaced immediately\n        # rather than only when the buffer rotation limit is reached.\n        full_content = \"\".join(self._buffer)\n        return upload_content_to_s3(\n            s3_client=s3_client,\n            bucket_name=bucket_name,\n            s3_key=self._current_key,\n            content=full_content,\n            content_type=content_type,\n        )\n\n\ndef create_s3_client(\n    aws_access_key_id: Optional[str],\n    aws_secret_access_key: Optional[str],\n    aws_region: Optional[str],\n):\n    kwargs = {}\n    if aws_access_key_id:\n        kwargs[\"aws_access_key_id\"] = aws_access_key_id\n    if aws_secret_access_key:\n        kwargs[\"aws_secret_access_key\"] = aws_secret_access_key\n    if aws_region:\n        kwargs[\"region_name\"] = aws_region\n    return boto3.client(\"s3\", **kwargs)\n\n\ndef generate_s3_key(s3_prefix: str, file_name_prefix: str, file_type: str) -> str:\n    timestamp = datetime.now().strftime(\"%Y_%m_%d_%H_%M_%S_%f\")\n    file_name = f\"{file_name_prefix.rstrip('/')}_{timestamp}.{file_type}\"\n    if s3_prefix:\n        prefix = s3_prefix.rstrip(\"/\")\n        return f\"{prefix}/{file_name}\"\n    return file_name\n\n\ndef upload_content_to_s3(\n    s3_client,\n    bucket_name: str,\n    s3_key: str,\n    content: str,\n    content_type: str,\n) -> dict:\n    content_bytes = content.encode(\"utf-8\")\n    last_error: Optional[Exception] = None\n    for attempt in range(1 + MAX_UPLOAD_RETRIES):\n        if attempt > 0:\n            delay = UPLOAD_RETRY_INITIAL_DELAY * (2 ** (attempt - 1))\n            logging.warning(\n                f\"Retrying S3 upload to s3://{bucket_name}/{s3_key} \"\n                f\"(attempt {attempt + 1}/{1 + MAX_UPLOAD_RETRIES}) after {delay:.1f}s...\"\n            )\n            time.sleep(delay)\n        try:\n            s3_client.put_object(\n                Bucket=bucket_name,\n                Key=s3_key,\n                Body=content_bytes,\n                ContentType=content_type,\n            )\n            return {\n                \"error_status\": False,\n                \"message\": f\"Data saved successfully to s3://{bucket_name}/{s3_key}\",\n            }\n        except ClientError as error:\n            error_code = error.response[\"Error\"][\"Code\"]\n            if error_code in NON_RETRYABLE_CLIENT_ERROR_CODES:\n                logging.warning(f\"Non-retryable S3 error ({error_code}): {error}\")\n                return {\"error_status\": True, \"message\": str(error)}\n            logging.warning(\n                f\"Retryable S3 error on attempt {attempt + 1}/{1 + MAX_UPLOAD_RETRIES} \"\n                f\"({error_code}): {error}\"\n            )\n            last_error = error\n        except BotoCoreError as error:\n            logging.warning(\n                f\"S3 connection error on attempt {attempt + 1}/{1 + MAX_UPLOAD_RETRIES}: {error}\"\n            )\n            last_error = error\n        except Exception as error:\n            logging.warning(f\"Unexpected error uploading to S3: {error}\")\n            return {\"error_status\": True, \"message\": str(error)}\n    return {\"error_status\": True, \"message\": str(last_error)}\n\n\ndef deduct_csv_header(content: str) -> str:\n    return \"\\n\".join(list(content.split(\"\\n\"))[1:])\n\n\ndef dump_json_inline(content: str) -> str:\n    parsed_content = json.loads(content)\n    return json.dumps(parsed_content)\n",
    "patch": null
  },
  {
    "trace_id": "05843692-aec2-4f30-bba2-79881e850fef",
    "function_name": "BlockManifest.describe_outputs",
    "file_path": "inference/core/workflows/core_steps/models/roboflow/semantic_segmentation/v1.py",
    "speedup_x": 20.922861442472072,
    "review_quality": "high",
    "pre_optimization_commit": "c20359386c628a08bde69f5f3f780cedd782c50c",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=INFERENCE_ID_KEY, kind=[INFERENCE_ID_KIND]),\n            OutputDefinition(\n                name=\"predictions\",\n                kind=[SEMANTIC_SEGMENTATION_PREDICTION_KIND],\n            ),\n            OutputDefinition(name=\"model_id\", kind=[ROBOFLOW_MODEL_ID_KIND]),\n        ]\n",
    "optimized_function_code": "from inference.core.workflows.execution_engine.constants import INFERENCE_ID_KEY\nfrom inference.core.workflows.execution_engine.entities.base import OutputDefinition\nfrom inference.core.workflows.execution_engine.entities.types import INFERENCE_ID_KIND, ROBOFLOW_MODEL_ID_KIND, SEMANTIC_SEGMENTATION_PREDICTION_KIND\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\nfrom typing import List\n\nLONG_DESCRIPTION = \"\"\"\nRun inference on a semantic segmentation model hosted on or uploaded to Roboflow.\n\nSemantic segmentation assigns a class label to every pixel in the image, producing a\ndense segmentation mask rather than per-object bounding boxes or instance masks.\n\nYou can query any model that is private to your account, or any public model available\non [Roboflow Universe](https://universe.roboflow.com).\n\nYou will need to set your Roboflow API key in your Inference environment to use this\nblock. To learn more about setting your Roboflow API key, [refer to the Inference\ndocumentation](https://inference.roboflow.com/quickstart/configure_api_key/).\n\"\"\"\n\n# Pre-construct output definitions to avoid repeated instantiation\n_OUTPUT_DEFINITIONS = [\n    OutputDefinition(name=INFERENCE_ID_KEY, kind=[INFERENCE_ID_KIND]),\n    OutputDefinition(\n        name=\"predictions\",\n        kind=[SEMANTIC_SEGMENTATION_PREDICTION_KIND],\n    ),\n    OutputDefinition(name=\"model_id\", kind=[ROBOFLOW_MODEL_ID_KIND]),\n]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return _OUTPUT_DEFINITIONS",
    "optimized_raw_markdown": "```python:inference/core/workflows/execution_engine/entities/base.py\nfrom inference.core.workflows.execution_engine.entities.types import Kind, WILDCARD_KIND\nfrom pydantic import BaseModel, Field\nfrom typing import List\n\nclass OutputDefinition(BaseModel):\n    name: str\n    kind: List[Kind] = Field(default_factory=lambda: [WILDCARD_KIND])\n```\n```python:inference/core/workflows/core_steps/models/roboflow/semantic_segmentation/v1.py\nfrom inference.core.workflows.execution_engine.constants import INFERENCE_ID_KEY\nfrom inference.core.workflows.execution_engine.entities.base import OutputDefinition\nfrom inference.core.workflows.execution_engine.entities.types import INFERENCE_ID_KIND, ROBOFLOW_MODEL_ID_KIND, SEMANTIC_SEGMENTATION_PREDICTION_KIND\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\nfrom typing import List\n\nLONG_DESCRIPTION = \"\"\"\nRun inference on a semantic segmentation model hosted on or uploaded to Roboflow.\n\nSemantic segmentation assigns a class label to every pixel in the image, producing a\ndense segmentation mask rather than per-object bounding boxes or instance masks.\n\nYou can query any model that is private to your account, or any public model available\non [Roboflow Universe](https://universe.roboflow.com).\n\nYou will need to set your Roboflow API key in your Inference environment to use this\nblock. To learn more about setting your Roboflow API key, [refer to the Inference\ndocumentation](https://inference.roboflow.com/quickstart/configure_api_key/).\n\"\"\"\n\n# Pre-construct output definitions to avoid repeated instantiation\n_OUTPUT_DEFINITIONS = [\n    OutputDefinition(name=INFERENCE_ID_KEY, kind=[INFERENCE_ID_KIND]),\n    OutputDefinition(\n        name=\"predictions\",\n        kind=[SEMANTIC_SEGMENTATION_PREDICTION_KIND],\n    ),\n    OutputDefinition(name=\"model_id\", kind=[ROBOFLOW_MODEL_ID_KIND]),\n]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return _OUTPUT_DEFINITIONS\n```",
    "optimized_function_only": "    def describe_outputs(cls) -> List[OutputDefinition]:\n        return _OUTPUT_DEFINITIONS",
    "original_file_content": "import base64\nfrom typing import Dict, List, Literal, Optional, Type, Union\nfrom uuid import uuid4\n\nimport cv2\nimport numpy as np\nimport pycocotools.mask as mask_utils\nimport supervision as sv\nfrom pydantic import ConfigDict\n\nfrom inference.core.entities.requests.inference import (\n    SemanticSegmentationInferenceRequest,\n)\nfrom inference.core.env import (\n    HOSTED_SEMANTIC_SEGMENTATION_URL,\n    LOCAL_INFERENCE_API_URL,\n    WORKFLOWS_REMOTE_API_TARGET,\n    WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_BATCH_SIZE,\n    WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS,\n)\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.entities import StepExecutionMode\nfrom inference.core.workflows.execution_engine.constants import (\n    DETECTION_ID_KEY,\n    INFERENCE_ID_KEY,\n    RLE_MASK_KEY_IN_SV_DETECTIONS,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    IMAGE_KIND,\n    INFERENCE_ID_KIND,\n    ROBOFLOW_MODEL_ID_KIND,\n    SEMANTIC_SEGMENTATION_PREDICTION_KIND,\n    ImageInputField,\n    RoboflowModelField,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\nfrom inference_sdk import InferenceConfiguration, InferenceHTTPClient\n\nLONG_DESCRIPTION = \"\"\"\nRun inference on a semantic segmentation model hosted on or uploaded to Roboflow.\n\nSemantic segmentation assigns a class label to every pixel in the image, producing a\ndense segmentation mask rather than per-object bounding boxes or instance masks.\n\nYou can query any model that is private to your account, or any public model available\non [Roboflow Universe](https://universe.roboflow.com).\n\nYou will need to set your Roboflow API key in your Inference environment to use this\nblock. To learn more about setting your Roboflow API key, [refer to the Inference\ndocumentation](https://inference.roboflow.com/quickstart/configure_api_key/).\n\"\"\"\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Semantic Segmentation Model\",\n            \"version\": \"v1\",\n            \"short_description\": \"Assign a class label to every pixel in the image.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"model\",\n            \"search_keywords\": [\"semantic\", \"segmentation\", \"deeplab\", \"deep_lab\"],\n            \"ui_manifest\": {\n                \"section\": \"model\",\n                \"icon\": \"far fa-paint-brush\",\n                \"blockPriority\": 3,\n                \"inference\": True,\n            },\n        },\n        protected_namespaces=(),\n    )\n    type: Literal[\"roboflow_core/roboflow_semantic_segmentation_model@v1\"]\n    images: Selector(kind=[IMAGE_KIND]) = ImageInputField\n    model_id: Union[Selector(kind=[ROBOFLOW_MODEL_ID_KIND]), str] = RoboflowModelField\n\n    @classmethod\n    def get_compatible_task_types(cls) -> Optional[List[str]]:\n        return [\"semantic-segmentation\"]\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return [\"images\"]\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=INFERENCE_ID_KEY, kind=[INFERENCE_ID_KIND]),\n            OutputDefinition(\n                name=\"predictions\",\n                kind=[SEMANTIC_SEGMENTATION_PREDICTION_KIND],\n            ),\n            OutputDefinition(name=\"model_id\", kind=[ROBOFLOW_MODEL_ID_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass RoboflowSemanticSegmentationModelBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"model_manager\", \"api_key\", \"step_execution_mode\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        model_id: str,\n    ) -> BlockResult:\n        if self._step_execution_mode is StepExecutionMode.LOCAL:\n            return self.run_locally(images=images, model_id=model_id)\n        elif self._step_execution_mode is StepExecutionMode.REMOTE:\n            return self.run_remotely(images=images, model_id=model_id)\n        else:\n            raise ValueError(\n                f\"Unknown step execution mode: {self._step_execution_mode}\"\n            )\n\n    def run_locally(\n        self,\n        images: Batch[WorkflowImageData],\n        model_id: str,\n    ) -> BlockResult:\n        inference_images = [i.to_inference_format(numpy_preferred=True) for i in images]\n        request = SemanticSegmentationInferenceRequest(\n            api_key=self._api_key,\n            model_id=model_id,\n            image=inference_images,\n            source=\"workflow-execution\",\n        )\n        self._model_manager.add_model(\n            model_id=model_id,\n            api_key=self._api_key,\n        )\n        predictions = self._model_manager.infer_from_request_sync(\n            model_id=model_id, request=request\n        )\n        if not isinstance(predictions, list):\n            predictions = [predictions]\n        predictions = [\n            e.model_dump(by_alias=True, exclude_none=True) for e in predictions\n        ]\n        return self._post_process_result(predictions=predictions, model_id=model_id)\n\n    def run_remotely(\n        self,\n        images: Batch[WorkflowImageData],\n        model_id: str,\n    ) -> BlockResult:\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_SEMANTIC_SEGMENTATION_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        client_config = InferenceConfiguration(\n            max_batch_size=WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_BATCH_SIZE,\n            max_concurrent_requests=WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS,\n            source=\"workflow-execution\",\n        )\n        client.configure(inference_configuration=client_config)\n        inference_images = [i.base64_image for i in images]\n        predictions = client.infer(\n            inference_input=inference_images,\n            model_id=model_id,\n        )\n        if not isinstance(predictions, list):\n            predictions = [predictions]\n        return self._post_process_result(predictions=predictions, model_id=model_id)\n\n    def _post_process_result(\n        self,\n        predictions: List[dict],\n        model_id: str,\n    ) -> BlockResult:\n        return [\n            {\n                INFERENCE_ID_KEY: prediction.get(INFERENCE_ID_KEY),\n                \"predictions\": self._convert_to_sv_detections(\n                    prediction.get(\"predictions\") or {}\n                ),\n                \"model_id\": model_id,\n            }\n            for prediction in predictions\n        ]\n\n    @staticmethod\n    def _convert_to_sv_detections(predictions_dict: Dict) -> sv.Detections:\n        seg_mask_b64 = predictions_dict.get(\"segmentation_mask\", \"\")\n        conf_mask_b64 = predictions_dict.get(\"confidence_mask\", \"\")\n        class_map: Dict[str, str] = predictions_dict.get(\"class_map\", {})\n\n        mask_bytes = base64.b64decode(seg_mask_b64)\n        nparr = np.frombuffer(mask_bytes, np.uint8)\n        mask_array = cv2.imdecode(nparr, cv2.IMREAD_GRAYSCALE)\n\n        if mask_array is None:\n            return sv.Detections.empty()\n\n        unique_class_ids = [cid for cid in np.unique(mask_array).tolist() if cid != 0]\n        if not unique_class_ids:\n            return sv.Detections.empty()\n\n        conf_array = None\n        if conf_mask_b64:\n            conf_bytes = base64.b64decode(conf_mask_b64)\n            conf_nparr = np.frombuffer(conf_bytes, np.uint8)\n            conf_array = cv2.imdecode(conf_nparr, cv2.IMREAD_GRAYSCALE)\n\n        xyxy_list, masks_list, class_id_list, class_name_list, confidence_list = (\n            [],\n            [],\n            [],\n            [],\n            [],\n        )\n        for class_id in unique_class_ids:\n            binary_mask = mask_array == class_id\n            # xyxy is a required sv.Detections field so we make a bounding box around the entire\n            # class mask even though this is not necessarily meaningful for non-contiguous masks.\n            rows = np.where(np.any(binary_mask, axis=1))[0]\n            cols = np.where(np.any(binary_mask, axis=0))[0]\n            xyxy_list.append([cols[0], rows[0], cols[-1], rows[-1]])\n            masks_list.append(binary_mask)\n            class_id_list.append(class_id)\n            class_name_list.append(class_map.get(str(class_id), str(class_id)))\n            if conf_array is not None:\n                confidence_list.append(float(conf_array[binary_mask].mean()) / 255.0)\n            else:\n                confidence_list.append(1.0)\n\n        rle_list = []\n        for mask in masks_list:\n            rle = mask_utils.encode(np.asfortranarray(mask.astype(np.uint8)))\n            rle[\"counts\"] = rle[\"counts\"].decode(\"utf-8\")\n            rle_list.append(rle)\n\n        detection_ids = np.array([str(uuid4()) for _ in class_id_list])\n        result = sv.Detections(\n            xyxy=np.array(xyxy_list, dtype=np.float64),\n            mask=None,\n            class_id=np.array(class_id_list),\n            confidence=np.array(confidence_list, dtype=np.float32),\n            data={\n                \"class_name\": np.array(class_name_list),\n                DETECTION_ID_KEY: detection_ids,\n                RLE_MASK_KEY_IN_SV_DETECTIONS: np.array(rle_list, dtype=object),\n            },\n        )\n\n        if conf_array is not None:\n            result[\"confidence_mask\"] = conf_array\n\n        return result\n",
    "patch": null
  },
  {
    "trace_id": "f1f66349-c618-4678-909f-fdbbf0cf50d9",
    "function_name": "S3SinkBlockV1._upload_separate_file",
    "file_path": "inference/core/workflows/core_steps/sinks/s3/v1.py",
    "speedup_x": 0.1538126447462854,
    "review_quality": "high",
    "pre_optimization_commit": "639c8e77ab90d6a43f32fe55a355373ae74e0924",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def _upload_separate_file(\n        self,\n        s3_client,\n        content: str,\n        file_type: Literal[\"csv\", \"json\", \"txt\"],\n        bucket_name: str,\n        s3_prefix: str,\n        file_name_prefix: str,\n    ) -> BlockResult:\n        s3_key = generate_s3_key(\n            s3_prefix=s3_prefix,\n            file_name_prefix=file_name_prefix,\n            file_type=file_type,\n        )\n        content_type = CONTENT_TYPES.get(file_type, \"text/plain\")\n        return upload_content_to_s3(\n            s3_client=s3_client,\n            bucket_name=bucket_name,\n            s3_key=s3_key,\n            content=content,\n            content_type=content_type,\n        )\n",
    "optimized_function_code": "import logging\nfrom datetime import datetime\nfrom typing import List, Literal, Optional\n\nfrom botocore.exceptions import BotoCoreError, ClientError\nfrom inference.core.workflows.prototypes.block import (BlockResult,\n                                                       WorkflowBlock)\n\nCONTENT_TYPES = {\n    \"csv\": \"text/csv\",\n    \"json\": \"application/json\",\n    \"jsonl\": \"application/x-ndjson\",\n    \"txt\": \"text/plain\",\n}\n\n\nclass S3SinkBlockV1(WorkflowBlock):\n\n    def __init__(self):\n        self._buffer: List[str] = []\n        self._entries_in_buffer: int = 0\n        self._current_key: Optional[str] = None\n\n    def _upload_separate_file(\n        self,\n        s3_client,\n        content: str,\n        file_type: Literal[\"csv\", \"json\", \"txt\"],\n        bucket_name: str,\n        s3_prefix: str,\n        file_name_prefix: str,\n    ) -> BlockResult:\n        s3_key = generate_s3_key(\n            s3_prefix=s3_prefix,\n            file_name_prefix=file_name_prefix,\n            file_type=file_type,\n        )\n        content_type = CONTENT_TYPES.get(file_type, \"text/plain\")\n        return upload_content_to_s3(\n            s3_client=s3_client,\n            bucket_name=bucket_name,\n            s3_key=s3_key,\n            content=content,\n            content_type=content_type,\n        )\n\n\ndef generate_s3_key(s3_prefix: str, file_name_prefix: str, file_type: str) -> str:\n    # Build the timestamp from datetime attributes to avoid strftime overhead.\n    dt = datetime.now()\n    timestamp = (\n        f\"{dt.year:04d}_{dt.month:02d}_{dt.day:02d}_\"\n        f\"{dt.hour:02d}_{dt.minute:02d}_{dt.second:02d}_\"\n        f\"{dt.microsecond:06d}\"\n    )\n    file_name = f\"{file_name_prefix}_{timestamp}.{file_type}\"\n    if s3_prefix:\n        prefix = s3_prefix.rstrip(\"/\")\n        return f\"{prefix}/{file_name}\"\n    return file_name\n\n\ndef upload_content_to_s3(\n    s3_client,\n    bucket_name: str,\n    s3_key: str,\n    content: str,\n    content_type: str,\n) -> dict:\n    try:\n        s3_client.put_object(\n            Bucket=bucket_name,\n            Key=s3_key,\n            Body=content.encode(\"utf-8\"),\n            ContentType=content_type,\n        )\n        return {\n            \"error_status\": False,\n            \"message\": f\"Data saved successfully to s3://{bucket_name}/{s3_key}\",\n        }\n    except (BotoCoreError, ClientError) as error:\n        err_str = str(error)\n        logging.warning(f\"Could not upload to S3: {err_str}\")\n        return {\"error_status\": True, \"message\": err_str}\n    except Exception as error:\n        err_str = str(error)\n        logging.warning(f\"Unexpected error uploading to S3: {err_str}\")\n        return {\"error_status\": True, \"message\": err_str}",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/sinks/s3/v1.py\nimport logging\nfrom datetime import datetime\nfrom typing import List, Literal, Optional\n\nfrom botocore.exceptions import BotoCoreError, ClientError\nfrom inference.core.workflows.prototypes.block import (BlockResult,\n                                                       WorkflowBlock)\n\nCONTENT_TYPES = {\n    \"csv\": \"text/csv\",\n    \"json\": \"application/json\",\n    \"jsonl\": \"application/x-ndjson\",\n    \"txt\": \"text/plain\",\n}\n\n\nclass S3SinkBlockV1(WorkflowBlock):\n\n    def __init__(self):\n        self._buffer: List[str] = []\n        self._entries_in_buffer: int = 0\n        self._current_key: Optional[str] = None\n\n    def _upload_separate_file(\n        self,\n        s3_client,\n        content: str,\n        file_type: Literal[\"csv\", \"json\", \"txt\"],\n        bucket_name: str,\n        s3_prefix: str,\n        file_name_prefix: str,\n    ) -> BlockResult:\n        s3_key = generate_s3_key(\n            s3_prefix=s3_prefix,\n            file_name_prefix=file_name_prefix,\n            file_type=file_type,\n        )\n        content_type = CONTENT_TYPES.get(file_type, \"text/plain\")\n        return upload_content_to_s3(\n            s3_client=s3_client,\n            bucket_name=bucket_name,\n            s3_key=s3_key,\n            content=content,\n            content_type=content_type,\n        )\n\n\ndef generate_s3_key(s3_prefix: str, file_name_prefix: str, file_type: str) -> str:\n    # Build the timestamp from datetime attributes to avoid strftime overhead.\n    dt = datetime.now()\n    timestamp = (\n        f\"{dt.year:04d}_{dt.month:02d}_{dt.day:02d}_\"\n        f\"{dt.hour:02d}_{dt.minute:02d}_{dt.second:02d}_\"\n        f\"{dt.microsecond:06d}\"\n    )\n    file_name = f\"{file_name_prefix}_{timestamp}.{file_type}\"\n    if s3_prefix:\n        prefix = s3_prefix.rstrip(\"/\")\n        return f\"{prefix}/{file_name}\"\n    return file_name\n\n\ndef upload_content_to_s3(\n    s3_client,\n    bucket_name: str,\n    s3_key: str,\n    content: str,\n    content_type: str,\n) -> dict:\n    try:\n        s3_client.put_object(\n            Bucket=bucket_name,\n            Key=s3_key,\n            Body=content.encode(\"utf-8\"),\n            ContentType=content_type,\n        )\n        return {\n            \"error_status\": False,\n            \"message\": f\"Data saved successfully to s3://{bucket_name}/{s3_key}\",\n        }\n    except (BotoCoreError, ClientError) as error:\n        err_str = str(error)\n        logging.warning(f\"Could not upload to S3: {err_str}\")\n        return {\"error_status\": True, \"message\": err_str}\n    except Exception as error:\n        err_str = str(error)\n        logging.warning(f\"Unexpected error uploading to S3: {err_str}\")\n        return {\"error_status\": True, \"message\": err_str}\n```",
    "optimized_function_only": "    def _upload_separate_file(\n        self,\n        s3_client,\n        content: str,\n        file_type: Literal[\"csv\", \"json\", \"txt\"],\n        bucket_name: str,\n        s3_prefix: str,\n        file_name_prefix: str,\n    ) -> BlockResult:\n        s3_key = generate_s3_key(\n            s3_prefix=s3_prefix,\n            file_name_prefix=file_name_prefix,\n            file_type=file_type,\n        )\n        content_type = CONTENT_TYPES.get(file_type, \"text/plain\")\n        return upload_content_to_s3(\n            s3_client=s3_client,\n            bucket_name=bucket_name,\n            s3_key=s3_key,\n            content=content,\n            content_type=content_type,\n        )\n",
    "original_file_content": "import json\nimport logging\nimport time\nfrom datetime import datetime\nfrom typing import Any, List, Literal, Optional, Type, Union\n\nimport boto3\nfrom botocore.exceptions import BotoCoreError, ClientError\nfrom pydantic import ConfigDict, Field, field_validator\n\nfrom inference.core.workflows.execution_engine.entities.base import OutputDefinition\nfrom inference.core.workflows.execution_engine.entities.types import (\n    BOOLEAN_KIND,\n    SECRET_KIND,\n    STRING_KIND,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nCONTENT_TYPES = {\n    \"csv\": \"text/csv\",\n    \"json\": \"application/json\",\n    \"jsonl\": \"application/x-ndjson\",\n    \"txt\": \"text/plain\",\n}\n\n# Errors that indicate a configuration or auth problem \u2014 retrying will not help.\nNON_RETRYABLE_CLIENT_ERROR_CODES = {\n    \"InvalidAccessKeyId\",\n    \"AccessDenied\",\n    \"NoSuchBucket\",\n    \"InvalidBucketName\",\n    \"SignatureDoesNotMatch\",\n    \"AuthFailure\",\n}\n\nMAX_UPLOAD_RETRIES = 3  # additional attempts after the initial try\nUPLOAD_RETRY_INITIAL_DELAY = 1.0  # seconds; doubles on each subsequent retry\n\nLONG_DESCRIPTION = \"\"\"\nSave workflow data directly to an AWS S3 bucket, supporting CSV, JSON, and text file formats with configurable output modes for aggregating multiple entries into single objects or saving each entry as a separate S3 object.\n\n## How This Block Works\n\nThis block uploads string content from workflow steps to S3 objects. The block:\n\n1. Takes string content (from formatters, predictions, or other string-producing blocks) and S3 configuration as input\n2. Connects to AWS S3 using the provided credentials (or the default AWS credential chain if none are supplied)\n3. Selects the appropriate upload strategy based on `output_mode`:\n   - **Separate Files Mode**: Creates a new S3 object for each input, generating unique keys with timestamps\n   - **Append Log Mode**: Buffers content in memory, uploading a complete object when `max_entries_per_file` is reached or when the block is destroyed\n4. For **separate files mode**: Generates a unique S3 key from the prefix, file name prefix, file type, and a timestamp, then uploads the content directly\n5. For **append log mode**:\n   - Buffers content entries in memory under a single S3 key\n   - Applies format-specific handling for appending:\n     - **CSV**: Removes the header row from subsequent appends (CSV content must include headers on first write)\n     - **JSON**: Converts to JSONL (JSON Lines) format, parsing and re-serializing each JSON document to fit on a single line\n     - **TXT**: Appends content directly with newlines\n   - Tracks entry count and uploads the full buffer as a complete S3 object when `max_entries_per_file` is reached, then starts a fresh buffer with a new key\n   - Uploads any remaining buffered data when the block is destroyed\n6. Returns error status and messages indicating save success or failure\n\nThe block supports two storage strategies: separate files mode creates individual timestamped S3 objects per input (useful for organizing outputs by execution), while append log mode accumulates entries in memory and writes them as complete S3 objects on rotation (useful for time-series logging with controlled upload frequency). S3 key names include timestamps (format: `YYYY_MM_DD_HH_MM_SS_microseconds`) for unique keys and chronological ordering.\n\n## AWS Credentials\n\nCredentials can be supplied in two ways:\n1. **Workflow inputs** \u2014 declare `aws_access_key_id` and `aws_secret_access_key` as workflow inputs of kind `parameter` and connect them to the corresponding fields. This keeps credentials out of the workflow definition and allows them to be supplied at runtime.\n2. **Secrets provider block** \u2014 connect the credential fields to the output of an `Environment Secrets Store` block, which reads values from server-side environment variables without embedding them in the workflow. Note: this is only available on self-hosted `inference` servers and cannot be used on the Roboflow hosted platform.\n\n## S3 Key Structure\n\nThe final S3 key is composed of:\n```\n{s3_prefix}/{file_name_prefix}_{timestamp}.{extension}\n```\nFor example, with `s3_prefix=\"logs/detections\"`, `file_name_prefix=\"run\"`, and `file_type=\"csv\"`:\n```\nlogs/detections/run_2024_10_18_14_09_57_622297.csv\n```\nIf `s3_prefix` is empty, the key starts directly with the file name.\n\n## Note on Append Log Mode\n\nIn append log mode, data is buffered in memory and only uploaded to S3 when:\n- The `max_entries_per_file` limit is reached (object rotation), or\n- The block instance is destroyed at workflow teardown\n\nThis means data may not be immediately visible in S3 after each step execution. Use `separate_files` mode if immediate S3 visibility is required.\n\n## Common Use Cases\n\n- **Cloud Data Logging**: Upload detection results, metrics, or workflow outputs directly to S3 for durable cloud storage and downstream processing\n- **Data Pipeline Integration**: Export formatted CSV or JSONL files to S3 for consumption by data pipelines, analytics tools, or ML training jobs\n- **Batch Result Archival**: Store individual inference results as separate S3 objects organized by timestamp and prefix\n- **Time-Series Collection**: Aggregate workflow outputs into batched JSONL or CSV files in S3 for cost-efficient log storage\n- **Cross-Service Integration**: Write data to S3 to trigger Lambda functions, feed SQS queues, or integrate with other AWS services\n\"\"\"\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"S3 Sink\",\n            \"version\": \"v1\",\n            \"short_description\": \"Upload data to an AWS S3 bucket.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"sink\",\n            \"ui_manifest\": {\n                \"section\": \"data_storage\",\n                \"icon\": \"fal fa-cloud-upload\",\n                \"blockPriority\": 4,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/s3_sink@v1\"]\n    content: Selector(kind=[STRING_KIND]) = Field(\n        description=\"String content to upload to S3. This should be formatted data from other workflow blocks (e.g., CSV content from CSV Formatter, JSON strings, or plain text). The content format should match the specified file_type. For CSV files in append_log mode, content must include header rows on the first write.\",\n        examples=[\"$steps.csv_formatter.csv_content\"],\n    )\n    file_type: Literal[\"csv\", \"json\", \"txt\"] = Field(\n        default=\"csv\",\n        description=\"Type of file to create: 'csv' (CSV format), 'json' (JSON format, or JSONL in append_log mode), or 'txt' (plain text). In append_log mode, JSON files are stored as .jsonl (JSON Lines) format with one JSON object per line.\",\n        examples=[\"csv\"],\n    )\n    output_mode: Literal[\"append_log\", \"separate_files\"] = Field(\n        description=\"Upload strategy: 'append_log' buffers multiple entries and uploads them as a single S3 object when the entry limit is reached (useful for batched logging), or 'separate_files' uploads each input as a new S3 object with a unique timestamp-based key (useful for per-execution outputs).\",\n        examples=[\"append_log\"],\n        json_schema_extra={\n            \"values_metadata\": {\n                \"append_log\": {\n                    \"name\": \"Append Log\",\n                    \"description\": \"Buffers multiple entries and uploads as a single S3 object on rotation\",\n                },\n                \"separate_files\": {\n                    \"name\": \"Separate File\",\n                    \"description\": \"Uploads a new S3 object for each input\",\n                },\n            }\n        },\n    )\n    bucket_name: Union[Selector(kind=[STRING_KIND]), str] = Field(\n        description=\"Name of the target S3 bucket. Can be a static string or a selector resolving to a string at runtime.\",\n        examples=[\"my-inference-results\"],\n    )\n    s3_prefix: Union[Selector(kind=[STRING_KIND]), str] = Field(\n        default=\"\",\n        description=\"S3 key prefix (folder path) where objects will be stored. Trailing slashes are normalized automatically. Combined with file_name_prefix and a timestamp to form the full object key. Example: 'logs/detections' produces keys like 'logs/detections/workflow_output_2024_10_18_14_09_57_622297.csv'.\",\n        examples=[\"logs/detections\"],\n        json_schema_extra={\n            \"always_visible\": True,\n        },\n    )\n    file_name_prefix: Union[Selector(kind=[STRING_KIND]), str] = Field(\n        default=\"workflow_output\",\n        description=\"Prefix used to generate S3 object names. Combined with a timestamp (format: YYYY_MM_DD_HH_MM_SS_microseconds) and file extension to create unique keys like 'workflow_output_2024_10_18_14_09_57_622297.csv'.\",\n        examples=[\"my_output\"],\n        json_schema_extra={\n            \"always_visible\": True,\n        },\n    )\n    max_entries_per_file: Union[int, Selector(kind=[STRING_KIND])] = Field(\n        default=1024,\n        description=\"Maximum number of buffered entries before uploading to S3 and starting a new object in append_log mode. When this limit is reached, the accumulated buffer is uploaded as a complete S3 object and a new buffer starts with a fresh key. Only applies when output_mode is 'append_log'. Must be at least 1.\",\n        examples=[1024],\n        json_schema_extra={\n            \"relevant_for\": {\n                \"output_mode\": {\n                    \"values\": [\"append_log\"],\n                    \"required\": True,\n                },\n            }\n        },\n    )\n    aws_access_key_id: Optional[\n        Union[Selector(kind=[SECRET_KIND, STRING_KIND]), str]\n    ] = Field(\n        default=None,\n        description=\"AWS access key ID for authentication. If not provided, boto3's default credential chain is used (environment variables, ~/.aws/credentials, or IAM role). Recommended: connect this to an Environment Secrets Store block rather than hardcoding.\",\n        examples=[\"$steps.secrets.aws_access_key_id\"],\n    )\n    aws_secret_access_key: Optional[\n        Union[Selector(kind=[SECRET_KIND, STRING_KIND]), str]\n    ] = Field(\n        default=None,\n        description=\"AWS secret access key for authentication. If not provided, boto3's default credential chain is used. Recommended: connect this to an Environment Secrets Store block rather than hardcoding.\",\n        examples=[\"$steps.secrets.aws_secret_access_key\"],\n    )\n    aws_region: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"AWS region where the bucket is located (e.g., 'us-east-1'). If not provided, boto3's default region is used (AWS_DEFAULT_REGION environment variable or ~/.aws/config).\",\n        examples=[\"us-east-1\"],\n    )\n\n    @field_validator(\"max_entries_per_file\")\n    @classmethod\n    def ensure_max_entries_per_file_is_correct(cls, value: Any) -> Any:\n        if isinstance(value, int) and value < 1:\n            raise ValueError(\"`max_entries_per_file` cannot be lower than 1.\")\n        return value\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"error_status\", kind=[BOOLEAN_KIND]),\n            OutputDefinition(name=\"message\", kind=[STRING_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass S3SinkBlockV1(WorkflowBlock):\n\n    def __init__(self):\n        self._buffer: List[str] = []\n        self._entries_in_buffer: int = 0\n        self._current_key: Optional[str] = None\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        content: str,\n        file_type: Literal[\"csv\", \"json\", \"txt\"],\n        output_mode: Literal[\"append_log\", \"separate_files\"],\n        bucket_name: str,\n        s3_prefix: str,\n        file_name_prefix: str,\n        max_entries_per_file: int,\n        aws_access_key_id: Optional[str] = None,\n        aws_secret_access_key: Optional[str] = None,\n        aws_region: Optional[str] = None,\n    ) -> BlockResult:\n        s3_client = create_s3_client(\n            aws_access_key_id=aws_access_key_id,\n            aws_secret_access_key=aws_secret_access_key,\n            aws_region=aws_region,\n        )\n\n        if output_mode == \"separate_files\":\n            return self._upload_separate_file(\n                s3_client=s3_client,\n                content=content,\n                file_type=file_type,\n                bucket_name=bucket_name,\n                s3_prefix=s3_prefix,\n                file_name_prefix=file_name_prefix,\n            )\n        return self._append_to_buffer(\n            s3_client=s3_client,\n            content=content,\n            file_type=file_type,\n            bucket_name=bucket_name,\n            s3_prefix=s3_prefix,\n            file_name_prefix=file_name_prefix,\n            max_entries_per_file=max_entries_per_file,\n        )\n\n    def _upload_separate_file(\n        self,\n        s3_client,\n        content: str,\n        file_type: Literal[\"csv\", \"json\", \"txt\"],\n        bucket_name: str,\n        s3_prefix: str,\n        file_name_prefix: str,\n    ) -> BlockResult:\n        s3_key = generate_s3_key(\n            s3_prefix=s3_prefix,\n            file_name_prefix=file_name_prefix,\n            file_type=file_type,\n        )\n        content_type = CONTENT_TYPES.get(file_type, \"text/plain\")\n        return upload_content_to_s3(\n            s3_client=s3_client,\n            bucket_name=bucket_name,\n            s3_key=s3_key,\n            content=content,\n            content_type=content_type,\n        )\n\n    def _append_to_buffer(\n        self,\n        s3_client,\n        content: str,\n        file_type: Literal[\"csv\", \"json\", \"txt\"],\n        bucket_name: str,\n        s3_prefix: str,\n        file_name_prefix: str,\n        max_entries_per_file: int,\n    ) -> BlockResult:\n        extension = file_type if file_type != \"json\" else \"jsonl\"\n        content_type = CONTENT_TYPES.get(extension, \"text/plain\")\n\n        if file_type == \"json\":\n            try:\n                content = dump_json_inline(content=content)\n            except Exception as error:\n                logging.warning(\n                    f\"Could not process JSON content in append mode: {error}\"\n                )\n                return {\"error_status\": True, \"message\": \"Invalid JSON content\"}\n\n        needs_rotation = (\n            self._current_key is not None\n            and self._entries_in_buffer >= max_entries_per_file\n        )\n        is_first_entry = self._current_key is None\n\n        if needs_rotation or is_first_entry:\n            self._buffer = []\n            self._entries_in_buffer = 0\n            self._current_key = generate_s3_key(\n                s3_prefix=s3_prefix,\n                file_name_prefix=file_name_prefix,\n                file_type=extension,\n            )\n        elif file_type == \"csv\":\n            content = deduct_csv_header(content=content)\n\n        if not content.endswith(\"\\n\"):\n            content = f\"{content}\\n\"\n        self._buffer.append(content)\n        self._entries_in_buffer += 1\n\n        # Always upload the full accumulated buffer so that every run() call\n        # validates credentials and permissions, and errors are surfaced immediately\n        # rather than only when the buffer rotation limit is reached.\n        full_content = \"\".join(self._buffer)\n        return upload_content_to_s3(\n            s3_client=s3_client,\n            bucket_name=bucket_name,\n            s3_key=self._current_key,\n            content=full_content,\n            content_type=content_type,\n        )\n\n\ndef create_s3_client(\n    aws_access_key_id: Optional[str],\n    aws_secret_access_key: Optional[str],\n    aws_region: Optional[str],\n):\n    kwargs = {}\n    if aws_access_key_id:\n        kwargs[\"aws_access_key_id\"] = aws_access_key_id\n    if aws_secret_access_key:\n        kwargs[\"aws_secret_access_key\"] = aws_secret_access_key\n    if aws_region:\n        kwargs[\"region_name\"] = aws_region\n    return boto3.client(\"s3\", **kwargs)\n\n\ndef generate_s3_key(s3_prefix: str, file_name_prefix: str, file_type: str) -> str:\n    timestamp = datetime.now().strftime(\"%Y_%m_%d_%H_%M_%S_%f\")\n    file_name = f\"{file_name_prefix.rstrip('/')}_{timestamp}.{file_type}\"\n    if s3_prefix:\n        prefix = s3_prefix.rstrip(\"/\")\n        return f\"{prefix}/{file_name}\"\n    return file_name\n\n\ndef upload_content_to_s3(\n    s3_client,\n    bucket_name: str,\n    s3_key: str,\n    content: str,\n    content_type: str,\n) -> dict:\n    content_bytes = content.encode(\"utf-8\")\n    last_error: Optional[Exception] = None\n    for attempt in range(1 + MAX_UPLOAD_RETRIES):\n        if attempt > 0:\n            delay = UPLOAD_RETRY_INITIAL_DELAY * (2 ** (attempt - 1))\n            logging.warning(\n                f\"Retrying S3 upload to s3://{bucket_name}/{s3_key} \"\n                f\"(attempt {attempt + 1}/{1 + MAX_UPLOAD_RETRIES}) after {delay:.1f}s...\"\n            )\n            time.sleep(delay)\n        try:\n            s3_client.put_object(\n                Bucket=bucket_name,\n                Key=s3_key,\n                Body=content_bytes,\n                ContentType=content_type,\n            )\n            return {\n                \"error_status\": False,\n                \"message\": f\"Data saved successfully to s3://{bucket_name}/{s3_key}\",\n            }\n        except ClientError as error:\n            error_code = error.response[\"Error\"][\"Code\"]\n            if error_code in NON_RETRYABLE_CLIENT_ERROR_CODES:\n                logging.warning(f\"Non-retryable S3 error ({error_code}): {error}\")\n                return {\"error_status\": True, \"message\": str(error)}\n            logging.warning(\n                f\"Retryable S3 error on attempt {attempt + 1}/{1 + MAX_UPLOAD_RETRIES} \"\n                f\"({error_code}): {error}\"\n            )\n            last_error = error\n        except BotoCoreError as error:\n            logging.warning(\n                f\"S3 connection error on attempt {attempt + 1}/{1 + MAX_UPLOAD_RETRIES}: {error}\"\n            )\n            last_error = error\n        except Exception as error:\n            logging.warning(f\"Unexpected error uploading to S3: {error}\")\n            return {\"error_status\": True, \"message\": str(error)}\n    return {\"error_status\": True, \"message\": str(last_error)}\n\n\ndef deduct_csv_header(content: str) -> str:\n    return \"\\n\".join(list(content.split(\"\\n\"))[1:])\n\n\ndef dump_json_inline(content: str) -> str:\n    parsed_content = json.loads(content)\n    return json.dumps(parsed_content)\n",
    "patch": null
  },
  {
    "trace_id": "e2ed6943-e598-4857-a03f-a932e8aa4dab",
    "function_name": "list_files",
    "file_path": "inference/core/managers/inference_models_cache_watchdog.py",
    "speedup_x": 0.6644900504969304,
    "review_quality": "high",
    "pre_optimization_commit": "5a720c57f76f195b877fd41ea082c5ca3ecac742",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def list_files(path: str) -> List[FileInfo]:\n    path = os.path.abspath(path)\n    if not os.path.exists(path):\n        return []\n    if os.path.islink(path):\n        return []\n    if os.path.isfile(path):\n        if path.endswith(LOCK_POSTFIX):\n            return []\n        stat = os.stat(path)\n        return [\n            FileInfo(\n                path=path,\n                size_mb=stat.st_size / BYTES_IN_MB,\n                modified_at=datetime.fromtimestamp(stat.st_mtime),\n            )\n        ]\n    results = []\n    for directory_path, directory_names, file_names in os.walk(path, followlinks=False):\n        for file_name in file_names:\n            file_path = os.path.join(directory_path, file_name)\n            if os.path.islink(file_path) or file_path.endswith(LOCK_POSTFIX):\n                continue\n            try:\n                stat = os.stat(file_path)\n            except OSError:\n                continue\n            results.append(\n                FileInfo(\n                    path=file_path,\n                    size_mb=stat.st_size / BYTES_IN_MB,\n                    modified_at=datetime.fromtimestamp(stat.st_mtime),\n                )\n            )\n    return results\n",
    "optimized_function_code": "import os\nfrom dataclasses import dataclass\nfrom datetime import datetime\nfrom typing import List\n\nBYTES_IN_MB = 1024 * 1024\nLOCK_POSTFIX = \".lock\"\n\n\n@dataclass(frozen=True)\nclass FileInfo:\n    path: str\n    size_mb: float\n    modified_at: datetime\n\n\ndef list_files(path: str) -> List[FileInfo]:\n    path = os.path.abspath(path)\n    if not os.path.exists(path):\n        return []\n    if os.path.islink(path):\n        return []\n    if os.path.isfile(path):\n        if path.endswith(LOCK_POSTFIX):\n            return []\n        stat = os.stat(path)\n        return [\n            FileInfo(\n                path=path,\n                size_mb=stat.st_size / BYTES_IN_MB,\n                modified_at=datetime.fromtimestamp(stat.st_mtime),\n            )\n        ]\n    results = []\n    bytes_in_mb = BYTES_IN_MB\n    lock_postfix = LOCK_POSTFIX\n    datetime_fromtimestamp = datetime.fromtimestamp\n    \n    def scan_directory(dir_path: str) -> None:\n        try:\n            with os.scandir(dir_path) as entries:\n                for entry in entries:\n                    if entry.is_symlink():\n                        continue\n                    if entry.is_file(follow_symlinks=False):\n                        if entry.name.endswith(lock_postfix):\n                            continue\n                        try:\n                            stat = entry.stat(follow_symlinks=False)\n                            results.append(\n                                FileInfo(\n                                    path=entry.path,\n                                    size_mb=stat.st_size / bytes_in_mb,\n                                    modified_at=datetime_fromtimestamp(stat.st_mtime),\n                                )\n                            )\n                        except OSError:\n                            continue\n                    elif entry.is_dir(follow_symlinks=False):\n                        scan_directory(entry.path)\n        except (OSError, PermissionError):\n            pass\n    \n    scan_directory(path)\n    return results",
    "optimized_raw_markdown": "```python:inference/core/managers/inference_models_cache_watchdog.py\nimport os\nfrom dataclasses import dataclass\nfrom datetime import datetime\nfrom typing import List\n\nBYTES_IN_MB = 1024 * 1024\nLOCK_POSTFIX = \".lock\"\n\n\n@dataclass(frozen=True)\nclass FileInfo:\n    path: str\n    size_mb: float\n    modified_at: datetime\n\n\ndef list_files(path: str) -> List[FileInfo]:\n    path = os.path.abspath(path)\n    if not os.path.exists(path):\n        return []\n    if os.path.islink(path):\n        return []\n    if os.path.isfile(path):\n        if path.endswith(LOCK_POSTFIX):\n            return []\n        stat = os.stat(path)\n        return [\n            FileInfo(\n                path=path,\n                size_mb=stat.st_size / BYTES_IN_MB,\n                modified_at=datetime.fromtimestamp(stat.st_mtime),\n            )\n        ]\n    results = []\n    bytes_in_mb = BYTES_IN_MB\n    lock_postfix = LOCK_POSTFIX\n    datetime_fromtimestamp = datetime.fromtimestamp\n    \n    def scan_directory(dir_path: str) -> None:\n        try:\n            with os.scandir(dir_path) as entries:\n                for entry in entries:\n                    if entry.is_symlink():\n                        continue\n                    if entry.is_file(follow_symlinks=False):\n                        if entry.name.endswith(lock_postfix):\n                            continue\n                        try:\n                            stat = entry.stat(follow_symlinks=False)\n                            results.append(\n                                FileInfo(\n                                    path=entry.path,\n                                    size_mb=stat.st_size / bytes_in_mb,\n                                    modified_at=datetime_fromtimestamp(stat.st_mtime),\n                                )\n                            )\n                        except OSError:\n                            continue\n                    elif entry.is_dir(follow_symlinks=False):\n                        scan_directory(entry.path)\n        except (OSError, PermissionError):\n            pass\n    \n    scan_directory(path)\n    return results\n```",
    "optimized_function_only": "def list_files(path: str) -> List[FileInfo]:\n    path = os.path.abspath(path)\n    if not os.path.exists(path):\n        return []\n    if os.path.islink(path):\n        return []\n    if os.path.isfile(path):\n        if path.endswith(LOCK_POSTFIX):\n            return []\n        stat = os.stat(path)\n        return [\n            FileInfo(\n                path=path,\n                size_mb=stat.st_size / BYTES_IN_MB,\n                modified_at=datetime.fromtimestamp(stat.st_mtime),\n            )\n        ]\n    results = []\n    bytes_in_mb = BYTES_IN_MB\n    lock_postfix = LOCK_POSTFIX\n    datetime_fromtimestamp = datetime.fromtimestamp\n    \n    def scan_directory(dir_path: str) -> None:\n        try:\n            with os.scandir(dir_path) as entries:\n                for entry in entries:\n                    if entry.is_symlink():\n                        continue\n                    if entry.is_file(follow_symlinks=False):\n                        if entry.name.endswith(lock_postfix):\n                            continue\n                        try:\n                            stat = entry.stat(follow_symlinks=False)\n                            results.append(\n                                FileInfo(\n                                    path=entry.path,\n                                    size_mb=stat.st_size / bytes_in_mb,\n                                    modified_at=datetime_fromtimestamp(stat.st_mtime),\n                                )\n                            )\n                        except OSError:\n                            continue\n                    elif entry.is_dir(follow_symlinks=False):\n                        scan_directory(entry.path)\n        except (OSError, PermissionError):\n            pass\n    \n    scan_directory(path)\n    return results",
    "original_file_content": "import os\nimport threading\nimport time\nfrom dataclasses import dataclass\nfrom datetime import datetime\nfrom enum import Enum\nfrom typing import List, Optional\n\nfrom filelock import FileLock\n\nfrom inference.core import logger\n\nSHARED_BLOBS_DIR = \"shared-blobs\"\nMODELS_CACHE_DIR = \"models-cache\"\nBYTES_IN_MB = 1024 * 1024\nSECONDS_IN_DAY = 60 * 60 * 24\nSECONDS_IN_MIN = 60\nLOCK_POSTFIX = \".lock\"\nRECENT_THRESHOLD_DAYS = 1\nWARM_THRESHOLD_DAYS = 7\nSTALE_THRESHOLD_DAYS = 30\nMIN_PURGE_INTERVAL_MINUTES = 15\n\n\n@dataclass(frozen=True)\nclass FileInfo:\n    path: str\n    size_mb: float\n    modified_at: datetime\n\n\nclass StalenessGroup(Enum):\n    ABANDONED = 0\n    STALE = 1\n    WARM = 2\n    RECENT = 3\n\n\nclass InferenceModelsCacheWatchdog:\n\n    def __init__(\n        self,\n        inference_home: str,\n        max_cache_size_mb: int,\n        interval_minutes: float,\n    ):\n        if interval_minutes < MIN_PURGE_INTERVAL_MINUTES:\n            logger.warning(\n                f\"Requested purge interval {interval_minutes}min is below minimum \"\n                f\"{MIN_PURGE_INTERVAL_MINUTES}min - falling back to minimum.\"\n            )\n            interval_minutes = MIN_PURGE_INTERVAL_MINUTES\n        self._inference_home = inference_home\n        self._max_cache_size_mb = max_cache_size_mb\n        self._interval_seconds = interval_minutes * SECONDS_IN_MIN\n        self._stop_event = threading.Event()\n        self._thread: Optional[threading.Thread] = None\n\n    def start(self) -> None:\n        if self._thread is not None and self._thread.is_alive():\n            logger.warning(\"Cache purge daemon is already running\")\n            return\n        self._stop_event.clear()\n        self._thread = threading.Thread(\n            target=self._run_loop,\n            daemon=True,\n            name=\"cache-purge-daemon\",\n        )\n        self._thread.start()\n        logger.info(\n            f\"Cache purge daemon started - interval: {self._interval_seconds}s, \"\n            f\"max cache size: {self._max_cache_size_mb}MB\"\n        )\n\n    def stop(self, timeout: Optional[float] = None) -> None:\n        self._stop_event.set()\n        if self._thread is not None:\n            self._thread.join(timeout=timeout)\n            self._thread = None\n        logger.info(\"Cache purge daemon stopped\")\n\n    def _run_loop(self) -> None:\n        while not self._stop_event.is_set():\n            cycle_start = time.monotonic()\n            try:\n                purge_inference_models_cache(\n                    inference_home=self._inference_home,\n                    max_cache_size_mb=self._max_cache_size_mb,\n                )\n            except Exception as e:\n                logger.error(f\"Cache purge cycle failed: {e}\", exc_info=True)\n            elapsed = time.monotonic() - cycle_start\n            remaining = self._interval_seconds - elapsed\n            if remaining <= 0:\n                logger.warning(\n                    f\"Cache purge took {elapsed}s, exceeding interval \"\n                    f\"of {self._interval_seconds}s - skipping next cycle\"\n                )\n                remaining = self._interval_seconds\n            self._stop_event.wait(timeout=remaining)\n\n\ndef purge_inference_models_cache(\n    inference_home: str,\n    max_cache_size_mb: int,\n) -> None:\n    directories_to_investigate = [\n        os.path.abspath(os.path.join(inference_home, SHARED_BLOBS_DIR)),\n        os.path.abspath(os.path.join(inference_home, MODELS_CACHE_DIR)),\n    ]\n    cache_index = build_current_cache_index(\n        directories_to_investigate=directories_to_investigate\n    )\n    current_cache_size = summarize_disk_size(files_info=cache_index)\n    if current_cache_size <= max_cache_size_mb:\n        logger.info(\n            f\"Purging inference models cache skipped - current {round(current_cache_size, 2)}MB, \"\n            f\"limit: {round(max_cache_size_mb, 2)}MB\"\n        )\n        return None\n    to_be_reclaimed = current_cache_size - max_cache_size_mb\n    cache_index_ranked = rank_for_deletion(files=cache_index)\n    nominated_for_deletion = nominate_files_for_deletion(\n        files=cache_index_ranked, to_be_reclaimed=to_be_reclaimed\n    )\n    purged = purge_files(files=nominated_for_deletion)\n    if purged < to_be_reclaimed:\n        logger.warning(\n            \"Could not fully purge inference-models cache - expected size to be reclaimed: \"\n            f\"{round(to_be_reclaimed, 2)}MB, actual reclaimed: {round(purged, 2)}MB\"\n        )\n    else:\n        logger.info(f\"Purge complete - reclaimed {round(purged, 2)}MB.\")\n    return None\n\n\ndef build_current_cache_index(\n    directories_to_investigate: List[str],\n) -> List[FileInfo]:\n    results = []\n    for directory_path in directories_to_investigate:\n        results.extend(list_files(path=directory_path))\n    return results\n\n\ndef list_files(path: str) -> List[FileInfo]:\n    path = os.path.abspath(path)\n    if not os.path.exists(path):\n        return []\n    if os.path.islink(path):\n        return []\n    if os.path.isfile(path):\n        if path.endswith(LOCK_POSTFIX):\n            return []\n        stat = os.stat(path)\n        return [\n            FileInfo(\n                path=path,\n                size_mb=stat.st_size / BYTES_IN_MB,\n                modified_at=datetime.fromtimestamp(stat.st_mtime),\n            )\n        ]\n    results = []\n    for directory_path, directory_names, file_names in os.walk(path, followlinks=False):\n        for file_name in file_names:\n            file_path = os.path.join(directory_path, file_name)\n            if os.path.islink(file_path) or file_path.endswith(LOCK_POSTFIX):\n                continue\n            try:\n                stat = os.stat(file_path)\n            except OSError:\n                continue\n            results.append(\n                FileInfo(\n                    path=file_path,\n                    size_mb=stat.st_size / BYTES_IN_MB,\n                    modified_at=datetime.fromtimestamp(stat.st_mtime),\n                )\n            )\n    return results\n\n\ndef summarize_disk_size(files_info: List[FileInfo]) -> float:\n    result = 0\n    for file_info in files_info:\n        result += file_info.size_mb\n    return result\n\n\ndef rank_for_deletion(\n    files: List[FileInfo],\n    now: Optional[datetime] = None,\n    recent_threshold_days: float = RECENT_THRESHOLD_DAYS,\n    warm_threshold_days: float = WARM_THRESHOLD_DAYS,\n    stale_threshold_days: float = STALE_THRESHOLD_DAYS,\n) -> List[FileInfo]:\n    if not files:\n        return []\n    if now is None:\n        now = datetime.now()\n\n    if not (recent_threshold_days < warm_threshold_days < stale_threshold_days):\n        raise ValueError(\n            f\"Thresholds must be in ascending order: \"\n            f\"recent ({recent_threshold_days}) < warm ({warm_threshold_days}) < stale ({stale_threshold_days})\"\n        )\n\n    def staleness_group(file_info: FileInfo) -> int:\n        age_days = (now - file_info.modified_at).total_seconds() / SECONDS_IN_DAY\n        if age_days > stale_threshold_days:\n            return StalenessGroup.ABANDONED.value\n        if age_days > warm_threshold_days:\n            return StalenessGroup.STALE.value\n        if age_days > recent_threshold_days:\n            return StalenessGroup.WARM.value\n        return StalenessGroup.RECENT.value\n\n    return sorted(files, key=lambda f: (staleness_group(f), -f.size_mb))\n\n\ndef nominate_files_for_deletion(\n    files: List[FileInfo], to_be_reclaimed: float\n) -> List[FileInfo]:\n    reclaimed = 0\n    to_delete = []\n    for file in files:\n        if reclaimed >= to_be_reclaimed:\n            break\n        to_delete.append(file)\n        reclaimed += file.size_mb\n    return to_delete\n\n\ndef purge_files(files: List[FileInfo], file_lock_acquire_timeout: int = 3) -> float:\n    result = 0\n    for file in files:\n        try:\n            file_absolute_path = os.path.abspath(file.path)\n            file_directory = os.path.dirname(file_absolute_path)\n            file_name = os.path.basename(file_absolute_path)\n            lock_path = os.path.join(file_directory, f\".{file_name}{LOCK_POSTFIX}\")\n            with FileLock(lock_path, timeout=file_lock_acquire_timeout):\n                os.remove(file.path)\n            result += file.size_mb\n        except FileNotFoundError:\n            pass\n        except Exception as e:\n            logger.warning(f\"Failed to purge cache file {file.path}: {e}\")\n    return result\n",
    "patch": null
  },
  {
    "trace_id": "f2e3e32d-e049-4f44-9060-3c90e3692762",
    "function_name": "rank_for_deletion",
    "file_path": "inference/core/managers/inference_models_cache_watchdog.py",
    "speedup_x": 0.8837321480253403,
    "review_quality": "high",
    "pre_optimization_commit": "5a720c57f76f195b877fd41ea082c5ca3ecac742",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def rank_for_deletion(\n    files: List[FileInfo],\n    now: Optional[datetime] = None,\n    recent_threshold_days: float = RECENT_THRESHOLD_DAYS,\n    warm_threshold_days: float = WARM_THRESHOLD_DAYS,\n    stale_threshold_days: float = STALE_THRESHOLD_DAYS,\n) -> List[FileInfo]:\n    if not files:\n        return []\n    if now is None:\n        now = datetime.now()\n\n    if not (recent_threshold_days < warm_threshold_days < stale_threshold_days):\n        raise ValueError(\n            f\"Thresholds must be in ascending order: \"\n            f\"recent ({recent_threshold_days}) < warm ({warm_threshold_days}) < stale ({stale_threshold_days})\"\n        )\n\n    def staleness_group(file_info: FileInfo) -> int:\n        age_days = (now - file_info.modified_at).total_seconds() / SECONDS_IN_DAY\n        if age_days > stale_threshold_days:\n            return StalenessGroup.ABANDONED.value\n        if age_days > warm_threshold_days:\n            return StalenessGroup.STALE.value\n        if age_days > recent_threshold_days:\n            return StalenessGroup.WARM.value\n        return StalenessGroup.RECENT.value\n\n    return sorted(files, key=lambda f: (staleness_group(f), -f.size_mb))\n",
    "optimized_function_code": "from dataclasses import dataclass\nfrom datetime import datetime, timedelta\nfrom enum import Enum\nfrom typing import List, Optional\n\nSECONDS_IN_DAY = 60 * 60 * 24\nRECENT_THRESHOLD_DAYS = 1\nWARM_THRESHOLD_DAYS = 7\nSTALE_THRESHOLD_DAYS = 30\n\n\n@dataclass(frozen=True)\nclass FileInfo:\n    path: str\n    size_mb: float\n    modified_at: datetime\n\n\nclass StalenessGroup(Enum):\n    ABANDONED = 0\n    STALE = 1\n    WARM = 2\n    RECENT = 3\n\n\ndef rank_for_deletion(\n    files: List[FileInfo],\n    now: Optional[datetime] = None,\n    recent_threshold_days: float = RECENT_THRESHOLD_DAYS,\n    warm_threshold_days: float = WARM_THRESHOLD_DAYS,\n    stale_threshold_days: float = STALE_THRESHOLD_DAYS,\n) -> List[FileInfo]:\n    if not files:\n        return []\n    if now is None:\n        now = datetime.now()\n\n    if not (recent_threshold_days < warm_threshold_days < stale_threshold_days):\n        raise ValueError(\n            f\"Thresholds must be in ascending order: \"\n            f\"recent ({recent_threshold_days}) < warm ({warm_threshold_days}) < stale ({stale_threshold_days})\"\n        )\n\n    # Precompute cutoff datetimes to avoid per-file float/timedelta allocation and division.\n    stale_cutoff = now - timedelta(seconds=stale_threshold_days * SECONDS_IN_DAY)\n    warm_cutoff = now - timedelta(seconds=warm_threshold_days * SECONDS_IN_DAY)\n    recent_cutoff = now - timedelta(seconds=recent_threshold_days * SECONDS_IN_DAY)\n\n    # Inline staleness grouping in the key to avoid an extra function call per file.\n    return sorted(\n        files,\n        key=lambda f: (\n            0 if f.modified_at < stale_cutoff\n            else 1 if f.modified_at < warm_cutoff\n            else 2 if f.modified_at < recent_cutoff\n            else 3,\n            -f.size_mb,\n        ),\n    )",
    "optimized_raw_markdown": "```python:inference/core/managers/inference_models_cache_watchdog.py\nfrom dataclasses import dataclass\nfrom datetime import datetime, timedelta\nfrom enum import Enum\nfrom typing import List, Optional\n\nSECONDS_IN_DAY = 60 * 60 * 24\nRECENT_THRESHOLD_DAYS = 1\nWARM_THRESHOLD_DAYS = 7\nSTALE_THRESHOLD_DAYS = 30\n\n\n@dataclass(frozen=True)\nclass FileInfo:\n    path: str\n    size_mb: float\n    modified_at: datetime\n\n\nclass StalenessGroup(Enum):\n    ABANDONED = 0\n    STALE = 1\n    WARM = 2\n    RECENT = 3\n\n\ndef rank_for_deletion(\n    files: List[FileInfo],\n    now: Optional[datetime] = None,\n    recent_threshold_days: float = RECENT_THRESHOLD_DAYS,\n    warm_threshold_days: float = WARM_THRESHOLD_DAYS,\n    stale_threshold_days: float = STALE_THRESHOLD_DAYS,\n) -> List[FileInfo]:\n    if not files:\n        return []\n    if now is None:\n        now = datetime.now()\n\n    if not (recent_threshold_days < warm_threshold_days < stale_threshold_days):\n        raise ValueError(\n            f\"Thresholds must be in ascending order: \"\n            f\"recent ({recent_threshold_days}) < warm ({warm_threshold_days}) < stale ({stale_threshold_days})\"\n        )\n\n    # Precompute cutoff datetimes to avoid per-file float/timedelta allocation and division.\n    stale_cutoff = now - timedelta(seconds=stale_threshold_days * SECONDS_IN_DAY)\n    warm_cutoff = now - timedelta(seconds=warm_threshold_days * SECONDS_IN_DAY)\n    recent_cutoff = now - timedelta(seconds=recent_threshold_days * SECONDS_IN_DAY)\n\n    # Inline staleness grouping in the key to avoid an extra function call per file.\n    return sorted(\n        files,\n        key=lambda f: (\n            0 if f.modified_at < stale_cutoff\n            else 1 if f.modified_at < warm_cutoff\n            else 2 if f.modified_at < recent_cutoff\n            else 3,\n            -f.size_mb,\n        ),\n    )\n```",
    "optimized_function_only": "def rank_for_deletion(\n    files: List[FileInfo],\n    now: Optional[datetime] = None,\n    recent_threshold_days: float = RECENT_THRESHOLD_DAYS,\n    warm_threshold_days: float = WARM_THRESHOLD_DAYS,\n    stale_threshold_days: float = STALE_THRESHOLD_DAYS,\n) -> List[FileInfo]:\n    if not files:\n        return []\n    if now is None:\n        now = datetime.now()\n\n    if not (recent_threshold_days < warm_threshold_days < stale_threshold_days):\n        raise ValueError(\n            f\"Thresholds must be in ascending order: \"\n            f\"recent ({recent_threshold_days}) < warm ({warm_threshold_days}) < stale ({stale_threshold_days})\"\n        )\n\n    # Precompute cutoff datetimes to avoid per-file float/timedelta allocation and division.\n    stale_cutoff = now - timedelta(seconds=stale_threshold_days * SECONDS_IN_DAY)\n    warm_cutoff = now - timedelta(seconds=warm_threshold_days * SECONDS_IN_DAY)\n    recent_cutoff = now - timedelta(seconds=recent_threshold_days * SECONDS_IN_DAY)\n\n    # Inline staleness grouping in the key to avoid an extra function call per file.\n    return sorted(\n        files,\n        key=lambda f: (\n            0 if f.modified_at < stale_cutoff\n            else 1 if f.modified_at < warm_cutoff\n            else 2 if f.modified_at < recent_cutoff\n            else 3,\n            -f.size_mb,\n        ),\n    )",
    "original_file_content": "import os\nimport threading\nimport time\nfrom dataclasses import dataclass\nfrom datetime import datetime\nfrom enum import Enum\nfrom typing import List, Optional\n\nfrom filelock import FileLock\n\nfrom inference.core import logger\n\nSHARED_BLOBS_DIR = \"shared-blobs\"\nMODELS_CACHE_DIR = \"models-cache\"\nBYTES_IN_MB = 1024 * 1024\nSECONDS_IN_DAY = 60 * 60 * 24\nSECONDS_IN_MIN = 60\nLOCK_POSTFIX = \".lock\"\nRECENT_THRESHOLD_DAYS = 1\nWARM_THRESHOLD_DAYS = 7\nSTALE_THRESHOLD_DAYS = 30\nMIN_PURGE_INTERVAL_MINUTES = 15\n\n\n@dataclass(frozen=True)\nclass FileInfo:\n    path: str\n    size_mb: float\n    modified_at: datetime\n\n\nclass StalenessGroup(Enum):\n    ABANDONED = 0\n    STALE = 1\n    WARM = 2\n    RECENT = 3\n\n\nclass InferenceModelsCacheWatchdog:\n\n    def __init__(\n        self,\n        inference_home: str,\n        max_cache_size_mb: int,\n        interval_minutes: float,\n    ):\n        if interval_minutes < MIN_PURGE_INTERVAL_MINUTES:\n            logger.warning(\n                f\"Requested purge interval {interval_minutes}min is below minimum \"\n                f\"{MIN_PURGE_INTERVAL_MINUTES}min - falling back to minimum.\"\n            )\n            interval_minutes = MIN_PURGE_INTERVAL_MINUTES\n        self._inference_home = inference_home\n        self._max_cache_size_mb = max_cache_size_mb\n        self._interval_seconds = interval_minutes * SECONDS_IN_MIN\n        self._stop_event = threading.Event()\n        self._thread: Optional[threading.Thread] = None\n\n    def start(self) -> None:\n        if self._thread is not None and self._thread.is_alive():\n            logger.warning(\"Cache purge daemon is already running\")\n            return\n        self._stop_event.clear()\n        self._thread = threading.Thread(\n            target=self._run_loop,\n            daemon=True,\n            name=\"cache-purge-daemon\",\n        )\n        self._thread.start()\n        logger.info(\n            f\"Cache purge daemon started - interval: {self._interval_seconds}s, \"\n            f\"max cache size: {self._max_cache_size_mb}MB\"\n        )\n\n    def stop(self, timeout: Optional[float] = None) -> None:\n        self._stop_event.set()\n        if self._thread is not None:\n            self._thread.join(timeout=timeout)\n            self._thread = None\n        logger.info(\"Cache purge daemon stopped\")\n\n    def _run_loop(self) -> None:\n        while not self._stop_event.is_set():\n            cycle_start = time.monotonic()\n            try:\n                purge_inference_models_cache(\n                    inference_home=self._inference_home,\n                    max_cache_size_mb=self._max_cache_size_mb,\n                )\n            except Exception as e:\n                logger.error(f\"Cache purge cycle failed: {e}\", exc_info=True)\n            elapsed = time.monotonic() - cycle_start\n            remaining = self._interval_seconds - elapsed\n            if remaining <= 0:\n                logger.warning(\n                    f\"Cache purge took {elapsed}s, exceeding interval \"\n                    f\"of {self._interval_seconds}s - skipping next cycle\"\n                )\n                remaining = self._interval_seconds\n            self._stop_event.wait(timeout=remaining)\n\n\ndef purge_inference_models_cache(\n    inference_home: str,\n    max_cache_size_mb: int,\n) -> None:\n    directories_to_investigate = [\n        os.path.abspath(os.path.join(inference_home, SHARED_BLOBS_DIR)),\n        os.path.abspath(os.path.join(inference_home, MODELS_CACHE_DIR)),\n    ]\n    cache_index = build_current_cache_index(\n        directories_to_investigate=directories_to_investigate\n    )\n    current_cache_size = summarize_disk_size(files_info=cache_index)\n    if current_cache_size <= max_cache_size_mb:\n        logger.info(\n            f\"Purging inference models cache skipped - current {round(current_cache_size, 2)}MB, \"\n            f\"limit: {round(max_cache_size_mb, 2)}MB\"\n        )\n        return None\n    to_be_reclaimed = current_cache_size - max_cache_size_mb\n    cache_index_ranked = rank_for_deletion(files=cache_index)\n    nominated_for_deletion = nominate_files_for_deletion(\n        files=cache_index_ranked, to_be_reclaimed=to_be_reclaimed\n    )\n    purged = purge_files(files=nominated_for_deletion)\n    if purged < to_be_reclaimed:\n        logger.warning(\n            \"Could not fully purge inference-models cache - expected size to be reclaimed: \"\n            f\"{round(to_be_reclaimed, 2)}MB, actual reclaimed: {round(purged, 2)}MB\"\n        )\n    else:\n        logger.info(f\"Purge complete - reclaimed {round(purged, 2)}MB.\")\n    return None\n\n\ndef build_current_cache_index(\n    directories_to_investigate: List[str],\n) -> List[FileInfo]:\n    results = []\n    for directory_path in directories_to_investigate:\n        results.extend(list_files(path=directory_path))\n    return results\n\n\ndef list_files(path: str) -> List[FileInfo]:\n    path = os.path.abspath(path)\n    if not os.path.exists(path):\n        return []\n    if os.path.islink(path):\n        return []\n    if os.path.isfile(path):\n        if path.endswith(LOCK_POSTFIX):\n            return []\n        stat = os.stat(path)\n        return [\n            FileInfo(\n                path=path,\n                size_mb=stat.st_size / BYTES_IN_MB,\n                modified_at=datetime.fromtimestamp(stat.st_mtime),\n            )\n        ]\n    results = []\n    for directory_path, directory_names, file_names in os.walk(path, followlinks=False):\n        for file_name in file_names:\n            file_path = os.path.join(directory_path, file_name)\n            if os.path.islink(file_path) or file_path.endswith(LOCK_POSTFIX):\n                continue\n            try:\n                stat = os.stat(file_path)\n            except OSError:\n                continue\n            results.append(\n                FileInfo(\n                    path=file_path,\n                    size_mb=stat.st_size / BYTES_IN_MB,\n                    modified_at=datetime.fromtimestamp(stat.st_mtime),\n                )\n            )\n    return results\n\n\ndef summarize_disk_size(files_info: List[FileInfo]) -> float:\n    result = 0\n    for file_info in files_info:\n        result += file_info.size_mb\n    return result\n\n\ndef rank_for_deletion(\n    files: List[FileInfo],\n    now: Optional[datetime] = None,\n    recent_threshold_days: float = RECENT_THRESHOLD_DAYS,\n    warm_threshold_days: float = WARM_THRESHOLD_DAYS,\n    stale_threshold_days: float = STALE_THRESHOLD_DAYS,\n) -> List[FileInfo]:\n    if not files:\n        return []\n    if now is None:\n        now = datetime.now()\n\n    if not (recent_threshold_days < warm_threshold_days < stale_threshold_days):\n        raise ValueError(\n            f\"Thresholds must be in ascending order: \"\n            f\"recent ({recent_threshold_days}) < warm ({warm_threshold_days}) < stale ({stale_threshold_days})\"\n        )\n\n    def staleness_group(file_info: FileInfo) -> int:\n        age_days = (now - file_info.modified_at).total_seconds() / SECONDS_IN_DAY\n        if age_days > stale_threshold_days:\n            return StalenessGroup.ABANDONED.value\n        if age_days > warm_threshold_days:\n            return StalenessGroup.STALE.value\n        if age_days > recent_threshold_days:\n            return StalenessGroup.WARM.value\n        return StalenessGroup.RECENT.value\n\n    return sorted(files, key=lambda f: (staleness_group(f), -f.size_mb))\n\n\ndef nominate_files_for_deletion(\n    files: List[FileInfo], to_be_reclaimed: float\n) -> List[FileInfo]:\n    reclaimed = 0\n    to_delete = []\n    for file in files:\n        if reclaimed >= to_be_reclaimed:\n            break\n        to_delete.append(file)\n        reclaimed += file.size_mb\n    return to_delete\n\n\ndef purge_files(files: List[FileInfo], file_lock_acquire_timeout: int = 3) -> float:\n    result = 0\n    for file in files:\n        try:\n            file_absolute_path = os.path.abspath(file.path)\n            file_directory = os.path.dirname(file_absolute_path)\n            file_name = os.path.basename(file_absolute_path)\n            lock_path = os.path.join(file_directory, f\".{file_name}{LOCK_POSTFIX}\")\n            with FileLock(lock_path, timeout=file_lock_acquire_timeout):\n                os.remove(file.path)\n            result += file.size_mb\n        except FileNotFoundError:\n            pass\n        except Exception as e:\n            logger.warning(f\"Failed to purge cache file {file.path}: {e}\")\n    return result\n",
    "patch": null
  },
  {
    "trace_id": "3b2cfefe-bf90-456b-9e2e-a60188196ff8",
    "function_name": "get_workflow_specification",
    "file_path": "inference/core/roboflow_api.py",
    "speedup_x": 0.5560104091973175,
    "review_quality": "medium",
    "pre_optimization_commit": "607c853289559d1117ee503cf7c703552e1306a7",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def get_workflow_specification(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    use_cache: bool = True,\n    ephemeral_cache: Optional[BaseCache] = None,\n    workflow_version_id: Optional[str] = None,\n) -> dict:\n    ephemeral_cache = ephemeral_cache or cache\n    if use_cache:\n        cached_entry = _retrieve_workflow_specification_from_ephemeral_cache(\n            api_key=api_key,\n            workspace_id=workspace_id,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n            ephemeral_cache=ephemeral_cache,\n        )\n        if cached_entry:\n            return cached_entry\n\n    if workspace_id == \"local\":\n        if not re.match(r\"^[\\w\\-]+$\", workflow_id):\n            raise ValueError(\"Invalid workflow id\")\n\n        workflow_hash = sha256(workflow_id.encode()).hexdigest()\n        local_file_path = (\n            Path(MODEL_CACHE_DIR) / \"workflow\" / \"local\" / f\"{workflow_hash}.json\"\n        )\n        if not local_file_path.exists():\n            raise FileNotFoundError(f\"Local workflow file not found: {local_file_path}\")\n\n        with local_file_path.open(\"r\", encoding=\"utf-8\") as f:\n            local_config = json.load(f)\n\n        # Mimic the same shape as the cloud response:\n        response = {\"workflow\": local_config}\n    else:\n        params = []\n        if api_key is not None:\n            params.append((\"api_key\", api_key))\n        if workflow_version_id is not None:\n            params.append((\"workflow_version\", workflow_version_id))\n        api_url = _add_params_to_url(\n            url=f\"{API_BASE_URL}/{workspace_id}/workflows/{workflow_id}\",\n            params=params,\n        )\n        try:\n            response = _get_from_url(url=api_url)\n            if USE_FILE_CACHE_FOR_WORKFLOWS_DEFINITIONS:\n                cache_workflow_response(\n                    workspace_id=workspace_id,\n                    workflow_id=workflow_id,\n                    api_key=api_key,\n                    response=response,\n                    workflow_version_id=workflow_version_id,\n                )\n        except (\n            requests.exceptions.ConnectionError,\n            ConnectionError,\n            requests.exceptions.Timeout,\n        ) as error:\n            if not USE_FILE_CACHE_FOR_WORKFLOWS_DEFINITIONS:\n                raise error\n            response = load_cached_workflow_response(\n                workspace_id=workspace_id,\n                workflow_id=workflow_id,\n                api_key=api_key,\n                workflow_version_id=workflow_version_id,\n            )\n            if response is None:\n                raise error\n\n    if \"workflow\" not in response or \"config\" not in response[\"workflow\"]:\n        raise MalformedWorkflowResponseError(\n            \"Could not find workflow specification in API response\"\n        )\n    try:\n        workflow_config = json.loads(response[\"workflow\"][\"config\"])\n        specification = workflow_config[\"specification\"]\n        if isinstance(specification, dict):\n            specification[\"id\"] = response[\"workflow\"].get(\"id\")\n        if use_cache:\n            _cache_workflow_specification_in_ephemeral_cache(\n                api_key=api_key,\n                workspace_id=workspace_id,\n                workflow_id=workflow_id,\n                workflow_version_id=workflow_version_id,\n                specification=specification,\n                ephemeral_cache=ephemeral_cache,\n            )\n        return specification\n    except KeyError as error:\n        raise MalformedWorkflowResponseError(\n            \"Workflow specification not found in Roboflow API response\"\n        ) from error\n    except (ValueError, TypeError) as error:\n        raise MalformedWorkflowResponseError(\n            \"Could not decode workflow specification in Roboflow API response\"\n        ) from error\n",
    "optimized_function_code": "import base64\nimport binascii\nimport hashlib\nimport json\nimport os\nimport re\nimport urllib.parse\nfrom hashlib import sha256\nfrom pathlib import Path\nfrom typing import List, Optional, Tuple, Union\n\nimport backoff\nimport requests\nfrom inference.core import logger\nfrom inference.core.cache import cache\nfrom inference.core.cache.base import BaseCache\nfrom inference.core.entities.types import WorkspaceID\nfrom inference.core.env import (API_BASE_URL, MD5_VERIFICATION_ENABLED,\n                                MODEL_CACHE_DIR,\n                                RETRY_CONNECTION_ERRORS_TO_ROBOFLOW_API,\n                                ROBOFLOW_API_REQUEST_TIMEOUT,\n                                ROBOFLOW_API_VERIFY_SSL,\n                                TRANSIENT_ROBOFLOW_API_ERRORS,\n                                TRANSIENT_ROBOFLOW_API_ERRORS_RETRIES,\n                                TRANSIENT_ROBOFLOW_API_ERRORS_RETRY_INTERVAL,\n                                USE_FILE_CACHE_FOR_WORKFLOWS_DEFINITIONS,\n                                WORKFLOWS_DEFINITION_CACHE_EXPIRY)\nfrom inference.core.exceptions import (MalformedWorkflowResponseError,\n                                       PaymentRequiredError, RetryRequestError,\n                                       RoboflowAPIForbiddenError,\n                                       RoboflowAPINotAuthorizedError,\n                                       RoboflowAPINotNotFoundError,\n                                       RoboflowAPIUnsuccessfulRequestError,\n                                       RoboflowAPIUsagePausedError)\nfrom inference.core.utils.requests import api_key_safe_raise_for_status\nfrom inference.core.utils.url_utils import wrap_url\nfrom requests import Response, Timeout\n\nNOT_FOUND_ERROR_MESSAGE = (\n    \"Could not find requested Roboflow resource. Check that the provided dataset and \"\n    \"version are correct, and check that the provided Roboflow API key has the correct permissions.\"\n)\n\nROBOFLOW_INFERENCE_VERSION_HEADER = \"X-Roboflow-Inference-Version\"\nALLOW_CHUNKED_RESPONSE_HEADER = \"X-Allow-Chunked\"\n\n\nDEFAULT_ERROR_HANDLERS = {\n    401: lambda e: raise_from_lambda(\n        e,\n        RoboflowAPINotAuthorizedError,\n        \"Unauthorized access to roboflow API - check API key. Visit \"\n        \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve one.\",\n    ),\n    402: lambda e: raise_from_lambda(\n        e,\n        PaymentRequiredError,\n        \"Not enough credits to perform this request. Verify your workspace billing page.\",\n    ),\n    403: lambda e: raise_from_lambda(\n        e,\n        RoboflowAPIForbiddenError,\n        \"Unauthorized access to roboflow API - check API key regarding correctness and required scopes. Visit \"\n        \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve one.\",\n    ),\n    404: lambda e: raise_from_lambda(\n        e, RoboflowAPINotNotFoundError, NOT_FOUND_ERROR_MESSAGE\n    ),\n    423: lambda e: raise_from_lambda(\n        e,\n        RoboflowAPIUsagePausedError,\n        \"Roboflow API usage is paused. Please contact your workspace administrator to re-enable api keys.\",\n    ),\n}\n\n\n\n_workflow_cache_key_memo: dict = {}\n\n\ndef cache_workflow_response(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    response: dict,\n    workflow_version_id: Optional[str] = None,\n):\n    workflow_cache_file = get_workflow_cache_file(\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        api_key=api_key,\n        workflow_version_id=workflow_version_id,\n    )\n    workflow_cache_dir = os.path.dirname(workflow_cache_file)\n    os.makedirs(workflow_cache_dir, exist_ok=True)\n    with open(workflow_cache_file, \"w\") as f:\n        json.dump(response, f)\n\n\n\n\ndef load_cached_workflow_response(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    workflow_version_id: Optional[str] = None,\n) -> Optional[dict]:\n    workflow_cache_file = get_workflow_cache_file(\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        api_key=api_key,\n        workflow_version_id=workflow_version_id,\n    )\n    try:\n        with open(workflow_cache_file, \"r\") as f:\n            return json.load(f)\n    except FileNotFoundError:\n        return None\n    except Exception:\n        delete_cached_workflow_response_if_exists(\n            workspace_id=workspace_id,\n            workflow_id=workflow_id,\n            api_key=api_key,\n            workflow_version_id=workflow_version_id,\n        )\n\n\n@wrap_roboflow_api_errors()\ndef get_workflow_specification(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    use_cache: bool = True,\n    ephemeral_cache: Optional[BaseCache] = None,\n    workflow_version_id: Optional[str] = None,\n) -> dict:\n    ephemeral_cache = ephemeral_cache or cache\n    if use_cache:\n        cached_entry = _retrieve_workflow_specification_from_ephemeral_cache(\n            api_key=api_key,\n            workspace_id=workspace_id,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n            ephemeral_cache=ephemeral_cache,\n        )\n        if cached_entry:\n            return cached_entry\n\n    if workspace_id == \"local\":\n        if not re.match(r\"^[\\w\\-]+$\", workflow_id):\n            raise ValueError(\"Invalid workflow id\")\n\n        workflow_hash = sha256(workflow_id.encode()).hexdigest()\n        local_file_path = (\n            Path(MODEL_CACHE_DIR) / \"workflow\" / \"local\" / f\"{workflow_hash}.json\"\n        )\n        if not local_file_path.exists():\n            raise FileNotFoundError(f\"Local workflow file not found: {local_file_path}\")\n\n        with local_file_path.open(\"r\", encoding=\"utf-8\") as f:\n            local_config = json.load(f)\n\n        # Mimic the same shape as the cloud response:\n        response = {\"workflow\": local_config}\n    else:\n        params = []\n        if api_key is not None:\n            params.append((\"api_key\", api_key))\n        if workflow_version_id is not None:\n            params.append((\"workflow_version\", workflow_version_id))\n        api_url = _add_params_to_url(\n            url=f\"{API_BASE_URL}/{workspace_id}/workflows/{workflow_id}\",\n            params=params,\n        )\n        try:\n            response = _get_from_url(url=api_url)\n            if USE_FILE_CACHE_FOR_WORKFLOWS_DEFINITIONS:\n                cache_workflow_response(\n                    workspace_id=workspace_id,\n                    workflow_id=workflow_id,\n                    api_key=api_key,\n                    response=response,\n                    workflow_version_id=workflow_version_id,\n                )\n        except (\n            requests.exceptions.ConnectionError,\n            ConnectionError,\n            requests.exceptions.Timeout,\n        ) as error:\n            if not USE_FILE_CACHE_FOR_WORKFLOWS_DEFINITIONS:\n                raise error\n            response = load_cached_workflow_response(\n                workspace_id=workspace_id,\n                workflow_id=workflow_id,\n                api_key=api_key,\n                workflow_version_id=workflow_version_id,\n            )\n            if response is None:\n                raise error\n\n    if \"workflow\" not in response or \"config\" not in response[\"workflow\"]:\n        raise MalformedWorkflowResponseError(\n            \"Could not find workflow specification in API response\"\n        )\n    try:\n        workflow_config = json.loads(response[\"workflow\"][\"config\"])\n        specification = workflow_config[\"specification\"]\n        if isinstance(specification, dict):\n            specification[\"id\"] = response[\"workflow\"].get(\"id\")\n        if use_cache:\n            _cache_workflow_specification_in_ephemeral_cache(\n                api_key=api_key,\n                workspace_id=workspace_id,\n                workflow_id=workflow_id,\n                workflow_version_id=workflow_version_id,\n                specification=specification,\n                ephemeral_cache=ephemeral_cache,\n            )\n        return specification\n    except KeyError as error:\n        raise MalformedWorkflowResponseError(\n            \"Workflow specification not found in Roboflow API response\"\n        ) from error\n    except (ValueError, TypeError) as error:\n        raise MalformedWorkflowResponseError(\n            \"Could not decode workflow specification in Roboflow API response\"\n        ) from error\n\n\ndef _retrieve_workflow_specification_from_ephemeral_cache(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    ephemeral_cache: BaseCache,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[dict]:\n    memo_key = (api_key, workspace_id, workflow_id, workflow_version_id)\n    cache_key = _workflow_cache_key_memo.get(memo_key)\n    if cache_key is None:\n        cache_key = _prepare_workflow_response_cache_key(\n            api_key=api_key,\n            workspace_id=workspace_id,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n        )\n        _workflow_cache_key_memo[memo_key] = cache_key\n    return ephemeral_cache.get(key=cache_key)\n\n\ndef _cache_workflow_specification_in_ephemeral_cache(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    specification: dict,\n    ephemeral_cache: BaseCache,\n    workflow_version_id: Optional[str] = None,\n) -> None:\n    memo_key = (api_key, workspace_id, workflow_id, workflow_version_id)\n    cache_key = _workflow_cache_key_memo.get(memo_key)\n    if cache_key is None:\n        cache_key = _prepare_workflow_response_cache_key(\n            api_key=api_key,\n            workspace_id=workspace_id,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n        )\n        _workflow_cache_key_memo[memo_key] = cache_key\n    ephemeral_cache.set(\n        key=cache_key,\n        value=specification,\n        expire=WORKFLOWS_DEFINITION_CACHE_EXPIRY,\n    )\n\n\n@backoff.on_exception(\n    backoff.constant,\n    exception=RetryRequestError,\n    max_tries=TRANSIENT_ROBOFLOW_API_ERRORS_RETRIES,\n    interval=TRANSIENT_ROBOFLOW_API_ERRORS_RETRY_INTERVAL,\n)\ndef _get_from_url(\n    url: str,\n    json_response: bool = True,\n    headers: Optional[dict] = None,\n) -> Union[Response, dict]:\n    full_url = wrap_url(url)\n    try:\n        response = requests.get(\n            full_url,\n            headers=build_roboflow_api_headers(explicit_headers=headers),\n            timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n            verify=ROBOFLOW_API_VERIFY_SSL,\n        )\n\n    except (ConnectionError, Timeout, requests.exceptions.ConnectionError) as error:\n        if RETRY_CONNECTION_ERRORS_TO_ROBOFLOW_API:\n            raise RetryRequestError(\n                message=\"Connectivity error\", inner_error=error\n            ) from error\n        raise error\n    try:\n        api_key_safe_raise_for_status(response=response)\n    except Exception as error:\n        if response.status_code in TRANSIENT_ROBOFLOW_API_ERRORS:\n            raise RetryRequestError(message=str(error), inner_error=error) from error\n        raise error\n\n    if MD5_VERIFICATION_ENABLED:\n        x_goog_hash = response.headers.get(\"x-goog-hash\")\n        if x_goog_hash is None:\n            logger.warning(\n                f\"MD5 verification enabled but response missing x-goog-hash header. \"\n                f\"Request url: {_url_for_safe_logging(full_url)}\"\n            )\n        else:\n            md5_part = None\n            for part in x_goog_hash.split(\",\"):\n                if part.strip().startswith(\"md5=\"):\n                    md5_part = part.strip()[4:]\n                    break\n            if md5_part is not None:\n                try:\n                    md5_from_header = base64.b64decode(md5_part)\n                except binascii.Error as decode_error:\n                    raise RoboflowAPIUnsuccessfulRequestError(\n                        \"Invalid MD5 value in x-goog-hash header: not valid base64\"\n                    ) from decode_error\n                if md5_from_header != hashlib.md5(response.content).digest():\n                    raise RoboflowAPIUnsuccessfulRequestError(\n                        \"MD5 hash does not match MD5 received from x-goog-hash header\"\n                    )\n            else:\n                logger.warning(\n                    f\"MD5 verification enabled but x-goog-hash header has no md5= part. \"\n                    f\"Request url: {_url_for_safe_logging(full_url)}\"\n                )\n\n    if json_response:\n        return response.json()\n    return response\n\n\ndef _add_params_to_url(url: str, params: List[Tuple[str, str]]) -> str:\n    if len(params) == 0:\n        return url\n    params_chunks = [\n        f\"{name}={urllib.parse.quote_plus(value)}\" for name, value in params\n    ]\n    parameters_string = \"&\".join(params_chunks)\n    return f\"{url}?{parameters_string}\"",
    "optimized_raw_markdown": "```python:inference/core/roboflow_api.py\nimport base64\nimport binascii\nimport hashlib\nimport json\nimport os\nimport re\nimport urllib.parse\nfrom hashlib import sha256\nfrom pathlib import Path\nfrom typing import List, Optional, Tuple, Union\n\nimport backoff\nimport requests\nfrom inference.core import logger\nfrom inference.core.cache import cache\nfrom inference.core.cache.base import BaseCache\nfrom inference.core.entities.types import WorkspaceID\nfrom inference.core.env import (API_BASE_URL, MD5_VERIFICATION_ENABLED,\n                                MODEL_CACHE_DIR,\n                                RETRY_CONNECTION_ERRORS_TO_ROBOFLOW_API,\n                                ROBOFLOW_API_REQUEST_TIMEOUT,\n                                ROBOFLOW_API_VERIFY_SSL,\n                                TRANSIENT_ROBOFLOW_API_ERRORS,\n                                TRANSIENT_ROBOFLOW_API_ERRORS_RETRIES,\n                                TRANSIENT_ROBOFLOW_API_ERRORS_RETRY_INTERVAL,\n                                USE_FILE_CACHE_FOR_WORKFLOWS_DEFINITIONS,\n                                WORKFLOWS_DEFINITION_CACHE_EXPIRY)\nfrom inference.core.exceptions import (MalformedWorkflowResponseError,\n                                       PaymentRequiredError, RetryRequestError,\n                                       RoboflowAPIForbiddenError,\n                                       RoboflowAPINotAuthorizedError,\n                                       RoboflowAPINotNotFoundError,\n                                       RoboflowAPIUnsuccessfulRequestError,\n                                       RoboflowAPIUsagePausedError)\nfrom inference.core.utils.requests import api_key_safe_raise_for_status\nfrom inference.core.utils.url_utils import wrap_url\nfrom requests import Response, Timeout\n\nNOT_FOUND_ERROR_MESSAGE = (\n    \"Could not find requested Roboflow resource. Check that the provided dataset and \"\n    \"version are correct, and check that the provided Roboflow API key has the correct permissions.\"\n)\n\nROBOFLOW_INFERENCE_VERSION_HEADER = \"X-Roboflow-Inference-Version\"\nALLOW_CHUNKED_RESPONSE_HEADER = \"X-Allow-Chunked\"\n\n\nDEFAULT_ERROR_HANDLERS = {\n    401: lambda e: raise_from_lambda(\n        e,\n        RoboflowAPINotAuthorizedError,\n        \"Unauthorized access to roboflow API - check API key. Visit \"\n        \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve one.\",\n    ),\n    402: lambda e: raise_from_lambda(\n        e,\n        PaymentRequiredError,\n        \"Not enough credits to perform this request. Verify your workspace billing page.\",\n    ),\n    403: lambda e: raise_from_lambda(\n        e,\n        RoboflowAPIForbiddenError,\n        \"Unauthorized access to roboflow API - check API key regarding correctness and required scopes. Visit \"\n        \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve one.\",\n    ),\n    404: lambda e: raise_from_lambda(\n        e, RoboflowAPINotNotFoundError, NOT_FOUND_ERROR_MESSAGE\n    ),\n    423: lambda e: raise_from_lambda(\n        e,\n        RoboflowAPIUsagePausedError,\n        \"Roboflow API usage is paused. Please contact your workspace administrator to re-enable api keys.\",\n    ),\n}\n\n\n\n_workflow_cache_key_memo: dict = {}\n\n\ndef cache_workflow_response(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    response: dict,\n    workflow_version_id: Optional[str] = None,\n):\n    workflow_cache_file = get_workflow_cache_file(\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        api_key=api_key,\n        workflow_version_id=workflow_version_id,\n    )\n    workflow_cache_dir = os.path.dirname(workflow_cache_file)\n    os.makedirs(workflow_cache_dir, exist_ok=True)\n    with open(workflow_cache_file, \"w\") as f:\n        json.dump(response, f)\n\n\n\n\ndef load_cached_workflow_response(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    workflow_version_id: Optional[str] = None,\n) -> Optional[dict]:\n    workflow_cache_file = get_workflow_cache_file(\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        api_key=api_key,\n        workflow_version_id=workflow_version_id,\n    )\n    try:\n        with open(workflow_cache_file, \"r\") as f:\n            return json.load(f)\n    except FileNotFoundError:\n        return None\n    except Exception:\n        delete_cached_workflow_response_if_exists(\n            workspace_id=workspace_id,\n            workflow_id=workflow_id,\n            api_key=api_key,\n            workflow_version_id=workflow_version_id,\n        )\n\n\n@wrap_roboflow_api_errors()\ndef get_workflow_specification(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    use_cache: bool = True,\n    ephemeral_cache: Optional[BaseCache] = None,\n    workflow_version_id: Optional[str] = None,\n) -> dict:\n    ephemeral_cache = ephemeral_cache or cache\n    if use_cache:\n        cached_entry = _retrieve_workflow_specification_from_ephemeral_cache(\n            api_key=api_key,\n            workspace_id=workspace_id,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n            ephemeral_cache=ephemeral_cache,\n        )\n        if cached_entry:\n            return cached_entry\n\n    if workspace_id == \"local\":\n        if not re.match(r\"^[\\w\\-]+$\", workflow_id):\n            raise ValueError(\"Invalid workflow id\")\n\n        workflow_hash = sha256(workflow_id.encode()).hexdigest()\n        local_file_path = (\n            Path(MODEL_CACHE_DIR) / \"workflow\" / \"local\" / f\"{workflow_hash}.json\"\n        )\n        if not local_file_path.exists():\n            raise FileNotFoundError(f\"Local workflow file not found: {local_file_path}\")\n\n        with local_file_path.open(\"r\", encoding=\"utf-8\") as f:\n            local_config = json.load(f)\n\n        # Mimic the same shape as the cloud response:\n        response = {\"workflow\": local_config}\n    else:\n        params = []\n        if api_key is not None:\n            params.append((\"api_key\", api_key))\n        if workflow_version_id is not None:\n            params.append((\"workflow_version\", workflow_version_id))\n        api_url = _add_params_to_url(\n            url=f\"{API_BASE_URL}/{workspace_id}/workflows/{workflow_id}\",\n            params=params,\n        )\n        try:\n            response = _get_from_url(url=api_url)\n            if USE_FILE_CACHE_FOR_WORKFLOWS_DEFINITIONS:\n                cache_workflow_response(\n                    workspace_id=workspace_id,\n                    workflow_id=workflow_id,\n                    api_key=api_key,\n                    response=response,\n                    workflow_version_id=workflow_version_id,\n                )\n        except (\n            requests.exceptions.ConnectionError,\n            ConnectionError,\n            requests.exceptions.Timeout,\n        ) as error:\n            if not USE_FILE_CACHE_FOR_WORKFLOWS_DEFINITIONS:\n                raise error\n            response = load_cached_workflow_response(\n                workspace_id=workspace_id,\n                workflow_id=workflow_id,\n                api_key=api_key,\n                workflow_version_id=workflow_version_id,\n            )\n            if response is None:\n                raise error\n\n    if \"workflow\" not in response or \"config\" not in response[\"workflow\"]:\n        raise MalformedWorkflowResponseError(\n            \"Could not find workflow specification in API response\"\n        )\n    try:\n        workflow_config = json.loads(response[\"workflow\"][\"config\"])\n        specification = workflow_config[\"specification\"]\n        if isinstance(specification, dict):\n            specification[\"id\"] = response[\"workflow\"].get(\"id\")\n        if use_cache:\n            _cache_workflow_specification_in_ephemeral_cache(\n                api_key=api_key,\n                workspace_id=workspace_id,\n                workflow_id=workflow_id,\n                workflow_version_id=workflow_version_id,\n                specification=specification,\n                ephemeral_cache=ephemeral_cache,\n            )\n        return specification\n    except KeyError as error:\n        raise MalformedWorkflowResponseError(\n            \"Workflow specification not found in Roboflow API response\"\n        ) from error\n    except (ValueError, TypeError) as error:\n        raise MalformedWorkflowResponseError(\n            \"Could not decode workflow specification in Roboflow API response\"\n        ) from error\n\n\ndef _retrieve_workflow_specification_from_ephemeral_cache(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    ephemeral_cache: BaseCache,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[dict]:\n    memo_key = (api_key, workspace_id, workflow_id, workflow_version_id)\n    cache_key = _workflow_cache_key_memo.get(memo_key)\n    if cache_key is None:\n        cache_key = _prepare_workflow_response_cache_key(\n            api_key=api_key,\n            workspace_id=workspace_id,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n        )\n        _workflow_cache_key_memo[memo_key] = cache_key\n    return ephemeral_cache.get(key=cache_key)\n\n\ndef _cache_workflow_specification_in_ephemeral_cache(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    specification: dict,\n    ephemeral_cache: BaseCache,\n    workflow_version_id: Optional[str] = None,\n) -> None:\n    memo_key = (api_key, workspace_id, workflow_id, workflow_version_id)\n    cache_key = _workflow_cache_key_memo.get(memo_key)\n    if cache_key is None:\n        cache_key = _prepare_workflow_response_cache_key(\n            api_key=api_key,\n            workspace_id=workspace_id,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n        )\n        _workflow_cache_key_memo[memo_key] = cache_key\n    ephemeral_cache.set(\n        key=cache_key,\n        value=specification,\n        expire=WORKFLOWS_DEFINITION_CACHE_EXPIRY,\n    )\n\n\n@backoff.on_exception(\n    backoff.constant,\n    exception=RetryRequestError,\n    max_tries=TRANSIENT_ROBOFLOW_API_ERRORS_RETRIES,\n    interval=TRANSIENT_ROBOFLOW_API_ERRORS_RETRY_INTERVAL,\n)\ndef _get_from_url(\n    url: str,\n    json_response: bool = True,\n    headers: Optional[dict] = None,\n) -> Union[Response, dict]:\n    full_url = wrap_url(url)\n    try:\n        response = requests.get(\n            full_url,\n            headers=build_roboflow_api_headers(explicit_headers=headers),\n            timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n            verify=ROBOFLOW_API_VERIFY_SSL,\n        )\n\n    except (ConnectionError, Timeout, requests.exceptions.ConnectionError) as error:\n        if RETRY_CONNECTION_ERRORS_TO_ROBOFLOW_API:\n            raise RetryRequestError(\n                message=\"Connectivity error\", inner_error=error\n            ) from error\n        raise error\n    try:\n        api_key_safe_raise_for_status(response=response)\n    except Exception as error:\n        if response.status_code in TRANSIENT_ROBOFLOW_API_ERRORS:\n            raise RetryRequestError(message=str(error), inner_error=error) from error\n        raise error\n\n    if MD5_VERIFICATION_ENABLED:\n        x_goog_hash = response.headers.get(\"x-goog-hash\")\n        if x_goog_hash is None:\n            logger.warning(\n                f\"MD5 verification enabled but response missing x-goog-hash header. \"\n                f\"Request url: {_url_for_safe_logging(full_url)}\"\n            )\n        else:\n            md5_part = None\n            for part in x_goog_hash.split(\",\"):\n                if part.strip().startswith(\"md5=\"):\n                    md5_part = part.strip()[4:]\n                    break\n            if md5_part is not None:\n                try:\n                    md5_from_header = base64.b64decode(md5_part)\n                except binascii.Error as decode_error:\n                    raise RoboflowAPIUnsuccessfulRequestError(\n                        \"Invalid MD5 value in x-goog-hash header: not valid base64\"\n                    ) from decode_error\n                if md5_from_header != hashlib.md5(response.content).digest():\n                    raise RoboflowAPIUnsuccessfulRequestError(\n                        \"MD5 hash does not match MD5 received from x-goog-hash header\"\n                    )\n            else:\n                logger.warning(\n                    f\"MD5 verification enabled but x-goog-hash header has no md5= part. \"\n                    f\"Request url: {_url_for_safe_logging(full_url)}\"\n                )\n\n    if json_response:\n        return response.json()\n    return response\n\n\ndef _add_params_to_url(url: str, params: List[Tuple[str, str]]) -> str:\n    if len(params) == 0:\n        return url\n    params_chunks = [\n        f\"{name}={urllib.parse.quote_plus(value)}\" for name, value in params\n    ]\n    parameters_string = \"&\".join(params_chunks)\n    return f\"{url}?{parameters_string}\"\n```",
    "optimized_function_only": "def get_workflow_specification(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    use_cache: bool = True,\n    ephemeral_cache: Optional[BaseCache] = None,\n    workflow_version_id: Optional[str] = None,\n) -> dict:\n    ephemeral_cache = ephemeral_cache or cache\n    if use_cache:\n        cached_entry = _retrieve_workflow_specification_from_ephemeral_cache(\n            api_key=api_key,\n            workspace_id=workspace_id,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n            ephemeral_cache=ephemeral_cache,\n        )\n        if cached_entry:\n            return cached_entry\n\n    if workspace_id == \"local\":\n        if not re.match(r\"^[\\w\\-]+$\", workflow_id):\n            raise ValueError(\"Invalid workflow id\")\n\n        workflow_hash = sha256(workflow_id.encode()).hexdigest()\n        local_file_path = (\n            Path(MODEL_CACHE_DIR) / \"workflow\" / \"local\" / f\"{workflow_hash}.json\"\n        )\n        if not local_file_path.exists():\n            raise FileNotFoundError(f\"Local workflow file not found: {local_file_path}\")\n\n        with local_file_path.open(\"r\", encoding=\"utf-8\") as f:\n            local_config = json.load(f)\n\n        # Mimic the same shape as the cloud response:\n        response = {\"workflow\": local_config}\n    else:\n        params = []\n        if api_key is not None:\n            params.append((\"api_key\", api_key))\n        if workflow_version_id is not None:\n            params.append((\"workflow_version\", workflow_version_id))\n        api_url = _add_params_to_url(\n            url=f\"{API_BASE_URL}/{workspace_id}/workflows/{workflow_id}\",\n            params=params,\n        )\n        try:\n            response = _get_from_url(url=api_url)\n            if USE_FILE_CACHE_FOR_WORKFLOWS_DEFINITIONS:\n                cache_workflow_response(\n                    workspace_id=workspace_id,\n                    workflow_id=workflow_id,\n                    api_key=api_key,\n                    response=response,\n                    workflow_version_id=workflow_version_id,\n                )\n        except (\n            requests.exceptions.ConnectionError,\n            ConnectionError,\n            requests.exceptions.Timeout,\n        ) as error:\n            if not USE_FILE_CACHE_FOR_WORKFLOWS_DEFINITIONS:\n                raise error\n            response = load_cached_workflow_response(\n                workspace_id=workspace_id,\n                workflow_id=workflow_id,\n                api_key=api_key,\n                workflow_version_id=workflow_version_id,\n            )\n            if response is None:\n                raise error\n\n    if \"workflow\" not in response or \"config\" not in response[\"workflow\"]:\n        raise MalformedWorkflowResponseError(\n            \"Could not find workflow specification in API response\"\n        )\n    try:\n        workflow_config = json.loads(response[\"workflow\"][\"config\"])\n        specification = workflow_config[\"specification\"]\n        if isinstance(specification, dict):\n            specification[\"id\"] = response[\"workflow\"].get(\"id\")\n        if use_cache:\n            _cache_workflow_specification_in_ephemeral_cache(\n                api_key=api_key,\n                workspace_id=workspace_id,\n                workflow_id=workflow_id,\n                workflow_version_id=workflow_version_id,\n                specification=specification,\n                ephemeral_cache=ephemeral_cache,\n            )\n        return specification\n    except KeyError as error:\n        raise MalformedWorkflowResponseError(\n            \"Workflow specification not found in Roboflow API response\"\n        ) from error\n    except (ValueError, TypeError) as error:\n        raise MalformedWorkflowResponseError(\n            \"Could not decode workflow specification in Roboflow API response\"\n        ) from error\n",
    "original_file_content": "import asyncio\nimport base64\nimport binascii\nimport hashlib\nimport json\nimport os\nimport re\nimport time\nimport urllib.parse\nfrom enum import Enum\nfrom hashlib import sha256\nfrom json import JSONDecodeError\nfrom pathlib import Path\nfrom typing import Any, Callable, Dict, List, Optional, Tuple, Type, Union\n\nimport aiohttp\nimport backoff\nimport requests\nfrom cachetools.func import ttl_cache\nfrom requests import Response, Timeout\nfrom requests_toolbelt import MultipartEncoder\n\nfrom inference.core import logger\nfrom inference.core.cache import cache\nfrom inference.core.cache.base import BaseCache\nfrom inference.core.cache.model_artifacts import get_cache_dir, initialise_cache\nfrom inference.core.entities.types import (\n    DatasetID,\n    ModelID,\n    ModelType,\n    TaskType,\n    VersionID,\n    WorkspaceID,\n)\nfrom inference.core.env import (\n    API_BASE_URL,\n    ENFORCE_CREDITS_VERIFICATION,\n    GCP_SERVERLESS,\n    INTERNAL_WEIGHTS_URL_SUFFIX,\n    MD5_VERIFICATION_ENABLED,\n    MODEL_CACHE_DIR,\n    MODELS_CACHE_AUTH_CACHE_MAX_SIZE,\n    MODELS_CACHE_AUTH_CACHE_TTL,\n    MODELS_CACHE_AUTH_ENABLED,\n    RETRY_CONNECTION_ERRORS_TO_ROBOFLOW_API,\n    ROBOFLOW_API_EXTRA_HEADERS,\n    ROBOFLOW_API_REQUEST_TIMEOUT,\n    ROBOFLOW_API_VERIFY_SSL,\n    ROBOFLOW_SERVICE_SECRET,\n    SINGLE_TENANT_WORKFLOW_CACHE,\n    TRANSIENT_ROBOFLOW_API_ERRORS,\n    TRANSIENT_ROBOFLOW_API_ERRORS_RETRIES,\n    TRANSIENT_ROBOFLOW_API_ERRORS_RETRY_INTERVAL,\n    USE_FILE_CACHE_FOR_WORKFLOWS_DEFINITIONS,\n    WORKFLOWS_DEFINITION_CACHE_EXPIRY,\n)\nfrom inference.core.exceptions import (\n    MalformedRoboflowAPIResponseError,\n    MalformedWorkflowResponseError,\n    MissingDefaultModelError,\n    PaymentRequiredError,\n    RetryRequestError,\n    RoboflowAPIConnectionError,\n    RoboflowAPIForbiddenError,\n    RoboflowAPIIAlreadyAnnotatedError,\n    RoboflowAPIIAnnotationRejectionError,\n    RoboflowAPIImageUploadRejectionError,\n    RoboflowAPINotAuthorizedError,\n    RoboflowAPINotNotFoundError,\n    RoboflowAPITimeoutError,\n    RoboflowAPIUnsuccessfulRequestError,\n    RoboflowAPIUsagePausedError,\n    WorkspaceLoadError,\n)\nfrom inference.core.telemetry import record_api_call, record_error, start_span\nfrom inference.core.utils.file_system import sanitize_path_segment\nfrom inference.core.utils.requests import (\n    api_key_safe_raise_for_status,\n    api_key_safe_raise_for_status_aiohttp,\n)\nfrom inference.core.utils.url_utils import wrap_url\nfrom inference.core.version import __version__\n\nENFORCE_CREDITS_VERIFICATION_HEADER = \"x-enforce-credits-verification\"\nENFORCE_INTERNAL_ARTIFACTS_URLS_HEADER = \"x-enforce-internal-artefacts-urls\"\n\nMODEL_TYPE_DEFAULTS = {\n    \"object-detection\": \"yolov5v2s\",\n    \"instance-segmentation\": \"yolact\",\n    \"classification\": \"vit\",\n    \"keypoint-detection\": \"yolov8n\",\n}\nPROJECT_TASK_TYPE_KEY = \"project_task_type\"\nMODEL_TYPE_KEY = \"model_type\"\n\nNOT_FOUND_ERROR_MESSAGE = (\n    \"Could not find requested Roboflow resource. Check that the provided dataset and \"\n    \"version are correct, and check that the provided Roboflow API key has the correct permissions.\"\n)\n\nROBOFLOW_INFERENCE_VERSION_HEADER = \"X-Roboflow-Inference-Version\"\nALLOW_CHUNKED_RESPONSE_HEADER = \"X-Allow-Chunked\"\n\n\ndef raise_from_lambda(\n    inner_error: Exception, exception_type: Type[Exception], message: str\n) -> None:\n    raise exception_type(message) from inner_error\n\n\nDEFAULT_ERROR_HANDLERS = {\n    401: lambda e: raise_from_lambda(\n        e,\n        RoboflowAPINotAuthorizedError,\n        \"Unauthorized access to roboflow API - check API key. Visit \"\n        \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve one.\",\n    ),\n    402: lambda e: raise_from_lambda(\n        e,\n        PaymentRequiredError,\n        \"Not enough credits to perform this request. Verify your workspace billing page.\",\n    ),\n    403: lambda e: raise_from_lambda(\n        e,\n        RoboflowAPIForbiddenError,\n        \"Unauthorized access to roboflow API - check API key regarding correctness and required scopes. Visit \"\n        \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve one.\",\n    ),\n    404: lambda e: raise_from_lambda(\n        e, RoboflowAPINotNotFoundError, NOT_FOUND_ERROR_MESSAGE\n    ),\n    423: lambda e: raise_from_lambda(\n        e,\n        RoboflowAPIUsagePausedError,\n        \"Roboflow API usage is paused. Please contact your workspace administrator to re-enable api keys.\",\n    ),\n}\n\n\ndef wrap_roboflow_api_errors(\n    http_errors_handlers: Optional[\n        Dict[int, Callable[[Union[requests.exceptions.HTTPError]], None]]\n    ] = None,\n) -> callable:\n    def decorator(function: callable) -> callable:\n        def wrapper(*args, **kwargs) -> Any:\n            t_start = time.perf_counter()\n            with start_span(\n                \"roboflow_api.call\",\n                {\"roboflow_api.function\": function.__name__},\n            ):\n                try:\n                    try:\n                        return function(*args, **kwargs)\n                    except RetryRequestError as error:\n                        raise error.inner_error\n                except Timeout as error:\n                    record_error(error)\n                    raise RoboflowAPITimeoutError(\n                        \"Timeout when attempting to connect to Roboflow API.\"\n                    ) from error\n                except (\n                    requests.exceptions.ConnectionError,\n                    ConnectionError,\n                ) as error:\n                    record_error(error)\n                    raise RoboflowAPIConnectionError(\n                        \"Could not connect to Roboflow API.\"\n                    ) from error\n                except requests.exceptions.HTTPError as error:\n                    record_error(error)\n                    user_handler_override = (\n                        http_errors_handlers if http_errors_handlers is not None else {}\n                    )\n                    status_code = error.response.status_code\n                    default_handler = DEFAULT_ERROR_HANDLERS.get(status_code)\n                    error_handler = user_handler_override.get(\n                        status_code, default_handler\n                    )\n                    if error_handler is not None:\n                        error_handler(error)\n                    raise RoboflowAPIUnsuccessfulRequestError(\n                        f\"Unsuccessful request to Roboflow API with response code: {status_code}\"\n                    ) from error\n                except requests.exceptions.InvalidJSONError as error:\n                    record_error(error)\n                    raise MalformedRoboflowAPIResponseError(\n                        \"Could not decode JSON response from Roboflow API.\"\n                    ) from error\n                finally:\n                    record_api_call(function.__name__, time.perf_counter() - t_start)\n\n        return wrapper\n\n    return decorator\n\n\ndef wrap_roboflow_api_errors_async(\n    http_errors_handlers: Optional[\n        Dict[int, Callable[[Union[aiohttp.ClientError]], None]]\n    ] = None,\n) -> callable:\n    def decorator(function: callable) -> callable:\n        async def wrapper(*args, **kwargs) -> Any:\n            t_start = time.perf_counter()\n            with start_span(\n                \"roboflow_api.call\",\n                {\"roboflow_api.function\": function.__name__},\n            ):\n                try:\n                    try:\n                        return await function(*args, **kwargs)\n                    except RetryRequestError as error:\n                        raise error.inner_error\n                except asyncio.TimeoutError as error:\n                    record_error(error)\n                    raise RoboflowAPITimeoutError(\n                        \"Timeout when attempting to connect to Roboflow API.\"\n                    ) from error\n                except (aiohttp.ClientConnectionError, ConnectionError) as error:\n                    record_error(error)\n                    raise RoboflowAPIConnectionError(\n                        \"Could not connect to Roboflow API.\"\n                    ) from error\n                except (aiohttp.ContentTypeError, JSONDecodeError) as error:\n                    record_error(error)\n                    raise MalformedRoboflowAPIResponseError(\n                        \"Could not decode JSON response from Roboflow API.\"\n                    ) from error\n                except aiohttp.ClientResponseError as error:\n                    record_error(error)\n                    user_handler_override = (\n                        http_errors_handlers if http_errors_handlers is not None else {}\n                    )\n                    status_code = error.status\n                    default_handler = DEFAULT_ERROR_HANDLERS.get(status_code)\n                    error_handler = user_handler_override.get(\n                        status_code, default_handler\n                    )\n                    if error_handler is not None:\n                        error_handler(error)\n                    raise RoboflowAPIUnsuccessfulRequestError(\n                        f\"Unsuccessful request to Roboflow API with response code: {status_code}\"\n                    ) from error\n                # remaining aiohttp.ClientError seems to qualify to simply pass-through raise\n                finally:\n                    record_api_call(function.__name__, time.perf_counter() - t_start)\n\n        return wrapper\n\n    return decorator\n\n\n@ttl_cache(ttl=MODELS_CACHE_AUTH_CACHE_TTL, maxsize=MODELS_CACHE_AUTH_CACHE_MAX_SIZE)\n@wrap_roboflow_api_errors()\ndef get_roboflow_workspace(api_key: str) -> WorkspaceID:\n    if not api_key:\n        raise WorkspaceLoadError(\"Empty workspace encountered, check your API key.\")\n\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/\",\n        params=[(\"api_key\", api_key), (\"nocache\", \"true\")],\n    )\n    api_key_info = _get_from_url(url=api_url)\n    workspace_id = api_key_info.get(\"workspace\")\n    if workspace_id is None:\n        raise WorkspaceLoadError(\"Empty workspace encountered, check your API key.\")\n    return workspace_id\n\n\n@wrap_roboflow_api_errors_async()\n@backoff.on_exception(\n    backoff.constant,\n    exception=RetryRequestError,\n    max_tries=TRANSIENT_ROBOFLOW_API_ERRORS_RETRIES,\n    interval=TRANSIENT_ROBOFLOW_API_ERRORS_RETRY_INTERVAL,\n)\nasync def get_roboflow_workspace_async(api_key: str) -> WorkspaceID:\n    try:\n        headers = build_roboflow_api_headers()\n        async with aiohttp.ClientSession() as session:\n            async with session.get(\n                f\"{API_BASE_URL}/\",\n                params={\"api_key\": api_key, \"nocache\": \"true\"},\n                headers=headers,\n                timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n            ) as response:\n                try:\n                    api_key_safe_raise_for_status_aiohttp(response=response)\n                except Exception as error:\n                    if response.status in TRANSIENT_ROBOFLOW_API_ERRORS:\n                        raise RetryRequestError(\n                            message=str(error), inner_error=error\n                        ) from error\n                    raise error\n                response_payload = await response.json()\n                workspace_id = response_payload.get(\"workspace\")\n                if workspace_id is None:\n                    raise WorkspaceLoadError(\n                        \"Empty workspace encountered, check your API key.\"\n                    )\n                return workspace_id\n    except (aiohttp.ClientConnectionError, ConnectionError) as error:\n        if RETRY_CONNECTION_ERRORS_TO_ROBOFLOW_API:\n            raise RetryRequestError(\n                message=\"Connectivity error\", inner_error=error\n            ) from error\n        raise error\n\n\n@wrap_roboflow_api_errors()\ndef add_custom_metadata(\n    api_key: str,\n    workspace_id: WorkspaceID,\n    inference_ids: List[str],\n    field_name: str,\n    field_value: str,\n):\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/inference-stats/metadata\",\n        params=[(\"api_key\", api_key), (\"nocache\", \"true\")],\n    )\n    response = requests.post(\n        url=api_url,\n        json={\n            \"data\": [\n                {\n                    \"inference_ids\": inference_ids,\n                    \"field_name\": field_name,\n                    \"field_value\": field_value,\n                }\n            ]\n        },\n        headers=build_roboflow_api_headers(),\n        timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n        verify=ROBOFLOW_API_VERIFY_SSL,\n    )\n    api_key_safe_raise_for_status(response=response)\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_dataset_type(\n    api_key: str, workspace_id: WorkspaceID, dataset_id: DatasetID\n) -> TaskType:\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/{dataset_id}\",\n        params=[(\"api_key\", api_key), (\"nocache\", \"true\")],\n    )\n    dataset_info = _get_from_url(url=api_url)\n    project_task_type = dataset_info.get(\"project\", {})\n    if \"type\" not in project_task_type:\n        logger.warning(\n            f\"Project task type not defined for workspace={workspace_id} and dataset={dataset_id}, defaulting \"\n            f\"to object-detection.\"\n        )\n    return project_task_type.get(\"type\", \"object-detection\")\n\n\n@wrap_roboflow_api_errors(\n    http_errors_handlers={\n        500: lambda e: raise_from_lambda(\n            e, RoboflowAPINotNotFoundError, NOT_FOUND_ERROR_MESSAGE\n        )\n        # this is temporary solution, empirically checked that backend API responds HTTP 500 on incorrect version.\n        # TO BE FIXED at backend, otherwise this error handling may overshadow existing backend problems.\n    }\n)\ndef get_roboflow_model_type(\n    api_key: str,\n    workspace_id: WorkspaceID,\n    dataset_id: DatasetID,\n    version_id: VersionID,\n    project_task_type: ModelType,\n) -> ModelType:\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/{dataset_id}/{version_id}\",\n        params=[(\"api_key\", api_key), (\"nocache\", \"true\")],\n    )\n    version_info = _get_from_url(url=api_url)\n    model_type = version_info[\"version\"]\n    if \"modelType\" not in model_type:\n        if project_task_type not in MODEL_TYPE_DEFAULTS:\n            raise MissingDefaultModelError(\n                f\"Could not set default model for {project_task_type}\"\n            )\n        logger.warning(\n            f\"Model type not defined - using default for {project_task_type} task.\"\n        )\n    return model_type.get(\"modelType\", MODEL_TYPE_DEFAULTS[project_task_type])\n\n\nclass ModelEndpointType(Enum):\n    ORT = \"ort\"\n    CORE_MODEL = \"core_model\"\n    OWLV2 = \"owlv2\"\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_model_data(\n    api_key: str,\n    model_id: str,\n    endpoint_type: ModelEndpointType,\n    device_id: str,\n    countinference: Optional[bool] = None,\n    service_secret: Optional[str] = None,\n) -> dict:\n    api_data_cache_key = f\"roboflow_api_data:{endpoint_type.value}:{model_id}\"\n    api_data = None\n    if not MODELS_CACHE_AUTH_ENABLED:\n        api_data = cache.get(api_data_cache_key)\n    if api_data is not None:\n        logger.debug(f\"Loaded model data from cache with key: {api_data_cache_key}.\")\n        return api_data\n    else:\n        params = [\n            (\"nocache\", \"true\"),\n            (\"device\", device_id),\n            (\"dynamic\", \"true\"),\n        ]\n        if api_key is not None:\n            params.append((\"api_key\", api_key))\n\n        if (\n            INTERNAL_WEIGHTS_URL_SUFFIX == \"serverless\"\n            and countinference is False\n            and service_secret == ROBOFLOW_SERVICE_SECRET\n        ):\n            params.append((\"countinference\", str(countinference).lower()))\n            params.append((\"service_secret\", service_secret))\n\n        api_base_url = urllib.parse.urljoin(API_BASE_URL, INTERNAL_WEIGHTS_URL_SUFFIX)\n        api_url = _add_params_to_url(\n            url=f\"{api_base_url}/{endpoint_type.value}/{model_id}\",\n            params=params,\n        )\n        api_data = _get_from_url(url=api_url)\n        cache.set(\n            api_data_cache_key,\n            api_data,\n            expire=10,\n        )\n        logger.debug(\n            f\"Loaded model data from Roboflow API and saved to cache with key: {api_data_cache_key}.\"\n        )\n        return api_data\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_instant_model_data(\n    api_key: str,\n    model_id: ModelID,\n    cache_prefix: str = \"roboflow_api_data\",\n    countinference: Optional[bool] = None,\n    service_secret: Optional[str] = None,\n) -> dict:\n    api_data_cache_key = f\"{cache_prefix}:{model_id}\"\n    api_data = None\n    if not MODELS_CACHE_AUTH_ENABLED:\n        api_data = cache.get(api_data_cache_key)\n    if api_data is not None:\n        logger.debug(f\"Loaded model data from cache with key: {api_data_cache_key}.\")\n        return api_data\n    else:\n        params = [\n            (\"model\", model_id),\n        ]\n        if api_key is not None:\n            params.append((\"api_key\", api_key))\n\n        if (\n            INTERNAL_WEIGHTS_URL_SUFFIX == \"serverless\"\n            and countinference is False\n            and service_secret == ROBOFLOW_SERVICE_SECRET\n        ):\n            params.append((\"countinference\", str(countinference).lower()))\n            params.append((\"service_secret\", service_secret))\n\n        api_base_url = urllib.parse.urljoin(API_BASE_URL, INTERNAL_WEIGHTS_URL_SUFFIX)\n        api_url = _add_params_to_url(\n            url=f\"{api_base_url}/getWeights\",\n            params=params,\n        )\n        api_data = _get_from_url(url=api_url)\n        cache.set(\n            api_data_cache_key,\n            api_data,\n            expire=10,\n        )\n        logger.debug(\n            f\"Loaded model data from Roboflow API and saved to cache with key: {api_data_cache_key}.\"\n        )\n        return api_data\n\n\n@wrap_roboflow_api_errors()\ndef get_model_metadata_from_inference_models_registry(\n    api_key: str,\n    model_id: ModelID,\n    cache_prefix: str = \"roboflow_api_data:inference_models_registry\",\n    countinference: Optional[bool] = None,\n    service_secret: Optional[str] = None,\n) -> dict:\n    # Watch out - this function should only be used to substitute get_roboflow_instant_model_data()\n    # and only in terms of getting model type and task type\n    # this is only stub to make sure auth works as it should for models which are not\n    # associated to project via version (for which old auth and metadata retrieval method work).\n    api_data_cache_key = f\"{cache_prefix}:{model_id}\"\n    api_data = None\n    if not MODELS_CACHE_AUTH_ENABLED:\n        api_data = cache.get(api_data_cache_key)\n    if api_data is not None:\n        logger.debug(f\"Loaded model data from cache with key: {api_data_cache_key}.\")\n        return api_data\n    query = [(\"modelId\", model_id)]\n    headers = {\"Authorization\": f\"Bearer {api_key}\"}\n    if GCP_SERVERLESS:\n        headers[ENFORCE_INTERNAL_ARTIFACTS_URLS_HEADER] = \"true\"\n    if ENFORCE_CREDITS_VERIFICATION:\n        skip = (\n            countinference is False\n            and service_secret is not None\n            and service_secret == ROBOFLOW_SERVICE_SECRET\n        )\n        if not skip:\n            headers[ENFORCE_CREDITS_VERIFICATION_HEADER] = \"true\"\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/models/v1/external/weights\",\n        params=query,\n    )\n    raw_api_data = _get_from_url(url=api_url, headers=headers)\n    api_data = {\n        \"modelType\": raw_api_data[\"modelMetadata\"][\"modelArchitecture\"],\n        \"taskType\": raw_api_data[\"modelMetadata\"][\"taskType\"],\n    }\n    cache.set(\n        api_data_cache_key,\n        api_data,\n        expire=10,\n    )\n    logger.debug(\n        f\"Loaded model data from Roboflow API (inference-models registry) \"\n        f\"and saved to cache with key: {api_data_cache_key}.\"\n    )\n    return api_data\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_base_lora(\n    api_key: str, repo: str, revision: str, device_id: str\n) -> dict:\n    full_path = f\"{repo.strip('/')}/{revision.strip('/')}\"\n    api_data_cache_key = f\"roboflow_api_data:lora-bases:{full_path}\"\n    api_data = None\n    if not MODELS_CACHE_AUTH_ENABLED:\n        api_data = cache.get(api_data_cache_key)\n    if api_data is not None:\n        logger.debug(f\"Loaded model data from cache with key: {api_data_cache_key}.\")\n        return api_data\n    else:\n        params = [\n            (\"nocache\", \"true\"),\n            (\"device\", device_id),\n            (\"repoAndRevision\", full_path),\n        ]\n        if api_key is not None:\n            params.append((\"api_key\", api_key))\n        api_url = _add_params_to_url(\n            url=f\"{API_BASE_URL}/lora_bases\",\n            params=params,\n        )\n        api_data = _get_from_url(url=api_url)\n        cache.set(\n            api_data_cache_key,\n            api_data,\n            expire=10,\n        )\n        logger.debug(\n            f\"Loaded lora base model data from Roboflow API and saved to cache with key: {api_data_cache_key}.\"\n        )\n        return api_data\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_active_learning_configuration(\n    api_key: str,\n    workspace_id: WorkspaceID,\n    dataset_id: DatasetID,\n) -> dict:\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/{dataset_id}/active_learning\",\n        params=[(\"api_key\", api_key)],\n    )\n    return _get_from_url(url=api_url)\n\n\n@wrap_roboflow_api_errors()\ndef register_image_at_roboflow(\n    api_key: str,\n    dataset_id: DatasetID,\n    local_image_id: str,\n    image_bytes: bytes,\n    batch_name: str,\n    tags: Optional[List[str]] = None,\n    inference_id: Optional[str] = None,\n    metadata: Optional[Dict[str, Any]] = None,\n) -> dict:\n    url = f\"{API_BASE_URL}/dataset/{dataset_id}/upload\"\n    params = [\n        (\"api_key\", api_key),\n        (\"batch\", batch_name),\n    ]\n    if inference_id is not None:\n        params.append((\"inference_id\", inference_id))\n    tags = tags if tags is not None else []\n    for tag in tags:\n        params.append((\"tag\", tag))\n    wrapped_url = wrap_url(_add_params_to_url(url=url, params=params))\n    fields = {\n        \"name\": f\"{local_image_id}.jpg\",\n        \"file\": (\"imageToUpload\", image_bytes, \"image/jpeg\"),\n    }\n    if metadata is not None:\n        fields[\"metadata\"] = json.dumps(metadata)\n    m = MultipartEncoder(fields=fields)\n    headers = build_roboflow_api_headers(\n        explicit_headers={\"Content-Type\": m.content_type},\n    )\n    response = requests.post(\n        url=wrapped_url,\n        data=m,\n        headers=headers,\n        timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n        verify=ROBOFLOW_API_VERIFY_SSL,\n    )\n    api_key_safe_raise_for_status(response=response)\n    parsed_response = response.json()\n    if not parsed_response.get(\"duplicate\") and not parsed_response.get(\"success\"):\n        raise RoboflowAPIImageUploadRejectionError(\n            f\"Server rejected image: {parsed_response}\"\n        )\n    return parsed_response\n\n\n@wrap_roboflow_api_errors(\n    http_errors_handlers={\n        409: lambda e: raise_from_lambda(\n            e,\n            RoboflowAPIIAlreadyAnnotatedError,\n            \"Given datapoint already has annotation.\",\n        )\n    }\n)\ndef annotate_image_at_roboflow(\n    api_key: str,\n    dataset_id: DatasetID,\n    local_image_id: str,\n    roboflow_image_id: str,\n    annotation_content: str,\n    annotation_file_type: str,\n    is_prediction: bool = True,\n) -> dict:\n    url = f\"{API_BASE_URL}/dataset/{dataset_id}/annotate/{roboflow_image_id}\"\n    params = [\n        (\"api_key\", api_key),\n        (\"name\", f\"{local_image_id}.{annotation_file_type}\"),\n        (\"prediction\", str(is_prediction).lower()),\n    ]\n    wrapped_url = wrap_url(_add_params_to_url(url=url, params=params))\n    headers = build_roboflow_api_headers(\n        explicit_headers={\"Content-Type\": \"text/plain\"},\n    )\n    response = requests.post(\n        wrapped_url,\n        data=annotation_content,\n        headers=headers,\n        timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n        verify=ROBOFLOW_API_VERIFY_SSL,\n    )\n    api_key_safe_raise_for_status(response=response)\n    parsed_response = response.json()\n    if \"error\" in parsed_response or not parsed_response.get(\"success\"):\n        raise RoboflowAPIIAnnotationRejectionError(\n            f\"Failed to save annotation for {roboflow_image_id}. API response: {parsed_response}\"\n        )\n    return parsed_response\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_labeling_batches(\n    api_key: str, workspace_id: WorkspaceID, dataset_id: str\n) -> dict:\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/{dataset_id}/batches\",\n        params=[(\"api_key\", api_key)],\n    )\n    return _get_from_url(url=api_url)\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_labeling_jobs(\n    api_key: str, workspace_id: WorkspaceID, dataset_id: str\n) -> dict:\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/{dataset_id}/jobs\",\n        params=[(\"api_key\", api_key)],\n    )\n    return _get_from_url(url=api_url)\n\n\ndef get_workflow_cache_file(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    workflow_version_id: Optional[str] = None,\n) -> str:\n    sanitized_workspace_id = sanitize_path_segment(workspace_id)\n    sanitized_workflow_id = sanitize_path_segment(workflow_id)\n    if SINGLE_TENANT_WORKFLOW_CACHE:\n        version_suffix = (\n            f\"_v{sanitize_path_segment(workflow_version_id)}\"\n            if workflow_version_id\n            else \"\"\n        )\n        filename = f\"{sanitized_workflow_id}{version_suffix}.json\"\n    else:\n        cache_seed = f\"{workspace_id}:{api_key or ''}\"\n        cache_fingerprint = hashlib.sha256(\n            cache_seed.encode(\"utf-8\"), usedforsecurity=False\n        ).hexdigest()\n        filename = f\"{sanitized_workflow_id}_{cache_fingerprint}.json\"\n    prefix = os.path.abspath(os.path.join(MODEL_CACHE_DIR, \"workflow\"))\n    result = os.path.abspath(\n        os.path.join(\n            prefix,\n            sanitized_workspace_id,\n            filename,\n        )\n    )\n    if not result.startswith(prefix):\n        raise ValueError(\n            \"Detected attempt to save workflow definition in insecure location\"\n        )\n    return result\n\n\ndef cache_workflow_response(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    response: dict,\n    workflow_version_id: Optional[str] = None,\n):\n    workflow_cache_file = get_workflow_cache_file(\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        api_key=api_key,\n        workflow_version_id=workflow_version_id,\n    )\n    workflow_cache_dir = os.path.dirname(workflow_cache_file)\n    if not os.path.exists(workflow_cache_dir):\n        os.makedirs(workflow_cache_dir, exist_ok=True)\n    with open(workflow_cache_file, \"w\") as f:\n        json.dump(response, f)\n\n\ndef delete_cached_workflow_response_if_exists(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    workflow_version_id: Optional[str] = None,\n) -> None:\n    workflow_cache_file = get_workflow_cache_file(\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        api_key=api_key,\n        workflow_version_id=workflow_version_id,\n    )\n    if os.path.exists(workflow_cache_file):\n        os.remove(workflow_cache_file)\n\n\ndef load_cached_workflow_response(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    workflow_version_id: Optional[str] = None,\n) -> Optional[dict]:\n    workflow_cache_file = get_workflow_cache_file(\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        api_key=api_key,\n        workflow_version_id=workflow_version_id,\n    )\n    if not os.path.exists(workflow_cache_file):\n        return None\n    try:\n        with open(workflow_cache_file, \"r\") as f:\n            return json.load(f)\n    except Exception:\n        delete_cached_workflow_response_if_exists(\n            workspace_id=workspace_id,\n            workflow_id=workflow_id,\n            api_key=api_key,\n            workflow_version_id=workflow_version_id,\n        )\n\n\n@wrap_roboflow_api_errors()\ndef get_workflow_specification(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    use_cache: bool = True,\n    ephemeral_cache: Optional[BaseCache] = None,\n    workflow_version_id: Optional[str] = None,\n) -> dict:\n    ephemeral_cache = ephemeral_cache or cache\n    if use_cache:\n        cached_entry = _retrieve_workflow_specification_from_ephemeral_cache(\n            api_key=api_key,\n            workspace_id=workspace_id,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n            ephemeral_cache=ephemeral_cache,\n        )\n        if cached_entry:\n            return cached_entry\n\n    if workspace_id == \"local\":\n        if not re.match(r\"^[\\w\\-]+$\", workflow_id):\n            raise ValueError(\"Invalid workflow id\")\n\n        workflow_hash = sha256(workflow_id.encode()).hexdigest()\n        local_file_path = (\n            Path(MODEL_CACHE_DIR) / \"workflow\" / \"local\" / f\"{workflow_hash}.json\"\n        )\n        if not local_file_path.exists():\n            raise FileNotFoundError(f\"Local workflow file not found: {local_file_path}\")\n\n        with local_file_path.open(\"r\", encoding=\"utf-8\") as f:\n            local_config = json.load(f)\n\n        # Mimic the same shape as the cloud response:\n        response = {\"workflow\": local_config}\n    else:\n        params = []\n        if api_key is not None:\n            params.append((\"api_key\", api_key))\n        if workflow_version_id is not None:\n            params.append((\"workflow_version\", workflow_version_id))\n        api_url = _add_params_to_url(\n            url=f\"{API_BASE_URL}/{workspace_id}/workflows/{workflow_id}\",\n            params=params,\n        )\n        try:\n            response = _get_from_url(url=api_url)\n            if USE_FILE_CACHE_FOR_WORKFLOWS_DEFINITIONS:\n                cache_workflow_response(\n                    workspace_id=workspace_id,\n                    workflow_id=workflow_id,\n                    api_key=api_key,\n                    response=response,\n                    workflow_version_id=workflow_version_id,\n                )\n        except (\n            requests.exceptions.ConnectionError,\n            ConnectionError,\n            requests.exceptions.Timeout,\n        ) as error:\n            if not USE_FILE_CACHE_FOR_WORKFLOWS_DEFINITIONS:\n                raise error\n            response = load_cached_workflow_response(\n                workspace_id=workspace_id,\n                workflow_id=workflow_id,\n                api_key=api_key,\n                workflow_version_id=workflow_version_id,\n            )\n            if response is None:\n                raise error\n\n    if \"workflow\" not in response or \"config\" not in response[\"workflow\"]:\n        raise MalformedWorkflowResponseError(\n            \"Could not find workflow specification in API response\"\n        )\n    try:\n        workflow_config = json.loads(response[\"workflow\"][\"config\"])\n        specification = workflow_config[\"specification\"]\n        if isinstance(specification, dict):\n            specification[\"id\"] = response[\"workflow\"].get(\"id\")\n        if use_cache:\n            _cache_workflow_specification_in_ephemeral_cache(\n                api_key=api_key,\n                workspace_id=workspace_id,\n                workflow_id=workflow_id,\n                workflow_version_id=workflow_version_id,\n                specification=specification,\n                ephemeral_cache=ephemeral_cache,\n            )\n        return specification\n    except KeyError as error:\n        raise MalformedWorkflowResponseError(\n            \"Workflow specification not found in Roboflow API response\"\n        ) from error\n    except (ValueError, TypeError) as error:\n        raise MalformedWorkflowResponseError(\n            \"Could not decode workflow specification in Roboflow API response\"\n        ) from error\n\n\ndef _retrieve_workflow_specification_from_ephemeral_cache(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    ephemeral_cache: BaseCache,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[dict]:\n    cache_key = _prepare_workflow_response_cache_key(\n        api_key=api_key,\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        workflow_version_id=workflow_version_id,\n    )\n    return ephemeral_cache.get(key=cache_key)\n\n\ndef _cache_workflow_specification_in_ephemeral_cache(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    specification: dict,\n    ephemeral_cache: BaseCache,\n    workflow_version_id: Optional[str] = None,\n) -> None:\n    cache_key = _prepare_workflow_response_cache_key(\n        api_key=api_key,\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        workflow_version_id=workflow_version_id,\n    )\n    ephemeral_cache.set(\n        key=cache_key,\n        value=specification,\n        expire=WORKFLOWS_DEFINITION_CACHE_EXPIRY,\n    )\n\n\ndef _prepare_workflow_response_cache_key(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> str:\n    workflow_version_suffix = (\n        f\":workflow_version={workflow_version_id}\" if workflow_version_id else \"\"\n    )\n    if SINGLE_TENANT_WORKFLOW_CACHE:\n        return (\n            f\"workflow_definition:{workspace_id}:{workflow_id}{workflow_version_suffix}\"\n        )\n    cache_seed = f\"{workspace_id}:{api_key or ''}\"\n    cache_fingerprint = hashlib.sha256(\n        cache_seed.encode(\"utf-8\"), usedforsecurity=False\n    ).hexdigest()\n    return f\"workflow_definition:{workspace_id}:{workflow_id}{workflow_version_suffix}:{cache_fingerprint}\"\n\n\n@wrap_roboflow_api_errors()\ndef get_from_url(\n    url: str,\n    json_response: bool = True,\n) -> Union[Response, dict]:\n    return _get_from_url(\n        url=url,\n        json_response=json_response,\n    )\n\n\n@backoff.on_exception(\n    backoff.constant,\n    exception=RetryRequestError,\n    max_tries=TRANSIENT_ROBOFLOW_API_ERRORS_RETRIES,\n    interval=TRANSIENT_ROBOFLOW_API_ERRORS_RETRY_INTERVAL,\n)\ndef _get_from_url(\n    url: str,\n    json_response: bool = True,\n    headers: Optional[dict] = None,\n) -> Union[Response, dict]:\n    full_url = wrap_url(url)\n    try:\n        response = requests.get(\n            full_url,\n            headers=build_roboflow_api_headers(explicit_headers=headers),\n            timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n            verify=ROBOFLOW_API_VERIFY_SSL,\n        )\n\n    except (ConnectionError, Timeout, requests.exceptions.ConnectionError) as error:\n        if RETRY_CONNECTION_ERRORS_TO_ROBOFLOW_API:\n            raise RetryRequestError(\n                message=\"Connectivity error\", inner_error=error\n            ) from error\n        raise error\n    try:\n        api_key_safe_raise_for_status(response=response)\n    except Exception as error:\n        if response.status_code in TRANSIENT_ROBOFLOW_API_ERRORS:\n            raise RetryRequestError(message=str(error), inner_error=error) from error\n        raise error\n\n    if MD5_VERIFICATION_ENABLED:\n        x_goog_hash = response.headers.get(\"x-goog-hash\")\n        if x_goog_hash is None:\n            logger.warning(\n                f\"MD5 verification enabled but response missing x-goog-hash header. \"\n                f\"Request url: {_url_for_safe_logging(full_url)}\"\n            )\n        else:\n            md5_part = None\n            for part in x_goog_hash.split(\",\"):\n                if part.strip().startswith(\"md5=\"):\n                    md5_part = part.strip()[4:]\n                    break\n            if md5_part is not None:\n                try:\n                    md5_from_header = base64.b64decode(md5_part)\n                except binascii.Error as decode_error:\n                    raise RoboflowAPIUnsuccessfulRequestError(\n                        \"Invalid MD5 value in x-goog-hash header: not valid base64\"\n                    ) from decode_error\n                if md5_from_header != hashlib.md5(response.content).digest():\n                    raise RoboflowAPIUnsuccessfulRequestError(\n                        \"MD5 hash does not match MD5 received from x-goog-hash header\"\n                    )\n            else:\n                logger.warning(\n                    f\"MD5 verification enabled but x-goog-hash header has no md5= part. \"\n                    f\"Request url: {_url_for_safe_logging(full_url)}\"\n                )\n\n    if json_response:\n        return response.json()\n    return response\n\n\ndef _test_range_request(url: str, timeout: int = 10) -> bool:\n    \"\"\"Test if server actually honors range requests by making a real range GET request.\n\n    Note: We can't rely on Accept-Ranges header alone because some servers/CDNs\n    advertise range support but return 200 (full file) instead of 206 (partial).\n    \"\"\"\n    try:\n        headers = {\"Range\": \"bytes=0-0\"}\n        response = requests.get(url, headers=headers, stream=True, timeout=timeout)\n        response.close()\n        if response.status_code == 206:\n            return True\n\n        return False\n    except Exception as e:\n        logger.warning(\n            f\"Failed to test range request support: {e}. Falling back to single-threaded download.\"\n        )\n        return False\n\n\ndef stream_url_to_cache(\n    url: str,\n    filename: str,\n    model_id: str,\n) -> None:\n    from inference_models.utils.download import download_files_to_directory\n\n    with start_span(\n        \"roboflow_api.download_artifact\",\n        {\"http.url\": _url_for_safe_logging(url), \"model.id\": model_id},\n    ):\n        initialise_cache(model_id=model_id)\n        cache_dir = get_cache_dir(model_id=model_id)\n        md5_hash = None\n\n        max_threads = 8 if _test_range_request(url) else 1\n\n        try:\n            download_files_to_directory(\n                target_dir=cache_dir,\n                files_specs=[(filename, url, md5_hash)],\n                verbose=True,\n                download_files_without_hash=True,\n                verify_hash_while_download=False,\n                max_threads_per_download=max_threads,\n            )\n        except Exception as e:\n            raise RoboflowAPIUnsuccessfulRequestError(\n                f\"Failed to download {filename}: {str(e)}\"\n            ) from e\n\n\ndef _url_for_safe_logging(url: str) -> str:\n    \"\"\"Return a URL safe to log by stripping the query string (and params/fragment).\n\n    Expects the full URL as used for the request (e.g. already wrapped).\n    Use this when logging request URLs so that sensitive query parameters\n    (e.g. api_key, tokens) are never written to logs.\n    \"\"\"\n    parsed = urllib.parse.urlparse(url)\n    return urllib.parse.urlunparse(\n        (parsed.scheme, parsed.netloc, parsed.path, \"\", \"\", \"\")\n    )\n\n\ndef _add_params_to_url(url: str, params: List[Tuple[str, str]]) -> str:\n    if len(params) == 0:\n        return url\n    params_chunks = [\n        f\"{name}={urllib.parse.quote_plus(value)}\" for name, value in params\n    ]\n    parameters_string = \"&\".join(params_chunks)\n    return f\"{url}?{parameters_string}\"\n\n\n@wrap_roboflow_api_errors()\ndef send_inference_results_to_model_monitoring(\n    api_key: str,\n    workspace_id: WorkspaceID,\n    inference_data: dict,\n):\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/inference-stats\",\n        params=[(\"api_key\", api_key)],\n    )\n    response = requests.post(\n        url=api_url,\n        json=inference_data,\n        headers=build_roboflow_api_headers(),\n        timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n        verify=ROBOFLOW_API_VERIFY_SSL,\n    )\n    api_key_safe_raise_for_status(response=response)\n\n\ndef get_extra_weights_provider_headers(\n    countinference: Optional[bool] = None,\n    service_secret: Optional[str] = None,\n) -> Optional[Dict[str, str]]:\n    headers = {}\n    if GCP_SERVERLESS:\n        headers[ENFORCE_INTERNAL_ARTIFACTS_URLS_HEADER] = \"true\"\n    if ENFORCE_CREDITS_VERIFICATION:\n        skip = (\n            countinference is False\n            and service_secret is not None\n            and service_secret == ROBOFLOW_SERVICE_SECRET\n        )\n        if not skip:\n            headers[ENFORCE_CREDITS_VERIFICATION_HEADER] = \"true\"\n    return build_roboflow_api_headers(explicit_headers=headers)\n\n\ndef build_roboflow_api_headers(\n    explicit_headers: Optional[Dict[str, Union[str, List[str]]]] = None,\n) -> Dict[str, Union[str, List[str]]]:\n    if explicit_headers is None:\n        explicit_headers = {}\n    explicit_headers = {\n        **explicit_headers,\n        ROBOFLOW_INFERENCE_VERSION_HEADER: __version__,\n        ALLOW_CHUNKED_RESPONSE_HEADER: \"true\",\n    }\n    if not ROBOFLOW_API_EXTRA_HEADERS:\n        return explicit_headers\n    try:\n        extra_headers: dict = json.loads(ROBOFLOW_API_EXTRA_HEADERS)\n        if explicit_headers:\n            extra_headers.update(explicit_headers)\n        return extra_headers\n    except ValueError:\n        logger.warning(\"Could not decode ROBOFLOW_API_EXTRA_HEADERS\")\n        return explicit_headers\n\n\ndef post_to_roboflow_api(\n    endpoint: str,\n    api_key: Optional[str],\n    payload: Optional[dict] = None,\n    params: Optional[List[Tuple[str, str]]] = None,\n    http_errors_handlers: Optional[\n        Dict[int, Callable[[Union[requests.exceptions.HTTPError]], None]]\n    ] = None,\n) -> dict:\n    \"\"\"Generic function to make a POST request to the Roboflow API.\n\n    Args:\n        endpoint: API endpoint path\n        api_key: Roboflow API key\n        payload: JSON payload\n        params: Additional URL parameters\n        http_errors_handlers: Optional custom HTTP error handlers by status code\n    \"\"\"\n\n    @wrap_roboflow_api_errors(http_errors_handlers=http_errors_handlers)\n    def _make_request():\n        url_params = []\n        if api_key:\n            url_params.append((\"api_key\", api_key))\n        if params:\n            url_params.extend(params)\n\n        full_url = _add_params_to_url(\n            url=f\"{API_BASE_URL}/{endpoint.strip('/')}\", params=url_params\n        )\n        wrapped_url = wrap_url(full_url)\n\n        headers = build_roboflow_api_headers()\n\n        response = requests.post(\n            url=wrapped_url,\n            json=payload,\n            headers=headers,\n            timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n            verify=ROBOFLOW_API_VERIFY_SSL,\n        )\n        api_key_safe_raise_for_status(response=response)\n        return response.json()\n\n    return _make_request()\n",
    "patch": null
  },
  {
    "trace_id": "e2340c87-696d-443e-9615-5c60f1b44ddb",
    "function_name": "InferenceModelsQwen3VLAdapter.map_inference_kwargs",
    "file_path": "inference/models/qwen3vl/qwen3vl_inference_models.py",
    "speedup_x": 1.3860738814158573,
    "review_quality": "medium",
    "pre_optimization_commit": "94995c6f87333bd982d3a4ded917f79d578a0c2f",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        pre_processing_overrides = PreProcessingOverrides(\n            disable_contrast_enhancement=kwargs.get(\"disable_preproc_contrast\", False),\n            disable_grayscale=kwargs.get(\"disable_preproc_grayscale\", False),\n            disable_static_crop=kwargs.get(\"disable_preproc_static_crop\", False),\n        )\n        kwargs[\"pre_processing_overrides\"] = pre_processing_overrides\n        return kwargs\n",
    "optimized_function_code": "from inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES, API_KEY,\n    DISABLED_INFERENCE_MODELS_BACKENDS, VALID_INFERENCE_MODELS_BACKENDS)\nfrom inference.core.models.base import Model\nfrom inference.core.roboflow_api import get_extra_weights_provider_headers\nfrom inference_models import AutoModel, PreProcessingOverrides\nfrom inference_models.models.qwen3vl.qwen3vl_hf import Qwen3VLHF\n\n# Cache for common PreProcessingOverrides instances\n_PREPROCESSING_OVERRIDES_CACHE = {}\n\ndef _get_cached_preprocessing_overrides(disable_contrast: bool, disable_grayscale: bool, disable_static_crop: bool) -> PreProcessingOverrides:\n    \"\"\"Get or create a cached PreProcessingOverrides instance.\"\"\"\n    cache_key = (disable_contrast, disable_grayscale, disable_static_crop)\n    if cache_key not in _PREPROCESSING_OVERRIDES_CACHE:\n        _PREPROCESSING_OVERRIDES_CACHE[cache_key] = PreProcessingOverrides(\n            disable_contrast_enhancement=disable_contrast,\n            disable_grayscale=disable_grayscale,\n            disable_static_crop=disable_static_crop,\n        )\n    return _PREPROCESSING_OVERRIDES_CACHE[cache_key]\n\nclass InferenceModelsQwen3VLAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n\n        self.task_type = \"lmm\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n        backend = list(\n            VALID_INFERENCE_MODELS_BACKENDS.difference(\n                DISABLED_INFERENCE_MODELS_BACKENDS\n            )\n        )\n        self._model: Qwen3VLHF = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            backend=backend,\n            **kwargs,\n        )\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        pre_processing_overrides = _get_cached_preprocessing_overrides(\n            kwargs.get(\"disable_preproc_contrast\", False),\n            kwargs.get(\"disable_preproc_grayscale\", False),\n            kwargs.get(\"disable_preproc_static_crop\", False),\n        )\n        kwargs[\"pre_processing_overrides\"] = pre_processing_overrides\n        return kwargs",
    "optimized_raw_markdown": "```python:inference/models/qwen3vl/qwen3vl_inference_models.py\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES, API_KEY,\n    DISABLED_INFERENCE_MODELS_BACKENDS, VALID_INFERENCE_MODELS_BACKENDS)\nfrom inference.core.models.base import Model\nfrom inference.core.roboflow_api import get_extra_weights_provider_headers\nfrom inference_models import AutoModel, PreProcessingOverrides\nfrom inference_models.models.qwen3vl.qwen3vl_hf import Qwen3VLHF\n\n# Cache for common PreProcessingOverrides instances\n_PREPROCESSING_OVERRIDES_CACHE = {}\n\ndef _get_cached_preprocessing_overrides(disable_contrast: bool, disable_grayscale: bool, disable_static_crop: bool) -> PreProcessingOverrides:\n    \"\"\"Get or create a cached PreProcessingOverrides instance.\"\"\"\n    cache_key = (disable_contrast, disable_grayscale, disable_static_crop)\n    if cache_key not in _PREPROCESSING_OVERRIDES_CACHE:\n        _PREPROCESSING_OVERRIDES_CACHE[cache_key] = PreProcessingOverrides(\n            disable_contrast_enhancement=disable_contrast,\n            disable_grayscale=disable_grayscale,\n            disable_static_crop=disable_static_crop,\n        )\n    return _PREPROCESSING_OVERRIDES_CACHE[cache_key]\n\nclass InferenceModelsQwen3VLAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n\n        self.task_type = \"lmm\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n        backend = list(\n            VALID_INFERENCE_MODELS_BACKENDS.difference(\n                DISABLED_INFERENCE_MODELS_BACKENDS\n            )\n        )\n        self._model: Qwen3VLHF = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            backend=backend,\n            **kwargs,\n        )\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        pre_processing_overrides = _get_cached_preprocessing_overrides(\n            kwargs.get(\"disable_preproc_contrast\", False),\n            kwargs.get(\"disable_preproc_grayscale\", False),\n            kwargs.get(\"disable_preproc_static_crop\", False),\n        )\n        kwargs[\"pre_processing_overrides\"] = pre_processing_overrides\n        return kwargs\n```",
    "optimized_function_only": "    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        pre_processing_overrides = _get_cached_preprocessing_overrides(\n            kwargs.get(\"disable_preproc_contrast\", False),\n            kwargs.get(\"disable_preproc_grayscale\", False),\n            kwargs.get(\"disable_preproc_static_crop\", False),\n        )\n        kwargs[\"pre_processing_overrides\"] = pre_processing_overrides\n        return kwargs",
    "original_file_content": "from typing import Any, List\n\nimport torch\n\nfrom inference.core.entities.responses import (\n    InferenceResponseImage,\n    LMMInferenceResponse,\n)\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n    API_KEY,\n    DISABLED_INFERENCE_MODELS_BACKENDS,\n    VALID_INFERENCE_MODELS_BACKENDS,\n)\nfrom inference.core.models.base import Model\nfrom inference.core.models.types import PreprocessReturnMetadata\nfrom inference.core.roboflow_api import get_extra_weights_provider_headers\nfrom inference.core.utils.image_utils import load_image_bgr\nfrom inference_models import AutoModel, PreProcessingOverrides\nfrom inference_models.models.qwen3vl.qwen3vl_hf import Qwen3VLHF\n\n\nclass InferenceModelsQwen3VLAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n\n        self.task_type = \"lmm\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n        backend = list(\n            VALID_INFERENCE_MODELS_BACKENDS.difference(\n                DISABLED_INFERENCE_MODELS_BACKENDS\n            )\n        )\n        self._model: Qwen3VLHF = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            backend=backend,\n            **kwargs,\n        )\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        pre_processing_overrides = PreProcessingOverrides(\n            disable_contrast_enhancement=kwargs.get(\"disable_preproc_contrast\", False),\n            disable_grayscale=kwargs.get(\"disable_preproc_grayscale\", False),\n            disable_static_crop=kwargs.get(\"disable_preproc_static_crop\", False),\n        )\n        kwargs[\"pre_processing_overrides\"] = pre_processing_overrides\n        return kwargs\n\n    def preprocess(self, image: Any, prompt: str = \"\", **kwargs):\n        is_batch = isinstance(image, list)\n        if is_batch:\n            raise ValueError(\"This model does not support batched-inference.\")\n        np_image = load_image_bgr(\n            image,\n            disable_preproc_auto_orient=kwargs.get(\n                \"disable_preproc_auto_orient\", False\n            ),\n        )\n        input_shape = PreprocessReturnMetadata({\"image_dims\": np_image.shape[:2][::-1]})\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return (\n            self._model.pre_process_generation(np_image, prompt, **mapped_kwargs),\n            input_shape,\n        )\n\n    def predict(self, inputs, **kwargs) -> torch.Tensor:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.generate(inputs, **mapped_kwargs)\n\n    def postprocess(\n        self,\n        predictions: torch.Tensor,\n        preprocess_return_metadata: PreprocessReturnMetadata,\n        **kwargs,\n    ) -> List[LMMInferenceResponse]:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        result = self._model.post_process_generation(predictions, **mapped_kwargs)[0]\n        return [\n            LMMInferenceResponse(\n                response=result,\n                image=InferenceResponseImage(\n                    width=preprocess_return_metadata[\"image_dims\"][0],\n                    height=preprocess_return_metadata[\"image_dims\"][1],\n                ),\n            )\n        ]\n\n    def clear_cache(self, delete_from_disk: bool = True) -> None:\n        \"\"\"Clears any cache if necessary. TODO: Implement this to delete the cache from the experimental model.\n\n        Args:\n            delete_from_disk (bool, optional): Whether to delete cached files from disk. Defaults to True.\n        \"\"\"\n        pass\n",
    "patch": null
  },
  {
    "trace_id": "9fed9137-e1b8-4edd-bc3d-fe711b05b1f9",
    "function_name": "InferenceModelsKeyPointsDetectionAdapter.map_inference_kwargs",
    "file_path": "inference/core/models/inference_models_adapters.py",
    "speedup_x": 0.13127884183444277,
    "review_quality": "high",
    "pre_optimization_commit": "459f2b015b4df2c21d99608520607c01d3460822",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        if \"request\" in kwargs:\n            keypoint_confidence_threshold = kwargs[\"request\"].keypoint_confidence\n            kwargs[\"key_points_threshold\"] = keypoint_confidence_threshold\n        pre_processing_overrides = PreProcessingOverrides(\n            disable_contrast_enhancement=kwargs.get(\"disable_preproc_contrast\", False),\n            disable_grayscale=kwargs.get(\"disable_preproc_grayscale\", False),\n            disable_static_crop=kwargs.get(\"disable_preproc_static_crop\", False),\n        )\n        kwargs[\"pre_processing_overrides\"] = pre_processing_overrides\n        return kwargs\n",
    "optimized_function_code": "from inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES, API_KEY,\n    DISABLED_INFERENCE_MODELS_BACKENDS, VALID_INFERENCE_MODELS_BACKENDS)\nfrom inference.core.models.base import Model\nfrom inference.core.roboflow_api import get_extra_weights_provider_headers\nfrom inference.models.aliases import resolve_roboflow_model_alias\nfrom inference_models import (AutoModel, KeyPointsDetectionModel,\n                              PreProcessingOverrides)\n\n# Cache for default PreProcessingOverrides instance\n_DEFAULT_PRE_PROCESSING_OVERRIDES = PreProcessingOverrides(\n    disable_contrast_enhancement=False,\n    disable_grayscale=False,\n    disable_static_crop=False,\n)\n\nclass InferenceModelsKeyPointsDetectionAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n        model_id = resolve_roboflow_model_alias(model_id=model_id)\n\n        self.task_type = \"keypoint-detection\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n        backend = list(\n            VALID_INFERENCE_MODELS_BACKENDS.difference(\n                DISABLED_INFERENCE_MODELS_BACKENDS\n            )\n        )\n        self._model: KeyPointsDetectionModel = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            backend=backend,\n            **kwargs,\n        )\n        self.class_names = list(self._model.class_names)\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        if \"request\" in kwargs:\n            keypoint_confidence_threshold = kwargs[\"request\"].keypoint_confidence\n            kwargs[\"key_points_threshold\"] = keypoint_confidence_threshold\n        \n        # Extract preprocessing flags once\n        disable_contrast = kwargs.get(\"disable_preproc_contrast\", False)\n        disable_grayscale = kwargs.get(\"disable_preproc_grayscale\", False)\n        disable_static_crop = kwargs.get(\"disable_preproc_static_crop\", False)\n        \n        # Use cached default instance when all flags are False\n        if not (disable_contrast or disable_grayscale or disable_static_crop):\n            pre_processing_overrides = _DEFAULT_PRE_PROCESSING_OVERRIDES\n        else:\n            pre_processing_overrides = PreProcessingOverrides(\n                disable_contrast_enhancement=disable_contrast,\n                disable_grayscale=disable_grayscale,\n                disable_static_crop=disable_static_crop,\n            )\n        kwargs[\"pre_processing_overrides\"] = pre_processing_overrides\n        return kwargs",
    "optimized_raw_markdown": "```python:inference/core/models/inference_models_adapters.py\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES, API_KEY,\n    DISABLED_INFERENCE_MODELS_BACKENDS, VALID_INFERENCE_MODELS_BACKENDS)\nfrom inference.core.models.base import Model\nfrom inference.core.roboflow_api import get_extra_weights_provider_headers\nfrom inference.models.aliases import resolve_roboflow_model_alias\nfrom inference_models import (AutoModel, KeyPointsDetectionModel,\n                              PreProcessingOverrides)\n\n# Cache for default PreProcessingOverrides instance\n_DEFAULT_PRE_PROCESSING_OVERRIDES = PreProcessingOverrides(\n    disable_contrast_enhancement=False,\n    disable_grayscale=False,\n    disable_static_crop=False,\n)\n\nclass InferenceModelsKeyPointsDetectionAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n        model_id = resolve_roboflow_model_alias(model_id=model_id)\n\n        self.task_type = \"keypoint-detection\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n        backend = list(\n            VALID_INFERENCE_MODELS_BACKENDS.difference(\n                DISABLED_INFERENCE_MODELS_BACKENDS\n            )\n        )\n        self._model: KeyPointsDetectionModel = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            backend=backend,\n            **kwargs,\n        )\n        self.class_names = list(self._model.class_names)\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        if \"request\" in kwargs:\n            keypoint_confidence_threshold = kwargs[\"request\"].keypoint_confidence\n            kwargs[\"key_points_threshold\"] = keypoint_confidence_threshold\n        \n        # Extract preprocessing flags once\n        disable_contrast = kwargs.get(\"disable_preproc_contrast\", False)\n        disable_grayscale = kwargs.get(\"disable_preproc_grayscale\", False)\n        disable_static_crop = kwargs.get(\"disable_preproc_static_crop\", False)\n        \n        # Use cached default instance when all flags are False\n        if not (disable_contrast or disable_grayscale or disable_static_crop):\n            pre_processing_overrides = _DEFAULT_PRE_PROCESSING_OVERRIDES\n        else:\n            pre_processing_overrides = PreProcessingOverrides(\n                disable_contrast_enhancement=disable_contrast,\n                disable_grayscale=disable_grayscale,\n                disable_static_crop=disable_static_crop,\n            )\n        kwargs[\"pre_processing_overrides\"] = pre_processing_overrides\n        return kwargs\n```",
    "optimized_function_only": "    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        if \"request\" in kwargs:\n            keypoint_confidence_threshold = kwargs[\"request\"].keypoint_confidence\n            kwargs[\"key_points_threshold\"] = keypoint_confidence_threshold\n        \n        # Extract preprocessing flags once\n        disable_contrast = kwargs.get(\"disable_preproc_contrast\", False)\n        disable_grayscale = kwargs.get(\"disable_preproc_grayscale\", False)\n        disable_static_crop = kwargs.get(\"disable_preproc_static_crop\", False)\n        \n        # Use cached default instance when all flags are False\n        if not (disable_contrast or disable_grayscale or disable_static_crop):\n            pre_processing_overrides = _DEFAULT_PRE_PROCESSING_OVERRIDES\n        else:\n            pre_processing_overrides = PreProcessingOverrides(\n                disable_contrast_enhancement=disable_contrast,\n                disable_grayscale=disable_grayscale,\n                disable_static_crop=disable_static_crop,\n            )\n        kwargs[\"pre_processing_overrides\"] = pre_processing_overrides\n        return kwargs",
    "original_file_content": "import base64\nimport io\nfrom io import BytesIO\nfrom time import perf_counter\nfrom typing import Any, List, Optional, Tuple, Union\n\nimport numpy as np\nimport torch\nfrom PIL import Image, ImageDraw, ImageFont\n\nfrom inference.core.entities.requests import (\n    ClassificationInferenceRequest,\n    InferenceRequest,\n)\nfrom inference.core.entities.responses.inference import (\n    ClassificationInferenceResponse,\n    InferenceResponse,\n    InferenceResponseImage,\n    InstanceSegmentationInferenceResponse,\n    InstanceSegmentationPrediction,\n    Keypoint,\n    KeypointsDetectionInferenceResponse,\n    KeypointsPrediction,\n    MultiLabelClassificationInferenceResponse,\n    ObjectDetectionInferenceResponse,\n    ObjectDetectionPrediction,\n    Point,\n    SemanticSegmentationInferenceResponse,\n    SemanticSegmentationPrediction,\n)\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n    API_KEY,\n    DISABLED_INFERENCE_MODELS_BACKENDS,\n    RFDETR_ONNX_MAX_RESOLUTION,\n    VALID_INFERENCE_MODELS_BACKENDS,\n)\nfrom inference.core.models.base import Model\nfrom inference.core.roboflow_api import get_extra_weights_provider_headers\nfrom inference.core.utils.image_utils import load_image_bgr, load_image_rgb\nfrom inference.core.utils.postprocess import masks2poly\nfrom inference.core.utils.visualisation import draw_detection_predictions\nfrom inference.models.aliases import resolve_roboflow_model_alias\nfrom inference_models import (\n    AutoModel,\n    ClassificationModel,\n    ClassificationPrediction,\n    Detections,\n    InstanceDetections,\n    InstanceSegmentationModel,\n    KeyPoints,\n    KeyPointsDetectionModel,\n    MultiLabelClassificationModel,\n    MultiLabelClassificationPrediction,\n    ObjectDetectionModel,\n    PreProcessingOverrides,\n    SemanticSegmentationModel,\n)\nfrom inference_models.models.base.semantic_segmentation import (\n    SemanticSegmentationResult,\n)\nfrom inference_models.models.base.types import PreprocessingMetadata\n\ndef _resolve_cached_model_path(model_id: str) -> str:\n    \"\"\"If the model is already in the inference-models local cache, return the\n    package directory path so ``AutoModel.from_pretrained`` can load directly\n    from disk without calling the Roboflow API.  Returns the original\n    *model_id* unchanged when no local cache hit is found.\n    \"\"\"\n    try:\n        from inference.core.cache.air_gapped import (\n            _get_inference_models_home,\n            _slugify_model_id,\n        )\n        from inference.core.env import MODEL_CACHE_DIR\n\n        slug = _slugify_model_id(model_id)\n        bases = [MODEL_CACHE_DIR]\n        inference_home = _get_inference_models_home()\n        if inference_home is not None and inference_home != MODEL_CACHE_DIR:\n            bases.append(inference_home)\n\n        for base in bases:\n            import os\n\n            slug_dir = os.path.join(base, \"models-cache\", slug)\n            if not os.path.isdir(slug_dir):\n                continue\n            for package_id in os.listdir(slug_dir):\n                package_dir = os.path.join(slug_dir, package_id)\n                if os.path.isfile(os.path.join(package_dir, \"model_config.json\")):\n                    return package_dir\n    except Exception:\n        pass\n    return model_id\n\n\nDEFAULT_COLOR_PALETTE = [\n    \"#A351FB\",\n    \"#FF4040\",\n    \"#FFA1A0\",\n    \"#FF7633\",\n    \"#FFB633\",\n    \"#D1D435\",\n    \"#4CFB12\",\n    \"#94CF1A\",\n    \"#40DE8A\",\n    \"#1B9640\",\n    \"#00D6C1\",\n    \"#2E9CAA\",\n    \"#00C4FF\",\n    \"#364797\",\n    \"#6675FF\",\n    \"#0019EF\",\n    \"#863AFF\",\n    \"#530087\",\n    \"#CD3AFF\",\n    \"#FF97CA\",\n    \"#FF39C9\",\n]\n\n\nclass InferenceModelsObjectDetectionAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n        model_id = resolve_roboflow_model_alias(model_id=model_id)\n\n        self.task_type = \"object-detection\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n        backend = list(\n            VALID_INFERENCE_MODELS_BACKENDS.difference(\n                DISABLED_INFERENCE_MODELS_BACKENDS\n            )\n        )\n        self._model: ObjectDetectionModel = AutoModel.from_pretrained(\n            model_id_or_path=_resolve_cached_model_path(model_id),\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            backend=backend,\n            rf_detr_max_input_resolution=RFDETR_ONNX_MAX_RESOLUTION,\n            **kwargs,\n        )\n        self.class_names = list(self._model.class_names)\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        pre_processing_overrides = PreProcessingOverrides(\n            disable_contrast_enhancement=kwargs.get(\"disable_preproc_contrast\", False),\n            disable_grayscale=kwargs.get(\"disable_preproc_grayscale\", False),\n            disable_static_crop=kwargs.get(\"disable_preproc_static_crop\", False),\n        )\n        kwargs[\"pre_processing_overrides\"] = pre_processing_overrides\n        return kwargs\n\n    def preprocess(self, image: Any, **kwargs):\n        is_batch = isinstance(image, list)\n        images = image if is_batch else [image]\n        np_images: List[np.ndarray] = [\n            load_image_bgr(\n                v,\n                disable_preproc_auto_orient=kwargs.get(\n                    \"disable_preproc_auto_orient\", False\n                ),\n            )\n            for v in images\n        ]\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.pre_process(np_images, **mapped_kwargs)\n\n    def predict(self, img_in, **kwargs):\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.forward(img_in, **mapped_kwargs)\n\n    def postprocess(\n        self,\n        predictions: List[Detections],\n        preprocess_return_metadata: PreprocessingMetadata,\n        **kwargs,\n    ) -> List[ObjectDetectionInferenceResponse]:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        detections_list = self._model.post_process(\n            predictions, preprocess_return_metadata, **mapped_kwargs\n        )\n\n        responses: List[ObjectDetectionInferenceResponse] = []\n        for preproc_metadata, det in zip(preprocess_return_metadata, detections_list):\n            H = preproc_metadata.original_size.height\n            W = preproc_metadata.original_size.width\n\n            xyxy = det.xyxy.detach().cpu().numpy()\n            confs = det.confidence.detach().cpu().numpy()\n            class_ids = det.class_id.detach().cpu().numpy()\n\n            predictions: List[ObjectDetectionPrediction] = []\n\n            for (x1, y1, x2, y2), conf, class_id in zip(xyxy, confs, class_ids):\n                cx = (float(x1) + float(x2)) / 2.0\n                cy = (float(y1) + float(y2)) / 2.0\n                w = float(x2) - float(x1)\n                h = float(y2) - float(y1)\n                class_id_int = int(class_id)\n                class_name = (\n                    self.class_names[class_id_int]\n                    if 0 <= class_id_int < len(self.class_names)\n                    else str(class_id_int)\n                )\n                if (\n                    kwargs.get(\"class_filter\")\n                    and class_name not in kwargs[\"class_filter\"]\n                ):\n                    continue\n                predictions.append(\n                    ObjectDetectionPrediction(\n                        x=cx,\n                        y=cy,\n                        width=w,\n                        height=h,\n                        confidence=float(conf),\n                        **{\"class\": class_name},\n                        class_id=class_id_int,\n                    )\n                )\n\n            responses.append(\n                ObjectDetectionInferenceResponse(\n                    predictions=predictions,\n                    image=InferenceResponseImage(width=W, height=H),\n                )\n            )\n        return responses\n\n    def clear_cache(self, delete_from_disk: bool = True) -> None:\n        \"\"\"Clears any cache if necessary. TODO: Implement this to delete the cache from the experimental model.\n\n        Args:\n            delete_from_disk (bool, optional): Whether to delete cached files from disk. Defaults to True.\n        \"\"\"\n        pass\n\n    def draw_predictions(\n        self,\n        inference_request: InferenceRequest,\n        inference_response: InferenceResponse,\n    ) -> bytes:\n        \"\"\"Draw predictions from an inference response onto the original image provided by an inference request\n\n        Args:\n            inference_request (ObjectDetectionInferenceRequest): The inference request containing the image on which to draw predictions\n            inference_response (ObjectDetectionInferenceResponse): The inference response containing predictions to be drawn\n\n        Returns:\n            str: A base64 encoded image string\n        \"\"\"\n        class_id_2_color = {\n            i: DEFAULT_COLOR_PALETTE[i % len(DEFAULT_COLOR_PALETTE)]\n            for i, class_name in enumerate(self._model.class_names)\n        }\n        return draw_detection_predictions(\n            inference_request=inference_request,\n            inference_response=inference_response,\n            colors=class_id_2_color,\n        )\n\n\nclass InferenceModelsInstanceSegmentationAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n        model_id = resolve_roboflow_model_alias(model_id=model_id)\n\n        self.task_type = \"instance-segmentation\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n        backend = list(\n            VALID_INFERENCE_MODELS_BACKENDS.difference(\n                DISABLED_INFERENCE_MODELS_BACKENDS\n            )\n        )\n        self._model: InstanceSegmentationModel = AutoModel.from_pretrained(\n            model_id_or_path=_resolve_cached_model_path(model_id),\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            backend=backend,\n            rf_detr_max_input_resolution=RFDETR_ONNX_MAX_RESOLUTION,\n            **kwargs,\n        )\n        self.class_names = list(self._model.class_names)\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        pre_processing_overrides = PreProcessingOverrides(\n            disable_contrast_enhancement=kwargs.get(\"disable_preproc_contrast\", False),\n            disable_grayscale=kwargs.get(\"disable_preproc_grayscale\", False),\n            disable_static_crop=kwargs.get(\"disable_preproc_static_crop\", False),\n        )\n        kwargs[\"pre_processing_overrides\"] = pre_processing_overrides\n        return kwargs\n\n    def preprocess(self, image: Any, **kwargs):\n        is_batch = isinstance(image, list)\n        images = image if is_batch else [image]\n        np_images: List[np.ndarray] = [\n            load_image_bgr(\n                v,\n                disable_preproc_auto_orient=kwargs.get(\n                    \"disable_preproc_auto_orient\", False\n                ),\n            )\n            for v in images\n        ]\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.pre_process(np_images, **mapped_kwargs)\n\n    def predict(self, img_in, **kwargs):\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.forward(img_in, **mapped_kwargs)\n\n    def postprocess(\n        self,\n        predictions: List[InstanceDetections],\n        preprocess_return_metadata: PreprocessingMetadata,\n        **kwargs,\n    ) -> List[InstanceSegmentationInferenceResponse]:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        detections_list = self._model.post_process(\n            predictions, preprocess_return_metadata, **mapped_kwargs\n        )\n\n        responses: List[InstanceSegmentationInferenceResponse] = []\n        for preproc_metadata, det in zip(preprocess_return_metadata, detections_list):\n            H = preproc_metadata.original_size.height\n            W = preproc_metadata.original_size.width\n\n            xyxy = det.xyxy.detach().cpu().numpy()\n            confs = det.confidence.detach().cpu().numpy()\n            masks = det.mask.detach().cpu().numpy()\n            polys = masks2poly(masks)\n            class_ids = det.class_id.detach().cpu().numpy()\n\n            predictions: List[InstanceSegmentationPrediction] = []\n\n            for (x1, y1, x2, y2), mask_as_poly, conf, class_id in zip(\n                xyxy, polys, confs, class_ids\n            ):\n                cx = (float(x1) + float(x2)) / 2.0\n                cy = (float(y1) + float(y2)) / 2.0\n                w = float(x2) - float(x1)\n                h = float(y2) - float(y1)\n                class_id_int = int(class_id)\n                class_name = (\n                    self.class_names[class_id_int]\n                    if 0 <= class_id_int < len(self.class_names)\n                    else str(class_id_int)\n                )\n                if (\n                    kwargs.get(\"class_filter\")\n                    and class_name not in kwargs[\"class_filter\"]\n                ):\n                    continue\n                predictions.append(\n                    InstanceSegmentationPrediction(\n                        x=cx,\n                        y=cy,\n                        width=w,\n                        height=h,\n                        confidence=float(conf),\n                        points=[\n                            Point(x=point[0], y=point[1]) for point in mask_as_poly\n                        ],\n                        **{\"class\": class_name},\n                        class_id=class_id_int,\n                    )\n                )\n\n            responses.append(\n                InstanceSegmentationInferenceResponse(\n                    predictions=predictions,\n                    image=InferenceResponseImage(width=W, height=H),\n                )\n            )\n        return responses\n\n    def clear_cache(self, delete_from_disk: bool = True) -> None:\n        \"\"\"Clears any cache if necessary. TODO: Implement this to delete the cache from the experimental model.\n\n        Args:\n            delete_from_disk (bool, optional): Whether to delete cached files from disk. Defaults to True.\n        \"\"\"\n        pass\n\n    def draw_predictions(\n        self,\n        inference_request: InferenceRequest,\n        inference_response: InferenceResponse,\n    ) -> bytes:\n        \"\"\"Draw predictions from an inference response onto the original image provided by an inference request\n\n        Args:\n            inference_request (ObjectDetectionInferenceRequest): The inference request containing the image on which to draw predictions\n            inference_response (ObjectDetectionInferenceResponse): The inference response containing predictions to be drawn\n\n        Returns:\n            str: A base64 encoded image string\n        \"\"\"\n        class_id_2_color = {\n            i: DEFAULT_COLOR_PALETTE[i % len(DEFAULT_COLOR_PALETTE)]\n            for i, class_name in enumerate(self._model.class_names)\n        }\n        return draw_detection_predictions(\n            inference_request=inference_request,\n            inference_response=inference_response,\n            colors=class_id_2_color,\n        )\n\n\nclass InferenceModelsKeyPointsDetectionAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n        model_id = resolve_roboflow_model_alias(model_id=model_id)\n\n        self.task_type = \"keypoint-detection\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n        backend = list(\n            VALID_INFERENCE_MODELS_BACKENDS.difference(\n                DISABLED_INFERENCE_MODELS_BACKENDS\n            )\n        )\n        self._model: KeyPointsDetectionModel = AutoModel.from_pretrained(\n            model_id_or_path=_resolve_cached_model_path(model_id),\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            backend=backend,\n            **kwargs,\n        )\n        self.class_names = list(self._model.class_names)\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        if \"request\" in kwargs:\n            keypoint_confidence_threshold = kwargs[\"request\"].keypoint_confidence\n            kwargs[\"key_points_threshold\"] = keypoint_confidence_threshold\n        pre_processing_overrides = PreProcessingOverrides(\n            disable_contrast_enhancement=kwargs.get(\"disable_preproc_contrast\", False),\n            disable_grayscale=kwargs.get(\"disable_preproc_grayscale\", False),\n            disable_static_crop=kwargs.get(\"disable_preproc_static_crop\", False),\n        )\n        kwargs[\"pre_processing_overrides\"] = pre_processing_overrides\n        return kwargs\n\n    def preprocess(self, image: Any, **kwargs):\n        is_batch = isinstance(image, list)\n        images = image if is_batch else [image]\n        np_images: List[np.ndarray] = [\n            load_image_bgr(\n                v,\n                disable_preproc_auto_orient=kwargs.get(\n                    \"disable_preproc_auto_orient\", False\n                ),\n            )\n            for v in images\n        ]\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.pre_process(np_images, **mapped_kwargs)\n\n    def predict(self, img_in, **kwargs):\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.forward(img_in, **mapped_kwargs)\n\n    def postprocess(\n        self,\n        predictions: Tuple[List[KeyPoints], Optional[List[Detections]]],\n        preprocess_return_metadata: PreprocessingMetadata,\n        **kwargs,\n    ) -> List[KeypointsDetectionInferenceResponse]:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        keypoints_list, detections_list = self._model.post_process(\n            predictions, preprocess_return_metadata, **mapped_kwargs\n        )\n        if detections_list is None:\n            raise RuntimeError(\n                \"Keypoints detection model does not provide instances detection - this is not supported for \"\n                \"models from `inference-models` package which are adapted to work with `inference`.\"\n            )\n        key_points_classes = self._model.key_points_classes\n        responses: List[KeypointsDetectionInferenceResponse] = []\n        for preproc_metadata, keypoints, det in zip(\n            preprocess_return_metadata, keypoints_list, detections_list\n        ):\n\n            H = preproc_metadata.original_size.height\n            W = preproc_metadata.original_size.width\n\n            xyxy = det.xyxy.detach().cpu().numpy()\n            confs = det.confidence.detach().cpu().numpy()\n            class_ids = det.class_id.detach().cpu().numpy()\n            keypoints_xy = keypoints.xy.detach().cpu().tolist()\n            keypoints_class_id = keypoints.class_id.detach().cpu().tolist()\n            keypoints_confidence = keypoints.confidence.detach().cpu().tolist()\n            predictions: List[KeypointsPrediction] = []\n\n            for (\n                (x1, y1, x2, y2),\n                conf,\n                class_id,\n                instance_keypoints_xy,\n                instance_keypoints_class_id,\n                instance_keypoints_confidence,\n            ) in zip(\n                xyxy,\n                confs,\n                class_ids,\n                keypoints_xy,\n                keypoints_class_id,\n                keypoints_confidence,\n            ):\n                cx = (float(x1) + float(x2)) / 2.0\n                cy = (float(y1) + float(y2)) / 2.0\n                w = float(x2) - float(x1)\n                h = float(y2) - float(y1)\n                class_id_int = int(class_id)\n                class_name = (\n                    self.class_names[class_id_int]\n                    if 0 <= class_id_int < len(self.class_names)\n                    else str(class_id_int)\n                )\n                if (\n                    kwargs.get(\"class_filter\")\n                    and class_name not in kwargs[\"class_filter\"]\n                ):\n                    continue\n                predictions.append(\n                    KeypointsPrediction(\n                        x=cx,\n                        y=cy,\n                        width=w,\n                        height=h,\n                        confidence=float(conf),\n                        **{\"class\": class_name},\n                        class_id=class_id_int,\n                        keypoints=model_keypoints_to_response(\n                            instance_keypoints_xy=instance_keypoints_xy,\n                            instance_keypoints_confidence=instance_keypoints_confidence,\n                            instance_keypoints_class_id=instance_keypoints_class_id,\n                            key_points_classes=key_points_classes,\n                        ),\n                    )\n                )\n\n            responses.append(\n                KeypointsDetectionInferenceResponse(\n                    predictions=predictions,\n                    image=InferenceResponseImage(width=W, height=H),\n                )\n            )\n\n        return responses\n\n    def clear_cache(self, delete_from_disk: bool = True) -> None:\n        \"\"\"Clears any cache if necessary. TODO: Implement this to delete the cache from the experimental model.\n\n        Args:\n            delete_from_disk (bool, optional): Whether to delete cached files from disk. Defaults to True.\n        \"\"\"\n        pass\n\n    def draw_predictions(\n        self,\n        inference_request: InferenceRequest,\n        inference_response: InferenceResponse,\n    ) -> bytes:\n        \"\"\"Draw predictions from an inference response onto the original image provided by an inference request\n\n        Args:\n            inference_request (ObjectDetectionInferenceRequest): The inference request containing the image on which to draw predictions\n            inference_response (ObjectDetectionInferenceResponse): The inference response containing predictions to be drawn\n\n        Returns:\n            str: A base64 encoded image string\n        \"\"\"\n        class_id_2_color = {\n            i: DEFAULT_COLOR_PALETTE[i % len(DEFAULT_COLOR_PALETTE)]\n            for i, class_name in enumerate(self._model.class_names)\n        }\n        return draw_detection_predictions(\n            inference_request=inference_request,\n            inference_response=inference_response,\n            colors=class_id_2_color,\n        )\n\n\ndef model_keypoints_to_response(\n    instance_keypoints_xy: List[\n        List[Union[float, int]]\n    ],  # (num_key_points_foc_class_of_object, 2)\n    instance_keypoints_confidence: List[float],  # (instance_key_points, )\n    instance_keypoints_class_id: int,\n    key_points_classes: List[List[str]],\n) -> List[Keypoint]:\n    keypoint_classes = key_points_classes[instance_keypoints_class_id]\n    results = []\n    for keypoint_class_id, ((x, y), confidence, keypoint_class_name) in enumerate(\n        zip(instance_keypoints_xy, instance_keypoints_confidence, keypoint_classes)\n    ):\n        if confidence <= 0.0:\n            continue\n        keypoint = Keypoint(\n            x=x,\n            y=y,\n            confidence=confidence,\n            class_id=keypoint_class_id,\n            **{\"class\": keypoint_class_name},\n        )\n        results.append(keypoint)\n    return results\n\n\nclass InferenceModelsClassificationAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n        model_id = resolve_roboflow_model_alias(model_id=model_id)\n\n        self.task_type = \"classification\"\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n        backend = list(\n            VALID_INFERENCE_MODELS_BACKENDS.difference(\n                DISABLED_INFERENCE_MODELS_BACKENDS\n            )\n        )\n        self._model: Union[ClassificationModel, MultiLabelClassificationModel] = (\n            AutoModel.from_pretrained(\n                model_id_or_path=_resolve_cached_model_path(model_id),\n                api_key=self.api_key,\n                allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n                allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n                weights_provider_extra_headers=extra_weights_provider_headers,\n                backend=backend,\n                **kwargs,\n            )\n        )\n        self.class_names = list(self._model.class_names)\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        pre_processing_overrides = PreProcessingOverrides(\n            disable_contrast_enhancement=kwargs.get(\"disable_preproc_contrast\", False),\n            disable_grayscale=kwargs.get(\"disable_preproc_grayscale\", False),\n            disable_static_crop=kwargs.get(\"disable_preproc_static_crop\", False),\n        )\n        kwargs[\"pre_processing_overrides\"] = pre_processing_overrides\n        return kwargs\n\n    def preprocess(self, image: Any, **kwargs):\n        is_batch = isinstance(image, list)\n        images = image if is_batch else [image]\n        np_images: List[np.ndarray] = [\n            load_image_bgr(\n                v,\n                disable_preproc_auto_orient=kwargs.get(\n                    \"disable_preproc_auto_orient\", False\n                ),\n            )\n            for v in images\n        ]\n        images_shapes = [i.shape[:2] for i in np_images]\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.pre_process(np_images, **mapped_kwargs), images_shapes\n\n    def predict(self, img_in, **kwargs):\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.forward(img_in, **mapped_kwargs)\n\n    def postprocess(\n        self,\n        predictions: Tuple[List[KeyPoints], Optional[List[Detections]]],\n        returned_metadata: List[Tuple[int, int]],\n        **kwargs,\n    ) -> Union[\n        List[MultiLabelClassificationInferenceResponse],\n        List[ClassificationInferenceResponse],\n    ]:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        post_processed_predictions = self._model.post_process(\n            predictions, **mapped_kwargs\n        )\n        if isinstance(post_processed_predictions, list):\n            # multi-label classification\n            return prepare_multi_label_classification_response(\n                post_processed_predictions,\n                image_sizes=returned_metadata,\n                class_names=self.class_names,\n                confidence_threshold=kwargs.get(\"confidence\", 0.5),\n            )\n        else:\n            # single-label classification\n            return prepare_classification_response(\n                post_processed_predictions,\n                image_sizes=returned_metadata,\n                class_names=self.class_names,\n                confidence_threshold=kwargs.get(\"confidence\", 0.5),\n            )\n\n    def clear_cache(self, delete_from_disk: bool = True) -> None:\n        \"\"\"Clears any cache if necessary. TODO: Implement this to delete the cache from the experimental model.\n\n        Args:\n            delete_from_disk (bool, optional): Whether to delete cached files from disk. Defaults to True.\n        \"\"\"\n        pass\n\n    def infer_from_request(\n        self,\n        request: ClassificationInferenceRequest,\n    ) -> Union[List[InferenceResponse], InferenceResponse]:\n        \"\"\"\n        Handle an inference request to produce an appropriate response.\n\n        Args:\n            request (ClassificationInferenceRequest): The request object encapsulating the image(s) and relevant parameters.\n\n        Returns:\n            Union[List[InferenceResponse], InferenceResponse]: The response object(s) containing the predictions, visualization, and other pertinent details. If a list of images was provided, a list of responses is returned. Otherwise, a single response is returned.\n\n        Notes:\n            - Starts a timer at the beginning to calculate inference time.\n            - Processes the image(s) through the `infer` method.\n            - Generates the appropriate response object(s) using `make_response`.\n            - Calculates and sets the time taken for inference.\n            - If visualization is requested, the predictions are drawn on the image.\n        \"\"\"\n        t1 = perf_counter()\n        responses = self.infer(**request.dict(), return_image_dims=True)\n        for response in responses:\n            response.time = perf_counter() - t1\n            response.inference_id = getattr(request, \"id\", None)\n\n        if request.visualize_predictions:\n            for response in responses:\n                response.visualization = draw_predictions(\n                    request, response, self.class_names\n                )\n\n        if not isinstance(request.image, list):\n            responses = responses[0]\n\n        return responses\n\n\ndef prepare_multi_label_classification_response(\n    post_processed_predictions: List[MultiLabelClassificationPrediction],\n    image_sizes: List[Tuple[int, int]],\n    class_names: List[str],\n    confidence_threshold: float,\n) -> List[MultiLabelClassificationInferenceResponse]:\n    results = []\n    for prediction, image_size in zip(post_processed_predictions, image_sizes):\n        image_predictions_dict = dict()\n        predicted_classes = []\n        for class_id, confidence in enumerate(prediction.confidence.cpu().tolist()):\n            cls_name = class_names[class_id]\n            image_predictions_dict[cls_name] = {\n                \"confidence\": confidence,\n                \"class_id\": class_id,\n            }\n            if confidence > confidence_threshold:\n                predicted_classes.append(cls_name)\n        results.append(\n            MultiLabelClassificationInferenceResponse(\n                predictions=image_predictions_dict,\n                predicted_classes=predicted_classes,\n                image=InferenceResponseImage(width=image_size[1], height=image_size[0]),\n                # essentially pushing a dummy values as I have no intention breaking the new API for the sake of delivering value that has no practical use\n            )\n        )\n    return results\n\n\ndef prepare_classification_response(\n    post_processed_predictions: ClassificationPrediction,\n    image_sizes: List[Tuple[int, int]],\n    class_names: List[str],\n    confidence_threshold: float,\n) -> List[ClassificationInferenceResponse]:\n    responses = []\n    for classes_confidence, image_size in zip(\n        post_processed_predictions.confidence.cpu().tolist(), image_sizes\n    ):\n        individual_classes_predictions = []\n        for i, cls_name in enumerate(class_names):\n            class_score = float(classes_confidence[i])\n            if class_score < confidence_threshold:\n                continue\n            class_prediction = {\n                \"class_id\": i,\n                \"class\": cls_name,\n                \"confidence\": round(class_score, 4),\n            }\n            individual_classes_predictions.append(class_prediction)\n        individual_classes_predictions = sorted(\n            individual_classes_predictions, key=lambda x: x[\"confidence\"], reverse=True\n        )\n        response = ClassificationInferenceResponse(\n            image=InferenceResponseImage(width=image_size[1], height=image_size[0]),\n            # essentially pushing a dummy values as I have no intention breaking the new API for the sake of delivering value that has no practical use\n            predictions=individual_classes_predictions,\n            top=(\n                individual_classes_predictions[0][\"class\"]\n                if individual_classes_predictions\n                else \"\"\n            ),\n            confidence=(\n                individual_classes_predictions[0][\"confidence\"]\n                if individual_classes_predictions\n                else 0.0\n            ),\n        )\n        responses.append(response)\n    return responses\n\n\ndef draw_predictions(inference_request, inference_response, class_names: List[str]):\n    \"\"\"Draw prediction visuals on an image.\n\n    This method overlays the predictions on the input image, including drawing rectangles and text to visualize the predicted classes.\n\n    Args:\n        inference_request: The request object containing the image and parameters.\n        inference_response: The response object containing the predictions and other details.\n        class_names: List of class names corresponding to the model's classes.\n\n    Returns:\n        bytes: The bytes of the visualized image in JPEG format.\n    \"\"\"\n    image = load_image_rgb(inference_request.image)\n    image = Image.fromarray(image)\n    draw = ImageDraw.Draw(image)\n    font = ImageFont.load_default()\n    class_id_2_color = {\n        i: DEFAULT_COLOR_PALETTE[i % len(DEFAULT_COLOR_PALETTE)]\n        for i, class_name in enumerate(class_names)\n    }\n    if isinstance(inference_response.predictions, list):\n        prediction = inference_response.predictions[0]\n        color = class_id_2_color.get(prediction.class_id, \"#4892EA\")\n        draw.rectangle(\n            [0, 0, image.size[1], image.size[0]],\n            outline=color,\n            width=inference_request.visualization_stroke_width,\n        )\n        text = f\"{prediction.class_id} - {prediction.class_name} {prediction.confidence:.2f}\"\n        text_size = font.getbbox(text)\n\n        # set button size + 10px margins\n        button_size = (text_size[2] + 20, text_size[3] + 20)\n        button_img = Image.new(\"RGBA\", button_size, color)\n        # put text on button with 10px margins\n        button_draw = ImageDraw.Draw(button_img)\n        button_draw.text((10, 10), text, font=font, fill=(255, 255, 255, 255))\n\n        # put button on source image in position (0, 0)\n        image.paste(button_img, (0, 0))\n    else:\n        if len(inference_response.predictions) > 0:\n            box_color = \"#4892EA\"\n            draw.rectangle(\n                [0, 0, image.size[1], image.size[0]],\n                outline=box_color,\n                width=inference_request.visualization_stroke_width,\n            )\n        row = 0\n        predictions = [\n            (cls_name, pred)\n            for cls_name, pred in inference_response.predictions.items()\n        ]\n        predictions = sorted(predictions, key=lambda x: x[1].confidence, reverse=True)\n        for i, (cls_name, pred) in enumerate(predictions):\n            color = class_id_2_color.get(cls_name, \"#4892EA\")\n            text = f\"{cls_name} {pred.confidence:.2f}\"\n            text_size = font.getbbox(text)\n\n            # set button size + 10px margins\n            button_size = (text_size[2] + 20, text_size[3] + 20)\n            button_img = Image.new(\"RGBA\", button_size, color)\n            # put text on button with 10px margins\n            button_draw = ImageDraw.Draw(button_img)\n            button_draw.text((10, 10), text, font=font, fill=(255, 255, 255, 255))\n\n            # put button on source image in position (0, 0)\n            image.paste(button_img, (0, row))\n            row += button_size[1]\n\n    buffered = BytesIO()\n    image = image.convert(\"RGB\")\n    image.save(buffered, format=\"JPEG\")\n    return buffered.getvalue()\n\n\nclass InferenceModelsSemanticSegmentationAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n        model_id = resolve_roboflow_model_alias(model_id=model_id)\n\n        self.task_type = \"semantic-segmentation\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n        backend = list(\n            VALID_INFERENCE_MODELS_BACKENDS.difference(\n                DISABLED_INFERENCE_MODELS_BACKENDS\n            )\n        )\n        self._model: SemanticSegmentationModel = AutoModel.from_pretrained(\n            model_id_or_path=_resolve_cached_model_path(model_id),\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            backend=backend,\n            **kwargs,\n        )\n        self.class_names = list(self._model.class_names)\n\n    @property\n    def class_map(self):\n        # match segment.roboflow.com\n        return {str(k): v for k, v in enumerate(self.class_names)}\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        pre_processing_overrides = PreProcessingOverrides(\n            disable_contrast_enhancement=kwargs.get(\"disable_preproc_contrast\", False),\n            disable_grayscale=kwargs.get(\"disable_preproc_grayscale\", False),\n            disable_static_crop=kwargs.get(\"disable_preproc_static_crop\", False),\n        )\n        kwargs[\"pre_processing_overrides\"] = pre_processing_overrides\n        return kwargs\n\n    def preprocess(self, image: Any, **kwargs):\n        is_batch = isinstance(image, list)\n        images = image if is_batch else [image]\n        np_images: List[np.ndarray] = [\n            load_image_bgr(\n                v,\n                disable_preproc_auto_orient=kwargs.get(\n                    \"disable_preproc_auto_orient\", False\n                ),\n            )\n            for v in images\n        ]\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.pre_process(np_images, **mapped_kwargs)\n\n    def predict(self, img_in, **kwargs):\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.forward(img_in, **mapped_kwargs)\n\n    def postprocess(\n        self,\n        predictions: torch.Tensor,\n        preprocess_return_metadata: PreprocessingMetadata,\n        **kwargs,\n    ) -> List[SemanticSegmentationInferenceResponse]:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        segmentation_results = self._model.post_process(\n            predictions, preprocess_return_metadata, **mapped_kwargs\n        )\n\n        responses: List[SemanticSegmentationInferenceResponse] = []\n        for preproc_metadata, segmentation in zip(\n            preprocess_return_metadata, segmentation_results\n        ):\n            height = preproc_metadata.original_size.height\n            width = preproc_metadata.original_size.width\n            response_image = InferenceResponseImage(width=width, height=height)\n            # WARNING! This way of conversion is hazardous - first of all, if background class is not in class names,\n            # for certain pre-processing, we end up with -1 values which will be wrapped to 255 - second of all,\n            # we can support only 256 classes - those constraints should be fine until inference 2.0\n            response_predictions = SemanticSegmentationPrediction(\n                segmentation_mask=self.img_to_b64_str(\n                    segmentation.segmentation_map.to(torch.uint8)\n                ),\n                confidence_mask=self.img_to_b64_str(\n                    (segmentation.confidence * 255).to(torch.uint8)\n                ),\n                class_map=self.class_map,\n                image=dict(response_image),\n            )\n            response = SemanticSegmentationInferenceResponse(\n                predictions=response_predictions,\n                image=response_image,\n            )\n            responses.append(response)\n        return responses\n\n    def clear_cache(self, delete_from_disk: bool = True) -> None:\n        \"\"\"Clears any cache if necessary. TODO: Implement this to delete the cache from the experimental model.\n\n        Args:\n            delete_from_disk (bool, optional): Whether to delete cached files from disk. Defaults to True.\n        \"\"\"\n        pass\n\n    def img_to_b64_str(self, img: torch.Tensor) -> str:\n        if img.dtype != torch.uint8:\n            raise ValueError(\n                f\"img_to_b64_str requires uint8 tensor but got dtype {img.dtype}\"\n            )\n\n        img = Image.fromarray(img.cpu().numpy())\n        buffered = io.BytesIO()\n        img.save(buffered, format=\"PNG\")\n\n        img_str = base64.b64encode(buffered.getvalue())\n        img_str = img_str.decode(\"ascii\")\n\n        return img_str\n\n    def draw_predictions(\n        self,\n        inference_request: InferenceRequest,\n        inference_response: InferenceResponse,\n    ) -> bytes:\n        raise NotImplementedError(\n            \"draw_predictions(...) is not implemented for semantic segmentation models - responses contain \"\n            \"visualization already.\"\n        )\n",
    "patch": null
  },
  {
    "trace_id": "fc44d53a-7c2f-4b37-9544-5cb566a3fe96",
    "function_name": "intersect_masks_per_dimension",
    "file_path": "inference/core/workflows/execution_engine/v1/executor/execution_data_manager/step_input_assembler.py",
    "speedup_x": 0.656500291854472,
    "review_quality": "high",
    "pre_optimization_commit": "90243bdc6278ef7d17b6db09dc1eb5b0d155b4be",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def intersect_masks_per_dimension(\n    batch_masks: List[Set[DynamicBatchIndex]],\n    dimensions: Set[int],\n) -> Dict[int, Set[DynamicBatchIndex]]:\n    \"\"\"Intersect masks at each dimensionality level.\n\n    For each dimension d, returns the set of indices (with length d) that appear\n    in every mask that has at least one index at that dimension. Masks with no\n    indices at d are ignored for that dimension. Used for intra-dimensional\n    intersection.\n    \"\"\"\n    sorted_dims = sorted(dimensions)\n    result: Dict[int, Set[DynamicBatchIndex]] = {}\n    for dim in sorted_dims:\n        sets_at_dim = [{idx for idx in mask if len(idx) == dim} for mask in batch_masks]\n        non_empty = [s for s in sets_at_dim if s]\n        result[dim] = set.intersection(*non_empty) if non_empty else set()\n    return result\n",
    "optimized_function_code": "from inference.core.workflows.execution_engine.v1.executor.execution_data_manager.dynamic_batches_manager import DynamicBatchIndex\nfrom typing import Dict, List, Set\n\ndef intersect_masks_per_dimension(\n    batch_masks: List[Set[DynamicBatchIndex]],\n    dimensions: Set[int],\n) -> Dict[int, Set[DynamicBatchIndex]]:\n    \"\"\"Intersect masks at each dimensionality level.\n\n    For each dimension d, returns the set of indices (with length d) that appear\n    in every mask that has at least one index at that dimension. Masks with no\n    indices at d are ignored for that dimension. Used for intra-dimensional\n    intersection.\n    \"\"\"\n    sorted_dims = sorted(dimensions)\n    result: Dict[int, Set[DynamicBatchIndex]] = {}\n    for dim in sorted_dims:\n        intersection = None\n        for mask in batch_masks:\n            indices_at_dim = {idx for idx in mask if len(idx) == dim}\n            if not indices_at_dim:\n                continue\n            if intersection is None:\n                intersection = indices_at_dim\n            else:\n                intersection &= indices_at_dim\n        result[dim] = intersection if intersection is not None else set()\n    return result",
    "optimized_raw_markdown": "```python:inference/core/workflows/execution_engine/v1/executor/execution_data_manager/step_input_assembler.py\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.dynamic_batches_manager import DynamicBatchIndex\nfrom typing import Dict, List, Set\n\ndef intersect_masks_per_dimension(\n    batch_masks: List[Set[DynamicBatchIndex]],\n    dimensions: Set[int],\n) -> Dict[int, Set[DynamicBatchIndex]]:\n    \"\"\"Intersect masks at each dimensionality level.\n\n    For each dimension d, returns the set of indices (with length d) that appear\n    in every mask that has at least one index at that dimension. Masks with no\n    indices at d are ignored for that dimension. Used for intra-dimensional\n    intersection.\n    \"\"\"\n    sorted_dims = sorted(dimensions)\n    result: Dict[int, Set[DynamicBatchIndex]] = {}\n    for dim in sorted_dims:\n        intersection = None\n        for mask in batch_masks:\n            indices_at_dim = {idx for idx in mask if len(idx) == dim}\n            if not indices_at_dim:\n                continue\n            if intersection is None:\n                intersection = indices_at_dim\n            else:\n                intersection &= indices_at_dim\n        result[dim] = intersection if intersection is not None else set()\n    return result\n```",
    "optimized_function_only": "def intersect_masks_per_dimension(\n    batch_masks: List[Set[DynamicBatchIndex]],\n    dimensions: Set[int],\n) -> Dict[int, Set[DynamicBatchIndex]]:\n    \"\"\"Intersect masks at each dimensionality level.\n\n    For each dimension d, returns the set of indices (with length d) that appear\n    in every mask that has at least one index at that dimension. Masks with no\n    indices at d are ignored for that dimension. Used for intra-dimensional\n    intersection.\n    \"\"\"\n    sorted_dims = sorted(dimensions)\n    result: Dict[int, Set[DynamicBatchIndex]] = {}\n    for dim in sorted_dims:\n        intersection = None\n        for mask in batch_masks:\n            indices_at_dim = {idx for idx in mask if len(idx) == dim}\n            if not indices_at_dim:\n                continue\n            if intersection is None:\n                intersection = indices_at_dim\n            else:\n                intersection &= indices_at_dim\n        result[dim] = intersection if intersection is not None else set()\n    return result",
    "original_file_content": "from dataclasses import dataclass\nfrom typing import Any, Dict, Generator, List, Optional, Set, Tuple, TypeVar, Union\n\nfrom inference.core.workflows.errors import AssumptionError, ExecutionEngineRuntimeError\nfrom inference.core.workflows.execution_engine.entities.base import Batch\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import (\n    AutoBatchCastingConfig,\n    CompoundStepInputDefinition,\n    DynamicStepInputDefinition,\n    StaticStepInputDefinition,\n    StepInputDefinition,\n    StepNode,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import (\n    get_last_chunk_of_selector,\n)\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.branching_manager import (\n    BranchingManager,\n)\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.dynamic_batches_manager import (\n    DynamicBatchesManager,\n    DynamicBatchIndex,\n)\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.execution_cache import (\n    ExecutionCache,\n)\n\nT = TypeVar(\"T\")\n\n\n@dataclass(frozen=True)\nclass BatchModeSIMDStepInput:\n    indices: List[DynamicBatchIndex]\n    parameters: Dict[str, Any]\n\n\n@dataclass(frozen=True)\nclass NonBatchModeSIMDStepInput:\n    index: DynamicBatchIndex\n    parameters: Dict[str, Any]\n\n\ndef construct_non_simd_step_input(\n    step_node: StepNode,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    branching_manager: BranchingManager,\n) -> Optional[Dict[str, Any]]:\n    if step_node.batch_oriented_parameters:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Attempted to get non-SIMD input for SIMD step: {step_node.name}.\"\n            f\"This is most likely a bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    masks = set()\n    for execution_branch in step_node.execution_branches_impacting_inputs:\n        if not branching_manager.is_execution_branch_registered(\n            execution_branch=execution_branch\n        ):\n            masks.add(False)\n            continue\n        if branching_manager.is_execution_branch_batch_oriented(\n            execution_branch=execution_branch\n        ):\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"For step: {step_node.name}, detected batch-oriented condition statements \"\n                f\"impacting non-SIMD step, which should be prevented by Workflows Compiler. \"\n                f\"This is most likely a bug. Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n        else:\n            mask = branching_manager.get_mask(execution_branch=execution_branch)\n            masks.add(mask)\n    if False in masks:\n        return None\n    result = {}\n    detected_empty_step_output_selector = False\n    for parameter_name, parameter_spec in step_node.input_data.items():\n        if parameter_spec.is_compound_input():\n            result[parameter_name], contains_empty_step_output_selector = (\n                construct_non_simd_step_compound_input(\n                    step_node=step_node,\n                    parameter_spec=parameter_spec,\n                    runtime_parameters=runtime_parameters,\n                    execution_cache=execution_cache,\n                )\n            )\n        else:\n            result[parameter_name], contains_empty_step_output_selector = (\n                construct_non_simd_step_non_compound_input(\n                    step_node=step_node,\n                    parameter_spec=parameter_spec,\n                    runtime_parameters=runtime_parameters,\n                    execution_cache=execution_cache,\n                )\n            )\n        detected_empty_step_output_selector = (\n            detected_empty_step_output_selector or contains_empty_step_output_selector\n        )\n    if (\n        detected_empty_step_output_selector\n        and not step_node.step_manifest.accepts_empty_values()\n    ):\n        return None\n    return result\n\n\ndef construct_non_simd_step_compound_input(\n    step_node: StepNode,\n    parameter_spec: CompoundStepInputDefinition,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> Tuple[Any, bool]:\n    if parameter_spec.represents_list_of_inputs():\n        return construct_non_simd_step_compound_list_input(\n            step_node=step_node,\n            parameter_spec=parameter_spec,\n            runtime_parameters=runtime_parameters,\n            execution_cache=execution_cache,\n        )\n    return construct_non_simd_step_compound_dict_input(\n        step_node=step_node,\n        parameter_spec=parameter_spec,\n        runtime_parameters=runtime_parameters,\n        execution_cache=execution_cache,\n    )\n\n\ndef construct_non_simd_step_compound_list_input(\n    step_node: StepNode,\n    parameter_spec: CompoundStepInputDefinition,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> Tuple[List[Any], bool]:\n    result = []\n    contains_empty_step_output_selector = False\n    for nested_definition in parameter_spec.iterate_through_definitions():\n        nested_value, value_contains_empty_selector = (\n            construct_non_simd_step_non_compound_input(\n                step_node=step_node,\n                parameter_spec=nested_definition,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n            )\n        )\n        result.append(nested_value)\n        contains_empty_step_output_selector = (\n            contains_empty_step_output_selector or value_contains_empty_selector\n        )\n    return result, contains_empty_step_output_selector\n\n\ndef construct_non_simd_step_compound_dict_input(\n    step_node: StepNode,\n    parameter_spec: CompoundStepInputDefinition,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> Tuple[Dict[str, Any], bool]:\n    result = {}\n    contains_empty_step_output_selector = False\n    for nested_definition in parameter_spec.iterate_through_definitions():\n        (\n            result[nested_definition.parameter_specification.nested_element_key],\n            value_contains_empty_selector,\n        ) = construct_non_simd_step_non_compound_input(\n            step_node=step_node,\n            parameter_spec=nested_definition,\n            runtime_parameters=runtime_parameters,\n            execution_cache=execution_cache,\n        )\n        contains_empty_step_output_selector = (\n            contains_empty_step_output_selector or value_contains_empty_selector\n        )\n    return result, contains_empty_step_output_selector\n\n\ndef construct_non_simd_step_non_compound_input(\n    step_node: StepNode,\n    parameter_spec: StepInputDefinition,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> Tuple[Any, bool]:\n    if parameter_spec.is_compound_input():\n        raise AssumptionError(\n            public_message=f\"Workflows Execution Error encountered unexpected state probably related to the fact \"\n            f\"that Workflows Compiler allowed for multi-level nesting of inputs selectors which \"\n            f\"is not supported. This is most likely the bug. Contact Roboflow team \"\n            f\"through github issues (https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if parameter_spec.is_batch_oriented():\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Encountered batch-oriented input for non-SIMD step: {step_node.name}.\"\n            f\"This is most likely a bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if parameter_spec.points_to_input():\n        parameter_spec: DynamicStepInputDefinition = parameter_spec  # type: ignore\n        input_name = get_last_chunk_of_selector(selector=parameter_spec.selector)\n        return runtime_parameters[input_name], False\n    if parameter_spec.points_to_step_output():\n        parameter_spec: DynamicStepInputDefinition = parameter_spec  # type: ignore\n        step_output = execution_cache.get_non_batch_output(\n            selector=parameter_spec.selector\n        )\n        return step_output, step_output is None\n    parameter_spec: StaticStepInputDefinition = parameter_spec  # type: ignore\n    return parameter_spec.value, False\n\n\ndef iterate_over_simd_step_input(\n    step_node: StepNode,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    dynamic_batches_manager: DynamicBatchesManager,\n    branching_manager: BranchingManager,\n) -> Generator[NonBatchModeSIMDStepInput, None, None]:\n    simd_step_input = construct_simd_step_input(\n        step_node=step_node,\n        runtime_parameters=runtime_parameters,\n        execution_cache=execution_cache,\n        dynamic_batches_manager=dynamic_batches_manager,\n        branching_manager=branching_manager,\n    )\n    parameters_generator = unfold_parameters(\n        parameters=simd_step_input.parameters,\n        indices=simd_step_input.indices,\n    )\n    for index, single_parameters_set in zip(\n        simd_step_input.indices, parameters_generator\n    ):\n        yield NonBatchModeSIMDStepInput(\n            index=index,\n            parameters=single_parameters_set,\n        )\n\n\ndef construct_simd_step_input(\n    step_node: StepNode,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    dynamic_batches_manager: DynamicBatchesManager,\n    branching_manager: BranchingManager,\n) -> BatchModeSIMDStepInput:\n    masks, scalars_discarded = construct_mask_for_all_inputs_dimensionalities(\n        step_node=step_node,\n        branching_manager=branching_manager,\n    )\n    return prepare_parameters(\n        step_node=step_node,\n        dynamic_batches_manager=dynamic_batches_manager,\n        masks=masks,\n        scalars_discarded=scalars_discarded,\n        runtime_parameters=runtime_parameters,\n        execution_cache=execution_cache,\n    )\n\n\ndef construct_mask_for_all_inputs_dimensionalities(\n    step_node: StepNode,\n    branching_manager: BranchingManager,\n) -> Tuple[Any, bool]:\n    inputs_dimensionalities = collect_inputs_dimensionalities(step_node=step_node)\n    all_dimensionalities = {dim for dim in inputs_dimensionalities.values() if dim > 0}\n    if step_node.control_flow_lineage_support:\n        for dim_level in step_node.control_flow_lineage_dims:\n            all_dimensionalities.add(dim_level)\n    batch_masks, non_batch_masks = [], set()\n    for execution_branch in step_node.execution_branches_impacting_inputs:\n        if not branching_manager.is_execution_branch_registered(\n            execution_branch=execution_branch\n        ):\n            non_batch_masks.add(False)\n            continue\n        if branching_manager.is_execution_branch_batch_oriented(\n            execution_branch=execution_branch\n        ):\n            mask = branching_manager.get_mask(execution_branch=execution_branch)\n            batch_masks.append(mask)\n        else:\n            mask = branching_manager.get_mask(execution_branch=execution_branch)\n            non_batch_masks.add(mask)\n    scalar_mask_contains_false = False in non_batch_masks\n    if scalar_mask_contains_false:\n        return {\n            dimension: set() for dimension in all_dimensionalities\n        }, scalar_mask_contains_false\n    return (\n        get_masks_intersection_for_dimensions(\n            batch_masks=batch_masks,\n            dimensions=all_dimensionalities,\n        ),\n        scalar_mask_contains_false,\n    )\n\n\ndef collect_inputs_dimensionalities(\n    step_node: StepNode,\n) -> Dict[str, int]:\n    result = {}\n    for parameter_name, parameter_specs in step_node.input_data.items():\n        if parameter_specs.is_compound_input():\n            dimensionalities = [\n                nested_definition.get_dimensionality()\n                for nested_definition in parameter_specs.iterate_through_definitions()\n            ]\n            # to help for empty values\n            dimensionalities.append(0)\n            result[parameter_name] = max(dimensionalities)\n        else:\n            result[parameter_name] = parameter_specs.get_dimensionality()\n    return result\n\n\ndef intersect_masks_per_dimension(\n    batch_masks: List[Set[DynamicBatchIndex]],\n    dimensions: Set[int],\n) -> Dict[int, Set[DynamicBatchIndex]]:\n    \"\"\"Intersect masks at each dimensionality level.\n\n    For each dimension d, returns the set of indices (with length d) that appear\n    in every mask that has at least one index at that dimension. Masks with no\n    indices at d are ignored for that dimension. Used for intra-dimensional\n    intersection.\n    \"\"\"\n    sorted_dims = sorted(dimensions)\n    result: Dict[int, Set[DynamicBatchIndex]] = {}\n    for dim in sorted_dims:\n        sets_at_dim = [{idx for idx in mask if len(idx) == dim} for mask in batch_masks]\n        non_empty = [s for s in sets_at_dim if s]\n        result[dim] = set.intersection(*non_empty) if non_empty else set()\n    return result\n\n\ndef filter_to_valid_prefix_chains(\n    per_dim_sets: Dict[int, Set[DynamicBatchIndex]],\n    dimensions: Set[int],\n) -> Dict[int, Set[DynamicBatchIndex]]:\n    \"\"\"Keep only indices that form a complete parent-child chain across dimensions.\n\n    Given per-dimension sets (e.g. from intersect_masks_per_dimension), retains\n    only indices that have a full lineage from the smallest to the largest\n    dimension. Used for inter-level intersection.\n    \"\"\"\n    sorted_dims = sorted(dimensions)\n    by_dim: Dict[int, Set[DynamicBatchIndex]] = {\n        dim: per_dim_sets.get(dim, set()) for dim in sorted_dims\n    }\n\n    if len(sorted_dims) <= 1:\n        return dict(by_dim)\n\n    prev_dim = {sorted_dims[i]: sorted_dims[i - 1] for i in range(1, len(sorted_dims))}\n\n    # Bottom-up: mark indices that have at least one descendant\n    has_child: Set[DynamicBatchIndex] = set()\n    for dim in reversed(sorted_dims):\n        for idx in by_dim[dim]:\n            if dim == sorted_dims[-1] or idx in has_child:\n                parent = idx[:-1]\n                if parent:\n                    has_child.add(parent)\n\n    # Top-down: keep indices only if full prefix chain exists\n    valid: Dict[int, Set[DynamicBatchIndex]] = {dim: set() for dim in sorted_dims}\n    for dim in sorted_dims:\n        for idx in by_dim[dim]:\n            parent = idx[:-1]\n            if dim == sorted_dims[0]:\n                if idx in has_child:\n                    valid[dim].add(idx)\n            elif parent in valid[prev_dim[dim]]:\n                if dim == sorted_dims[-1] or idx in has_child:\n                    valid[dim].add(idx)\n\n    return valid\n\n\ndef get_masks_intersection_for_dimensions(\n    batch_masks: List[Set[DynamicBatchIndex]],\n    dimensions: Set[int],\n) -> Dict[int, Optional[Set[DynamicBatchIndex]]]:\n    \"\"\"Intersect masks at each dimension and filter to valid prefix chains.\"\"\"\n    if not batch_masks:\n        return {dim: None for dim in dimensions}\n\n    sorted_dims = sorted(dimensions)\n\n    if len(sorted_dims) <= 1:\n        result = intersect_masks_per_dimension(batch_masks, dimensions)\n        return {dim: result[dim] for dim in sorted_dims}\n\n    per_dim = intersect_masks_per_dimension(batch_masks, dimensions)\n    return filter_to_valid_prefix_chains(per_dim, dimensions)\n\n\nclass GuardForIndicesWrapping:\n\n    def __init__(self):\n        self._registered_wrapping: Optional[List[DynamicBatchIndex]] = None\n\n    def register_wrapping(\n        self, indices_before_wrapping: List[DynamicBatchIndex]\n    ) -> None:\n        if self._registered_wrapping is None:\n            self._registered_wrapping = indices_before_wrapping\n        elif self._registered_wrapping != indices_before_wrapping:\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Detected a situation when step requires dimensionality wrapping, but\"\n                f\"different inputs register different elements indices to wrap which is illegal \"\n                f\"and should be detected earlier by Workflows compiler. This is most likely a bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n\n\ndef prepare_parameters(\n    step_node: StepNode,\n    dynamic_batches_manager: DynamicBatchesManager,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> BatchModeSIMDStepInput:\n    step_requests_batch_input = step_node.step_manifest.accepts_batch_input()\n    result = {}\n    indices_for_parameter = {}\n    guard_of_indices_wrapping = GuardForIndicesWrapping()\n    compound_inputs = set()\n    contains_empty_scalar_step_output_selector = False\n    for parameter_name, parameter_specs in step_node.input_data.items():\n        if parameter_specs.is_compound_input():\n            (\n                result[parameter_name],\n                indices_for_parameter[parameter_name],\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_compound_parameter_value(\n                parameter=parameter_specs,\n                step_execution_dimensionality=step_node.step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=step_node.auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n            compound_inputs.add(parameter_name)\n        else:\n            (\n                result[parameter_name],\n                indices_for_parameter[parameter_name],\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=parameter_specs,\n                step_execution_dimensionality=step_node.step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=step_node.auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n        contains_empty_scalar_step_output_selector = (\n            contains_empty_scalar_step_output_selector\n            or value_contains_empty_scalar_step_output_selector\n        )\n    batch_parameters_indices = [\n        i for i in indices_for_parameter.values() if i is not None\n    ]\n    ensure_compound_input_indices_match(indices=batch_parameters_indices)\n    if not batch_parameters_indices:\n        if not step_node.control_flow_lineage_support:\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"For step: {step_node.name} which is assessed by Workflows Compiler as \"\n                f\"SIMD step Execution Engine cannot detect neither batch inputs nor control flow inputs. \"\n                f\"This is most likely a bug. Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n        indices = dynamic_batches_manager.get_indices_for_data_lineage(\n            lineage=step_node.control_flow_lineage_support,\n        )\n        mask_dimension = len(step_node.control_flow_lineage_support)\n        mask_for_dimension = masks.get(mask_dimension)\n        if mask_for_dimension is not None:\n            indices = [idx for idx in indices if idx in mask_for_dimension]\n    else:\n        indices = batch_parameters_indices[0]\n    if not step_node.step_manifest.accepts_empty_values():\n        if contains_empty_scalar_step_output_selector:\n            return BatchModeSIMDStepInput(\n                indices=[],\n                parameters={},\n            )\n        empty_indices = get_empty_batch_elements_indices(value=result)\n        if empty_indices:\n            indices = [e for e in indices if e not in empty_indices]\n            result = remove_indices(value=result, indices=empty_indices)\n    return BatchModeSIMDStepInput(\n        indices=indices,\n        parameters=result,\n    )\n\n\ndef get_compound_parameter_value(\n    parameter: CompoundStepInputDefinition,\n    step_execution_dimensionality: int,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n    dynamic_batches_manager: DynamicBatchesManager,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n    auto_batch_casting_lineage_supports: Dict[str, AutoBatchCastingConfig],\n    step_requests_batch_input: bool,\n) -> Tuple[Union[list, Dict[str, Any]], Optional[List[DynamicBatchIndex]], bool]:\n    contains_empty_scalar_step_output_selector = False\n    batch_indices = []\n    if parameter.represents_list_of_inputs():\n        result = []\n        for nested_element in parameter.iterate_through_definitions():\n            (\n                non_compound_parameter_value,\n                non_compound_indices,\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=nested_element,\n                step_execution_dimensionality=step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n            result.append(non_compound_parameter_value)\n            contains_empty_scalar_step_output_selector = (\n                contains_empty_scalar_step_output_selector\n                or value_contains_empty_scalar_step_output_selector\n            )\n            if non_compound_indices is not None:\n                batch_indices.append(non_compound_indices)\n    else:\n        result = {}\n        for nested_element in parameter.iterate_through_definitions():\n            (\n                non_compound_parameter_value,\n                non_compound_indices,\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=nested_element,\n                step_execution_dimensionality=step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n            result[nested_element.parameter_specification.nested_element_key] = (\n                non_compound_parameter_value\n            )\n            contains_empty_scalar_step_output_selector = (\n                contains_empty_scalar_step_output_selector\n                or value_contains_empty_scalar_step_output_selector\n            )\n            if non_compound_indices is not None:\n                batch_indices.append(non_compound_indices)\n    ensure_compound_input_indices_match(indices=batch_indices)\n    result_indices = None\n    if len(batch_indices) > 0:\n        result_indices = batch_indices[0]\n    return result, result_indices, contains_empty_scalar_step_output_selector\n\n\ndef get_non_compound_parameter_value(\n    parameter: StepInputDefinition,\n    step_execution_dimensionality: int,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n    dynamic_batches_manager: DynamicBatchesManager,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n    auto_batch_casting_lineage_supports: Dict[str, AutoBatchCastingConfig],\n    step_requests_batch_input: bool,\n) -> Tuple[Any, Optional[List[DynamicBatchIndex]], bool]:\n    if not parameter.is_batch_oriented():\n        requested_as_batch = (\n            parameter.parameter_specification.parameter_name\n            in auto_batch_casting_lineage_supports\n        )\n        if parameter.points_to_input():\n            input_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n            parameter_name = get_last_chunk_of_selector(\n                selector=input_parameter.selector\n            )\n            if not requested_as_batch:\n                return runtime_parameters[parameter_name], None, False\n            else:\n                return apply_auto_batch_casting(\n                    parameter_name=parameter_name,\n                    value=runtime_parameters[parameter_name],\n                    auto_batch_casting_config=auto_batch_casting_lineage_supports[\n                        parameter.parameter_specification.parameter_name\n                    ],\n                    contains_empty_scalar_step_output_selector=False,\n                    dynamic_batches_manager=dynamic_batches_manager,\n                    step_execution_dimensionality=step_execution_dimensionality,\n                    guard_of_indices_wrapping=guard_of_indices_wrapping,\n                    step_requests_batch_input=step_requests_batch_input,\n                    masks=masks,\n                    scalars_discarded=False,\n                )\n        elif parameter.points_to_step_output():\n            input_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n            value = execution_cache.get_non_batch_output(\n                selector=input_parameter.selector\n            )\n            if not requested_as_batch:\n                return value, None, value is None\n            else:\n                return apply_auto_batch_casting(\n                    parameter_name=parameter.parameter_specification.parameter_name,\n                    value=value,\n                    auto_batch_casting_config=auto_batch_casting_lineage_supports[\n                        parameter.parameter_specification.parameter_name\n                    ],\n                    contains_empty_scalar_step_output_selector=value is None,\n                    dynamic_batches_manager=dynamic_batches_manager,\n                    step_execution_dimensionality=step_execution_dimensionality,\n                    guard_of_indices_wrapping=guard_of_indices_wrapping,\n                    step_requests_batch_input=step_requests_batch_input,\n                    masks=masks,\n                    scalars_discarded=scalars_discarded,\n                )\n        else:\n            static_input: StaticStepInputDefinition = parameter  # type: ignore\n            if not requested_as_batch or static_input.value is None:\n                # when we have Optional[Selector()] in manifest - we must retain\n                # ability to inject None into the run(...) parameters - as\n                # if we treat that as actual batch and broadcast Batch[None],\n                # we would behave exactly as condition execution does -\n                # and the logic executing after this, will filter-out empty\n                # elements - so on None, we behave \"the old way\" regardless of the fact that ABC\n                # was requested\n                return static_input.value, None, False\n            else:\n                return apply_auto_batch_casting(\n                    parameter_name=parameter.parameter_specification.parameter_name,\n                    value=static_input.value,\n                    auto_batch_casting_config=auto_batch_casting_lineage_supports[\n                        parameter.parameter_specification.parameter_name\n                    ],\n                    contains_empty_scalar_step_output_selector=False,\n                    dynamic_batches_manager=dynamic_batches_manager,\n                    step_execution_dimensionality=step_execution_dimensionality,\n                    guard_of_indices_wrapping=guard_of_indices_wrapping,\n                    step_requests_batch_input=step_requests_batch_input,\n                    masks=masks,\n                    scalars_discarded=False,\n                )\n    dynamic_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n    parameter_dimensionality = dynamic_parameter.get_dimensionality()\n    lineage_indices = dynamic_batches_manager.get_indices_for_data_lineage(\n        lineage=dynamic_parameter.data_lineage,\n    )\n    mask_for_dimension = masks[parameter_dimensionality]\n    if dynamic_parameter.points_to_input():\n        input_name = get_last_chunk_of_selector(selector=dynamic_parameter.selector)\n        batch_input = _flatten_batch_oriented_inputs(\n            runtime_parameters[input_name],\n            dimensionality=parameter_dimensionality,\n        )\n        if mask_for_dimension is not None:\n            if len(lineage_indices) != len(batch_input):\n                raise ExecutionEngineRuntimeError(\n                    public_message=f\"Detected a situation when input parameter: \"\n                    f\"{input_name}\"\n                    f\"size is mismatched compared to mask requested for that input. \"\n                    f\"Input length: {len(batch_input)}, mask size: {len(lineage_indices)}. \"\n                    f\"This is most likely a bug. \"\n                    f\"Contact Roboflow team through github issues \"\n                    f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                    f\"the problem - including workflow definition you use.\",\n                    context=\"workflow_execution | step_input_assembling\",\n                )\n            batch_input = [\n                input_element if element_index in mask_for_dimension else None\n                for element_index, input_element in zip(lineage_indices, batch_input)\n            ]\n    else:\n        batch_input = execution_cache.get_batch_output(\n            selector=dynamic_parameter.selector,\n            batch_elements_indices=lineage_indices,\n            mask=mask_for_dimension,\n        )\n    if step_execution_dimensionality == parameter_dimensionality:\n        return Batch(batch_input, lineage_indices), lineage_indices, False\n    if step_execution_dimensionality > parameter_dimensionality:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter.parameter_specification.parameter_name}\"\n            f\"has a dimensionality {parameter_dimensionality} larger \"\n            f\"than step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if abs(parameter_dimensionality - step_execution_dimensionality) > 1:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter.parameter_specification.parameter_name}\"\n            f\"has a dimensionality {parameter_dimensionality} differing more than one level \"\n            f\"from step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if step_execution_dimensionality == 0 and not step_requests_batch_input:\n        return Batch(batch_input, lineage_indices), lineage_indices, False\n    upper_lineage = dynamic_parameter.data_lineage[:-1]\n    if len(upper_lineage) == 0:\n        if not step_requests_batch_input:\n            raise AssumptionError(\n                public_message=f\"Parameter: {parameter.parameter_specification.parameter_name} \"\n                f\"requires dimensionality wrapping, but registered lineage support is incompatible \"\n                f\"which should be detected by the compiler. This is most likely a bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n        upper_level_indices = [()]\n    else:\n        upper_level_indices = dynamic_batches_manager.get_indices_for_data_lineage(\n            lineage=dynamic_parameter.data_lineage[:-1],\n        )\n    result = reduce_batch_dimensionality(\n        indices=lineage_indices,\n        upper_level_index=upper_level_indices,\n        data=batch_input,\n        guard_of_indices_wrapping=guard_of_indices_wrapping,\n    )\n    return result, result.indices, False\n\n\ndef apply_auto_batch_casting(\n    parameter_name: str,\n    value: Any,\n    auto_batch_casting_config: AutoBatchCastingConfig,\n    contains_empty_scalar_step_output_selector: bool,\n    dynamic_batches_manager: DynamicBatchesManager,\n    step_execution_dimensionality: int,\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n    step_requests_batch_input: bool,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n) -> Tuple[Any, List[DynamicBatchIndex], bool]:\n    if auto_batch_casting_config.lineage_support is None:\n        indices = [(0,) * auto_batch_casting_config.casted_dimensionality]\n    else:\n        indices = dynamic_batches_manager.get_indices_for_data_lineage(\n            lineage=auto_batch_casting_config.lineage_support,\n        )\n        missing_dimensions = auto_batch_casting_config.casted_dimensionality - len(\n            auto_batch_casting_config.lineage_support\n        )\n        if missing_dimensions > 0:\n            padding = (0,) * missing_dimensions\n            indices = [i + padding for i in indices]\n    if scalars_discarded:\n        batch_content = [None] * len(indices)\n    elif auto_batch_casting_config.lineage_support is None:\n        batch_content = [value] * len(indices)\n    else:\n        support_dimensionality = len(auto_batch_casting_config.lineage_support)\n        mask_for_support_dimensionality = masks[support_dimensionality]\n        if mask_for_support_dimensionality is None:\n            batch_content = [value] * len(indices)\n        else:\n            batch_content = []\n            for index in indices:\n                if index[:support_dimensionality] in mask_for_support_dimensionality:\n                    batch_content.append(value)\n                else:\n                    batch_content.append(None)\n    created_batch = Batch(content=batch_content, indices=indices)\n    if step_execution_dimensionality == auto_batch_casting_config.casted_dimensionality:\n        return (\n            created_batch,\n            indices,\n            contains_empty_scalar_step_output_selector or scalars_discarded,\n        )\n    if step_execution_dimensionality > auto_batch_casting_config.casted_dimensionality:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter_name}\"\n            f\"has auto-batch casted dimensionality {auto_batch_casting_config.casted_dimensionality} larger \"\n            f\"than step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if (\n        abs(\n            auto_batch_casting_config.casted_dimensionality\n            - step_execution_dimensionality\n        )\n        > 1\n    ):\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter_name} has auto batch casted \"\n            f\"dimensionality {auto_batch_casting_config.casted_dimensionality} differing more than one level \"\n            f\"from step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    upper_level_lineage_dimensionality = (\n        auto_batch_casting_config.casted_dimensionality - 1\n    )\n    if upper_level_lineage_dimensionality == 0 and not step_requests_batch_input:\n        # for batch collapse into scalar\n        return (\n            created_batch,\n            indices,\n            contains_empty_scalar_step_output_selector or scalars_discarded,\n        )\n    if auto_batch_casting_config.lineage_support is None:\n        upper_level_indices = [indices[0][:-1]]\n    else:\n        upper_level_lineage = auto_batch_casting_config.lineage_support[\n            :upper_level_lineage_dimensionality\n        ]\n        if (\n            upper_level_lineage_dimensionality < 1\n            or len(upper_level_lineage) < upper_level_lineage_dimensionality\n        ):\n            if not step_requests_batch_input:\n                raise AssumptionError(\n                    public_message=f\"Detected a situation when parameter: {parameter_name} requires dimensionality \"\n                    f\"wrapping, but registered lineage support is incompatible which should be detected \"\n                    f\"by the compiler. This is most likely a bug. \"\n                    f\"Contact Roboflow team through github issues \"\n                    f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                    f\"the problem - including workflow definition you use.\",\n                    context=\"workflow_execution | step_input_assembling\",\n                )\n            upper_level_indices = [()]\n        else:\n            upper_level_indices = dynamic_batches_manager.get_indices_for_data_lineage(\n                lineage=upper_level_lineage,\n            )\n    result = reduce_batch_dimensionality(\n        indices=indices,\n        upper_level_index=upper_level_indices,\n        data=batch_content,\n        guard_of_indices_wrapping=guard_of_indices_wrapping,\n    )\n    return (\n        result,\n        result.indices,\n        contains_empty_scalar_step_output_selector or scalars_discarded,\n    )\n\n\ndef _flatten_batch_oriented_inputs(\n    inputs: list,\n    dimensionality: int,\n) -> List[Any]:\n    if dimensionality == 0 or not isinstance(inputs, list):\n        raise AssumptionError(\n            public_message=f\"Could not prepare batch-oriented input data. This is most likely the bug. Contact \"\n            f\"Roboflow team through github issues (https://github.com/roboflow/inference/issues) \"\n            f\"providing full context of the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if dimensionality == 1:\n        return inputs\n    result = []\n    for element in inputs:\n        result.extend(\n            _flatten_batch_oriented_inputs(\n                inputs=element, dimensionality=dimensionality - 1\n            )\n        )\n    return result\n\n\ndef reduce_batch_dimensionality(\n    indices: List[DynamicBatchIndex],\n    upper_level_index: List[DynamicBatchIndex],\n    data: List[T],\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n) -> Batch[Optional[Batch[T]]]:\n    guard_of_indices_wrapping.register_wrapping(indices_before_wrapping=indices)\n    already_spotted_downgraded_indices = set()\n    wrapped_batch_index, wrapped_batch_content = [], []\n    upper_level_indices_data = {index: None for index in upper_level_index}\n    for index, data in zip(indices, data):\n        downgraded_index = index[:-1]\n        if downgraded_index in already_spotted_downgraded_indices:\n            wrapped_batch_index.append(index)\n            wrapped_batch_content.append(data)\n        else:\n            if wrapped_batch_index:\n                upper_level_indices_data[wrapped_batch_index[-1][:-1]] = Batch(\n                    content=wrapped_batch_content, indices=wrapped_batch_index\n                )\n            already_spotted_downgraded_indices.add(downgraded_index)\n            wrapped_batch_index = [index]\n            wrapped_batch_content = [data]\n    if wrapped_batch_index:\n        upper_level_indices_data[wrapped_batch_index[-1][:-1]] = Batch(\n            content=wrapped_batch_content, indices=wrapped_batch_index\n        )\n    return Batch(\n        content=[upper_level_indices_data[index] for index in upper_level_index],\n        indices=upper_level_index,\n    )\n\n\ndef ensure_compound_input_indices_match(indices: List[List[DynamicBatchIndex]]) -> None:\n    if len(indices) < 2:\n        return None\n    reference_set = set(indices[0])\n    for index in indices[1:]:\n        other_set = set(index)\n        if reference_set != other_set:\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Detected a situation when step input parameters cannot be created \"\n                f\"due to missmatch in batch element indices. This is most likely a bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n\n\ndef get_empty_batch_elements_indices(value: Any) -> Set[DynamicBatchIndex]:\n    result = set()\n    if isinstance(value, dict):\n        for v in value.values():\n            value_result = get_empty_batch_elements_indices(v)\n            result = result.union(value_result)\n    if isinstance(value, list):\n        for v in value:\n            value_result = get_empty_batch_elements_indices(v)\n            result = result.union(value_result)\n    if isinstance(value, Batch):\n        for index, value_element in value.iter_with_indices():\n            if isinstance(value_element, Batch):\n                value_result = get_empty_batch_elements_indices(value=value_element)\n                result = result.union(value_result)\n            elif value_element is None:\n                result.add(index)\n    return result\n\n\ndef remove_indices(value: Any, indices: Set[DynamicBatchIndex]) -> Any:\n    if isinstance(value, dict):\n        return {k: remove_indices(value=v, indices=indices) for k, v in value.items()}\n    if isinstance(value, list):\n        return [remove_indices(value=v, indices=indices) for v in value]\n    if isinstance(value, Batch):\n        return value.remove_by_indices(indices_to_remove=indices)\n    return value\n\n\ndef unfold_parameters(\n    parameters: Dict[str, Any],\n    indices: Optional[\n        List[tuple]\n    ] = None,  # TODO: none here is only for unit tests to pass\n) -> Generator[Dict[str, Any], None, None]:\n    batch_parameters = get_batch_parameters(parameters=parameters)\n    non_batch_parameters = {\n        k: v for k, v in parameters.items() if k not in batch_parameters\n    }\n    if not batch_parameters:\n        if not non_batch_parameters:\n            return None\n        if indices:\n            for _ in indices:\n                yield non_batch_parameters\n        else:\n            yield non_batch_parameters\n        return None\n    for unfolded_batch_parameters in iterate_over_batches(\n        batch_parameters=batch_parameters\n    ):\n        yield {**unfolded_batch_parameters, **non_batch_parameters}\n\n\ndef get_batch_parameters(parameters: Dict[str, Any]) -> Dict[str, Any]:\n    result = {}\n    for name, value in parameters.items():\n        if isinstance(value, Batch):\n            result[name] = value\n        elif isinstance(value, list) and any(isinstance(v, Batch) for v in value):\n            result[name] = value\n        elif isinstance(value, dict) and any(\n            isinstance(v, Batch) for v in value.values()\n        ):\n            result[name] = value\n    return result\n\n\ndef iterate_over_batches(\n    batch_parameters: Dict[str, Any],\n) -> Generator[Dict[str, Any], None, None]:\n    index = 0\n    end = False\n    while not end:\n        result = {}\n        for name, value in batch_parameters.items():\n            if isinstance(value, Batch):\n                if len(value) <= index:\n                    end = True\n                    break\n                result[name] = value[index]\n            elif isinstance(value, list):\n                to_yield = []\n                for element in value:\n                    if isinstance(element, Batch):\n                        if len(element) <= index:\n                            end = True\n                            break\n                        to_yield.append(element[index])\n                    else:\n                        to_yield.append(element)\n                result[name] = to_yield\n            elif isinstance(value, dict):\n                to_yield = {}\n                for key, key_value in value.items():\n                    if not isinstance(key_value, Batch):\n                        to_yield[key] = key_value\n                    else:\n                        if len(key_value) <= index:\n                            end = True\n                            break\n                        else:\n                            to_yield[key] = key_value[index]\n                result[name] = to_yield\n        index += 1\n        if not end:\n            yield result\n",
    "patch": null
  },
  {
    "trace_id": "1c64d4d6-2d98-4c94-9f87-a3db5df1e019",
    "function_name": "construct_mask_for_all_inputs_dimensionalities",
    "file_path": "inference/core/workflows/execution_engine/v1/executor/execution_data_manager/step_input_assembler.py",
    "speedup_x": 0.5129887829991205,
    "review_quality": "high",
    "pre_optimization_commit": "8087a916a2439f01bf6c577c892bb43e0fa39731",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def construct_mask_for_all_inputs_dimensionalities(\n    step_node: StepNode,\n    branching_manager: BranchingManager,\n) -> Tuple[Any, bool]:\n    inputs_dimensionalities = collect_inputs_dimensionalities(step_node=step_node)\n    all_dimensionalities = {dim for dim in inputs_dimensionalities.values() if dim > 0}\n    batch_masks, non_batch_masks = [], set()\n    for execution_branch in step_node.execution_branches_impacting_inputs:\n        if not branching_manager.is_execution_branch_registered(\n            execution_branch=execution_branch\n        ):\n            non_batch_masks.add(False)\n            continue\n        if branching_manager.is_execution_branch_batch_oriented(\n            execution_branch=execution_branch\n        ):\n            mask = branching_manager.get_mask(execution_branch=execution_branch)\n            batch_masks.append(mask)\n        else:\n            mask = branching_manager.get_mask(execution_branch=execution_branch)\n            non_batch_masks.add(mask)\n    scalar_mask_contains_false = False in non_batch_masks\n    if scalar_mask_contains_false:\n        return {\n            dimension: set() for dimension in all_dimensionalities\n        }, scalar_mask_contains_false\n    return (\n        get_masks_intersection_for_dimensions(\n            batch_masks=batch_masks,\n            dimensions=all_dimensionalities,\n        ),\n        scalar_mask_contains_false,\n    )\n",
    "optimized_function_code": "from inference.core.workflows.execution_engine.v1.compiler.entities import StepNode\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.branching_manager import BranchingManager\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.dynamic_batches_manager import DynamicBatchIndex\nfrom typing import Any, Dict, List, Optional, Set, Tuple\n\n\ndef construct_mask_for_all_inputs_dimensionalities(\n    step_node: StepNode,\n    branching_manager: BranchingManager,\n) -> Tuple[Any, bool]:\n    inputs_dimensionalities = collect_inputs_dimensionalities(step_node=step_node)\n    all_dimensionalities = {dim for dim in inputs_dimensionalities.values() if dim > 0}\n    batch_masks, non_batch_masks = [], set()\n    \n    # Cache dictionary and method lookups to avoid repeated attribute access\n    masks_dict = branching_manager._masks\n    batch_compat_dict = branching_manager._batch_compatibility\n    \n    for execution_branch in step_node.execution_branches_impacting_inputs:\n        if execution_branch not in masks_dict:\n            non_batch_masks.add(False)\n            continue\n        if batch_compat_dict[execution_branch]:\n            mask = masks_dict[execution_branch]\n            batch_masks.append(mask)\n        else:\n            mask = masks_dict[execution_branch]\n            non_batch_masks.add(mask)\n    scalar_mask_contains_false = False in non_batch_masks\n    if scalar_mask_contains_false:\n        return {\n            dimension: set() for dimension in all_dimensionalities\n        }, scalar_mask_contains_false\n    return (\n        get_masks_intersection_for_dimensions(\n            batch_masks=batch_masks,\n            dimensions=all_dimensionalities,\n        ),\n        scalar_mask_contains_false,\n    )\n\n\ndef collect_inputs_dimensionalities(\n    step_node: StepNode,\n) -> Dict[str, int]:\n    result = {}\n    for parameter_name, parameter_specs in step_node.input_data.items():\n        if parameter_specs.is_compound_input():\n            dimensionalities = [\n                nested_definition.get_dimensionality()\n                for nested_definition in parameter_specs.iterate_through_definitions()\n            ]\n            # to help for empty values\n            dimensionalities.append(0)\n            result[parameter_name] = max(dimensionalities)\n        else:\n            result[parameter_name] = parameter_specs.get_dimensionality()\n    return result\n\n\ndef get_masks_intersection_for_dimensions(\n    batch_masks: List[Set[DynamicBatchIndex]],\n    dimensions: Set[int],\n) -> Dict[int, Optional[Set[DynamicBatchIndex]]]:\n    # TODO: verify with unit tests! Claude implementation\n    if not batch_masks:\n        return {dim: None for dim in dimensions}\n\n    sorted_dims = sorted(dimensions)\n\n    # Group indices by their tuple length, only keeping relevant dimensions\n    by_dim: Dict[int, Set[DynamicBatchIndex]] = {dim: set() for dim in sorted_dims}\n    for mask in batch_masks:\n        for idx in mask:\n            by_dim[len(idx)].add(idx)\n\n\n    if len(sorted_dims) <= 1:\n        return {dim: by_dim[dim] for dim in sorted_dims}\n\n    prev_dim = {sorted_dims[i]: sorted_dims[i - 1] for i in range(1, len(sorted_dims))}\n\n    # Bottom-up: mark indices that have at least one descendant\n    has_child: Set[DynamicBatchIndex] = set()\n    for dim in reversed(sorted_dims):\n        for idx in by_dim[dim]:\n            if dim == sorted_dims[-1] or idx in has_child:\n                parent = idx[:-1]\n                if parent:\n                    has_child.add(parent)\n\n    # Top-down: keep indices only if full prefix chain exists\n    valid: Dict[int, Set[DynamicBatchIndex]] = {dim: set() for dim in sorted_dims}\n    for dim in sorted_dims:\n        for idx in by_dim[dim]:\n            parent = idx[:-1]\n            if dim == sorted_dims[0]:\n                if idx in has_child:\n                    valid[dim].add(idx)\n            elif parent in valid[prev_dim[dim]]:\n                if dim == sorted_dims[-1] or idx in has_child:\n                    valid[dim].add(idx)\n\n    return valid",
    "optimized_raw_markdown": "```python:inference/core/workflows/execution_engine/v1/executor/execution_data_manager/step_input_assembler.py\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import StepNode\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.branching_manager import BranchingManager\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.dynamic_batches_manager import DynamicBatchIndex\nfrom typing import Any, Dict, List, Optional, Set, Tuple\n\n\ndef construct_mask_for_all_inputs_dimensionalities(\n    step_node: StepNode,\n    branching_manager: BranchingManager,\n) -> Tuple[Any, bool]:\n    inputs_dimensionalities = collect_inputs_dimensionalities(step_node=step_node)\n    all_dimensionalities = {dim for dim in inputs_dimensionalities.values() if dim > 0}\n    batch_masks, non_batch_masks = [], set()\n    \n    # Cache dictionary and method lookups to avoid repeated attribute access\n    masks_dict = branching_manager._masks\n    batch_compat_dict = branching_manager._batch_compatibility\n    \n    for execution_branch in step_node.execution_branches_impacting_inputs:\n        if execution_branch not in masks_dict:\n            non_batch_masks.add(False)\n            continue\n        if batch_compat_dict[execution_branch]:\n            mask = masks_dict[execution_branch]\n            batch_masks.append(mask)\n        else:\n            mask = masks_dict[execution_branch]\n            non_batch_masks.add(mask)\n    scalar_mask_contains_false = False in non_batch_masks\n    if scalar_mask_contains_false:\n        return {\n            dimension: set() for dimension in all_dimensionalities\n        }, scalar_mask_contains_false\n    return (\n        get_masks_intersection_for_dimensions(\n            batch_masks=batch_masks,\n            dimensions=all_dimensionalities,\n        ),\n        scalar_mask_contains_false,\n    )\n\n\ndef collect_inputs_dimensionalities(\n    step_node: StepNode,\n) -> Dict[str, int]:\n    result = {}\n    for parameter_name, parameter_specs in step_node.input_data.items():\n        if parameter_specs.is_compound_input():\n            dimensionalities = [\n                nested_definition.get_dimensionality()\n                for nested_definition in parameter_specs.iterate_through_definitions()\n            ]\n            # to help for empty values\n            dimensionalities.append(0)\n            result[parameter_name] = max(dimensionalities)\n        else:\n            result[parameter_name] = parameter_specs.get_dimensionality()\n    return result\n\n\ndef get_masks_intersection_for_dimensions(\n    batch_masks: List[Set[DynamicBatchIndex]],\n    dimensions: Set[int],\n) -> Dict[int, Optional[Set[DynamicBatchIndex]]]:\n    # TODO: verify with unit tests! Claude implementation\n    if not batch_masks:\n        return {dim: None for dim in dimensions}\n\n    sorted_dims = sorted(dimensions)\n\n    # Group indices by their tuple length, only keeping relevant dimensions\n    by_dim: Dict[int, Set[DynamicBatchIndex]] = {dim: set() for dim in sorted_dims}\n    for mask in batch_masks:\n        for idx in mask:\n            by_dim[len(idx)].add(idx)\n\n\n    if len(sorted_dims) <= 1:\n        return {dim: by_dim[dim] for dim in sorted_dims}\n\n    prev_dim = {sorted_dims[i]: sorted_dims[i - 1] for i in range(1, len(sorted_dims))}\n\n    # Bottom-up: mark indices that have at least one descendant\n    has_child: Set[DynamicBatchIndex] = set()\n    for dim in reversed(sorted_dims):\n        for idx in by_dim[dim]:\n            if dim == sorted_dims[-1] or idx in has_child:\n                parent = idx[:-1]\n                if parent:\n                    has_child.add(parent)\n\n    # Top-down: keep indices only if full prefix chain exists\n    valid: Dict[int, Set[DynamicBatchIndex]] = {dim: set() for dim in sorted_dims}\n    for dim in sorted_dims:\n        for idx in by_dim[dim]:\n            parent = idx[:-1]\n            if dim == sorted_dims[0]:\n                if idx in has_child:\n                    valid[dim].add(idx)\n            elif parent in valid[prev_dim[dim]]:\n                if dim == sorted_dims[-1] or idx in has_child:\n                    valid[dim].add(idx)\n\n    return valid\n```",
    "optimized_function_only": "def construct_mask_for_all_inputs_dimensionalities(\n    step_node: StepNode,\n    branching_manager: BranchingManager,\n) -> Tuple[Any, bool]:\n    inputs_dimensionalities = collect_inputs_dimensionalities(step_node=step_node)\n    all_dimensionalities = {dim for dim in inputs_dimensionalities.values() if dim > 0}\n    batch_masks, non_batch_masks = [], set()\n    \n    # Cache dictionary and method lookups to avoid repeated attribute access\n    masks_dict = branching_manager._masks\n    batch_compat_dict = branching_manager._batch_compatibility\n    \n    for execution_branch in step_node.execution_branches_impacting_inputs:\n        if execution_branch not in masks_dict:\n            non_batch_masks.add(False)\n            continue\n        if batch_compat_dict[execution_branch]:\n            mask = masks_dict[execution_branch]\n            batch_masks.append(mask)\n        else:\n            mask = masks_dict[execution_branch]\n            non_batch_masks.add(mask)\n    scalar_mask_contains_false = False in non_batch_masks\n    if scalar_mask_contains_false:\n        return {\n            dimension: set() for dimension in all_dimensionalities\n        }, scalar_mask_contains_false\n    return (\n        get_masks_intersection_for_dimensions(\n            batch_masks=batch_masks,\n            dimensions=all_dimensionalities,\n        ),\n        scalar_mask_contains_false,\n    )\n",
    "original_file_content": "from dataclasses import dataclass\nfrom typing import Any, Dict, Generator, List, Optional, Set, Tuple, TypeVar, Union\n\nfrom inference.core.workflows.errors import AssumptionError, ExecutionEngineRuntimeError\nfrom inference.core.workflows.execution_engine.entities.base import Batch\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import (\n    AutoBatchCastingConfig,\n    CompoundStepInputDefinition,\n    DynamicStepInputDefinition,\n    StaticStepInputDefinition,\n    StepInputDefinition,\n    StepNode,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import (\n    get_last_chunk_of_selector,\n)\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.branching_manager import (\n    BranchingManager,\n)\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.dynamic_batches_manager import (\n    DynamicBatchesManager,\n    DynamicBatchIndex,\n)\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.execution_cache import (\n    ExecutionCache,\n)\n\nT = TypeVar(\"T\")\n\n\n@dataclass(frozen=True)\nclass BatchModeSIMDStepInput:\n    indices: List[DynamicBatchIndex]\n    parameters: Dict[str, Any]\n\n\n@dataclass(frozen=True)\nclass NonBatchModeSIMDStepInput:\n    index: DynamicBatchIndex\n    parameters: Dict[str, Any]\n\n\ndef construct_non_simd_step_input(\n    step_node: StepNode,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    branching_manager: BranchingManager,\n) -> Optional[Dict[str, Any]]:\n    if step_node.batch_oriented_parameters:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Attempted to get non-SIMD input for SIMD step: {step_node.name}.\"\n            f\"This is most likely a bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    masks = set()\n    for execution_branch in step_node.execution_branches_impacting_inputs:\n        if not branching_manager.is_execution_branch_registered(\n            execution_branch=execution_branch\n        ):\n            masks.add(False)\n            continue\n        if branching_manager.is_execution_branch_batch_oriented(\n            execution_branch=execution_branch\n        ):\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"For step: {step_node.name}, detected batch-oriented condition statements \"\n                f\"impacting non-SIMD step, which should be prevented by Workflows Compiler. \"\n                f\"This is most likely a bug. Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n        else:\n            mask = branching_manager.get_mask(execution_branch=execution_branch)\n            masks.add(mask)\n    if False in masks:\n        return None\n    result = {}\n    detected_empty_step_output_selector = False\n    for parameter_name, parameter_spec in step_node.input_data.items():\n        if parameter_spec.is_compound_input():\n            result[parameter_name], contains_empty_step_output_selector = (\n                construct_non_simd_step_compound_input(\n                    step_node=step_node,\n                    parameter_spec=parameter_spec,\n                    runtime_parameters=runtime_parameters,\n                    execution_cache=execution_cache,\n                )\n            )\n        else:\n            result[parameter_name], contains_empty_step_output_selector = (\n                construct_non_simd_step_non_compound_input(\n                    step_node=step_node,\n                    parameter_spec=parameter_spec,\n                    runtime_parameters=runtime_parameters,\n                    execution_cache=execution_cache,\n                )\n            )\n        detected_empty_step_output_selector = (\n            detected_empty_step_output_selector or contains_empty_step_output_selector\n        )\n    if (\n        detected_empty_step_output_selector\n        and not step_node.step_manifest.accepts_empty_values()\n    ):\n        return None\n    return result\n\n\ndef construct_non_simd_step_compound_input(\n    step_node: StepNode,\n    parameter_spec: CompoundStepInputDefinition,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> Tuple[Any, bool]:\n    if parameter_spec.represents_list_of_inputs():\n        return construct_non_simd_step_compound_list_input(\n            step_node=step_node,\n            parameter_spec=parameter_spec,\n            runtime_parameters=runtime_parameters,\n            execution_cache=execution_cache,\n        )\n    return construct_non_simd_step_compound_dict_input(\n        step_node=step_node,\n        parameter_spec=parameter_spec,\n        runtime_parameters=runtime_parameters,\n        execution_cache=execution_cache,\n    )\n\n\ndef construct_non_simd_step_compound_list_input(\n    step_node: StepNode,\n    parameter_spec: CompoundStepInputDefinition,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> Tuple[List[Any], bool]:\n    result = []\n    contains_empty_step_output_selector = False\n    for nested_definition in parameter_spec.iterate_through_definitions():\n        nested_value, value_contains_empty_selector = (\n            construct_non_simd_step_non_compound_input(\n                step_node=step_node,\n                parameter_spec=nested_definition,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n            )\n        )\n        result.append(nested_value)\n        contains_empty_step_output_selector = (\n            contains_empty_step_output_selector or value_contains_empty_selector\n        )\n    return result, contains_empty_step_output_selector\n\n\ndef construct_non_simd_step_compound_dict_input(\n    step_node: StepNode,\n    parameter_spec: CompoundStepInputDefinition,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> Tuple[Dict[str, Any], bool]:\n    result = {}\n    contains_empty_step_output_selector = False\n    for nested_definition in parameter_spec.iterate_through_definitions():\n        (\n            result[nested_definition.parameter_specification.nested_element_key],\n            value_contains_empty_selector,\n        ) = construct_non_simd_step_non_compound_input(\n            step_node=step_node,\n            parameter_spec=nested_definition,\n            runtime_parameters=runtime_parameters,\n            execution_cache=execution_cache,\n        )\n        contains_empty_step_output_selector = (\n            contains_empty_step_output_selector or value_contains_empty_selector\n        )\n    return result, contains_empty_step_output_selector\n\n\ndef construct_non_simd_step_non_compound_input(\n    step_node: StepNode,\n    parameter_spec: StepInputDefinition,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> Tuple[Any, bool]:\n    if parameter_spec.is_compound_input():\n        raise AssumptionError(\n            public_message=f\"Workflows Execution Error encountered unexpected state probably related to the fact \"\n            f\"that Workflows Compiler allowed for multi-level nesting of inputs selectors which \"\n            f\"is not supported. This is most likely the bug. Contact Roboflow team \"\n            f\"through github issues (https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if parameter_spec.is_batch_oriented():\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Encountered batch-oriented input for non-SIMD step: {step_node.name}.\"\n            f\"This is most likely a bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if parameter_spec.points_to_input():\n        parameter_spec: DynamicStepInputDefinition = parameter_spec  # type: ignore\n        input_name = get_last_chunk_of_selector(selector=parameter_spec.selector)\n        return runtime_parameters[input_name], False\n    if parameter_spec.points_to_step_output():\n        parameter_spec: DynamicStepInputDefinition = parameter_spec  # type: ignore\n        step_output = execution_cache.get_non_batch_output(\n            selector=parameter_spec.selector\n        )\n        return step_output, step_output is None\n    parameter_spec: StaticStepInputDefinition = parameter_spec  # type: ignore\n    return parameter_spec.value, False\n\n\ndef iterate_over_simd_step_input(\n    step_node: StepNode,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    dynamic_batches_manager: DynamicBatchesManager,\n    branching_manager: BranchingManager,\n) -> Generator[NonBatchModeSIMDStepInput, None, None]:\n    simd_step_input = construct_simd_step_input(\n        step_node=step_node,\n        runtime_parameters=runtime_parameters,\n        execution_cache=execution_cache,\n        dynamic_batches_manager=dynamic_batches_manager,\n        branching_manager=branching_manager,\n    )\n    parameters_generator = unfold_parameters(parameters=simd_step_input.parameters)\n    for index, single_parameters_set in zip(\n        simd_step_input.indices, parameters_generator\n    ):\n        yield NonBatchModeSIMDStepInput(\n            index=index,\n            parameters=single_parameters_set,\n        )\n\n\ndef construct_simd_step_input(\n    step_node: StepNode,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    dynamic_batches_manager: DynamicBatchesManager,\n    branching_manager: BranchingManager,\n) -> BatchModeSIMDStepInput:\n    print(\"step_node\", step_node.name)\n    masks, scalars_discarded = construct_mask_for_all_inputs_dimensionalities(\n        step_node=step_node,\n        branching_manager=branching_manager,\n    )\n    print(\"masks\", masks)\n    return prepare_parameters(\n        step_node=step_node,\n        dynamic_batches_manager=dynamic_batches_manager,\n        masks=masks,\n        scalars_discarded=scalars_discarded,\n        runtime_parameters=runtime_parameters,\n        execution_cache=execution_cache,\n    )\n\n\ndef construct_mask_for_all_inputs_dimensionalities(\n    step_node: StepNode,\n    branching_manager: BranchingManager,\n) -> Tuple[Any, bool]:\n    inputs_dimensionalities = collect_inputs_dimensionalities(step_node=step_node)\n    all_dimensionalities = {dim for dim in inputs_dimensionalities.values() if dim > 0}\n    batch_masks, non_batch_masks = [], set()\n    for execution_branch in step_node.execution_branches_impacting_inputs:\n        if not branching_manager.is_execution_branch_registered(\n            execution_branch=execution_branch\n        ):\n            non_batch_masks.add(False)\n            continue\n        if branching_manager.is_execution_branch_batch_oriented(\n            execution_branch=execution_branch\n        ):\n            mask = branching_manager.get_mask(execution_branch=execution_branch)\n            batch_masks.append(mask)\n        else:\n            mask = branching_manager.get_mask(execution_branch=execution_branch)\n            non_batch_masks.add(mask)\n    scalar_mask_contains_false = False in non_batch_masks\n    if scalar_mask_contains_false:\n        return {\n            dimension: set() for dimension in all_dimensionalities\n        }, scalar_mask_contains_false\n    return (\n        get_masks_intersection_for_dimensions(\n            batch_masks=batch_masks,\n            dimensions=all_dimensionalities,\n        ),\n        scalar_mask_contains_false,\n    )\n\n\ndef collect_inputs_dimensionalities(\n    step_node: StepNode,\n) -> Dict[str, int]:\n    result = {}\n    for parameter_name, parameter_specs in step_node.input_data.items():\n        if parameter_specs.is_compound_input():\n            dimensionalities = [\n                nested_definition.get_dimensionality()\n                for nested_definition in parameter_specs.iterate_through_definitions()\n            ]\n            # to help for empty values\n            dimensionalities.append(0)\n            result[parameter_name] = max(dimensionalities)\n        else:\n            result[parameter_name] = parameter_specs.get_dimensionality()\n    return result\n\n\ndef get_masks_intersection_for_dimensions(\n    batch_masks: List[Set[DynamicBatchIndex]],\n    dimensions: Set[int],\n) -> Dict[int, Optional[Set[DynamicBatchIndex]]]:\n    # TODO: verify with unit tests! Claude implementation\n    if not batch_masks:\n        return {dim: None for dim in dimensions}\n\n    sorted_dims = sorted(dimensions)\n\n    # Group indices by their tuple length, only keeping relevant dimensions\n    by_dim: Dict[int, Set[DynamicBatchIndex]] = {dim: set() for dim in sorted_dims}\n    for mask in batch_masks:\n        for idx in mask:\n            by_dim[len(idx)].add(idx)\n\n    if len(sorted_dims) <= 1:\n        return {dim: by_dim[dim] for dim in sorted_dims}\n\n    prev_dim = {sorted_dims[i]: sorted_dims[i - 1] for i in range(1, len(sorted_dims))}\n\n    # Bottom-up: mark indices that have at least one descendant\n    has_child: Set[DynamicBatchIndex] = set()\n    for dim in reversed(sorted_dims):\n        for idx in by_dim[dim]:\n            if dim == sorted_dims[-1] or idx in has_child:\n                parent = idx[:-1]\n                if parent:\n                    has_child.add(parent)\n\n    # Top-down: keep indices only if full prefix chain exists\n    valid: Dict[int, Set[DynamicBatchIndex]] = {dim: set() for dim in sorted_dims}\n    for dim in sorted_dims:\n        for idx in by_dim[dim]:\n            parent = idx[:-1]\n            if dim == sorted_dims[0]:\n                if idx in has_child:\n                    valid[dim].add(idx)\n            elif parent in valid[prev_dim[dim]]:\n                if dim == sorted_dims[-1] or idx in has_child:\n                    valid[dim].add(idx)\n\n    return valid\n\n\nclass GuardForIndicesWrapping:\n\n    def __init__(self):\n        self._registered_wrapping: Optional[List[DynamicBatchIndex]] = None\n\n    def register_wrapping(\n        self, indices_before_wrapping: List[DynamicBatchIndex]\n    ) -> None:\n        if self._registered_wrapping is None:\n            self._registered_wrapping = indices_before_wrapping\n        elif self._registered_wrapping != indices_before_wrapping:\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Detected a situation when step requires dimensionality wrapping, but\"\n                f\"different inputs register different elements indices to wrap which is illegal \"\n                f\"and should be detected earlier by Workflows compiler. This is most likely a bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n\n\ndef prepare_parameters(\n    step_node: StepNode,\n    dynamic_batches_manager: DynamicBatchesManager,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> BatchModeSIMDStepInput:\n    step_requests_batch_input = step_node.step_manifest.accepts_batch_input()\n    result = {}\n    indices_for_parameter = {}\n    guard_of_indices_wrapping = GuardForIndicesWrapping()\n    compound_inputs = set()\n    contains_empty_scalar_step_output_selector = False\n    for parameter_name, parameter_specs in step_node.input_data.items():\n        if parameter_specs.is_compound_input():\n            (\n                result[parameter_name],\n                indices_for_parameter[parameter_name],\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_compound_parameter_value(\n                parameter=parameter_specs,\n                step_execution_dimensionality=step_node.step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=step_node.auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n            compound_inputs.add(parameter_name)\n        else:\n            (\n                result[parameter_name],\n                indices_for_parameter[parameter_name],\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=parameter_specs,\n                step_execution_dimensionality=step_node.step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=step_node.auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n        contains_empty_scalar_step_output_selector = (\n            contains_empty_scalar_step_output_selector\n            or value_contains_empty_scalar_step_output_selector\n        )\n    batch_parameters_indices = [\n        i for i in indices_for_parameter.values() if i is not None\n    ]\n    ensure_compound_input_indices_match(indices=batch_parameters_indices)\n    if not batch_parameters_indices:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"For step: {step_node.name} which is assessed by Workflows Compiler as \"\n            f\"SIMD step Execution Engine cannot detect batch inputs. \"\n            f\"This is most likely a bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    print(\"batch_parameters_indices\", batch_parameters_indices)\n    indices = batch_parameters_indices[0]\n    if not step_node.step_manifest.accepts_empty_values():\n        if contains_empty_scalar_step_output_selector:\n            return BatchModeSIMDStepInput(\n                indices=[],\n                parameters={},\n            )\n        empty_indices = get_empty_batch_elements_indices(value=result)\n        print(\"empty_indices\", empty_indices)\n        if empty_indices:\n            indices = [e for e in indices if e not in empty_indices]\n            result = remove_indices(value=result, indices=empty_indices)\n    print(indices, result)\n    return BatchModeSIMDStepInput(\n        indices=indices,\n        parameters=result,\n    )\n\n\ndef get_compound_parameter_value(\n    parameter: CompoundStepInputDefinition,\n    step_execution_dimensionality: int,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n    dynamic_batches_manager: DynamicBatchesManager,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n    auto_batch_casting_lineage_supports: Dict[str, AutoBatchCastingConfig],\n    step_requests_batch_input: bool,\n) -> Tuple[Union[list, Dict[str, Any]], Optional[List[DynamicBatchIndex]], bool]:\n    contains_empty_scalar_step_output_selector = False\n    batch_indices = []\n    if parameter.represents_list_of_inputs():\n        result = []\n        for nested_element in parameter.iterate_through_definitions():\n            (\n                non_compound_parameter_value,\n                non_compound_indices,\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=nested_element,\n                step_execution_dimensionality=step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n            result.append(non_compound_parameter_value)\n            contains_empty_scalar_step_output_selector = (\n                contains_empty_scalar_step_output_selector\n                or value_contains_empty_scalar_step_output_selector\n            )\n            if non_compound_indices is not None:\n                batch_indices.append(non_compound_indices)\n    else:\n        result = {}\n        for nested_element in parameter.iterate_through_definitions():\n            (\n                non_compound_parameter_value,\n                non_compound_indices,\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=nested_element,\n                step_execution_dimensionality=step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n            result[nested_element.parameter_specification.nested_element_key] = (\n                non_compound_parameter_value\n            )\n            contains_empty_scalar_step_output_selector = (\n                contains_empty_scalar_step_output_selector\n                or value_contains_empty_scalar_step_output_selector\n            )\n            if non_compound_indices is not None:\n                batch_indices.append(non_compound_indices)\n    ensure_compound_input_indices_match(indices=batch_indices)\n    result_indices = None\n    if len(batch_indices) > 0:\n        result_indices = batch_indices[0]\n    return result, result_indices, contains_empty_scalar_step_output_selector\n\n\ndef get_non_compound_parameter_value(\n    parameter: StepInputDefinition,\n    step_execution_dimensionality: int,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n    dynamic_batches_manager: DynamicBatchesManager,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n    auto_batch_casting_lineage_supports: Dict[str, AutoBatchCastingConfig],\n    step_requests_batch_input: bool,\n) -> Tuple[Any, Optional[List[DynamicBatchIndex]], bool]:\n    if not parameter.is_batch_oriented():\n        requested_as_batch = (\n            parameter.parameter_specification.parameter_name\n            in auto_batch_casting_lineage_supports\n        )\n        if parameter.points_to_input():\n            input_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n            parameter_name = get_last_chunk_of_selector(\n                selector=input_parameter.selector\n            )\n            if not requested_as_batch:\n                return runtime_parameters[parameter_name], None, False\n            else:\n                return apply_auto_batch_casting(\n                    parameter_name=parameter_name,\n                    value=runtime_parameters[parameter_name],\n                    auto_batch_casting_config=auto_batch_casting_lineage_supports[\n                        parameter.parameter_specification.parameter_name\n                    ],\n                    contains_empty_scalar_step_output_selector=False,\n                    dynamic_batches_manager=dynamic_batches_manager,\n                    step_execution_dimensionality=step_execution_dimensionality,\n                    guard_of_indices_wrapping=guard_of_indices_wrapping,\n                    step_requests_batch_input=step_requests_batch_input,\n                    masks=masks,\n                    scalars_discarded=False,\n                )\n        elif parameter.points_to_step_output():\n            input_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n            value = execution_cache.get_non_batch_output(\n                selector=input_parameter.selector\n            )\n            if not requested_as_batch:\n                return value, None, value is None\n            else:\n                return apply_auto_batch_casting(\n                    parameter_name=parameter.parameter_specification.parameter_name,\n                    value=value,\n                    auto_batch_casting_config=auto_batch_casting_lineage_supports[\n                        parameter.parameter_specification.parameter_name\n                    ],\n                    contains_empty_scalar_step_output_selector=value is None,\n                    dynamic_batches_manager=dynamic_batches_manager,\n                    step_execution_dimensionality=step_execution_dimensionality,\n                    guard_of_indices_wrapping=guard_of_indices_wrapping,\n                    step_requests_batch_input=step_requests_batch_input,\n                    masks=masks,\n                    scalars_discarded=scalars_discarded,\n                )\n        else:\n            static_input: StaticStepInputDefinition = parameter  # type: ignore\n            if not requested_as_batch or static_input.value is None:\n                # when we have Optional[Selector()] in manifest - we must retain\n                # ability to inject None into the run(...) parameters - as\n                # if we treat that as actual batch and broadcast Batch[None],\n                # we would behave exactly as condition execution does -\n                # and the logic executing after this, will filter-out empty\n                # elements - so on None, we behave \"the old way\" regardless of the fact that ABC\n                # was requested\n                return static_input.value, None, False\n            else:\n                return apply_auto_batch_casting(\n                    parameter_name=parameter.parameter_specification.parameter_name,\n                    value=static_input.value,\n                    auto_batch_casting_config=auto_batch_casting_lineage_supports[\n                        parameter.parameter_specification.parameter_name\n                    ],\n                    contains_empty_scalar_step_output_selector=False,\n                    dynamic_batches_manager=dynamic_batches_manager,\n                    step_execution_dimensionality=step_execution_dimensionality,\n                    guard_of_indices_wrapping=guard_of_indices_wrapping,\n                    step_requests_batch_input=step_requests_batch_input,\n                    masks=masks,\n                    scalars_discarded=False,\n                )\n    dynamic_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n    parameter_dimensionality = dynamic_parameter.get_dimensionality()\n    lineage_indices = dynamic_batches_manager.get_indices_for_data_lineage(\n        lineage=dynamic_parameter.data_lineage,\n    )\n    mask_for_dimension = masks[parameter_dimensionality]\n    if dynamic_parameter.points_to_input():\n        input_name = get_last_chunk_of_selector(selector=dynamic_parameter.selector)\n        batch_input = _flatten_batch_oriented_inputs(\n            runtime_parameters[input_name],\n            dimensionality=parameter_dimensionality,\n        )\n        if mask_for_dimension is not None:\n            if len(lineage_indices) != len(batch_input):\n                raise ExecutionEngineRuntimeError(\n                    public_message=f\"Detected a situation when input parameter: \"\n                    f\"{input_name}\"\n                    f\"size is mismatched compared to mask requested for that input. \"\n                    f\"Input length: {len(batch_input)}, mask size: {len(lineage_indices)}. \"\n                    f\"This is most likely a bug. \"\n                    f\"Contact Roboflow team through github issues \"\n                    f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                    f\"the problem - including workflow definition you use.\",\n                    context=\"workflow_execution | step_input_assembling\",\n                )\n            batch_input = [\n                input_element if element_index in mask_for_dimension else None\n                for element_index, input_element in zip(lineage_indices, batch_input)\n            ]\n    else:\n        batch_input = execution_cache.get_batch_output(\n            selector=dynamic_parameter.selector,\n            batch_elements_indices=lineage_indices,\n            mask=mask_for_dimension,\n        )\n    if step_execution_dimensionality == parameter_dimensionality:\n        return Batch(batch_input, lineage_indices), lineage_indices, False\n    if step_execution_dimensionality > parameter_dimensionality:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter.parameter_specification.parameter_name}\"\n            f\"has a dimensionality {parameter_dimensionality} larger \"\n            f\"than step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if abs(parameter_dimensionality - step_execution_dimensionality) > 1:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter.parameter_specification.parameter_name}\"\n            f\"has a dimensionality {parameter_dimensionality} differing more than one level \"\n            f\"from step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if step_execution_dimensionality == 0 and not step_requests_batch_input:\n        return Batch(batch_input, lineage_indices), lineage_indices, False\n    upper_lineage = dynamic_parameter.data_lineage[:-1]\n    if len(upper_lineage) == 0:\n        if not step_requests_batch_input:\n            raise AssumptionError(\n                public_message=f\"Parameter: {parameter.parameter_specification.parameter_name} \"\n                f\"requires dimensionality wrapping, but registered lineage support is incompatible \"\n                f\"which should be detected by the compiler. This is most likely a bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n        upper_level_indices = [()]\n    else:\n        upper_level_indices = dynamic_batches_manager.get_indices_for_data_lineage(\n            lineage=dynamic_parameter.data_lineage[:-1],\n        )\n    result = reduce_batch_dimensionality(\n        indices=lineage_indices,\n        upper_level_index=upper_level_indices,\n        data=batch_input,\n        guard_of_indices_wrapping=guard_of_indices_wrapping,\n    )\n    return result, result.indices, False\n\n\ndef apply_auto_batch_casting(\n    parameter_name: str,\n    value: Any,\n    auto_batch_casting_config: AutoBatchCastingConfig,\n    contains_empty_scalar_step_output_selector: bool,\n    dynamic_batches_manager: DynamicBatchesManager,\n    step_execution_dimensionality: int,\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n    step_requests_batch_input: bool,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n) -> Tuple[Any, List[DynamicBatchIndex], bool]:\n    if auto_batch_casting_config.lineage_support is None:\n        indices = [(0,) * auto_batch_casting_config.casted_dimensionality]\n    else:\n        indices = dynamic_batches_manager.get_indices_for_data_lineage(\n            lineage=auto_batch_casting_config.lineage_support,\n        )\n        missing_dimensions = auto_batch_casting_config.casted_dimensionality - len(\n            auto_batch_casting_config.lineage_support\n        )\n        if missing_dimensions > 0:\n            padding = (0,) * missing_dimensions\n            indices = [i + padding for i in indices]\n    if scalars_discarded:\n        batch_content = [None] * len(indices)\n    elif auto_batch_casting_config.lineage_support is None:\n        batch_content = [value] * len(indices)\n    else:\n        support_dimensionality = len(auto_batch_casting_config.lineage_support)\n        mask_for_support_dimensionality = masks[support_dimensionality]\n        if mask_for_support_dimensionality is None:\n            batch_content = [value] * len(indices)\n        else:\n            batch_content = []\n            for index in indices:\n                if index[:support_dimensionality] in mask_for_support_dimensionality:\n                    batch_content.append(value)\n                else:\n                    batch_content.append(None)\n    created_batch = Batch(content=batch_content, indices=indices)\n    if step_execution_dimensionality == auto_batch_casting_config.casted_dimensionality:\n        return (\n            created_batch,\n            indices,\n            contains_empty_scalar_step_output_selector or scalars_discarded,\n        )\n    if step_execution_dimensionality > auto_batch_casting_config.casted_dimensionality:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter_name}\"\n            f\"has auto-batch casted dimensionality {auto_batch_casting_config.casted_dimensionality} larger \"\n            f\"than step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if (\n        abs(\n            auto_batch_casting_config.casted_dimensionality\n            - step_execution_dimensionality\n        )\n        > 1\n    ):\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter_name} has auto batch casted \"\n            f\"dimensionality {auto_batch_casting_config.casted_dimensionality} differing more than one level \"\n            f\"from step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    upper_level_lineage_dimensionality = (\n        auto_batch_casting_config.casted_dimensionality - 1\n    )\n    if upper_level_lineage_dimensionality == 0 and not step_requests_batch_input:\n        # for batch collapse into scalar\n        return (\n            created_batch,\n            indices,\n            contains_empty_scalar_step_output_selector or scalars_discarded,\n        )\n    if auto_batch_casting_config.lineage_support is None:\n        upper_level_indices = [indices[0][:-1]]\n    else:\n        upper_level_lineage = auto_batch_casting_config.lineage_support[\n            :upper_level_lineage_dimensionality\n        ]\n        if (\n            upper_level_lineage_dimensionality < 1\n            or len(upper_level_lineage) < upper_level_lineage_dimensionality\n        ):\n            if not step_requests_batch_input:\n                raise AssumptionError(\n                    public_message=f\"Detected a situation when parameter: {parameter_name} requires dimensionality \"\n                    f\"wrapping, but registered lineage support is incompatible which should be detected \"\n                    f\"by the compiler. This is most likely a bug. \"\n                    f\"Contact Roboflow team through github issues \"\n                    f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                    f\"the problem - including workflow definition you use.\",\n                    context=\"workflow_execution | step_input_assembling\",\n                )\n            upper_level_indices = [()]\n        else:\n            upper_level_indices = dynamic_batches_manager.get_indices_for_data_lineage(\n                lineage=upper_level_lineage,\n            )\n    result = reduce_batch_dimensionality(\n        indices=indices,\n        upper_level_index=upper_level_indices,\n        data=batch_content,\n        guard_of_indices_wrapping=guard_of_indices_wrapping,\n    )\n    return (\n        result,\n        result.indices,\n        contains_empty_scalar_step_output_selector or scalars_discarded,\n    )\n\n\ndef _flatten_batch_oriented_inputs(\n    inputs: list,\n    dimensionality: int,\n) -> List[Any]:\n    if dimensionality == 0 or not isinstance(inputs, list):\n        raise AssumptionError(\n            public_message=f\"Could not prepare batch-oriented input data. This is most likely the bug. Contact \"\n            f\"Roboflow team through github issues (https://github.com/roboflow/inference/issues) \"\n            f\"providing full context of the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if dimensionality == 1:\n        return inputs\n    result = []\n    for element in inputs:\n        result.extend(\n            _flatten_batch_oriented_inputs(\n                inputs=element, dimensionality=dimensionality - 1\n            )\n        )\n    return result\n\n\ndef reduce_batch_dimensionality(\n    indices: List[DynamicBatchIndex],\n    upper_level_index: List[DynamicBatchIndex],\n    data: List[T],\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n) -> Batch[Optional[Batch[T]]]:\n    guard_of_indices_wrapping.register_wrapping(indices_before_wrapping=indices)\n    already_spotted_downgraded_indices = set()\n    wrapped_batch_index, wrapped_batch_content = [], []\n    upper_level_indices_data = {index: None for index in upper_level_index}\n    for index, data in zip(indices, data):\n        downgraded_index = index[:-1]\n        if downgraded_index in already_spotted_downgraded_indices:\n            wrapped_batch_index.append(index)\n            wrapped_batch_content.append(data)\n        else:\n            if wrapped_batch_index:\n                upper_level_indices_data[wrapped_batch_index[-1][:-1]] = Batch(\n                    content=wrapped_batch_content, indices=wrapped_batch_index\n                )\n            already_spotted_downgraded_indices.add(downgraded_index)\n            wrapped_batch_index = [index]\n            wrapped_batch_content = [data]\n    if wrapped_batch_index:\n        upper_level_indices_data[wrapped_batch_index[-1][:-1]] = Batch(\n            content=wrapped_batch_content, indices=wrapped_batch_index\n        )\n    return Batch(\n        content=[upper_level_indices_data[index] for index in upper_level_index],\n        indices=upper_level_index,\n    )\n\n\ndef ensure_compound_input_indices_match(indices: List[List[DynamicBatchIndex]]) -> None:\n    if len(indices) < 2:\n        return None\n    reference_set = set(indices[0])\n    for index in indices[1:]:\n        other_set = set(index)\n        if reference_set != other_set:\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Detected a situation when step input parameters cannot be created \"\n                f\"due to missmatch in batch element indices. This is most likely a bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n\n\ndef get_empty_batch_elements_indices(value: Any) -> Set[DynamicBatchIndex]:\n    result = set()\n    if isinstance(value, dict):\n        for v in value.values():\n            value_result = get_empty_batch_elements_indices(v)\n            result = result.union(value_result)\n    if isinstance(value, list):\n        for v in value:\n            value_result = get_empty_batch_elements_indices(v)\n            result = result.union(value_result)\n    if isinstance(value, Batch):\n        for index, value_element in value.iter_with_indices():\n            if isinstance(value_element, Batch):\n                value_result = get_empty_batch_elements_indices(value=value_element)\n                result = result.union(value_result)\n            elif value_element is None:\n                result.add(index)\n    return result\n\n\ndef remove_indices(value: Any, indices: Set[DynamicBatchIndex]) -> Any:\n    if isinstance(value, dict):\n        return {k: remove_indices(value=v, indices=indices) for k, v in value.items()}\n    if isinstance(value, list):\n        return [remove_indices(value=v, indices=indices) for v in value]\n    if isinstance(value, Batch):\n        return value.remove_by_indices(indices_to_remove=indices)\n    return value\n\n\ndef unfold_parameters(\n    parameters: Dict[str, Any],\n) -> Generator[Dict[str, Any], None, None]:\n    batch_parameters = get_batch_parameters(parameters=parameters)\n    non_batch_parameters = {\n        k: v for k, v in parameters.items() if k not in batch_parameters\n    }\n    if not batch_parameters:\n        if not non_batch_parameters:\n            return None\n        yield non_batch_parameters\n        return None\n    for unfolded_batch_parameters in iterate_over_batches(\n        batch_parameters=batch_parameters\n    ):\n        yield {**unfolded_batch_parameters, **non_batch_parameters}\n\n\ndef get_batch_parameters(parameters: Dict[str, Any]) -> Dict[str, Any]:\n    result = {}\n    for name, value in parameters.items():\n        if isinstance(value, Batch):\n            result[name] = value\n        elif isinstance(value, list) and any(isinstance(v, Batch) for v in value):\n            result[name] = value\n        elif isinstance(value, dict) and any(\n            isinstance(v, Batch) for v in value.values()\n        ):\n            result[name] = value\n    return result\n\n\ndef iterate_over_batches(\n    batch_parameters: Dict[str, Any],\n) -> Generator[Dict[str, Any], None, None]:\n    index = 0\n    end = False\n    while not end:\n        result = {}\n        for name, value in batch_parameters.items():\n            if isinstance(value, Batch):\n                if len(value) <= index:\n                    end = True\n                    break\n                result[name] = value[index]\n            elif isinstance(value, list):\n                to_yield = []\n                for element in value:\n                    if isinstance(element, Batch):\n                        if len(element) <= index:\n                            end = True\n                            break\n                        to_yield.append(element[index])\n                    else:\n                        to_yield.append(element)\n                result[name] = to_yield\n            elif isinstance(value, dict):\n                to_yield = {}\n                for key, key_value in value.items():\n                    if not isinstance(key_value, Batch):\n                        to_yield[key] = key_value\n                    else:\n                        if len(key_value) <= index:\n                            end = True\n                            break\n                        else:\n                            to_yield[key] = key_value[index]\n                result[name] = to_yield\n        index += 1\n        if not end:\n            yield result\n",
    "patch": null
  },
  {
    "trace_id": "cc36ae04-c6c3-4068-b718-3c91f6c3bc46",
    "function_name": "establish_control_flow_edge",
    "file_path": "inference/core/workflows/execution_engine/v1/compiler/graph_constructor.py",
    "speedup_x": 0.31966222014197676,
    "review_quality": "high",
    "pre_optimization_commit": "90243bdc6278ef7d17b6db09dc1eb5b0d155b4be",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def establish_control_flow_edge(\n    source_step_selector: str,\n    target_step_parsed_selector: ParsedSelector,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    if not step_definition_allows_control_flow_references(\n        parsed_selector=target_step_parsed_selector\n    ):\n        raise ExecutionGraphStructureError(\n            public_message=f\"Detected reference to other step in manifest of step {source_step_selector}. \"\n            f\"This is not allowed, as step manifest does not define any properties of type `StepSelector` \"\n            f\"allowing for defining connections between steps that represent flow control in `workflows`.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    target_step_selector = get_step_selector_from_its_output(\n        step_output_selector=target_step_parsed_selector.value\n    )\n    source_compilation_data = node_as(\n        execution_graph=execution_graph,\n        node=source_step_selector,\n        expected_type=StepNode,\n    )\n    target_compilation_data = node_as(\n        execution_graph=execution_graph,\n        node=target_step_selector,\n        expected_type=StepNode,\n    )\n    nodes_categories = {\n        source_compilation_data.node_category,\n        target_compilation_data.node_category,\n    }\n    if nodes_categories != {NodeCategory.STEP_NODE}:\n        raise ExecutionGraphStructureError(\n            public_message=f\"Attempted to create flow-control connection between workflow nodes: \"\n            f\"{source_step_selector} and {target_step_selector}, one of which is not denoted\"\n            f\"as step node.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    execution_graph.add_edge(\n        source_step_selector,\n        target_step_selector,\n    )\n    if target_step_selector in source_compilation_data.child_execution_branches:\n        raise ExecutionGraphStructureError(\n            public_message=f\"While establishing flow-control connection between source `{source_step_selector}` \"\n            f\"and target `{target_step_selector}` it was discovered that source step defines\"\n            f\"control flow transition into target one more than once, which is not allowed as \"\n            f\"that situation creates ambiguity in selecting execution branch.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    execution_branch_name = f\"Branch[{source_step_selector} -> {target_step_parsed_selector.definition.property_name}]\"\n    source_compilation_data.child_execution_branches[target_step_selector] = (\n        execution_branch_name\n    )\n    target_compilation_data.execution_branches_impacting_inputs.add(\n        execution_branch_name\n    )\n    return execution_graph\n",
    "optimized_function_code": "from inference.core.workflows.errors import ExecutionGraphStructureError\nfrom inference.core.workflows.execution_engine.entities.types import \\\n    STEP_AS_SELECTED_ELEMENT\nfrom inference.core.workflows.execution_engine.introspection.entities import \\\n    ParsedSelector\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import (\n    NodeCategory, StepNode)\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import (\n    get_step_selector_from_its_output, node_as)\nfrom networkx import DiGraph\n\n\ndef establish_control_flow_edge(\n    source_step_selector: str,\n    target_step_parsed_selector: ParsedSelector,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    allows_control_flow = False\n    for definition in target_step_parsed_selector.definition.allowed_references:\n        if definition.selected_element == STEP_AS_SELECTED_ELEMENT:\n            allows_control_flow = True\n            break\n    if not allows_control_flow:\n        raise ExecutionGraphStructureError(\n            public_message=f\"Detected reference to other step in manifest of step {source_step_selector}. \"\n            f\"This is not allowed, as step manifest does not define any properties of type `StepSelector` \"\n            f\"allowing for defining connections between steps that represent flow control in `workflows`.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    target_step_selector = get_step_selector_from_its_output(\n        step_output_selector=target_step_parsed_selector.value\n    )\n    source_compilation_data = node_as(\n        execution_graph=execution_graph,\n        node=source_step_selector,\n        expected_type=StepNode,\n    )\n    target_compilation_data = node_as(\n        execution_graph=execution_graph,\n        node=target_step_selector,\n        expected_type=StepNode,\n    )\n    if not (\n        source_compilation_data.node_category is NodeCategory.STEP_NODE\n        and target_compilation_data.node_category is NodeCategory.STEP_NODE\n    ):\n        raise ExecutionGraphStructureError(\n            public_message=f\"Attempted to create flow-control connection between workflow nodes: \"\n            f\"{source_step_selector} and {target_step_selector}, one of which is not denoted\"\n            f\"as step node.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    execution_graph.add_edge(\n        source_step_selector,\n        target_step_selector,\n    )\n    if target_step_selector in source_compilation_data.child_execution_branches:\n        raise ExecutionGraphStructureError(\n            public_message=f\"While establishing flow-control connection between source `{source_step_selector}` \"\n            f\"and target `{target_step_selector}` it was discovered that source step defines\"\n            f\"control flow transition into target one more than once, which is not allowed as \"\n            f\"that situation creates ambiguity in selecting execution branch.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    execution_branch_name = f\"Branch[{source_step_selector} -> {target_step_parsed_selector.definition.property_name}]\"\n    source_compilation_data.child_execution_branches[target_step_selector] = (\n        execution_branch_name\n    )\n    target_compilation_data.execution_branches_impacting_inputs.add(\n        execution_branch_name\n    )\n    return execution_graph\n\n\ndef step_definition_allows_control_flow_references(\n    parsed_selector: ParsedSelector,\n) -> bool:\n    return any(\n        definition.selected_element == STEP_AS_SELECTED_ELEMENT\n        for definition in parsed_selector.definition.allowed_references\n    )",
    "optimized_raw_markdown": "```python:inference/core/workflows/execution_engine/v1/compiler/graph_constructor.py\nfrom inference.core.workflows.errors import ExecutionGraphStructureError\nfrom inference.core.workflows.execution_engine.entities.types import \\\n    STEP_AS_SELECTED_ELEMENT\nfrom inference.core.workflows.execution_engine.introspection.entities import \\\n    ParsedSelector\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import (\n    NodeCategory, StepNode)\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import (\n    get_step_selector_from_its_output, node_as)\nfrom networkx import DiGraph\n\n\ndef establish_control_flow_edge(\n    source_step_selector: str,\n    target_step_parsed_selector: ParsedSelector,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    allows_control_flow = False\n    for definition in target_step_parsed_selector.definition.allowed_references:\n        if definition.selected_element == STEP_AS_SELECTED_ELEMENT:\n            allows_control_flow = True\n            break\n    if not allows_control_flow:\n        raise ExecutionGraphStructureError(\n            public_message=f\"Detected reference to other step in manifest of step {source_step_selector}. \"\n            f\"This is not allowed, as step manifest does not define any properties of type `StepSelector` \"\n            f\"allowing for defining connections between steps that represent flow control in `workflows`.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    target_step_selector = get_step_selector_from_its_output(\n        step_output_selector=target_step_parsed_selector.value\n    )\n    source_compilation_data = node_as(\n        execution_graph=execution_graph,\n        node=source_step_selector,\n        expected_type=StepNode,\n    )\n    target_compilation_data = node_as(\n        execution_graph=execution_graph,\n        node=target_step_selector,\n        expected_type=StepNode,\n    )\n    if not (\n        source_compilation_data.node_category is NodeCategory.STEP_NODE\n        and target_compilation_data.node_category is NodeCategory.STEP_NODE\n    ):\n        raise ExecutionGraphStructureError(\n            public_message=f\"Attempted to create flow-control connection between workflow nodes: \"\n            f\"{source_step_selector} and {target_step_selector}, one of which is not denoted\"\n            f\"as step node.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    execution_graph.add_edge(\n        source_step_selector,\n        target_step_selector,\n    )\n    if target_step_selector in source_compilation_data.child_execution_branches:\n        raise ExecutionGraphStructureError(\n            public_message=f\"While establishing flow-control connection between source `{source_step_selector}` \"\n            f\"and target `{target_step_selector}` it was discovered that source step defines\"\n            f\"control flow transition into target one more than once, which is not allowed as \"\n            f\"that situation creates ambiguity in selecting execution branch.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    execution_branch_name = f\"Branch[{source_step_selector} -> {target_step_parsed_selector.definition.property_name}]\"\n    source_compilation_data.child_execution_branches[target_step_selector] = (\n        execution_branch_name\n    )\n    target_compilation_data.execution_branches_impacting_inputs.add(\n        execution_branch_name\n    )\n    return execution_graph\n\n\ndef step_definition_allows_control_flow_references(\n    parsed_selector: ParsedSelector,\n) -> bool:\n    return any(\n        definition.selected_element == STEP_AS_SELECTED_ELEMENT\n        for definition in parsed_selector.definition.allowed_references\n    )\n```",
    "optimized_function_only": "def establish_control_flow_edge(\n    source_step_selector: str,\n    target_step_parsed_selector: ParsedSelector,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    allows_control_flow = False\n    for definition in target_step_parsed_selector.definition.allowed_references:\n        if definition.selected_element == STEP_AS_SELECTED_ELEMENT:\n            allows_control_flow = True\n            break\n    if not allows_control_flow:\n        raise ExecutionGraphStructureError(\n            public_message=f\"Detected reference to other step in manifest of step {source_step_selector}. \"\n            f\"This is not allowed, as step manifest does not define any properties of type `StepSelector` \"\n            f\"allowing for defining connections between steps that represent flow control in `workflows`.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    target_step_selector = get_step_selector_from_its_output(\n        step_output_selector=target_step_parsed_selector.value\n    )\n    source_compilation_data = node_as(\n        execution_graph=execution_graph,\n        node=source_step_selector,\n        expected_type=StepNode,\n    )\n    target_compilation_data = node_as(\n        execution_graph=execution_graph,\n        node=target_step_selector,\n        expected_type=StepNode,\n    )\n    if not (\n        source_compilation_data.node_category is NodeCategory.STEP_NODE\n        and target_compilation_data.node_category is NodeCategory.STEP_NODE\n    ):\n        raise ExecutionGraphStructureError(\n            public_message=f\"Attempted to create flow-control connection between workflow nodes: \"\n            f\"{source_step_selector} and {target_step_selector}, one of which is not denoted\"\n            f\"as step node.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    execution_graph.add_edge(\n        source_step_selector,\n        target_step_selector,\n    )\n    if target_step_selector in source_compilation_data.child_execution_branches:\n        raise ExecutionGraphStructureError(\n            public_message=f\"While establishing flow-control connection between source `{source_step_selector}` \"\n            f\"and target `{target_step_selector}` it was discovered that source step defines\"\n            f\"control flow transition into target one more than once, which is not allowed as \"\n            f\"that situation creates ambiguity in selecting execution branch.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    execution_branch_name = f\"Branch[{source_step_selector} -> {target_step_parsed_selector.definition.property_name}]\"\n    source_compilation_data.child_execution_branches[target_step_selector] = (\n        execution_branch_name\n    )\n    target_compilation_data.execution_branches_impacting_inputs.add(\n        execution_branch_name\n    )\n    return execution_graph\n",
    "original_file_content": "import itertools\nfrom collections import defaultdict\nfrom copy import copy, deepcopy\nfrom typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union\nfrom uuid import uuid4\n\nimport networkx as nx\nfrom networkx import DiGraph\n\nfrom inference.core import logger\nfrom inference.core.workflows.errors import (\n    AssumptionError,\n    BlockInterfaceError,\n    ControlFlowDefinitionError,\n    ExecutionGraphStructureError,\n    InvalidReferenceTargetError,\n    StepInputDimensionalityError,\n    StepInputLineageError,\n    WorkflowBlockError,\n)\nfrom inference.core.workflows.execution_engine.constants import (\n    NODE_COMPILATION_OUTPUT_PROPERTY,\n    PARSED_NODE_INPUT_SELECTORS_PROPERTY,\n    TOP_LEVEL_LINEAGES_KEY,\n    WORKFLOW_INPUT_BATCH_LINEAGE_ID,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    InputType,\n    JsonField,\n    OutputDefinition,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    STEP_AS_SELECTED_ELEMENT,\n    Kind,\n)\nfrom inference.core.workflows.execution_engine.introspection.entities import (\n    ParsedSelector,\n)\nfrom inference.core.workflows.execution_engine.introspection.selectors_parser import (\n    get_step_selectors,\n)\nfrom inference.core.workflows.execution_engine.profiling.core import (\n    WorkflowsProfiler,\n    execution_phase,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import (\n    AutoBatchCastingConfig,\n    CompoundStepInputDefinition,\n    DictOfStepInputDefinitions,\n    DynamicStepInputDefinition,\n    ExecutionGraphNode,\n    InputDimensionalitySpecification,\n    InputNode,\n    ListOfStepInputDefinitions,\n    NodeCategory,\n    NodeInputCategory,\n    OutputNode,\n    ParameterSpecification,\n    ParsedWorkflowDefinition,\n    PropertyPredecessorDefinition,\n    StaticStepInputDefinition,\n    StepInputData,\n    StepInputDefinition,\n    StepNode,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.graph_traversal import (\n    traverse_graph_ensuring_parents_are_reached_first,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.reference_type_checker import (\n    validate_reference_kinds,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import (\n    construct_input_selector,\n    construct_output_selector,\n    construct_step_selector,\n    get_last_chunk_of_selector,\n    get_nodes_of_specific_category,\n    get_step_selector_from_its_output,\n    identify_lineage,\n    is_control_flow_step,\n    is_input_node,\n    is_input_selector,\n    is_output_node,\n    is_step_node,\n    is_step_output_selector,\n    is_step_selector,\n    node_as,\n)\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nNODE_DEFINITION_KEY = \"definition\"\nSTEP_INPUT_SELECTORS_PROPERTY = \"step_input_selectors\"\nEXCLUDED_FIELDS = {\"type\", \"name\"}\n\n\n@execution_phase(\n    name=\"execution_graph_creation\",\n    categories=[\"execution_engine_operation\"],\n)\ndef prepare_execution_graph(\n    workflow_definition: ParsedWorkflowDefinition,\n    profiler: Optional[WorkflowsProfiler] = None,\n) -> DiGraph:\n    execution_graph = construct_graph(\n        workflow_definition=workflow_definition,\n    )\n    if not nx.is_directed_acyclic_graph(execution_graph):\n        raise ExecutionGraphStructureError(\n            public_message=f\"Detected cycle in execution graph. This means that there is output from one \"\n            f\"step that is connected to input of other step creating loop in the graph that would \"\n            f\"never end if executed.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    return denote_data_flow_in_workflow(\n        execution_graph=execution_graph,\n        parsed_workflow_definition=workflow_definition,\n    )\n\n\ndef construct_graph(\n    workflow_definition: ParsedWorkflowDefinition,\n) -> DiGraph:\n    execution_graph = nx.DiGraph()\n    execution_graph = add_input_nodes_for_graph(\n        inputs=workflow_definition.inputs,\n        execution_graph=execution_graph,\n    )\n    execution_graph = add_steps_nodes_for_graph(\n        steps=workflow_definition.steps,\n        execution_graph=execution_graph,\n    )\n    execution_graph = add_output_nodes_for_graph(\n        outputs=workflow_definition.outputs,\n        execution_graph=execution_graph,\n    )\n    execution_graph = add_steps_edges(\n        workflow_definition=workflow_definition,\n        execution_graph=execution_graph,\n    )\n    return add_edges_for_outputs(\n        workflow_definition=workflow_definition,\n        execution_graph=execution_graph,\n    )\n\n\ndef add_input_nodes_for_graph(\n    inputs: List[InputType],\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for input_spec in inputs:\n        input_selector = construct_input_selector(input_name=input_spec.name)\n        if input_spec.is_batch_oriented():\n            if input_spec.dimensionality < 1:\n                raise ExecutionGraphStructureError(\n                    public_message=f\"Detected batch oriented input `{input_spec.name}` with \"\n                    f\"declared dimensionality `{input_spec.dimensionality}` which is below \"\n                    f\"one (one is minimum dimensionality of the batch). Fix input definition in\"\n                    f\"your Workflow.\",\n                    context=\"workflow_compilation | execution_graph_construction\",\n                )\n            data_lineage = [WORKFLOW_INPUT_BATCH_LINEAGE_ID]\n            for _ in range(input_spec.dimensionality - 1):\n                # TODO: this may end up being a bug - with ability for multi-step debugging, if we will\n                #  ever have a situation that there will be multiple step outputs with nested\n                #  dimensionality with the same lineage, this re-construction method will\n                #  assign a different lineage identifier, causing the inputs being non-composable in\n                #  a single execution branch\n                data_lineage.append(f\"{uuid4()}\")\n        else:\n            data_lineage = []\n        compilation_output = InputNode(\n            node_category=NodeCategory.INPUT_NODE,\n            name=input_spec.name,\n            selector=input_selector,\n            data_lineage=data_lineage,\n            input_manifest=input_spec,\n        )\n        execution_graph.add_node(\n            input_selector,\n            **{\n                NODE_COMPILATION_OUTPUT_PROPERTY: compilation_output,\n            },\n        )\n    return execution_graph\n\n\ndef add_steps_nodes_for_graph(\n    steps: List[WorkflowBlockManifest],\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for step in steps:\n        step_selector = construct_step_selector(step_name=step.name)\n        compilation_output = StepNode(\n            node_category=NodeCategory.STEP_NODE,\n            name=step.name,\n            selector=step_selector,\n            data_lineage=[],\n            step_manifest=step,\n        )\n        execution_graph.add_node(\n            step_selector,\n            **{\n                NODE_COMPILATION_OUTPUT_PROPERTY: compilation_output,\n            },\n        )\n    return execution_graph\n\n\ndef add_output_nodes_for_graph(\n    outputs: List[JsonField],\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for output_spec in outputs:\n        output_selector = construct_output_selector(name=output_spec.name)\n        compilation_output = OutputNode(\n            node_category=NodeCategory.OUTPUT_NODE,\n            name=output_spec.name,\n            selector=output_selector,\n            data_lineage=[],\n            output_manifest=output_spec,\n        )\n        execution_graph.add_node(\n            output_selector,\n            **{\n                NODE_COMPILATION_OUTPUT_PROPERTY: compilation_output,\n            },\n        )\n    return execution_graph\n\n\ndef add_steps_edges(\n    workflow_definition: ParsedWorkflowDefinition,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for step in workflow_definition.steps:\n        source_step_selector = construct_step_selector(step_name=step.name)\n        step_selectors = get_step_selectors(step_manifest=step)\n        execution_graph.nodes[source_step_selector][\n            PARSED_NODE_INPUT_SELECTORS_PROPERTY\n        ] = step_selectors\n        execution_graph = add_edges_for_step(\n            execution_graph=execution_graph,\n            source_step_selector=source_step_selector,\n            target_step_parsed_selectors=step_selectors,\n        )\n    return execution_graph\n\n\ndef add_edges_for_step(\n    execution_graph: DiGraph,\n    source_step_selector: str,\n    target_step_parsed_selectors: List[ParsedSelector],\n) -> DiGraph:\n    for target_step_parsed_selector in target_step_parsed_selectors:\n        execution_graph = add_edge_for_step(\n            execution_graph=execution_graph,\n            source_step_selector=source_step_selector,\n            target_step_parsed_selector=target_step_parsed_selector,\n        )\n    return execution_graph\n\n\ndef add_edge_for_step(\n    execution_graph: DiGraph,\n    source_step_selector: str,\n    target_step_parsed_selector: ParsedSelector,\n) -> DiGraph:\n    target_step_selector = get_step_selector_from_its_output(\n        step_output_selector=target_step_parsed_selector.value\n    )\n    verify_edge_is_created_between_existing_nodes(\n        execution_graph=execution_graph,\n        start=source_step_selector,\n        end=target_step_selector,\n    )\n    if is_step_selector(target_step_parsed_selector.value):\n        return establish_control_flow_edge(\n            source_step_selector=source_step_selector,\n            target_step_parsed_selector=target_step_parsed_selector,\n            execution_graph=execution_graph,\n        )\n    if is_input_selector(target_step_parsed_selector.value):\n        input_node_compilation_data = node_as(\n            execution_graph=execution_graph,\n            node=target_step_parsed_selector.value,\n            expected_type=InputNode,\n        )\n        actual_input_kind = input_node_compilation_data.input_manifest.kind\n    else:\n        other_step_compilation_data = node_as(\n            execution_graph=execution_graph,\n            node=target_step_selector,\n            expected_type=StepNode,\n        )\n        source_step_compilation_data = node_as(\n            execution_graph=execution_graph,\n            node=source_step_selector,\n            expected_type=StepNode,\n        )\n        actual_input_kind = get_kind_of_value_provided_in_step_output(\n            step_manifest=other_step_compilation_data.step_manifest,\n            step_property=get_last_chunk_of_selector(\n                selector=target_step_parsed_selector.value\n            ),\n            source_step_manifest=source_step_compilation_data.step_manifest,\n        )\n    expected_input_kind = list(\n        itertools.chain.from_iterable(\n            ref.kind\n            for ref in target_step_parsed_selector.definition.allowed_references\n        )\n    )\n    error_message = (\n        f\"Failed to validate reference provided for step: {source_step_selector} regarding property: \"\n        f\"{target_step_parsed_selector.definition.property_name} with value: {target_step_parsed_selector.value}. \"\n        f\"Allowed kinds of references for this property: {list(set(e.name for e in expected_input_kind))}. \"\n        f\"Types of output for referred property: \"\n        f\"{list(set(a.name if isinstance(a, Kind) else a for a in actual_input_kind))}\"\n    )\n    validate_reference_kinds(\n        expected=expected_input_kind,\n        actual=actual_input_kind,\n        error_message=error_message,\n    )\n    if execution_graph.has_edge(target_step_selector, source_step_selector):\n        edge_data = execution_graph.edges[(target_step_selector, source_step_selector)]\n        if STEP_INPUT_SELECTORS_PROPERTY not in edge_data:\n            edge_data[STEP_INPUT_SELECTORS_PROPERTY] = []\n        edge_data[STEP_INPUT_SELECTORS_PROPERTY].append(\n            target_step_parsed_selector,\n        )\n    else:\n        execution_graph.add_edge(\n            target_step_selector,\n            source_step_selector,\n            **{STEP_INPUT_SELECTORS_PROPERTY: [target_step_parsed_selector]},\n        )\n    return execution_graph\n\n\ndef establish_control_flow_edge(\n    source_step_selector: str,\n    target_step_parsed_selector: ParsedSelector,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    if not step_definition_allows_control_flow_references(\n        parsed_selector=target_step_parsed_selector\n    ):\n        raise ExecutionGraphStructureError(\n            public_message=f\"Detected reference to other step in manifest of step {source_step_selector}. \"\n            f\"This is not allowed, as step manifest does not define any properties of type `StepSelector` \"\n            f\"allowing for defining connections between steps that represent flow control in `workflows`.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    target_step_selector = get_step_selector_from_its_output(\n        step_output_selector=target_step_parsed_selector.value\n    )\n    source_compilation_data = node_as(\n        execution_graph=execution_graph,\n        node=source_step_selector,\n        expected_type=StepNode,\n    )\n    target_compilation_data = node_as(\n        execution_graph=execution_graph,\n        node=target_step_selector,\n        expected_type=StepNode,\n    )\n    nodes_categories = {\n        source_compilation_data.node_category,\n        target_compilation_data.node_category,\n    }\n    if nodes_categories != {NodeCategory.STEP_NODE}:\n        raise ExecutionGraphStructureError(\n            public_message=f\"Attempted to create flow-control connection between workflow nodes: \"\n            f\"{source_step_selector} and {target_step_selector}, one of which is not denoted\"\n            f\"as step node.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    execution_graph.add_edge(\n        source_step_selector,\n        target_step_selector,\n    )\n    if target_step_selector in source_compilation_data.child_execution_branches:\n        raise ExecutionGraphStructureError(\n            public_message=f\"While establishing flow-control connection between source `{source_step_selector}` \"\n            f\"and target `{target_step_selector}` it was discovered that source step defines\"\n            f\"control flow transition into target one more than once, which is not allowed as \"\n            f\"that situation creates ambiguity in selecting execution branch.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    execution_branch_name = f\"Branch[{source_step_selector} -> {target_step_parsed_selector.definition.property_name}]\"\n    source_compilation_data.child_execution_branches[target_step_selector] = (\n        execution_branch_name\n    )\n    target_compilation_data.execution_branches_impacting_inputs.add(\n        execution_branch_name\n    )\n    return execution_graph\n\n\ndef step_definition_allows_control_flow_references(\n    parsed_selector: ParsedSelector,\n) -> bool:\n    return any(\n        definition.selected_element == STEP_AS_SELECTED_ELEMENT\n        for definition in parsed_selector.definition.allowed_references\n    )\n\n\ndef get_kind_of_value_provided_in_step_output(\n    step_manifest: WorkflowBlockManifest,\n    step_property: str,\n    source_step_manifest: WorkflowBlockManifest,\n) -> List[Kind]:\n    referred_node_outputs = step_manifest.get_actual_outputs()\n    actual_kind = []\n    matched_property = False\n    for output in referred_node_outputs:\n        if output.name != step_property:\n            continue\n        matched_property = True\n        actual_kind.extend(output.kind)\n    if not matched_property:\n        property_name = get_property_with_invalid_selector(\n            manifest=source_step_manifest,\n            step_property=step_property,\n        )\n        raise ExecutionGraphStructureError(\n            public_message=f\"Found reference to non-existing property `{step_property}` of step `{step_manifest.name}`.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=source_step_manifest.name,\n                    block_type=source_step_manifest.type,\n                    property_name=property_name,\n                    property_details=f\"'{step_manifest.name}.{step_property}' is an invalid reference\",\n                )\n            ],\n        )\n    return actual_kind\n\n\ndef add_edges_for_step_inputs(\n    execution_graph: DiGraph,\n    input_selectors: Set[str],\n    step_selector: str,\n) -> DiGraph:\n    for input_selector in input_selectors:\n        if is_step_output_selector(selector_or_value=input_selector):\n            input_selector = get_step_selector_from_its_output(\n                step_output_selector=input_selector\n            )\n        verify_edge_is_created_between_existing_nodes(\n            execution_graph=execution_graph,\n            start=input_selector,\n            end=step_selector,\n        )\n        execution_graph.add_edge(input_selector, step_selector)\n    return execution_graph\n\n\ndef add_edges_for_outputs(\n    workflow_definition: ParsedWorkflowDefinition,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for output in workflow_definition.outputs:\n        node_selector = output.selector\n        if is_step_output_selector(selector_or_value=node_selector):\n            node_selector = get_step_selector_from_its_output(\n                step_output_selector=node_selector\n            )\n        output_selector = construct_output_selector(name=output.name)\n        verify_edge_is_created_between_existing_nodes(\n            execution_graph=execution_graph,\n            start=node_selector,\n            end=output_selector,\n        )\n        output_node_manifest = node_as(\n            execution_graph=execution_graph,\n            node=output_selector,\n            expected_type=OutputNode,\n        )\n        if is_step_output_selector(selector_or_value=output.selector):\n            step_manifest = execution_graph.nodes[node_selector][\n                NODE_COMPILATION_OUTPUT_PROPERTY\n            ].step_manifest\n            step_outputs = step_manifest.get_actual_outputs()\n            denote_output_node_kind_based_on_step_outputs(\n                output_selector=output.selector,\n                step_outputs=step_outputs,\n                output_node_manifest=output_node_manifest,\n            )\n        else:\n            input_manifest = node_as(\n                execution_graph=execution_graph,\n                node=node_selector,\n                expected_type=InputNode,\n            ).input_manifest\n            output_node_manifest.kind = copy(input_manifest.kind)\n        execution_graph.add_edge(node_selector, output_selector)\n    return execution_graph\n\n\ndef verify_edge_is_created_between_existing_nodes(\n    execution_graph: DiGraph,\n    start: str,\n    end: str,\n) -> None:\n    if not execution_graph.has_node(start) or not execution_graph.has_node(end):\n        invalid_block = start if not execution_graph.has_node(start) else end\n        referencing_block = end if invalid_block == start else start\n\n        step_type = None\n        property_name = None\n        if execution_graph.has_node(referencing_block):\n            if is_step_node(execution_graph, referencing_block):\n                step_manifest = node_as(\n                    execution_graph=execution_graph,\n                    node=referencing_block,\n                    expected_type=StepNode,\n                ).step_manifest\n                step_type = step_manifest.type\n                property_name = get_property_with_invalid_selector(\n                    manifest=step_manifest,\n                    step_property=invalid_block,\n                )\n\n        block_id = (\n            \"$outputs\"\n            if referencing_block.startswith(\"$outputs.\")\n            else get_last_chunk_of_selector(selector=referencing_block)\n        )\n        property_name = (\n            get_last_chunk_of_selector(selector=referencing_block)\n            if referencing_block.startswith(\"$outputs.\")\n            else property_name\n        )\n\n        is_input = is_input_selector(selector_or_value=invalid_block)\n        raise InvalidReferenceTargetError(\n            public_message=f\"Workflow references '{invalid_block}' which points to a non-existent {is_input and 'input parameter' or 'block'}.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=block_id,\n                    block_type=step_type,\n                    property_name=property_name,\n                    property_details=f\"Invalid reference to {invalid_block}\",\n                ),\n            ],\n        )\n\n\ndef denote_output_node_kind_based_on_step_outputs(\n    output_selector: str,\n    step_outputs: List[OutputDefinition],\n    output_node_manifest: OutputNode,\n) -> None:\n    selected_output_name = get_last_chunk_of_selector(selector=output_selector)\n    kinds_for_outputs = {output.name: output.kind for output in step_outputs}\n\n    if selected_output_name == \"*\":\n        output_node_manifest.kind = deepcopy(kinds_for_outputs)\n        return None\n    if selected_output_name not in kinds_for_outputs:\n        output_name = output_node_manifest.output_manifest.name\n\n        raise InvalidReferenceTargetError(\n            public_message=f\"Workflow output references '{output_selector}' which points to a non-existent block property.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=\"$outputs\",\n                    property_name=output_name,\n                    property_details=f\"Invalid reference to {output_selector}\",\n                ),\n            ],\n        )\n    output_node_manifest.kind = copy(kinds_for_outputs[selected_output_name])\n    return None\n\n\ndef denote_data_flow_in_workflow(\n    execution_graph: DiGraph,\n    parsed_workflow_definition: ParsedWorkflowDefinition,\n) -> nx.DiGraph:\n    block_manifest_by_step_name = {\n        step.name: step for step in parsed_workflow_definition.steps\n    }\n    super_input_node = \"<super-input>\"\n    execution_graph = add_super_input_node_in_execution_graph(\n        execution_graph=execution_graph,\n        super_input_node=super_input_node,\n    )\n    execution_graph.nodes[super_input_node][NODE_COMPILATION_OUTPUT_PROPERTY] = (\n        InputNode(\n            node_category=NodeCategory.INPUT_NODE,\n            name=super_input_node,\n            selector=f\"$inputs.{super_input_node}\",\n            data_lineage=[],\n            input_manifest=None,  # this is expected never to be reached\n        )\n    )\n    top_level_data_lineage = set()\n    for node in traverse_graph_ensuring_parents_are_reached_first(\n        graph=execution_graph,\n        start_node=super_input_node,\n    ):\n        execution_graph = denote_data_flow_for_node(\n            execution_graph=execution_graph,\n            node=node,\n            block_manifest_by_step_name=block_manifest_by_step_name,\n            on_top_level_lineage_denoted=lambda element: top_level_data_lineage.add(\n                element\n            ),\n        )\n    execution_graph.remove_node(super_input_node)\n    execution_graph.graph[TOP_LEVEL_LINEAGES_KEY] = top_level_data_lineage\n    return execution_graph\n\n\ndef denote_data_flow_for_node(\n    execution_graph: DiGraph,\n    node: str,\n    block_manifest_by_step_name: Dict[str, WorkflowBlockManifest],\n    on_top_level_lineage_denoted: Callable[[str], None],\n) -> DiGraph:\n    if is_input_node(execution_graph=execution_graph, node=node):\n        # everything already set there, in the previous stage of compilation\n        return execution_graph\n    if is_step_node(execution_graph=execution_graph, node=node):\n        step_name = get_last_chunk_of_selector(selector=node)\n        if step_name not in block_manifest_by_step_name:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler expected manifest for the step: {step_name} to be registered \"\n                f\"but this condition is not met. This is most likely the bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | retrieving_predecessors_for_output\",\n            )\n        manifest = block_manifest_by_step_name[step_name]\n        return denote_data_flow_for_step(\n            execution_graph=execution_graph,\n            node=node,\n            manifest=manifest,\n            on_top_level_lineage_denoted=on_top_level_lineage_denoted,\n        )\n    if is_output_node(execution_graph=execution_graph, node=node):\n        # output is allowed to have exactly one predecessor\n        output_predecessors = list(execution_graph.predecessors(node))\n        if len(output_predecessors) != 1:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler expected each output in compiled graph to have one predecessor, \"\n                f\"but this condition is not met for node {node}. This is most likely the bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | retrieving_predecessors_for_output\",\n            )\n        predecessor_node = output_predecessors[0]\n        predecessor_node_data = node_as(\n            execution_graph=execution_graph,\n            node=predecessor_node,\n            expected_type=ExecutionGraphNode,\n        )\n        predecessor_node_lineage = predecessor_node_data.data_lineage\n        output_node_data = node_as(\n            execution_graph=execution_graph,\n            node=node,\n            expected_type=OutputNode,\n        )\n        output_node_data.data_lineage = predecessor_node_lineage\n        return execution_graph\n    raise AssumptionError(\n        f\"Workflow Compiler encountered node: {node} which cannot be classified as known node type. \"\n        f\"This is most likely the bug. Contact Roboflow team through github issues \"\n        f\"(https://github.com/roboflow/inference/issues) providing full \"\n        f\"context of the problem - including workflow definition you use.\",\n        context=\"workflow_compilation | execution_graph_construction | denoting_data_flow_for_step\",\n    )\n\n\ndef denote_data_flow_for_step(\n    execution_graph: DiGraph,\n    node: str,\n    manifest: WorkflowBlockManifest,\n    on_top_level_lineage_denoted: Callable[[str], None],\n) -> DiGraph:\n    all_control_flow_predecessors, all_non_control_flow_predecessors = (\n        separate_control_flow_predecessors_from_data_providers(\n            execution_graph=execution_graph, node=node\n        )\n    )\n    input_data = build_input_data_for_step(\n        manifest=manifest,\n        step_node=node,\n        data_providing_predecessors=all_non_control_flow_predecessors,\n        execution_graph=execution_graph,\n    )\n    step_name = get_last_chunk_of_selector(node)\n    step_node_data = node_as(\n        execution_graph=execution_graph,\n        node=node,\n        expected_type=StepNode,\n    )\n    parsed_step_input_selectors: List[ParsedSelector] = execution_graph.nodes[node][\n        PARSED_NODE_INPUT_SELECTORS_PROPERTY\n    ]\n    batch_compatibility_of_properties = retrieve_batch_compatibility_of_input_selectors(\n        input_selectors=parsed_step_input_selectors\n    )\n    scalar_parameters_to_be_batched = (\n        verify_declared_batch_compatibility_against_actual_inputs(\n            node=node,\n            step_node_data=step_node_data,\n            input_data=input_data,\n            batch_compatibility_of_properties=batch_compatibility_of_properties,\n        )\n    )\n    input_dimensionality_offsets = manifest.get_input_dimensionality_offsets()\n    verify_step_input_dimensionality_offsets(\n        step_name=step_name,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n    )\n    inputs_dimensionalities = get_inputs_dimensionalities(\n        step_name=step_name,\n        step_type=manifest.type,\n        input_data=input_data,\n        scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n    )\n    logger.debug(\n        f\"For step: {node}, detected the following input dimensionalities: {inputs_dimensionalities}\"\n    )\n    parameters_with_batch_inputs = grab_parameters_defining_batch_inputs(\n        inputs_dimensionalities=inputs_dimensionalities,\n    )\n    dimensionality_reference_property = manifest.get_dimensionality_reference_property()\n    output_dimensionality_offset = manifest.get_output_dimensionality_offset()\n    verify_step_input_dimensionality_offsets(\n        step_name=step_name,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n    )\n    verify_output_offset(\n        step_name=step_name,\n        parameters_with_batch_inputs=parameters_with_batch_inputs,\n        dimensionality_reference_property=dimensionality_reference_property,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n        output_dimensionality_offset=output_dimensionality_offset,\n    )\n    verify_input_data_dimensionality(\n        step_name=step_name,\n        step_type=manifest.type,\n        dimensionality_reference_property=dimensionality_reference_property,\n        inputs_dimensionalities=inputs_dimensionalities,\n        dimensionality_offstes=input_dimensionality_offsets,\n    )\n    all_data_derived_lineages = get_input_data_lineage_excluding_auto_batch_casting(\n        step_name=step_name,\n        input_data=input_data,\n        scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n    )\n    all_control_flow_lineages = get_lineage_derived_from_control_flow(\n        control_flow_steps_selectors=all_control_flow_predecessors,\n        execution_graph=execution_graph,\n    )\n    verify_compatibility_of_input_data_lineage_with_control_flow_lineage(\n        step_name=step_name,\n        inputs_lineage=all_data_derived_lineages,\n        control_flow_steps_selectors=all_control_flow_predecessors,\n        execution_graph=execution_graph,\n    )\n    step_node_data.input_data = input_data\n    step_node_data.dimensionality_reference_property = dimensionality_reference_property\n    step_node_data.control_flow_lineage_dims = [\n        len(_lineage) for _lineage in all_control_flow_lineages if _lineage\n    ]\n    step_node_data.batch_oriented_parameters = parameters_with_batch_inputs\n    if not all_data_derived_lineages and not all_control_flow_lineages:\n        if manifest.get_output_dimensionality_offset() > 0:\n            # brave decision to open a Pandora box\n            data_lineage = [node]\n        else:\n            data_lineage = []\n        control_flow_lineage_support = []\n    else:\n        data_lineage, control_flow_lineage_support = (\n            establish_batch_oriented_step_lineage(\n                step_selector=node,\n                all_data_derived_lineages=all_data_derived_lineages,\n                all_control_flow_lineages=all_control_flow_lineages,\n                input_data=input_data,\n                dimensionality_reference_property=dimensionality_reference_property,\n                output_dimensionality_offset=output_dimensionality_offset,\n            )\n        )\n    step_node_data.step_execution_dimensionality = (\n        establish_step_execution_dimensionality(\n            inputs_dimensionalities=inputs_dimensionalities,\n            control_flow_lineage_support=control_flow_lineage_support,\n            output_dimensionality_offset=output_dimensionality_offset,\n        )\n    )\n    lineage_supports = get_lineage_support_for_auto_batch_casted_parameters(\n        input_dimensionalities=inputs_dimensionalities,\n        all_lineages_of_batch_parameters=all_data_derived_lineages,\n        scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n    )\n    step_node_data.auto_batch_casting_lineage_supports = lineage_supports\n    step_node_data.control_flow_lineage_support = control_flow_lineage_support\n    if data_lineage:\n        on_top_level_lineage_denoted(data_lineage[0])\n    step_node_data.data_lineage = data_lineage\n    return execution_graph\n\n\ndef _collect_unique_control_flow_lineages_with_step_mapping(\n    control_flow_steps_selectors: List[str],\n    execution_graph: nx.DiGraph,\n) -> Tuple[List[List[str]], Dict[int, List[str]]]:\n    \"\"\"\n    Collect data lineages from control flow steps and deduplicate by lineage id.\n\n    For each given control flow step selector, reads its data_lineage from the\n    execution graph. Returns unique non-empty lineages (by identify_lineage id)\n    and a mapping from lineage id to every step selector that produced that\n    lineage (used e.g. for error reporting when lineage is incompatible).\n\n    Args:\n        control_flow_steps_selectors: Step selectors (node ids) of control\n            flow steps whose data_lineage is to be collected.\n        execution_graph: The workflow execution graph containing step nodes\n            and their data_lineage.\n\n    Returns:\n        A tuple of (unique_lineages, lineage_id_to_step_selectors):\n        - unique_lineages: list of distinct non-empty data lineages.\n        - lineage_id_to_step_selectors: map from lineage id to list of step\n          selectors whose data_lineage has that id (includes empty lineages).\n    \"\"\"\n    unique_lineages: List[List[str]] = []\n    seen_lineage_ids: Set[int] = set()\n    lineage_id_to_step_selectors: Dict[int, List[str]] = defaultdict(list)\n\n    for step_selector in control_flow_steps_selectors:\n        step_data = node_as(\n            execution_graph=execution_graph,\n            node=step_selector,\n            expected_type=StepNode,\n        )\n        lineage = step_data.data_lineage\n        lineage_id = identify_lineage(lineage)\n        lineage_id_to_step_selectors[lineage_id].append(step_selector)\n        if lineage and lineage_id not in seen_lineage_ids:\n            seen_lineage_ids.add(lineage_id)\n            unique_lineages.append(lineage)\n\n    return unique_lineages, dict(lineage_id_to_step_selectors)\n\n\ndef get_lineage_derived_from_control_flow(\n    control_flow_steps_selectors: List[str],\n    execution_graph: nx.DiGraph,\n) -> List[List[str]]:\n    \"\"\"\n    Return unique non-empty data lineages from the given control flow steps.\n\n    Each lineage is taken from the step's data_lineage in the execution graph.\n    Lineages are deduplicated by lineage id (see identify_lineage); empty\n    lineages are omitted. Used when establishing batch-oriented step lineage.\n\n    Args:\n        control_flow_steps_selectors: Step selectors (node ids) of control\n            flow steps whose data_lineage is to be collected.\n        execution_graph: The workflow execution graph containing step nodes\n            and their data_lineage.\n\n    Returns:\n        List of distinct non-empty data lineages, one per unique lineage id.\n    \"\"\"\n    unique_lineages, _ = _collect_unique_control_flow_lineages_with_step_mapping(\n        control_flow_steps_selectors=control_flow_steps_selectors,\n        execution_graph=execution_graph,\n    )\n    return unique_lineages\n\n\ndef separate_control_flow_predecessors_from_data_providers(\n    execution_graph: DiGraph,\n    node: str,\n) -> Tuple[List[str], List[str]]:\n    all_predecessors = list(execution_graph.predecessors(node))\n    all_control_flow_predecessors = [\n        predecessor\n        for predecessor in all_predecessors\n        if is_control_flow_step(execution_graph=execution_graph, node=predecessor)\n    ]\n    all_non_control_flow_predecessors = [\n        predecessor\n        for predecessor in all_predecessors\n        if not is_control_flow_step(execution_graph=execution_graph, node=predecessor)\n    ]\n    return all_control_flow_predecessors, all_non_control_flow_predecessors\n\n\ndef build_input_data_for_step(\n    manifest: WorkflowBlockManifest,\n    step_node: str,\n    data_providing_predecessors: List[str],\n    execution_graph: DiGraph,\n) -> StepInputData:\n    predecessors_by_property_name = get_predecessors_for_step_manifest_properties(\n        execution_graph=execution_graph,\n        step_node=step_node,\n        data_providing_predecessors=data_providing_predecessors,\n    )\n    manifest_fields_values = get_manifest_fields_values(step_manifest=manifest)\n    result = {}\n    for name, value in manifest_fields_values.items():\n        result[name] = build_input_property(\n            step_node=step_node,\n            manifest_property_name=name,\n            manifest_property_value=value,\n            predecessors_by_property_name=predecessors_by_property_name,\n            execution_graph=execution_graph,\n        )\n    return result\n\n\ndef get_predecessors_for_step_manifest_properties(\n    execution_graph: DiGraph, step_node: str, data_providing_predecessors: List[str]\n) -> Dict[str, List[PropertyPredecessorDefinition]]:\n    predecessors_by_property_name = defaultdict(list)\n    for predecessor in data_providing_predecessors:\n        edge_data = execution_graph.edges[(predecessor, step_node)]\n        # STEP_INPUT_SELECTORS_PROPERTY is optional, as special <super-input> node may be directly\n        # connected to step\n        selectors_associated_to_edge: List[ParsedSelector] = edge_data.get(\n            STEP_INPUT_SELECTORS_PROPERTY, []\n        )\n        for selector_associated_to_edge in selectors_associated_to_edge:\n            definition = PropertyPredecessorDefinition(\n                predecessor_selector=predecessor,\n                parsed_selector=selector_associated_to_edge,\n            )\n            predecessors_by_property_name[\n                selector_associated_to_edge.definition.property_name\n            ].append(definition)\n    return predecessors_by_property_name\n\n\ndef build_input_property(\n    step_node: str,\n    manifest_property_name: str,\n    manifest_property_value: Any,\n    predecessors_by_property_name: Dict[str, List[PropertyPredecessorDefinition]],\n    execution_graph: DiGraph,\n) -> Union[StepInputDefinition, CompoundStepInputDefinition]:\n    if manifest_property_name not in predecessors_by_property_name:\n        return StaticStepInputDefinition(\n            parameter_specification=ParameterSpecification(\n                parameter_name=manifest_property_name,\n            ),\n            category=NodeInputCategory.STATIC_VALUE,\n            value=manifest_property_value,\n        )\n    if isinstance(manifest_property_value, dict):\n        return build_nested_dictionary_for_input_property(\n            step_node=step_node,\n            manifest_property_name=manifest_property_name,\n            manifest_property_value=manifest_property_value,\n            predecessors_definitions=predecessors_by_property_name[\n                manifest_property_name\n            ],\n            execution_graph=execution_graph,\n        )\n    if isinstance(manifest_property_value, list):\n        return build_nested_list_for_input_property(\n            step_node=step_node,\n            manifest_property_name=manifest_property_name,\n            manifest_property_value=manifest_property_value,\n            predecessors_definitions=predecessors_by_property_name[\n                manifest_property_name\n            ],\n            execution_graph=execution_graph,\n        )\n    matching_predecessors_data = predecessors_by_property_name[manifest_property_name]\n    if len(matching_predecessors_data) != 1:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler deduced that property `{manifest_property_name}` of step `{step_node}` \"\n            f\"should be fed with data coming from exactly one execution graph node, but found \"\n            f\"{len(matching_predecessors_data)} data sources. This is most likely the bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n        )\n    predecessor_selector, predecessor_parsed_selector = (\n        matching_predecessors_data[0].predecessor_selector,\n        matching_predecessors_data[0].parsed_selector,\n    )\n    if is_input_node(execution_graph=execution_graph, node=predecessor_selector):\n        predecessor_node_data = node_as(\n            execution_graph=execution_graph,\n            node=matching_predecessors_data[0].predecessor_selector,\n            expected_type=InputNode,\n        )\n        category = (\n            NodeInputCategory.BATCH_INPUT_PARAMETER\n            if predecessor_node_data.is_batch_oriented()\n            else NodeInputCategory.NON_BATCH_INPUT_PARAMETER\n        )\n        return DynamicStepInputDefinition(\n            parameter_specification=ParameterSpecification(\n                parameter_name=manifest_property_name,\n            ),\n            category=category,\n            data_lineage=predecessor_node_data.data_lineage,\n            selector=predecessor_node_data.selector,\n        )\n    if is_step_node(execution_graph=execution_graph, node=predecessor_selector):\n        predecessor_node_data = node_as(\n            execution_graph=execution_graph,\n            node=matching_predecessors_data[0].predecessor_selector,\n            expected_type=StepNode,\n        )\n        category = (\n            NodeInputCategory.BATCH_STEP_OUTPUT\n            if predecessor_node_data.output_dimensionality > 0\n            else NodeInputCategory.NON_BATCH_STEP_OUTPUT\n        )\n        return DynamicStepInputDefinition(\n            parameter_specification=ParameterSpecification(\n                parameter_name=manifest_property_name,\n            ),\n            category=category,\n            data_lineage=predecessor_node_data.data_lineage,\n            selector=predecessor_parsed_selector.value,\n        )\n    raise AssumptionError(\n        public_message=f\"Workflow Compiler for property `{manifest_property_name}` of step `{step_node}` \"\n        f\"found data providing predecessor `{predecessor_selector}` which has unsupported step type.\"\n        f\"This is most likely the bug. \"\n        f\"Contact Roboflow team through github issues \"\n        f\"(https://github.com/roboflow/inference/issues) providing full \"\n        f\"context of the problem - including workflow definition you use.\",\n        context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n    )\n\n\ndef build_nested_dictionary_for_input_property(\n    step_node: str,\n    manifest_property_name: str,\n    manifest_property_value: dict,\n    predecessors_definitions: List[PropertyPredecessorDefinition],\n    execution_graph: DiGraph,\n) -> DictOfStepInputDefinitions:\n    nested_property_name2data: Dict[Optional[str], PropertyPredecessorDefinition] = {\n        predecessor_definition.parsed_selector.key: predecessor_definition\n        for predecessor_definition in predecessors_definitions\n    }\n    result = {}\n    for nested_dict_key, nested_dict_value in manifest_property_value.items():\n        if nested_dict_key not in nested_property_name2data:\n            result[nested_dict_key] = StaticStepInputDefinition(\n                parameter_specification=ParameterSpecification(\n                    parameter_name=manifest_property_name,\n                    nested_element_key=nested_dict_key,\n                ),\n                category=NodeInputCategory.STATIC_VALUE,\n                value=nested_dict_value,\n            )\n            continue\n        referred_node_selector = nested_property_name2data[\n            nested_dict_key\n        ].predecessor_selector\n        referred_node_parsed_selector = nested_property_name2data[\n            nested_dict_key\n        ].parsed_selector\n        if is_input_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=InputNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_INPUT_PARAMETER\n                if predecessor_node_data.is_batch_oriented()\n                else NodeInputCategory.NON_BATCH_INPUT_PARAMETER\n            )\n            result[nested_dict_key] = DynamicStepInputDefinition(\n                parameter_specification=ParameterSpecification(\n                    parameter_name=manifest_property_name,\n                    nested_element_key=nested_dict_key,\n                ),\n                category=category,\n                data_lineage=predecessor_node_data.data_lineage,\n                selector=predecessor_node_data.selector,\n            )\n            continue\n        if is_step_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=StepNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_STEP_OUTPUT\n                if predecessor_node_data.output_dimensionality > 0\n                else NodeInputCategory.NON_BATCH_STEP_OUTPUT\n            )\n            result[nested_dict_key] = DynamicStepInputDefinition(\n                parameter_specification=ParameterSpecification(\n                    parameter_name=manifest_property_name,\n                    nested_element_key=nested_dict_key,\n                ),\n                category=category,\n                data_lineage=predecessor_node_data.data_lineage,\n                selector=referred_node_parsed_selector.value,\n            )\n            continue\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for property `{manifest_property_name}` of step `{step_node}` \"\n            f\"found data providing predecessor `{referred_node_selector}` which has \"\n            f\"unsupported step type (key: {nested_dict_key} of nested data dictionary). \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n        )\n    return DictOfStepInputDefinitions(\n        name=manifest_property_name,\n        nested_definitions=result,\n    )\n\n\ndef get_manifest_fields_values(step_manifest: WorkflowBlockManifest) -> Dict[str, Any]:\n    result = {}\n    for field in step_manifest.model_fields:\n        if field in EXCLUDED_FIELDS:\n            continue\n        result[field] = getattr(step_manifest, field)\n    return result\n\n\ndef build_nested_list_for_input_property(\n    step_node: str,\n    manifest_property_name: str,\n    manifest_property_value: list,\n    predecessors_definitions: List[PropertyPredecessorDefinition],\n    execution_graph: DiGraph,\n) -> ListOfStepInputDefinitions:\n    nested_index2data: Dict[Optional[int], PropertyPredecessorDefinition] = {\n        e.parsed_selector.index: e for e in predecessors_definitions\n    }\n    result = []\n    for index, element in enumerate(manifest_property_value):\n        if index not in nested_index2data:\n            result.append(\n                StaticStepInputDefinition(\n                    parameter_specification=ParameterSpecification(\n                        parameter_name=manifest_property_name,\n                        nested_element_index=index,\n                    ),\n                    category=NodeInputCategory.STATIC_VALUE,\n                    value=element,\n                )\n            )\n            continue\n        referred_node_selector = nested_index2data[index].predecessor_selector\n        referred_node_parsed_selector = nested_index2data[index].parsed_selector\n        if is_input_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=InputNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_INPUT_PARAMETER\n                if predecessor_node_data.is_batch_oriented()\n                else NodeInputCategory.NON_BATCH_INPUT_PARAMETER\n            )\n            result.append(\n                DynamicStepInputDefinition(\n                    parameter_specification=ParameterSpecification(\n                        parameter_name=manifest_property_name,\n                        nested_element_index=index,\n                    ),\n                    category=category,\n                    data_lineage=predecessor_node_data.data_lineage,\n                    selector=predecessor_node_data.selector,\n                )\n            )\n            continue\n        if is_step_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=StepNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_STEP_OUTPUT\n                if predecessor_node_data.output_dimensionality > 0\n                else NodeInputCategory.NON_BATCH_STEP_OUTPUT\n            )\n            result.append(\n                DynamicStepInputDefinition(\n                    parameter_specification=ParameterSpecification(\n                        parameter_name=manifest_property_name,\n                        nested_element_index=index,\n                    ),\n                    category=category,\n                    data_lineage=predecessor_node_data.data_lineage,\n                    selector=referred_node_parsed_selector.value,\n                )\n            )\n            continue\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for property `{manifest_property_name}` of step `{step_node}` \"\n            f\"found data providing predecessor `{referred_node_selector}` which has \"\n            f\"unsupported step type (index: {index} of nested data list). \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n        )\n    return ListOfStepInputDefinitions(\n        name=manifest_property_name,\n        nested_definitions=result,\n    )\n\n\ndef verify_step_input_dimensionality_offsets(\n    step_name: str,\n    input_dimensionality_offsets: Dict[str, int],\n) -> None:\n    min_offset, max_offset = None, None\n    for offset in input_dimensionality_offsets.values():\n        if min_offset is None or offset < min_offset:\n            min_offset = offset\n        if max_offset is None or offset > max_offset:\n            max_offset = offset\n    if min_offset is None or max_offset is None:\n        return None\n    if min_offset < 0 or max_offset < 0:\n        raise BlockInterfaceError(\n            public_message=f\"Offsets could not be negative, but block defining step: {step_name} defines that values.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_input_offset_definitions\",\n        )\n    if abs(max_offset - min_offset) > 1:\n        raise BlockInterfaceError(\n            public_message=\"Offsets of input parameters could not differ more than 1, but block defining step {step_name} \"\n            f\"violates that rule.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_input_offset_definitions\",\n        )\n\n\ndef verify_output_offset(\n    step_name: str,\n    parameters_with_batch_inputs: Set[str],\n    input_dimensionality_offsets: Dict[str, int],\n    dimensionality_reference_property: Optional[str],\n    output_dimensionality_offset: int,\n) -> None:\n    if not parameters_with_batch_inputs and output_dimensionality_offset < 0:\n        raise StepInputDimensionalityError(\n            public_message=f\"Block defining step {step_name} defines negative dimensionality offset while only \"\n            f\"scalar inputs being provided - the block cannot run as there is no dimension to collapse.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if (\n        dimensionality_reference_property is not None\n        and dimensionality_reference_property not in parameters_with_batch_inputs\n    ):\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} defines dimensionality reference property \"\n            f\"which is not in scope of parameters bring batch-oriented input, which makes it impossible \"\n            f\"to use as reference for output dimensionality.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if output_dimensionality_offset not in {-1, 0, 1}:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} defines output dimensionality offset \"\n            f\"being {output_dimensionality_offset}, whereas it is only possible for that offset being \"\n            f\"in set [-1, 0, 1].\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    different_offsets = {o for o in input_dimensionality_offsets.values()}\n    if len(parameters_with_batch_inputs) != len(input_dimensionality_offsets):\n        # assumption of default offset being zero - and this one does not need to be manifested\n        # by block\n        different_offsets.add(0)\n    if 0 not in different_offsets and parameters_with_batch_inputs:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} explicitly defines input dimensionalities offsets\"\n            f\"with {input_dimensionality_offsets}, but the definition lack 0-level input, which is \"\n            f\"not allowed, as in this scenario offsets could be adjusted to include 0\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if len(different_offsets) > 1 and dimensionality_reference_property is None:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} explicitly defines input dimensionality \"\n            f\"offsets {input_dimensionality_offsets}. In this scenario it is required to provide dimensionality \"\n            f\"reference property.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if len(different_offsets) > 1 and output_dimensionality_offset != 0:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} explicitly defines input dimensionality \"\n            f\"offsets {input_dimensionality_offsets} and output dimensionality offset {output_dimensionality_offset} \"\n            f\"where the latter is not 0, but for inputs differing with dimensionality it is only possible to keep \"\n            f\"output dimensionality the same and point reference parameter.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n\n\ndef verify_input_data_dimensionality(\n    step_name: str,\n    step_type: str,\n    dimensionality_reference_property: Optional[str],\n    inputs_dimensionalities: Dict[str, Set[int]],\n    dimensionality_offstes: Dict[str, int],\n) -> None:\n    parameter_name2dimensionality_specification = (\n        grab_input_data_dimensionality_specifications(\n            step_name=step_name,\n            inputs_dimensionalities=inputs_dimensionalities,\n            dimensionality_offstes=dimensionality_offstes,\n        )\n    )\n    if not parameter_name2dimensionality_specification:\n        # nothing to check if no batch-oriented inputs\n        return None\n    different_dimensionalities_of_parameters = {\n        specification.actual_dimensionality\n        for specification in parameter_name2dimensionality_specification.values()\n    }\n    if dimensionality_reference_property is None:\n        if len(different_dimensionalities_of_parameters) > 1:\n            parameter2dimensionality = {\n                k: e.actual_dimensionality\n                for k, e in parameter_name2dimensionality_specification.items()\n            }\n            raise StepInputDimensionalityError(\n                public_message=f\"Block defining step {step_name} does not define dimensionality reference property, \"\n                f\"which means that all batch-oriented parameters must be at the same dimensionality level, \"\n                f\"but detected the following dimensionalities for parameters {parameter2dimensionality}\",\n                context=\"workflow_compilation | execution_graph_construction | denoting_step_inputs_dimensionality\",\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=step_name,\n                        block_type=step_type,\n                        block_details=f\"Dimensionality of input parameters doesn't match: {parameter2dimensionality}\",\n                    )\n                ],\n            )\n        return None\n    reference_specification = parameter_name2dimensionality_specification[\n        dimensionality_reference_property\n    ]\n    expected_dimensionalities = {\n        property_name: (e.expected_offset - reference_specification.expected_offset)\n        + reference_specification.actual_dimensionality\n        for property_name, e in parameter_name2dimensionality_specification.items()\n    }\n    if any(dim <= 0 for dim in expected_dimensionalities.values()):\n        raise StepInputDimensionalityError(\n            public_message=f\"Given the definition of block defining step {step_name} and data provided, \"\n            f\"the block would expect batch input dimensionality to be 0 or below, which is invalid.\",\n            context=\"workflow_compilation | execution_graph_construction | denoting_step_inputs_dimensionality\",\n        )\n    for property_name, expected_dimensionality in expected_dimensionalities.items():\n        actual_dimensionality = parameter_name2dimensionality_specification[\n            property_name\n        ].actual_dimensionality\n        if actual_dimensionality != expected_dimensionality:\n            raise StepInputDimensionalityError(\n                public_message=f\"Data fed into step `{step_name}` property `{property_name}` has \"\n                f\"actual dimensionality {actual_dimensionality}, \"\n                f\"when expected was {expected_dimensionality}\",\n                context=\"workflow_compilation | execution_graph_construction | denoting_step_inputs_dimensionality\",\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=step_name,\n                        block_type=step_type,\n                        property_name=property_name,\n                        property_details=f\"Expected dimensionality {expected_dimensionality}, but received dimensionality {actual_dimensionality}\",\n                    )\n                ],\n            )\n    return None\n\n\ndef grab_input_data_dimensionality_specifications(\n    step_name: str,\n    inputs_dimensionalities: Dict[str, Set[int]],\n    dimensionality_offstes: Dict[str, int],\n) -> Dict[str, InputDimensionalitySpecification]:\n    result = {}\n    for parameter_name, dimensionality in inputs_dimensionalities.items():\n        parameter_offset = dimensionality_offstes.get(parameter_name, 0)\n        non_zero_dimensionalities_for_parameter = {d for d in dimensionality if d > 0}\n        if len(non_zero_dimensionalities_for_parameter) > 1:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler for step: `{step_name}` and parameter: {parameter_name}\"\n                f\"found multiple different values of actual input dimensionalities: \"\n                f\"`{non_zero_dimensionalities_for_parameter}` which should be detected and addresses \"\n                f\"at earlier stages of compilation.\"\n                f\"This is most likely the bug. Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n            )\n        if non_zero_dimensionalities_for_parameter:\n            actual_dimensionality = next(iter(non_zero_dimensionalities_for_parameter))\n            result[parameter_name] = InputDimensionalitySpecification(\n                actual_dimensionality=actual_dimensionality,\n                expected_offset=parameter_offset,\n            )\n    return result\n\n\ndef verify_compatibility_of_input_data_lineage_with_control_flow_lineage(\n    step_name: str,\n    inputs_lineage: List[List[str]],\n    control_flow_steps_selectors: List[str],\n    execution_graph: DiGraph,\n) -> None:\n    \"\"\"\n    Ensure control flow steps' data lineage is compatible with the step's inputs.\n\n    Control flow steps that affect this step must operate on data that is\n    compatible with the data fed to the step; otherwise the step could never\n    execute. Compares unique control flow lineages against input lineage\n    prefixes and raises ControlFlowDefinitionError if any control flow lineage\n    is not covered by the inputs.\n\n    If inputs_lineage is empty, there is no sense to verify compatibility. The lineage of the\n    step should be established based on the control flow lineages.\n\n    Args:\n        step_name: Name of the step being verified (used in error messages).\n        inputs_lineage: Data lineages derived from the step's input data.\n        control_flow_steps_selectors: Step selectors of control flow steps\n            that affect this step's execution.\n        execution_graph: The workflow execution graph.\n\n    Raises:\n        ControlFlowDefinitionError: When a control flow step's lineage is not\n            compatible with the step's input lineage (step would never execute).\n    \"\"\"\n    (\n        batch_oriented_control_flow_lineages,\n        lineage_id2control_flow_steps,\n    ) = _collect_unique_control_flow_lineages_with_step_mapping(\n        control_flow_steps_selectors=control_flow_steps_selectors,\n        execution_graph=execution_graph,\n    )\n    if not inputs_lineage:\n        return\n\n    all_input_lineage_prefixes = get_all_batch_lineage_prefixes(lineages=inputs_lineage)\n    all_input_lineage_prefixes_hashes = {\n        identify_lineage(lineage=lineage) for lineage in all_input_lineage_prefixes\n    }\n    for control_flow_lineage in batch_oriented_control_flow_lineages:\n        control_flow_lineage_id = identify_lineage(lineage=control_flow_lineage)\n        if control_flow_lineage_id not in all_input_lineage_prefixes_hashes:\n            problematic_flow_control_steps = lineage_id2control_flow_steps[\n                control_flow_lineage_id\n            ]\n            raise ControlFlowDefinitionError(\n                public_message=f\"Step {step_name} execution is impacted by control flow outcome of the following \"\n                f\"steps {problematic_flow_control_steps} which make decision based on data that is \"\n                f\"not compatible with data fed to the step {step_name} - which would cause the step \"\n                f\"to never execute. This behaviour is invalid and prevented upfront by Workflows compiler.\",\n                context=\"workflow_compilation | execution_graph_construction | verification_of_control_flow_lineage\",\n            )\n\n\ndef get_all_batch_lineage_prefixes(lineages: List[List[str]]) -> List[List[str]]:\n    result = []\n    already_spotted = set()\n    for lineage in lineages:\n        lineage_prefixes = get_batch_lineage_prefixes(lineage=lineage)\n        for lineage_prefix in lineage_prefixes:\n            lineage_prefix_id = identify_lineage(lineage=lineage_prefix)\n            if lineage_prefix_id not in already_spotted:\n                already_spotted.add(lineage_prefix_id)\n                result.append(lineage_prefix)\n    return result\n\n\ndef get_batch_lineage_prefixes(lineage: List[str]) -> List[List[str]]:\n    if not lineage:\n        return []\n    result = []\n    prefix = []\n    for i in range(len(lineage)):\n        prefix.append(lineage[i])\n        result.append(copy(prefix))\n    return result\n\n\ndef get_inputs_dimensionalities(\n    step_name: str,\n    step_type: str,\n    input_data: StepInputData,\n    scalar_parameters_to_be_batched: Set[str],\n    input_dimensionality_offsets: Dict[str, int],\n) -> Dict[str, Set[int]]:\n    result = defaultdict(set)\n    dimensionalities_spotted = set()\n    offset_parameters = {\n        parameter: value\n        for parameter, value in input_dimensionality_offsets.items()\n        if value > 0\n    }\n    non_offset_parameters_dimensionality_values = set()\n    for property_name, input_definition in input_data.items():\n        if property_name in offset_parameters:\n            continue\n        if input_definition.is_compound_input():\n            for value in input_definition.iterate_through_definitions():\n                if value.is_batch_oriented():\n                    non_offset_parameters_dimensionality_values.add(\n                        value.get_dimensionality()\n                    )\n        elif input_definition.is_batch_oriented():\n            non_offset_parameters_dimensionality_values.add(\n                input_definition.get_dimensionality()\n            )\n    if len(non_offset_parameters_dimensionality_values) > 1:\n        raise StepInputDimensionalityError(\n            public_message=f\"For step {step_name} attempted to plug input data that are in different dimensions, \"\n            f\"whereas block defines the inputs to be equal in that terms.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_input_data\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=step_name,\n                    block_type=step_type,\n                    block_details=f\"Dimensionality of input parameters differs by more than 1. Detected dimensions: {dict(result)}\",\n                )\n            ],\n        )\n    non_offset_parameters_dimensionality_value = (\n        non_offset_parameters_dimensionality_values.pop()\n        if len(non_offset_parameters_dimensionality_values) > 0\n        else 1\n    )\n    for property_name, input_definition in input_data.items():\n        if input_definition.is_compound_input():\n            result[property_name] = get_compound_input_dimensionality(\n                step_name=step_name,\n                step_type=step_type,\n                property_name=property_name,\n                input_definition=input_definition,\n                scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n                non_offset_parameters_dimensionality_value=non_offset_parameters_dimensionality_value,\n                offset_parameters=offset_parameters,\n            )\n        else:\n            if property_name in scalar_parameters_to_be_batched:\n                if property_name not in offset_parameters:\n                    result[property_name] = {non_offset_parameters_dimensionality_value}\n                else:\n                    result[property_name] = (\n                        non_offset_parameters_dimensionality_value\n                        + offset_parameters[property_name]\n                    )\n            else:\n                result[property_name] = {input_definition.get_dimensionality()}\n        dimensionalities_spotted.update(result[property_name])\n    non_zero_dimensionalities_spotted = {d for d in dimensionalities_spotted if d != 0}\n    if len(non_zero_dimensionalities_spotted) > 0:\n        min_dim, max_dim = min(non_zero_dimensionalities_spotted), max(\n            non_zero_dimensionalities_spotted\n        )\n        if abs(max_dim - min_dim) > 1:\n            raise StepInputDimensionalityError(\n                public_message=f\"For step {step_name} attempted to plug input data differing in dimensionality more than 1\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_input_data\",\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=step_name,\n                        block_type=step_type,\n                        block_details=f\"Dimensionality of input parameters differs by more than 1. Detected dimensions: {dict(result)}\",\n                    )\n                ],\n            )\n    return result\n\n\ndef get_compound_input_dimensionality(\n    step_name: str,\n    property_name: str,\n    step_type: str,\n    input_definition: CompoundStepInputDefinition,\n    scalar_parameters_to_be_batched: Set[str],\n    offset_parameters: Dict[str, int],\n    non_offset_parameters_dimensionality_value: int,\n) -> Set[int]:\n    dimensionalities_spotted = set()\n    for definition in input_definition.iterate_through_definitions():\n        if (\n            property_name not in scalar_parameters_to_be_batched\n            or definition.is_batch_oriented()\n        ):\n            dimensionalities_spotted.add(definition.get_dimensionality())\n        elif property_name not in offset_parameters:\n            dimensionalities_spotted.add(non_offset_parameters_dimensionality_value)\n        else:\n            dimensionalities_spotted.add(\n                non_offset_parameters_dimensionality_value\n                + offset_parameters[property_name]\n            )\n    non_zero_dimensionalities = {e for e in dimensionalities_spotted if e != 0}\n    if len(non_zero_dimensionalities) > 1:\n        raise StepInputDimensionalityError(\n            public_message=f\"While evaluating compound property {property_name} of step {step_name}, \"\n            f\"detected multiple inputs of differing batch dimensionalities: {non_zero_dimensionalities}\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_input_data\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=step_name,\n                    block_type=step_type,\n                    property_name=property_name,\n                    property_details=f\"Detected multiple inputs of differing batch dimensionalities: {non_zero_dimensionalities}\",\n                )\n            ],\n        )\n    return dimensionalities_spotted\n\n\ndef grab_parameters_defining_batch_inputs(\n    inputs_dimensionalities: Dict[str, Set[int]],\n) -> Set[str]:\n    result = set()\n    for paremeter, dimensionalities in inputs_dimensionalities.items():\n        batch_dimensionalities = {d for d in dimensionalities if d > 0}\n        if len(batch_dimensionalities):\n            result.add(paremeter)\n    return result\n\n\ndef retrieve_batch_compatibility_of_input_selectors(\n    input_selectors: List[ParsedSelector],\n) -> Dict[str, Set[bool]]:\n    batch_compatibility_of_properties = defaultdict(set)\n    for parsed_selector in input_selectors:\n        for reference in parsed_selector.definition.allowed_references:\n            batch_compatibility_of_properties[\n                parsed_selector.definition.property_name\n            ].update(reference.points_to_batch)\n    return batch_compatibility_of_properties\n\n\ndef verify_declared_batch_compatibility_against_actual_inputs(\n    node: str,\n    step_node_data: StepNode,\n    input_data: StepInputData,\n    batch_compatibility_of_properties: Dict[str, Set[bool]],\n) -> Set[str]:\n    scalar_parameters_to_be_batched = set()\n    parameters_accepting_batches_and_scalars = set(\n        step_node_data.step_manifest.get_parameters_accepting_batches_and_scalars()\n    )\n    hardcoded_inputs_to_be_batch_compatible = set(\n        step_node_data.step_manifest.get_parameters_enforcing_auto_batch_casting()\n        + step_node_data.step_manifest.get_parameters_accepting_batches()\n    )\n    for property_name, input_definition in input_data.items():\n        if property_name not in batch_compatibility_of_properties:\n            actual_input_is_batch = {False}\n            if property_name in parameters_accepting_batches_and_scalars:\n                batch_compatibility = {True, False}\n            elif property_name in hardcoded_inputs_to_be_batch_compatible:\n                batch_compatibility = {True}\n            else:\n                continue\n        elif input_definition.is_compound_input():\n            actual_input_is_batch = {\n                element.is_batch_oriented()\n                for element in input_definition.iterate_through_definitions()\n            }\n            batch_compatibility = batch_compatibility_of_properties[property_name]\n        else:\n            actual_input_is_batch = {input_definition.is_batch_oriented()}\n            batch_compatibility = batch_compatibility_of_properties[property_name]\n        step_accepts_batch_input = step_node_data.step_manifest.accepts_batch_input()\n        if (\n            step_accepts_batch_input\n            and batch_compatibility == {False}\n            and True in actual_input_is_batch\n        ):\n            raise ExecutionGraphStructureError(\n                public_message=f\"Detected invalid reference plugged \"\n                f\"into property `{property_name}` of step `{node}` - the step \"\n                f\"property do not accept batch-oriented inputs, yet the input selector \"\n                f\"holds one - this indicates the problem with \"\n                f\"construction of your Workflow - usually the problem occurs when non-batch oriented \"\n                f\"step inputs are filled with outputs of batch-oriented steps or batch-oriented inputs.\",\n                context=\"workflow_compilation | execution_graph_construction\",\n            )\n        if batch_compatibility == {True} and False in actual_input_is_batch:\n            scalar_parameters_to_be_batched.add(property_name)\n    return scalar_parameters_to_be_batched\n\n\ndef get_input_data_lineage_excluding_auto_batch_casting(\n    step_name: str,\n    input_data: StepInputData,\n    scalar_parameters_to_be_batched: Set[str],\n) -> List[List[str]]:\n    lineage_deduplication_set = set()\n    lineages = []\n    for property_name, input_definition in input_data.items():\n        new_lineages_detected_within_property_data = get_lineage_for_input_property(\n            step_name=step_name,\n            property_name=property_name,\n            input_definition=input_definition,\n            lineage_deduplication_set=lineage_deduplication_set,\n        )\n        if (\n            property_name in scalar_parameters_to_be_batched\n            and len(new_lineages_detected_within_property_data) == 0\n        ):\n            continue\n        lineages.extend(new_lineages_detected_within_property_data)\n    if not lineages:\n        return lineages\n    verify_lineages(step_name=step_name, detected_lineages=lineages)\n    return lineages\n\n\ndef get_lineage_support_for_auto_batch_casted_parameters(\n    input_dimensionalities: Dict[str, Set[int]],\n    scalar_parameters_to_be_batched: Set[str],\n    all_lineages_of_batch_parameters: List[List[str]],\n) -> Dict[str, AutoBatchCastingConfig]:\n    longest_lineage_support = find_longest_lineage_support(\n        all_lineages_of_batch_parameters=all_lineages_of_batch_parameters,\n    )\n    result = {}\n    for parameter_name in scalar_parameters_to_be_batched:\n        parameter_dimensionality = max(input_dimensionalities[parameter_name])\n        if longest_lineage_support is None:\n            lineage_support = None\n        else:\n            lineage_support = longest_lineage_support[:parameter_dimensionality]\n        result[parameter_name] = AutoBatchCastingConfig(\n            casted_dimensionality=parameter_dimensionality,\n            lineage_support=lineage_support,\n        )\n    return result\n\n\ndef find_longest_lineage_support(\n    all_lineages_of_batch_parameters: List[List[str]],\n) -> Optional[List[str]]:\n    longest_longest_lineage_support = []\n    for lineage in all_lineages_of_batch_parameters:\n        if len(lineage) > len(longest_longest_lineage_support):\n            longest_longest_lineage_support = lineage\n    if len(longest_longest_lineage_support) == 0:\n        return None\n    return longest_longest_lineage_support\n\n\ndef get_lineage_for_input_property(\n    step_name: str,\n    property_name: str,\n    input_definition: Union[StepInputDefinition, CompoundStepInputDefinition],\n    lineage_deduplication_set: Set[int],\n) -> List[List[str]]:\n    if input_definition.is_compound_input():\n        return get_lineage_from_compound_input(\n            step_name=step_name,\n            property_name=property_name,\n            input_definition=input_definition,\n            lineage_deduplication_set=lineage_deduplication_set,\n        )\n    lineages = []\n    if input_definition.is_batch_oriented():\n        lineage = input_definition.data_lineage\n        lineage_id = identify_lineage(lineage=lineage)\n        if lineage_id not in lineage_deduplication_set:\n            lineage_deduplication_set.add(lineage_id)\n            lineages.append(lineage)\n    return lineages\n\n\ndef get_lineage_from_compound_input(\n    step_name: str,\n    property_name: str,\n    input_definition: Union[StepInputDefinition, CompoundStepInputDefinition],\n    lineage_deduplication_set: Set[int],\n) -> List[List[str]]:\n    lineages = []\n    for nested_element in input_definition.iterate_through_definitions():\n        if nested_element.is_batch_oriented():\n            lineage = nested_element.data_lineage\n            lineage_id = identify_lineage(lineage=lineage)\n            if lineage_id not in lineage_deduplication_set:\n                lineage_deduplication_set.add(lineage_id)\n                lineages.append(lineage)\n    if len(lineages) > 1:\n        raise StepInputLineageError(\n            public_message=f\"Input data provided for step: `{step_name}` comes with multiple different lineages \"\n            f\"{lineages} for property `{property_name}` accepting \"\n            f\"multiple selectors, which is not allowed.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    return lineages\n\n\ndef verify_lineages(step_name: str, detected_lineages: List[List[str]]) -> None:\n    lineages_by_length = defaultdict(list)\n    for lineage in detected_lineages:\n        lineages_by_length[len(lineage)].append(lineage)\n    if len(lineages_by_length) > 2:\n        raise StepInputLineageError(\n            public_message=f\"Input data provided for step: `{step_name}` comes with lineages at more than two \"\n            f\"dimensionality levels, which should not be possible.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    lineage_lengths = sorted(lineages_by_length.keys())\n    for lineage_length in lineage_lengths:\n        if len(lineages_by_length[lineage_length]) > 1:\n            raise StepInputLineageError(\n                public_message=f\"Among step `{step_name}` inputs found different lineages at the same  \"\n                f\"dimensionality levels dimensionality.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if len(lineages_by_length[lineage_lengths[-1]]) > 1 and len(lineage_lengths) < 2:\n        raise StepInputLineageError(\n            public_message=f\"If lineage differ at the last level, then Execution Engine requires at least one \"\n            f\"higher-dimension  input that will come with common lineage, but this is not the \"\n            f\"case for step {step_name}.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    if len(lineage_lengths) == 2:\n        reference_lineage = lineages_by_length[lineage_lengths[0]][0]\n        if reference_lineage != lineages_by_length[lineage_lengths[1]][0][:-1]:\n            raise StepInputLineageError(\n                public_message=f\"Step `{step_name}` inputs does not share common lineage. Differing element: \"\n                f\"{lineages_by_length[lineage_lengths[1]][0]}, \"\n                f\"reference lineage prefix: {reference_lineage}\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n\n\ndef establish_step_execution_dimensionality(\n    inputs_dimensionalities: Dict[str, Set[int]],\n    control_flow_lineage_support: List[str],\n    output_dimensionality_offset: int,\n) -> int:\n    \"\"\"\n    Determine how many batch dimensions (execution slices) a step runs with.\n\n    Used during workflow compilation in denote_data_flow_for_step. The result\n    is stored on StepNode.step_execution_dimensionality and consumed at\n    execution time to:\n    - Drive how many times the step is executed (which batch indices/slices).\n    - Align and expand inputs (e.g. auto-batch casting) to match this size.\n    - Validate that parameter dimensionalities are compatible (runtime checks\n      in step_input_assembler and manager).\n\n    Logic:\n    - If no input has non-zero dimensionality but the step is gated by\n      control flow (control_flow_lineage_support non-empty), the\n      dimensionality is the number of control-flow branches.\n    - Otherwise, the minimum non-zero input dimensionality is used; if\n      output_dimensionality_offset < 0 (step reduces batch dimension),\n      one is subtracted.\n\n    Args:\n        inputs_dimensionalities: Per-input sets of dimensionalities (from\n            get_inputs_dimensionalities).\n        control_flow_lineage_support: Lineage identifiers for control-flow\n            branches that gate this step (from establish_batch_oriented_step_lineage).\n        output_dimensionality_offset: Block's output dimensionality offset\n            (positive = expand, negative = reduce batch dimension).\n\n    Returns:\n        The number of batch dimensions (execution slices) for this step.\n    \"\"\"\n    step_execution_dimensionality = 0\n    non_zero_dimensionalities = {\n        dimensionality\n        for dimensionalities in inputs_dimensionalities.values()\n        for dimensionality in dimensionalities\n        if dimensionality > 0\n    }\n    if len(non_zero_dimensionalities) == 0 and len(control_flow_lineage_support) > 0:\n        return len(control_flow_lineage_support)\n    if len(non_zero_dimensionalities) > 0:\n        step_execution_dimensionality = min(non_zero_dimensionalities)\n        if output_dimensionality_offset < 0:\n            step_execution_dimensionality -= 1\n    return step_execution_dimensionality\n\n\ndef establish_batch_oriented_step_lineage(\n    step_selector: str,\n    all_data_derived_lineages: List[List[str]],\n    all_control_flow_lineages: List[List[str]],\n    input_data: StepInputData,\n    dimensionality_reference_property: Optional[str],\n    output_dimensionality_offset: int,\n) -> Tuple[List[str], List[str]]:\n    reference_lineage, control_flow_lineage_support = get_reference_lineage(\n        step_selector=step_selector,\n        all_data_derived_lineages=all_data_derived_lineages,\n        all_control_flow_lineages=all_control_flow_lineages,\n        input_data=input_data,\n        dimensionality_reference_property=dimensionality_reference_property,\n    )\n    if output_dimensionality_offset < 0:\n        result_dimensionality = reference_lineage[:output_dimensionality_offset]\n        return result_dimensionality, []\n    if output_dimensionality_offset == 0:\n        return reference_lineage, control_flow_lineage_support\n    reference_lineage.append(step_selector)\n    return reference_lineage, []\n\n\ndef get_reference_lineage(\n    step_selector: str,\n    all_data_derived_lineages: List[List[str]],\n    all_control_flow_lineages: List[List[str]],\n    input_data: StepInputData,\n    dimensionality_reference_property: Optional[str],\n) -> Tuple[List[str], List[str]]:\n    if not all_data_derived_lineages:\n        if len(all_control_flow_lineages) == 1:\n            return copy(all_control_flow_lineages[0]), copy(\n                all_control_flow_lineages[0]\n            )\n        # Multiple control-flow lineages and no data-derived lineage: pick the deepest.\n        max_lineage_len = max(len(lineage) for lineage in all_control_flow_lineages)\n        lineages_matching_max_len = [\n            _lineage\n            for _lineage in all_control_flow_lineages\n            if len(_lineage) == max_lineage_len\n        ]\n        if len(lineages_matching_max_len) == 1:\n            return copy(lineages_matching_max_len[0]), copy(\n                lineages_matching_max_len[0]\n            )\n        else:\n            raise AssumptionError(\n                public_message=f\"Multiple control-flow lineages at the same level for step `{step_selector}` \"\n                f\"and no data-derived lineage; unique lineage level required. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if len(all_data_derived_lineages) == 1:\n        return copy(all_data_derived_lineages[0]), []\n    if dimensionality_reference_property not in input_data:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` expected dimensionality_reference_property \"\n            f\"presence to be verified at earlier stages, which did not happen as expected. \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    property_data = input_data[dimensionality_reference_property]\n    if property_data.is_compound_input():\n        lineage = None\n        for nested_element in property_data.iterate_through_definitions():\n            if nested_element.is_batch_oriented():\n                lineage = copy(nested_element.data_lineage)\n                return lineage, []\n        if lineage is None:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n                f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if not property_data.is_batch_oriented():\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n            f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    return copy(property_data.data_lineage), []\n\n\ndef get_property_with_invalid_selector(\n    manifest: WorkflowBlockManifest, step_property: str\n) -> Optional[str]:\n    property_name = None\n    for key, value in manifest.__dict__.items():\n        if isinstance(value, str) and step_property in value:\n            property_name = key\n            break\n    return property_name\n\n\ndef add_super_input_node_in_execution_graph(\n    execution_graph: DiGraph,\n    super_input_node: str,\n) -> DiGraph:\n    nodes_to_attach_super_input_into = get_nodes_of_specific_category(\n        execution_graph=execution_graph,\n        category=NodeCategory.INPUT_NODE,\n    )\n    step_nodes_without_predecessors = [\n        node\n        for node in execution_graph.nodes\n        if not list(execution_graph.predecessors(node))\n    ]\n    nodes_to_attach_super_input_into.update(step_nodes_without_predecessors)\n    execution_graph.add_node(super_input_node)\n    for node in nodes_to_attach_super_input_into:\n        execution_graph.add_edge(super_input_node, node)\n    return execution_graph\n",
    "patch": null
  },
  {
    "trace_id": "f21854d7-d885-44e2-818a-b0bfb0d8d7d1",
    "function_name": "filter_to_valid_prefix_chains",
    "file_path": "inference/core/workflows/execution_engine/v1/executor/execution_data_manager/step_input_assembler.py",
    "speedup_x": 0.32089148487849195,
    "review_quality": "high",
    "pre_optimization_commit": "90243bdc6278ef7d17b6db09dc1eb5b0d155b4be",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def filter_to_valid_prefix_chains(\n    per_dim_sets: Dict[int, Set[DynamicBatchIndex]],\n    dimensions: Set[int],\n) -> Dict[int, Set[DynamicBatchIndex]]:\n    \"\"\"Keep only indices that form a complete parent-child chain across dimensions.\n\n    Given per-dimension sets (e.g. from intersect_masks_per_dimension), retains\n    only indices that have a full lineage from the smallest to the largest\n    dimension. Used for inter-level intersection.\n    \"\"\"\n    sorted_dims = sorted(dimensions)\n    by_dim: Dict[int, Set[DynamicBatchIndex]] = {\n        dim: per_dim_sets.get(dim, set()) for dim in sorted_dims\n    }\n\n    if len(sorted_dims) <= 1:\n        return dict(by_dim)\n\n    prev_dim = {sorted_dims[i]: sorted_dims[i - 1] for i in range(1, len(sorted_dims))}\n\n    # Bottom-up: mark indices that have at least one descendant\n    has_child: Set[DynamicBatchIndex] = set()\n    for dim in reversed(sorted_dims):\n        for idx in by_dim[dim]:\n            if dim == sorted_dims[-1] or idx in has_child:\n                parent = idx[:-1]\n                if parent:\n                    has_child.add(parent)\n\n    # Top-down: keep indices only if full prefix chain exists\n    valid: Dict[int, Set[DynamicBatchIndex]] = {dim: set() for dim in sorted_dims}\n    for dim in sorted_dims:\n        for idx in by_dim[dim]:\n            parent = idx[:-1]\n            if dim == sorted_dims[0]:\n                if idx in has_child:\n                    valid[dim].add(idx)\n            elif parent in valid[prev_dim[dim]]:\n                if dim == sorted_dims[-1] or idx in has_child:\n                    valid[dim].add(idx)\n\n    return valid\n",
    "optimized_function_code": "from typing import Dict, Set\n\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.dynamic_batches_manager import \\\n    DynamicBatchIndex\n\n\ndef filter_to_valid_prefix_chains(\n    per_dim_sets: Dict[int, Set[DynamicBatchIndex]],\n    dimensions: Set[int],\n) -> Dict[int, Set[DynamicBatchIndex]]:\n    \"\"\"Keep only indices that form a complete parent-child chain across dimensions.\n\n    Given per-dimension sets (e.g. from intersect_masks_per_dimension), retains\n    only indices that have a full lineage from the smallest to the largest\n    dimension. Used for inter-level intersection.\n    \"\"\"\n    sorted_dims = sorted(dimensions)\n    by_dim: Dict[int, Set[DynamicBatchIndex]] = {\n        dim: per_dim_sets.get(dim, set()) for dim in sorted_dims\n    }\n\n    if len(sorted_dims) <= 1:\n        return dict(by_dim)\n\n    prev_dim = {sorted_dims[i]: sorted_dims[i - 1] for i in range(1, len(sorted_dims))}\n\n    # Bottom-up: mark indices that have at least one descendant\n    has_child: Set[DynamicBatchIndex] = set()\n    last_dim = sorted_dims[-1]\n    for dim in reversed(sorted_dims):\n        is_last_dim = (dim == last_dim)\n        dim_indices = by_dim[dim]\n        \n        for idx in dim_indices:\n            if is_last_dim or idx in has_child:\n                parent = idx[:-1]\n                if parent:\n                    has_child.add(parent)\n\n    # Top-down: keep indices only if full prefix chain exists\n    valid: Dict[int, Set[DynamicBatchIndex]] = {dim: set() for dim in sorted_dims}\n    first_dim = sorted_dims[0]\n    \n    for dim in sorted_dims:\n        is_first_dim = (dim == first_dim)\n        is_last_dim = (dim == last_dim)\n        dim_indices = by_dim[dim]\n        valid_dim = valid[dim]\n        \n        if is_first_dim:\n            # First dimension: only keep if has children\n            for idx in dim_indices:\n                if idx in has_child:\n                    valid_dim.add(idx)\n        else:\n            # Other dimensions: check parent chain\n            valid_parent_dim = valid[prev_dim[dim]]\n            \n            if is_last_dim:\n                # Last dimension: no need to check has_child\n                for idx in dim_indices:\n                    parent = idx[:-1]\n                    if parent in valid_parent_dim:\n                        valid_dim.add(idx)\n            else:\n                # Middle dimensions: check both parent and has_child\n                for idx in dim_indices:\n                    parent = idx[:-1]\n                    if parent in valid_parent_dim and idx in has_child:\n                        valid_dim.add(idx)\n\n    return valid",
    "optimized_raw_markdown": "```python:inference/core/workflows/execution_engine/v1/executor/execution_data_manager/step_input_assembler.py\nfrom typing import Dict, Set\n\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.dynamic_batches_manager import \\\n    DynamicBatchIndex\n\n\ndef filter_to_valid_prefix_chains(\n    per_dim_sets: Dict[int, Set[DynamicBatchIndex]],\n    dimensions: Set[int],\n) -> Dict[int, Set[DynamicBatchIndex]]:\n    \"\"\"Keep only indices that form a complete parent-child chain across dimensions.\n\n    Given per-dimension sets (e.g. from intersect_masks_per_dimension), retains\n    only indices that have a full lineage from the smallest to the largest\n    dimension. Used for inter-level intersection.\n    \"\"\"\n    sorted_dims = sorted(dimensions)\n    by_dim: Dict[int, Set[DynamicBatchIndex]] = {\n        dim: per_dim_sets.get(dim, set()) for dim in sorted_dims\n    }\n\n    if len(sorted_dims) <= 1:\n        return dict(by_dim)\n\n    prev_dim = {sorted_dims[i]: sorted_dims[i - 1] for i in range(1, len(sorted_dims))}\n\n    # Bottom-up: mark indices that have at least one descendant\n    has_child: Set[DynamicBatchIndex] = set()\n    last_dim = sorted_dims[-1]\n    for dim in reversed(sorted_dims):\n        is_last_dim = (dim == last_dim)\n        dim_indices = by_dim[dim]\n        \n        for idx in dim_indices:\n            if is_last_dim or idx in has_child:\n                parent = idx[:-1]\n                if parent:\n                    has_child.add(parent)\n\n    # Top-down: keep indices only if full prefix chain exists\n    valid: Dict[int, Set[DynamicBatchIndex]] = {dim: set() for dim in sorted_dims}\n    first_dim = sorted_dims[0]\n    \n    for dim in sorted_dims:\n        is_first_dim = (dim == first_dim)\n        is_last_dim = (dim == last_dim)\n        dim_indices = by_dim[dim]\n        valid_dim = valid[dim]\n        \n        if is_first_dim:\n            # First dimension: only keep if has children\n            for idx in dim_indices:\n                if idx in has_child:\n                    valid_dim.add(idx)\n        else:\n            # Other dimensions: check parent chain\n            valid_parent_dim = valid[prev_dim[dim]]\n            \n            if is_last_dim:\n                # Last dimension: no need to check has_child\n                for idx in dim_indices:\n                    parent = idx[:-1]\n                    if parent in valid_parent_dim:\n                        valid_dim.add(idx)\n            else:\n                # Middle dimensions: check both parent and has_child\n                for idx in dim_indices:\n                    parent = idx[:-1]\n                    if parent in valid_parent_dim and idx in has_child:\n                        valid_dim.add(idx)\n\n    return valid\n```",
    "optimized_function_only": "def filter_to_valid_prefix_chains(\n    per_dim_sets: Dict[int, Set[DynamicBatchIndex]],\n    dimensions: Set[int],\n) -> Dict[int, Set[DynamicBatchIndex]]:\n    \"\"\"Keep only indices that form a complete parent-child chain across dimensions.\n\n    Given per-dimension sets (e.g. from intersect_masks_per_dimension), retains\n    only indices that have a full lineage from the smallest to the largest\n    dimension. Used for inter-level intersection.\n    \"\"\"\n    sorted_dims = sorted(dimensions)\n    by_dim: Dict[int, Set[DynamicBatchIndex]] = {\n        dim: per_dim_sets.get(dim, set()) for dim in sorted_dims\n    }\n\n    if len(sorted_dims) <= 1:\n        return dict(by_dim)\n\n    prev_dim = {sorted_dims[i]: sorted_dims[i - 1] for i in range(1, len(sorted_dims))}\n\n    # Bottom-up: mark indices that have at least one descendant\n    has_child: Set[DynamicBatchIndex] = set()\n    last_dim = sorted_dims[-1]\n    for dim in reversed(sorted_dims):\n        is_last_dim = (dim == last_dim)\n        dim_indices = by_dim[dim]\n        \n        for idx in dim_indices:\n            if is_last_dim or idx in has_child:\n                parent = idx[:-1]\n                if parent:\n                    has_child.add(parent)\n\n    # Top-down: keep indices only if full prefix chain exists\n    valid: Dict[int, Set[DynamicBatchIndex]] = {dim: set() for dim in sorted_dims}\n    first_dim = sorted_dims[0]\n    \n    for dim in sorted_dims:\n        is_first_dim = (dim == first_dim)\n        is_last_dim = (dim == last_dim)\n        dim_indices = by_dim[dim]\n        valid_dim = valid[dim]\n        \n        if is_first_dim:\n            # First dimension: only keep if has children\n            for idx in dim_indices:\n                if idx in has_child:\n                    valid_dim.add(idx)\n        else:\n            # Other dimensions: check parent chain\n            valid_parent_dim = valid[prev_dim[dim]]\n            \n            if is_last_dim:\n                # Last dimension: no need to check has_child\n                for idx in dim_indices:\n                    parent = idx[:-1]\n                    if parent in valid_parent_dim:\n                        valid_dim.add(idx)\n            else:\n                # Middle dimensions: check both parent and has_child\n                for idx in dim_indices:\n                    parent = idx[:-1]\n                    if parent in valid_parent_dim and idx in has_child:\n                        valid_dim.add(idx)\n\n    return valid",
    "original_file_content": "from dataclasses import dataclass\nfrom typing import Any, Dict, Generator, List, Optional, Set, Tuple, TypeVar, Union\n\nfrom inference.core.workflows.errors import AssumptionError, ExecutionEngineRuntimeError\nfrom inference.core.workflows.execution_engine.entities.base import Batch\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import (\n    AutoBatchCastingConfig,\n    CompoundStepInputDefinition,\n    DynamicStepInputDefinition,\n    StaticStepInputDefinition,\n    StepInputDefinition,\n    StepNode,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import (\n    get_last_chunk_of_selector,\n)\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.branching_manager import (\n    BranchingManager,\n)\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.dynamic_batches_manager import (\n    DynamicBatchesManager,\n    DynamicBatchIndex,\n)\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.execution_cache import (\n    ExecutionCache,\n)\n\nT = TypeVar(\"T\")\n\n\n@dataclass(frozen=True)\nclass BatchModeSIMDStepInput:\n    indices: List[DynamicBatchIndex]\n    parameters: Dict[str, Any]\n\n\n@dataclass(frozen=True)\nclass NonBatchModeSIMDStepInput:\n    index: DynamicBatchIndex\n    parameters: Dict[str, Any]\n\n\ndef construct_non_simd_step_input(\n    step_node: StepNode,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    branching_manager: BranchingManager,\n) -> Optional[Dict[str, Any]]:\n    if step_node.batch_oriented_parameters:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Attempted to get non-SIMD input for SIMD step: {step_node.name}.\"\n            f\"This is most likely a bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    masks = set()\n    for execution_branch in step_node.execution_branches_impacting_inputs:\n        if not branching_manager.is_execution_branch_registered(\n            execution_branch=execution_branch\n        ):\n            masks.add(False)\n            continue\n        if branching_manager.is_execution_branch_batch_oriented(\n            execution_branch=execution_branch\n        ):\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"For step: {step_node.name}, detected batch-oriented condition statements \"\n                f\"impacting non-SIMD step, which should be prevented by Workflows Compiler. \"\n                f\"This is most likely a bug. Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n        else:\n            mask = branching_manager.get_mask(execution_branch=execution_branch)\n            masks.add(mask)\n    if False in masks:\n        return None\n    result = {}\n    detected_empty_step_output_selector = False\n    for parameter_name, parameter_spec in step_node.input_data.items():\n        if parameter_spec.is_compound_input():\n            result[parameter_name], contains_empty_step_output_selector = (\n                construct_non_simd_step_compound_input(\n                    step_node=step_node,\n                    parameter_spec=parameter_spec,\n                    runtime_parameters=runtime_parameters,\n                    execution_cache=execution_cache,\n                )\n            )\n        else:\n            result[parameter_name], contains_empty_step_output_selector = (\n                construct_non_simd_step_non_compound_input(\n                    step_node=step_node,\n                    parameter_spec=parameter_spec,\n                    runtime_parameters=runtime_parameters,\n                    execution_cache=execution_cache,\n                )\n            )\n        detected_empty_step_output_selector = (\n            detected_empty_step_output_selector or contains_empty_step_output_selector\n        )\n    if (\n        detected_empty_step_output_selector\n        and not step_node.step_manifest.accepts_empty_values()\n    ):\n        return None\n    return result\n\n\ndef construct_non_simd_step_compound_input(\n    step_node: StepNode,\n    parameter_spec: CompoundStepInputDefinition,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> Tuple[Any, bool]:\n    if parameter_spec.represents_list_of_inputs():\n        return construct_non_simd_step_compound_list_input(\n            step_node=step_node,\n            parameter_spec=parameter_spec,\n            runtime_parameters=runtime_parameters,\n            execution_cache=execution_cache,\n        )\n    return construct_non_simd_step_compound_dict_input(\n        step_node=step_node,\n        parameter_spec=parameter_spec,\n        runtime_parameters=runtime_parameters,\n        execution_cache=execution_cache,\n    )\n\n\ndef construct_non_simd_step_compound_list_input(\n    step_node: StepNode,\n    parameter_spec: CompoundStepInputDefinition,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> Tuple[List[Any], bool]:\n    result = []\n    contains_empty_step_output_selector = False\n    for nested_definition in parameter_spec.iterate_through_definitions():\n        nested_value, value_contains_empty_selector = (\n            construct_non_simd_step_non_compound_input(\n                step_node=step_node,\n                parameter_spec=nested_definition,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n            )\n        )\n        result.append(nested_value)\n        contains_empty_step_output_selector = (\n            contains_empty_step_output_selector or value_contains_empty_selector\n        )\n    return result, contains_empty_step_output_selector\n\n\ndef construct_non_simd_step_compound_dict_input(\n    step_node: StepNode,\n    parameter_spec: CompoundStepInputDefinition,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> Tuple[Dict[str, Any], bool]:\n    result = {}\n    contains_empty_step_output_selector = False\n    for nested_definition in parameter_spec.iterate_through_definitions():\n        (\n            result[nested_definition.parameter_specification.nested_element_key],\n            value_contains_empty_selector,\n        ) = construct_non_simd_step_non_compound_input(\n            step_node=step_node,\n            parameter_spec=nested_definition,\n            runtime_parameters=runtime_parameters,\n            execution_cache=execution_cache,\n        )\n        contains_empty_step_output_selector = (\n            contains_empty_step_output_selector or value_contains_empty_selector\n        )\n    return result, contains_empty_step_output_selector\n\n\ndef construct_non_simd_step_non_compound_input(\n    step_node: StepNode,\n    parameter_spec: StepInputDefinition,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> Tuple[Any, bool]:\n    if parameter_spec.is_compound_input():\n        raise AssumptionError(\n            public_message=f\"Workflows Execution Error encountered unexpected state probably related to the fact \"\n            f\"that Workflows Compiler allowed for multi-level nesting of inputs selectors which \"\n            f\"is not supported. This is most likely the bug. Contact Roboflow team \"\n            f\"through github issues (https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if parameter_spec.is_batch_oriented():\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Encountered batch-oriented input for non-SIMD step: {step_node.name}.\"\n            f\"This is most likely a bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if parameter_spec.points_to_input():\n        parameter_spec: DynamicStepInputDefinition = parameter_spec  # type: ignore\n        input_name = get_last_chunk_of_selector(selector=parameter_spec.selector)\n        return runtime_parameters[input_name], False\n    if parameter_spec.points_to_step_output():\n        parameter_spec: DynamicStepInputDefinition = parameter_spec  # type: ignore\n        step_output = execution_cache.get_non_batch_output(\n            selector=parameter_spec.selector\n        )\n        return step_output, step_output is None\n    parameter_spec: StaticStepInputDefinition = parameter_spec  # type: ignore\n    return parameter_spec.value, False\n\n\ndef iterate_over_simd_step_input(\n    step_node: StepNode,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    dynamic_batches_manager: DynamicBatchesManager,\n    branching_manager: BranchingManager,\n) -> Generator[NonBatchModeSIMDStepInput, None, None]:\n    simd_step_input = construct_simd_step_input(\n        step_node=step_node,\n        runtime_parameters=runtime_parameters,\n        execution_cache=execution_cache,\n        dynamic_batches_manager=dynamic_batches_manager,\n        branching_manager=branching_manager,\n    )\n    parameters_generator = unfold_parameters(\n        parameters=simd_step_input.parameters,\n        indices=simd_step_input.indices,\n    )\n    for index, single_parameters_set in zip(\n        simd_step_input.indices, parameters_generator\n    ):\n        yield NonBatchModeSIMDStepInput(\n            index=index,\n            parameters=single_parameters_set,\n        )\n\n\ndef construct_simd_step_input(\n    step_node: StepNode,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    dynamic_batches_manager: DynamicBatchesManager,\n    branching_manager: BranchingManager,\n) -> BatchModeSIMDStepInput:\n    masks, scalars_discarded = construct_mask_for_all_inputs_dimensionalities(\n        step_node=step_node,\n        branching_manager=branching_manager,\n    )\n    return prepare_parameters(\n        step_node=step_node,\n        dynamic_batches_manager=dynamic_batches_manager,\n        masks=masks,\n        scalars_discarded=scalars_discarded,\n        runtime_parameters=runtime_parameters,\n        execution_cache=execution_cache,\n    )\n\n\ndef construct_mask_for_all_inputs_dimensionalities(\n    step_node: StepNode,\n    branching_manager: BranchingManager,\n) -> Tuple[Any, bool]:\n    inputs_dimensionalities = collect_inputs_dimensionalities(step_node=step_node)\n    all_dimensionalities = {dim for dim in inputs_dimensionalities.values() if dim > 0}\n    if step_node.control_flow_lineage_support:\n        for dim_level in step_node.control_flow_lineage_dims:\n            all_dimensionalities.add(dim_level)\n    batch_masks, non_batch_masks = [], set()\n    for execution_branch in step_node.execution_branches_impacting_inputs:\n        if not branching_manager.is_execution_branch_registered(\n            execution_branch=execution_branch\n        ):\n            non_batch_masks.add(False)\n            continue\n        if branching_manager.is_execution_branch_batch_oriented(\n            execution_branch=execution_branch\n        ):\n            mask = branching_manager.get_mask(execution_branch=execution_branch)\n            batch_masks.append(mask)\n        else:\n            mask = branching_manager.get_mask(execution_branch=execution_branch)\n            non_batch_masks.add(mask)\n    scalar_mask_contains_false = False in non_batch_masks\n    if scalar_mask_contains_false:\n        return {\n            dimension: set() for dimension in all_dimensionalities\n        }, scalar_mask_contains_false\n    return (\n        get_masks_intersection_for_dimensions(\n            batch_masks=batch_masks,\n            dimensions=all_dimensionalities,\n        ),\n        scalar_mask_contains_false,\n    )\n\n\ndef collect_inputs_dimensionalities(\n    step_node: StepNode,\n) -> Dict[str, int]:\n    result = {}\n    for parameter_name, parameter_specs in step_node.input_data.items():\n        if parameter_specs.is_compound_input():\n            dimensionalities = [\n                nested_definition.get_dimensionality()\n                for nested_definition in parameter_specs.iterate_through_definitions()\n            ]\n            # to help for empty values\n            dimensionalities.append(0)\n            result[parameter_name] = max(dimensionalities)\n        else:\n            result[parameter_name] = parameter_specs.get_dimensionality()\n    return result\n\n\ndef intersect_masks_per_dimension(\n    batch_masks: List[Set[DynamicBatchIndex]],\n    dimensions: Set[int],\n) -> Dict[int, Set[DynamicBatchIndex]]:\n    \"\"\"Intersect masks at each dimensionality level.\n\n    For each dimension d, returns the set of indices (with length d) that appear\n    in every mask that has at least one index at that dimension. Masks with no\n    indices at d are ignored for that dimension. Used for intra-dimensional\n    intersection.\n    \"\"\"\n    sorted_dims = sorted(dimensions)\n    result: Dict[int, Set[DynamicBatchIndex]] = {}\n    for dim in sorted_dims:\n        sets_at_dim = [{idx for idx in mask if len(idx) == dim} for mask in batch_masks]\n        non_empty = [s for s in sets_at_dim if s]\n        result[dim] = set.intersection(*non_empty) if non_empty else set()\n    return result\n\n\ndef filter_to_valid_prefix_chains(\n    per_dim_sets: Dict[int, Set[DynamicBatchIndex]],\n    dimensions: Set[int],\n) -> Dict[int, Set[DynamicBatchIndex]]:\n    \"\"\"Keep only indices that form a complete parent-child chain across dimensions.\n\n    Given per-dimension sets (e.g. from intersect_masks_per_dimension), retains\n    only indices that have a full lineage from the smallest to the largest\n    dimension. Used for inter-level intersection.\n    \"\"\"\n    sorted_dims = sorted(dimensions)\n    by_dim: Dict[int, Set[DynamicBatchIndex]] = {\n        dim: per_dim_sets.get(dim, set()) for dim in sorted_dims\n    }\n\n    if len(sorted_dims) <= 1:\n        return dict(by_dim)\n\n    prev_dim = {sorted_dims[i]: sorted_dims[i - 1] for i in range(1, len(sorted_dims))}\n\n    # Bottom-up: mark indices that have at least one descendant\n    has_child: Set[DynamicBatchIndex] = set()\n    for dim in reversed(sorted_dims):\n        for idx in by_dim[dim]:\n            if dim == sorted_dims[-1] or idx in has_child:\n                parent = idx[:-1]\n                if parent:\n                    has_child.add(parent)\n\n    # Top-down: keep indices only if full prefix chain exists\n    valid: Dict[int, Set[DynamicBatchIndex]] = {dim: set() for dim in sorted_dims}\n    for dim in sorted_dims:\n        for idx in by_dim[dim]:\n            parent = idx[:-1]\n            if dim == sorted_dims[0]:\n                if idx in has_child:\n                    valid[dim].add(idx)\n            elif parent in valid[prev_dim[dim]]:\n                if dim == sorted_dims[-1] or idx in has_child:\n                    valid[dim].add(idx)\n\n    return valid\n\n\ndef get_masks_intersection_for_dimensions(\n    batch_masks: List[Set[DynamicBatchIndex]],\n    dimensions: Set[int],\n) -> Dict[int, Optional[Set[DynamicBatchIndex]]]:\n    \"\"\"Intersect masks at each dimension and filter to valid prefix chains.\"\"\"\n    if not batch_masks:\n        return {dim: None for dim in dimensions}\n\n    sorted_dims = sorted(dimensions)\n\n    if len(sorted_dims) <= 1:\n        result = intersect_masks_per_dimension(batch_masks, dimensions)\n        return {dim: result[dim] for dim in sorted_dims}\n\n    per_dim = intersect_masks_per_dimension(batch_masks, dimensions)\n    return filter_to_valid_prefix_chains(per_dim, dimensions)\n\n\nclass GuardForIndicesWrapping:\n\n    def __init__(self):\n        self._registered_wrapping: Optional[List[DynamicBatchIndex]] = None\n\n    def register_wrapping(\n        self, indices_before_wrapping: List[DynamicBatchIndex]\n    ) -> None:\n        if self._registered_wrapping is None:\n            self._registered_wrapping = indices_before_wrapping\n        elif self._registered_wrapping != indices_before_wrapping:\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Detected a situation when step requires dimensionality wrapping, but\"\n                f\"different inputs register different elements indices to wrap which is illegal \"\n                f\"and should be detected earlier by Workflows compiler. This is most likely a bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n\n\ndef prepare_parameters(\n    step_node: StepNode,\n    dynamic_batches_manager: DynamicBatchesManager,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> BatchModeSIMDStepInput:\n    step_requests_batch_input = step_node.step_manifest.accepts_batch_input()\n    result = {}\n    indices_for_parameter = {}\n    guard_of_indices_wrapping = GuardForIndicesWrapping()\n    compound_inputs = set()\n    contains_empty_scalar_step_output_selector = False\n    for parameter_name, parameter_specs in step_node.input_data.items():\n        if parameter_specs.is_compound_input():\n            (\n                result[parameter_name],\n                indices_for_parameter[parameter_name],\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_compound_parameter_value(\n                parameter=parameter_specs,\n                step_execution_dimensionality=step_node.step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=step_node.auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n            compound_inputs.add(parameter_name)\n        else:\n            (\n                result[parameter_name],\n                indices_for_parameter[parameter_name],\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=parameter_specs,\n                step_execution_dimensionality=step_node.step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=step_node.auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n        contains_empty_scalar_step_output_selector = (\n            contains_empty_scalar_step_output_selector\n            or value_contains_empty_scalar_step_output_selector\n        )\n    batch_parameters_indices = [\n        i for i in indices_for_parameter.values() if i is not None\n    ]\n    ensure_compound_input_indices_match(indices=batch_parameters_indices)\n    if not batch_parameters_indices:\n        if not step_node.control_flow_lineage_support:\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"For step: {step_node.name} which is assessed by Workflows Compiler as \"\n                f\"SIMD step Execution Engine cannot detect neither batch inputs nor control flow inputs. \"\n                f\"This is most likely a bug. Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n        indices = dynamic_batches_manager.get_indices_for_data_lineage(\n            lineage=step_node.control_flow_lineage_support,\n        )\n        mask_dimension = len(step_node.control_flow_lineage_support)\n        mask_for_dimension = masks.get(mask_dimension)\n        if mask_for_dimension is not None:\n            indices = [idx for idx in indices if idx in mask_for_dimension]\n    else:\n        indices = batch_parameters_indices[0]\n    if not step_node.step_manifest.accepts_empty_values():\n        if contains_empty_scalar_step_output_selector:\n            return BatchModeSIMDStepInput(\n                indices=[],\n                parameters={},\n            )\n        empty_indices = get_empty_batch_elements_indices(value=result)\n        if empty_indices:\n            indices = [e for e in indices if e not in empty_indices]\n            result = remove_indices(value=result, indices=empty_indices)\n    return BatchModeSIMDStepInput(\n        indices=indices,\n        parameters=result,\n    )\n\n\ndef get_compound_parameter_value(\n    parameter: CompoundStepInputDefinition,\n    step_execution_dimensionality: int,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n    dynamic_batches_manager: DynamicBatchesManager,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n    auto_batch_casting_lineage_supports: Dict[str, AutoBatchCastingConfig],\n    step_requests_batch_input: bool,\n) -> Tuple[Union[list, Dict[str, Any]], Optional[List[DynamicBatchIndex]], bool]:\n    contains_empty_scalar_step_output_selector = False\n    batch_indices = []\n    if parameter.represents_list_of_inputs():\n        result = []\n        for nested_element in parameter.iterate_through_definitions():\n            (\n                non_compound_parameter_value,\n                non_compound_indices,\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=nested_element,\n                step_execution_dimensionality=step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n            result.append(non_compound_parameter_value)\n            contains_empty_scalar_step_output_selector = (\n                contains_empty_scalar_step_output_selector\n                or value_contains_empty_scalar_step_output_selector\n            )\n            if non_compound_indices is not None:\n                batch_indices.append(non_compound_indices)\n    else:\n        result = {}\n        for nested_element in parameter.iterate_through_definitions():\n            (\n                non_compound_parameter_value,\n                non_compound_indices,\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=nested_element,\n                step_execution_dimensionality=step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n            result[nested_element.parameter_specification.nested_element_key] = (\n                non_compound_parameter_value\n            )\n            contains_empty_scalar_step_output_selector = (\n                contains_empty_scalar_step_output_selector\n                or value_contains_empty_scalar_step_output_selector\n            )\n            if non_compound_indices is not None:\n                batch_indices.append(non_compound_indices)\n    ensure_compound_input_indices_match(indices=batch_indices)\n    result_indices = None\n    if len(batch_indices) > 0:\n        result_indices = batch_indices[0]\n    return result, result_indices, contains_empty_scalar_step_output_selector\n\n\ndef get_non_compound_parameter_value(\n    parameter: StepInputDefinition,\n    step_execution_dimensionality: int,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n    dynamic_batches_manager: DynamicBatchesManager,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n    auto_batch_casting_lineage_supports: Dict[str, AutoBatchCastingConfig],\n    step_requests_batch_input: bool,\n) -> Tuple[Any, Optional[List[DynamicBatchIndex]], bool]:\n    if not parameter.is_batch_oriented():\n        requested_as_batch = (\n            parameter.parameter_specification.parameter_name\n            in auto_batch_casting_lineage_supports\n        )\n        if parameter.points_to_input():\n            input_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n            parameter_name = get_last_chunk_of_selector(\n                selector=input_parameter.selector\n            )\n            if not requested_as_batch:\n                return runtime_parameters[parameter_name], None, False\n            else:\n                return apply_auto_batch_casting(\n                    parameter_name=parameter_name,\n                    value=runtime_parameters[parameter_name],\n                    auto_batch_casting_config=auto_batch_casting_lineage_supports[\n                        parameter.parameter_specification.parameter_name\n                    ],\n                    contains_empty_scalar_step_output_selector=False,\n                    dynamic_batches_manager=dynamic_batches_manager,\n                    step_execution_dimensionality=step_execution_dimensionality,\n                    guard_of_indices_wrapping=guard_of_indices_wrapping,\n                    step_requests_batch_input=step_requests_batch_input,\n                    masks=masks,\n                    scalars_discarded=False,\n                )\n        elif parameter.points_to_step_output():\n            input_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n            value = execution_cache.get_non_batch_output(\n                selector=input_parameter.selector\n            )\n            if not requested_as_batch:\n                return value, None, value is None\n            else:\n                return apply_auto_batch_casting(\n                    parameter_name=parameter.parameter_specification.parameter_name,\n                    value=value,\n                    auto_batch_casting_config=auto_batch_casting_lineage_supports[\n                        parameter.parameter_specification.parameter_name\n                    ],\n                    contains_empty_scalar_step_output_selector=value is None,\n                    dynamic_batches_manager=dynamic_batches_manager,\n                    step_execution_dimensionality=step_execution_dimensionality,\n                    guard_of_indices_wrapping=guard_of_indices_wrapping,\n                    step_requests_batch_input=step_requests_batch_input,\n                    masks=masks,\n                    scalars_discarded=scalars_discarded,\n                )\n        else:\n            static_input: StaticStepInputDefinition = parameter  # type: ignore\n            if not requested_as_batch or static_input.value is None:\n                # when we have Optional[Selector()] in manifest - we must retain\n                # ability to inject None into the run(...) parameters - as\n                # if we treat that as actual batch and broadcast Batch[None],\n                # we would behave exactly as condition execution does -\n                # and the logic executing after this, will filter-out empty\n                # elements - so on None, we behave \"the old way\" regardless of the fact that ABC\n                # was requested\n                return static_input.value, None, False\n            else:\n                return apply_auto_batch_casting(\n                    parameter_name=parameter.parameter_specification.parameter_name,\n                    value=static_input.value,\n                    auto_batch_casting_config=auto_batch_casting_lineage_supports[\n                        parameter.parameter_specification.parameter_name\n                    ],\n                    contains_empty_scalar_step_output_selector=False,\n                    dynamic_batches_manager=dynamic_batches_manager,\n                    step_execution_dimensionality=step_execution_dimensionality,\n                    guard_of_indices_wrapping=guard_of_indices_wrapping,\n                    step_requests_batch_input=step_requests_batch_input,\n                    masks=masks,\n                    scalars_discarded=False,\n                )\n    dynamic_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n    parameter_dimensionality = dynamic_parameter.get_dimensionality()\n    lineage_indices = dynamic_batches_manager.get_indices_for_data_lineage(\n        lineage=dynamic_parameter.data_lineage,\n    )\n    mask_for_dimension = masks[parameter_dimensionality]\n    if dynamic_parameter.points_to_input():\n        input_name = get_last_chunk_of_selector(selector=dynamic_parameter.selector)\n        batch_input = _flatten_batch_oriented_inputs(\n            runtime_parameters[input_name],\n            dimensionality=parameter_dimensionality,\n        )\n        if mask_for_dimension is not None:\n            if len(lineage_indices) != len(batch_input):\n                raise ExecutionEngineRuntimeError(\n                    public_message=f\"Detected a situation when input parameter: \"\n                    f\"{input_name}\"\n                    f\"size is mismatched compared to mask requested for that input. \"\n                    f\"Input length: {len(batch_input)}, mask size: {len(lineage_indices)}. \"\n                    f\"This is most likely a bug. \"\n                    f\"Contact Roboflow team through github issues \"\n                    f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                    f\"the problem - including workflow definition you use.\",\n                    context=\"workflow_execution | step_input_assembling\",\n                )\n            batch_input = [\n                input_element if element_index in mask_for_dimension else None\n                for element_index, input_element in zip(lineage_indices, batch_input)\n            ]\n    else:\n        batch_input = execution_cache.get_batch_output(\n            selector=dynamic_parameter.selector,\n            batch_elements_indices=lineage_indices,\n            mask=mask_for_dimension,\n        )\n    if step_execution_dimensionality == parameter_dimensionality:\n        return Batch(batch_input, lineage_indices), lineage_indices, False\n    if step_execution_dimensionality > parameter_dimensionality:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter.parameter_specification.parameter_name}\"\n            f\"has a dimensionality {parameter_dimensionality} larger \"\n            f\"than step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if abs(parameter_dimensionality - step_execution_dimensionality) > 1:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter.parameter_specification.parameter_name}\"\n            f\"has a dimensionality {parameter_dimensionality} differing more than one level \"\n            f\"from step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if step_execution_dimensionality == 0 and not step_requests_batch_input:\n        return Batch(batch_input, lineage_indices), lineage_indices, False\n    upper_lineage = dynamic_parameter.data_lineage[:-1]\n    if len(upper_lineage) == 0:\n        if not step_requests_batch_input:\n            raise AssumptionError(\n                public_message=f\"Parameter: {parameter.parameter_specification.parameter_name} \"\n                f\"requires dimensionality wrapping, but registered lineage support is incompatible \"\n                f\"which should be detected by the compiler. This is most likely a bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n        upper_level_indices = [()]\n    else:\n        upper_level_indices = dynamic_batches_manager.get_indices_for_data_lineage(\n            lineage=dynamic_parameter.data_lineage[:-1],\n        )\n    result = reduce_batch_dimensionality(\n        indices=lineage_indices,\n        upper_level_index=upper_level_indices,\n        data=batch_input,\n        guard_of_indices_wrapping=guard_of_indices_wrapping,\n    )\n    return result, result.indices, False\n\n\ndef apply_auto_batch_casting(\n    parameter_name: str,\n    value: Any,\n    auto_batch_casting_config: AutoBatchCastingConfig,\n    contains_empty_scalar_step_output_selector: bool,\n    dynamic_batches_manager: DynamicBatchesManager,\n    step_execution_dimensionality: int,\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n    step_requests_batch_input: bool,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n) -> Tuple[Any, List[DynamicBatchIndex], bool]:\n    if auto_batch_casting_config.lineage_support is None:\n        indices = [(0,) * auto_batch_casting_config.casted_dimensionality]\n    else:\n        indices = dynamic_batches_manager.get_indices_for_data_lineage(\n            lineage=auto_batch_casting_config.lineage_support,\n        )\n        missing_dimensions = auto_batch_casting_config.casted_dimensionality - len(\n            auto_batch_casting_config.lineage_support\n        )\n        if missing_dimensions > 0:\n            padding = (0,) * missing_dimensions\n            indices = [i + padding for i in indices]\n    if scalars_discarded:\n        batch_content = [None] * len(indices)\n    elif auto_batch_casting_config.lineage_support is None:\n        batch_content = [value] * len(indices)\n    else:\n        support_dimensionality = len(auto_batch_casting_config.lineage_support)\n        mask_for_support_dimensionality = masks[support_dimensionality]\n        if mask_for_support_dimensionality is None:\n            batch_content = [value] * len(indices)\n        else:\n            batch_content = []\n            for index in indices:\n                if index[:support_dimensionality] in mask_for_support_dimensionality:\n                    batch_content.append(value)\n                else:\n                    batch_content.append(None)\n    created_batch = Batch(content=batch_content, indices=indices)\n    if step_execution_dimensionality == auto_batch_casting_config.casted_dimensionality:\n        return (\n            created_batch,\n            indices,\n            contains_empty_scalar_step_output_selector or scalars_discarded,\n        )\n    if step_execution_dimensionality > auto_batch_casting_config.casted_dimensionality:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter_name}\"\n            f\"has auto-batch casted dimensionality {auto_batch_casting_config.casted_dimensionality} larger \"\n            f\"than step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if (\n        abs(\n            auto_batch_casting_config.casted_dimensionality\n            - step_execution_dimensionality\n        )\n        > 1\n    ):\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter_name} has auto batch casted \"\n            f\"dimensionality {auto_batch_casting_config.casted_dimensionality} differing more than one level \"\n            f\"from step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    upper_level_lineage_dimensionality = (\n        auto_batch_casting_config.casted_dimensionality - 1\n    )\n    if upper_level_lineage_dimensionality == 0 and not step_requests_batch_input:\n        # for batch collapse into scalar\n        return (\n            created_batch,\n            indices,\n            contains_empty_scalar_step_output_selector or scalars_discarded,\n        )\n    if auto_batch_casting_config.lineage_support is None:\n        upper_level_indices = [indices[0][:-1]]\n    else:\n        upper_level_lineage = auto_batch_casting_config.lineage_support[\n            :upper_level_lineage_dimensionality\n        ]\n        if (\n            upper_level_lineage_dimensionality < 1\n            or len(upper_level_lineage) < upper_level_lineage_dimensionality\n        ):\n            if not step_requests_batch_input:\n                raise AssumptionError(\n                    public_message=f\"Detected a situation when parameter: {parameter_name} requires dimensionality \"\n                    f\"wrapping, but registered lineage support is incompatible which should be detected \"\n                    f\"by the compiler. This is most likely a bug. \"\n                    f\"Contact Roboflow team through github issues \"\n                    f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                    f\"the problem - including workflow definition you use.\",\n                    context=\"workflow_execution | step_input_assembling\",\n                )\n            upper_level_indices = [()]\n        else:\n            upper_level_indices = dynamic_batches_manager.get_indices_for_data_lineage(\n                lineage=upper_level_lineage,\n            )\n    result = reduce_batch_dimensionality(\n        indices=indices,\n        upper_level_index=upper_level_indices,\n        data=batch_content,\n        guard_of_indices_wrapping=guard_of_indices_wrapping,\n    )\n    return (\n        result,\n        result.indices,\n        contains_empty_scalar_step_output_selector or scalars_discarded,\n    )\n\n\ndef _flatten_batch_oriented_inputs(\n    inputs: list,\n    dimensionality: int,\n) -> List[Any]:\n    if dimensionality == 0 or not isinstance(inputs, list):\n        raise AssumptionError(\n            public_message=f\"Could not prepare batch-oriented input data. This is most likely the bug. Contact \"\n            f\"Roboflow team through github issues (https://github.com/roboflow/inference/issues) \"\n            f\"providing full context of the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if dimensionality == 1:\n        return inputs\n    result = []\n    for element in inputs:\n        result.extend(\n            _flatten_batch_oriented_inputs(\n                inputs=element, dimensionality=dimensionality - 1\n            )\n        )\n    return result\n\n\ndef reduce_batch_dimensionality(\n    indices: List[DynamicBatchIndex],\n    upper_level_index: List[DynamicBatchIndex],\n    data: List[T],\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n) -> Batch[Optional[Batch[T]]]:\n    guard_of_indices_wrapping.register_wrapping(indices_before_wrapping=indices)\n    already_spotted_downgraded_indices = set()\n    wrapped_batch_index, wrapped_batch_content = [], []\n    upper_level_indices_data = {index: None for index in upper_level_index}\n    for index, data in zip(indices, data):\n        downgraded_index = index[:-1]\n        if downgraded_index in already_spotted_downgraded_indices:\n            wrapped_batch_index.append(index)\n            wrapped_batch_content.append(data)\n        else:\n            if wrapped_batch_index:\n                upper_level_indices_data[wrapped_batch_index[-1][:-1]] = Batch(\n                    content=wrapped_batch_content, indices=wrapped_batch_index\n                )\n            already_spotted_downgraded_indices.add(downgraded_index)\n            wrapped_batch_index = [index]\n            wrapped_batch_content = [data]\n    if wrapped_batch_index:\n        upper_level_indices_data[wrapped_batch_index[-1][:-1]] = Batch(\n            content=wrapped_batch_content, indices=wrapped_batch_index\n        )\n    return Batch(\n        content=[upper_level_indices_data[index] for index in upper_level_index],\n        indices=upper_level_index,\n    )\n\n\ndef ensure_compound_input_indices_match(indices: List[List[DynamicBatchIndex]]) -> None:\n    if len(indices) < 2:\n        return None\n    reference_set = set(indices[0])\n    for index in indices[1:]:\n        other_set = set(index)\n        if reference_set != other_set:\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Detected a situation when step input parameters cannot be created \"\n                f\"due to missmatch in batch element indices. This is most likely a bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n\n\ndef get_empty_batch_elements_indices(value: Any) -> Set[DynamicBatchIndex]:\n    result = set()\n    if isinstance(value, dict):\n        for v in value.values():\n            value_result = get_empty_batch_elements_indices(v)\n            result = result.union(value_result)\n    if isinstance(value, list):\n        for v in value:\n            value_result = get_empty_batch_elements_indices(v)\n            result = result.union(value_result)\n    if isinstance(value, Batch):\n        for index, value_element in value.iter_with_indices():\n            if isinstance(value_element, Batch):\n                value_result = get_empty_batch_elements_indices(value=value_element)\n                result = result.union(value_result)\n            elif value_element is None:\n                result.add(index)\n    return result\n\n\ndef remove_indices(value: Any, indices: Set[DynamicBatchIndex]) -> Any:\n    if isinstance(value, dict):\n        return {k: remove_indices(value=v, indices=indices) for k, v in value.items()}\n    if isinstance(value, list):\n        return [remove_indices(value=v, indices=indices) for v in value]\n    if isinstance(value, Batch):\n        return value.remove_by_indices(indices_to_remove=indices)\n    return value\n\n\ndef unfold_parameters(\n    parameters: Dict[str, Any],\n    indices: Optional[\n        List[tuple]\n    ] = None,  # TODO: none here is only for unit tests to pass\n) -> Generator[Dict[str, Any], None, None]:\n    batch_parameters = get_batch_parameters(parameters=parameters)\n    non_batch_parameters = {\n        k: v for k, v in parameters.items() if k not in batch_parameters\n    }\n    if not batch_parameters:\n        if not non_batch_parameters:\n            return None\n        if indices:\n            for _ in indices:\n                yield non_batch_parameters\n        else:\n            yield non_batch_parameters\n        return None\n    for unfolded_batch_parameters in iterate_over_batches(\n        batch_parameters=batch_parameters\n    ):\n        yield {**unfolded_batch_parameters, **non_batch_parameters}\n\n\ndef get_batch_parameters(parameters: Dict[str, Any]) -> Dict[str, Any]:\n    result = {}\n    for name, value in parameters.items():\n        if isinstance(value, Batch):\n            result[name] = value\n        elif isinstance(value, list) and any(isinstance(v, Batch) for v in value):\n            result[name] = value\n        elif isinstance(value, dict) and any(\n            isinstance(v, Batch) for v in value.values()\n        ):\n            result[name] = value\n    return result\n\n\ndef iterate_over_batches(\n    batch_parameters: Dict[str, Any],\n) -> Generator[Dict[str, Any], None, None]:\n    index = 0\n    end = False\n    while not end:\n        result = {}\n        for name, value in batch_parameters.items():\n            if isinstance(value, Batch):\n                if len(value) <= index:\n                    end = True\n                    break\n                result[name] = value[index]\n            elif isinstance(value, list):\n                to_yield = []\n                for element in value:\n                    if isinstance(element, Batch):\n                        if len(element) <= index:\n                            end = True\n                            break\n                        to_yield.append(element[index])\n                    else:\n                        to_yield.append(element)\n                result[name] = to_yield\n            elif isinstance(value, dict):\n                to_yield = {}\n                for key, key_value in value.items():\n                    if not isinstance(key_value, Batch):\n                        to_yield[key] = key_value\n                    else:\n                        if len(key_value) <= index:\n                            end = True\n                            break\n                        else:\n                            to_yield[key] = key_value[index]\n                result[name] = to_yield\n        index += 1\n        if not end:\n            yield result\n",
    "patch": null
  },
  {
    "trace_id": "4fc8878d-dd27-427b-9b92-bb0cc1b863cd",
    "function_name": "get_reference_lineage",
    "file_path": "inference/core/workflows/execution_engine/v1/compiler/graph_constructor.py",
    "speedup_x": 0.612501453657402,
    "review_quality": "high",
    "pre_optimization_commit": "HEAD",
    "resolution_method": "db_code_only",
    "source": "db_features",
    "original_function_code": "def get_reference_lineage(\n    step_selector: str,\n    all_data_derived_lineages: List[List[str]],\n    all_control_flow_lineages: List[List[str]],\n    input_data: StepInputData,\n    dimensionality_reference_property: Optional[str],\n) -> Tuple[List[str], List[str]]:\n    if not all_data_derived_lineages:\n        if len(all_control_flow_lineages) == 1:\n            return copy(all_control_flow_lineages[0]), copy(\n                all_control_flow_lineages[0]\n            )\n        # Multiple control-flow lineages and no data-derived lineage: pick the shortest.\n        # Mask intersection in the executor (get_masks_intersection_up_to_dimension) truncates\n        # each branch's indices to [:dimension] and intersects. Only at the minimum lineage\n        # length do all branches have comparable indices; at a higher dimension, longer-lineage\n        # indices would not match shorter ones, giving empty or wrong intersections.\n        min_lineage_len = min(len(lineage) for lineage in all_control_flow_lineages)\n        lineages_matching_min_len = [\n            _lineage\n            for _lineage in all_control_flow_lineages\n            if len(_lineage) == min_lineage_len\n        ]\n        if len(lineages_matching_min_len) == 1:\n            return copy(lineages_matching_min_len[0]), copy(\n                lineages_matching_min_len[0]\n            )\n        else:\n            raise ValueError(\n                \"SAFE-GUARD - multiple control-flow lineages with same minimum length \"\n                \"and no data-derived lineage; unique shortest lineage required.\"\n            )\n    if len(all_data_derived_lineages) == 1:\n        return copy(all_data_derived_lineages[0]), []\n    if dimensionality_reference_property not in input_data:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` expected dimensionality_reference_property \"\n            f\"presence to be verified at earlier stages, which did not happen as expected. \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    property_data = input_data[dimensionality_reference_property]\n    if property_data.is_compound_input():\n        lineage = None\n        for nested_element in property_data.iterate_through_definitions():\n            if nested_element.is_batch_oriented():\n                lineage = copy(nested_element.data_lineage)\n                return lineage, []\n        if lineage is None:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n                f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if not property_data.is_batch_oriented():\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n            f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    return copy(property_data.data_lineage), []",
    "optimized_function_code": "from typing import List, Optional, Tuple\n\nfrom inference.core.workflows.errors import AssumptionError\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import \\\n    StepInputData\n\n\ndef get_reference_lineage(\n    step_selector: str,\n    all_data_derived_lineages: List[List[str]],\n    all_control_flow_lineages: List[List[str]],\n    input_data: StepInputData,\n    dimensionality_reference_property: Optional[str],\n) -> Tuple[List[str], List[str]]:\n    if not all_data_derived_lineages:\n        if len(all_control_flow_lineages) == 1:\n            candidate = all_control_flow_lineages[0]\n            return candidate.copy(), candidate.copy()\n        # Multiple control-flow lineages and no data-derived lineage: pick the shortest.\n        # Mask intersection in the executor (get_masks_intersection_up_to_dimension) truncates\n        # each branch's indices to [:dimension] and intersects. Only at the minimum lineage\n        # length do all branches have comparable indices; at a higher dimension, longer-lineage\n        # indices would not match shorter ones, giving empty or wrong intersections.\n        min_lineage_len = None\n        lineages_matching_min_len_count = 0\n        candidate_lineage = None\n        for _lineage in all_control_flow_lineages:\n            l = len(_lineage)\n            if min_lineage_len is None or l < min_lineage_len:\n                min_lineage_len = l\n                candidate_lineage = _lineage\n                lineages_matching_min_len_count = 1\n            elif l == min_lineage_len:\n                lineages_matching_min_len_count += 1\n        if lineages_matching_min_len_count == 1:\n            return candidate_lineage.copy(), candidate_lineage.copy()\n        else:\n            raise ValueError(\n                \"SAFE-GUARD - multiple control-flow lineages with same minimum length \"\n                \"and no data-derived lineage; unique shortest lineage required.\"\n            )\n    if len(all_data_derived_lineages) == 1:\n        return all_data_derived_lineages[0].copy(), []\n    if dimensionality_reference_property not in input_data:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` expected dimensionality_reference_property \"\n            f\"presence to be verified at earlier stages, which did not happen as expected. \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    property_data = input_data[dimensionality_reference_property]\n    if property_data.is_compound_input():\n        lineage = None\n        for nested_element in property_data.iterate_through_definitions():\n            if nested_element.is_batch_oriented():\n                lineage = nested_element.data_lineage.copy()\n                return lineage, []\n        if lineage is None:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n                f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if not property_data.is_batch_oriented():\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n            f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    return property_data.data_lineage.copy(), []",
    "optimized_raw_markdown": "```python:inference/core/workflows/execution_engine/v1/compiler/graph_constructor.py\nfrom typing import List, Optional, Tuple\n\nfrom inference.core.workflows.errors import AssumptionError\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import \\\n    StepInputData\n\n\ndef get_reference_lineage(\n    step_selector: str,\n    all_data_derived_lineages: List[List[str]],\n    all_control_flow_lineages: List[List[str]],\n    input_data: StepInputData,\n    dimensionality_reference_property: Optional[str],\n) -> Tuple[List[str], List[str]]:\n    if not all_data_derived_lineages:\n        if len(all_control_flow_lineages) == 1:\n            candidate = all_control_flow_lineages[0]\n            return candidate.copy(), candidate.copy()\n        # Multiple control-flow lineages and no data-derived lineage: pick the shortest.\n        # Mask intersection in the executor (get_masks_intersection_up_to_dimension) truncates\n        # each branch's indices to [:dimension] and intersects. Only at the minimum lineage\n        # length do all branches have comparable indices; at a higher dimension, longer-lineage\n        # indices would not match shorter ones, giving empty or wrong intersections.\n        min_lineage_len = None\n        lineages_matching_min_len_count = 0\n        candidate_lineage = None\n        for _lineage in all_control_flow_lineages:\n            l = len(_lineage)\n            if min_lineage_len is None or l < min_lineage_len:\n                min_lineage_len = l\n                candidate_lineage = _lineage\n                lineages_matching_min_len_count = 1\n            elif l == min_lineage_len:\n                lineages_matching_min_len_count += 1\n        if lineages_matching_min_len_count == 1:\n            return candidate_lineage.copy(), candidate_lineage.copy()\n        else:\n            raise ValueError(\n                \"SAFE-GUARD - multiple control-flow lineages with same minimum length \"\n                \"and no data-derived lineage; unique shortest lineage required.\"\n            )\n    if len(all_data_derived_lineages) == 1:\n        return all_data_derived_lineages[0].copy(), []\n    if dimensionality_reference_property not in input_data:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` expected dimensionality_reference_property \"\n            f\"presence to be verified at earlier stages, which did not happen as expected. \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    property_data = input_data[dimensionality_reference_property]\n    if property_data.is_compound_input():\n        lineage = None\n        for nested_element in property_data.iterate_through_definitions():\n            if nested_element.is_batch_oriented():\n                lineage = nested_element.data_lineage.copy()\n                return lineage, []\n        if lineage is None:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n                f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if not property_data.is_batch_oriented():\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n            f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    return property_data.data_lineage.copy(), []\n```",
    "optimized_function_only": "def get_reference_lineage(\n    step_selector: str,\n    all_data_derived_lineages: List[List[str]],\n    all_control_flow_lineages: List[List[str]],\n    input_data: StepInputData,\n    dimensionality_reference_property: Optional[str],\n) -> Tuple[List[str], List[str]]:\n    if not all_data_derived_lineages:\n        if len(all_control_flow_lineages) == 1:\n            candidate = all_control_flow_lineages[0]\n            return candidate.copy(), candidate.copy()\n        # Multiple control-flow lineages and no data-derived lineage: pick the shortest.\n        # Mask intersection in the executor (get_masks_intersection_up_to_dimension) truncates\n        # each branch's indices to [:dimension] and intersects. Only at the minimum lineage\n        # length do all branches have comparable indices; at a higher dimension, longer-lineage\n        # indices would not match shorter ones, giving empty or wrong intersections.\n        min_lineage_len = None\n        lineages_matching_min_len_count = 0\n        candidate_lineage = None\n        for _lineage in all_control_flow_lineages:\n            l = len(_lineage)\n            if min_lineage_len is None or l < min_lineage_len:\n                min_lineage_len = l\n                candidate_lineage = _lineage\n                lineages_matching_min_len_count = 1\n            elif l == min_lineage_len:\n                lineages_matching_min_len_count += 1\n        if lineages_matching_min_len_count == 1:\n            return candidate_lineage.copy(), candidate_lineage.copy()\n        else:\n            raise ValueError(\n                \"SAFE-GUARD - multiple control-flow lineages with same minimum length \"\n                \"and no data-derived lineage; unique shortest lineage required.\"\n            )\n    if len(all_data_derived_lineages) == 1:\n        return all_data_derived_lineages[0].copy(), []\n    if dimensionality_reference_property not in input_data:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` expected dimensionality_reference_property \"\n            f\"presence to be verified at earlier stages, which did not happen as expected. \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    property_data = input_data[dimensionality_reference_property]\n    if property_data.is_compound_input():\n        lineage = None\n        for nested_element in property_data.iterate_through_definitions():\n            if nested_element.is_batch_oriented():\n                lineage = nested_element.data_lineage.copy()\n                return lineage, []\n        if lineage is None:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n                f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if not property_data.is_batch_oriented():\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n            f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    return property_data.data_lineage.copy(), []",
    "original_file_content": "from copy import copy\nfrom inference.core.workflows.errors import AssumptionError\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import StepInputData\nfrom typing import List, Optional, Tuple\n\ndef get_reference_lineage(\n    step_selector: str,\n    all_data_derived_lineages: List[List[str]],\n    all_control_flow_lineages: List[List[str]],\n    input_data: StepInputData,\n    dimensionality_reference_property: Optional[str],\n) -> Tuple[List[str], List[str]]:\n    if not all_data_derived_lineages:\n        if len(all_control_flow_lineages) == 1:\n            return copy(all_control_flow_lineages[0]), copy(\n                all_control_flow_lineages[0]\n            )\n        # Multiple control-flow lineages and no data-derived lineage: pick the shortest.\n        # Mask intersection in the executor (get_masks_intersection_up_to_dimension) truncates\n        # each branch's indices to [:dimension] and intersects. Only at the minimum lineage\n        # length do all branches have comparable indices; at a higher dimension, longer-lineage\n        # indices would not match shorter ones, giving empty or wrong intersections.\n        min_lineage_len = min(len(lineage) for lineage in all_control_flow_lineages)\n        lineages_matching_min_len = [\n            _lineage\n            for _lineage in all_control_flow_lineages\n            if len(_lineage) == min_lineage_len\n        ]\n        if len(lineages_matching_min_len) == 1:\n            return copy(lineages_matching_min_len[0]), copy(\n                lineages_matching_min_len[0]\n            )\n        else:\n            raise ValueError(\n                \"SAFE-GUARD - multiple control-flow lineages with same minimum length \"\n                \"and no data-derived lineage; unique shortest lineage required.\"\n            )\n    if len(all_data_derived_lineages) == 1:\n        return copy(all_data_derived_lineages[0]), []\n    if dimensionality_reference_property not in input_data:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` expected dimensionality_reference_property \"\n            f\"presence to be verified at earlier stages, which did not happen as expected. \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    property_data = input_data[dimensionality_reference_property]\n    if property_data.is_compound_input():\n        lineage = None\n        for nested_element in property_data.iterate_through_definitions():\n            if nested_element.is_batch_oriented():\n                lineage = copy(nested_element.data_lineage)\n                return lineage, []\n        if lineage is None:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n                f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if not property_data.is_batch_oriented():\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n            f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    return copy(property_data.data_lineage), []",
    "patch": null
  },
  {
    "trace_id": "c8a50b18-0431-47c6-88ff-3fb28b95cecf",
    "function_name": "establish_batch_oriented_step_lineage",
    "file_path": "inference/core/workflows/execution_engine/v1/compiler/graph_constructor.py",
    "speedup_x": 0.5382143891208309,
    "review_quality": "high",
    "pre_optimization_commit": "90243bdc6278ef7d17b6db09dc1eb5b0d155b4be",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def establish_batch_oriented_step_lineage(\n    step_selector: str,\n    all_data_derived_lineages: List[List[str]],\n    all_control_flow_lineages: List[List[str]],\n    input_data: StepInputData,\n    dimensionality_reference_property: Optional[str],\n    output_dimensionality_offset: int,\n) -> Tuple[List[str], List[str]]:\n    reference_lineage, control_flow_lineage_support = get_reference_lineage(\n        step_selector=step_selector,\n        all_data_derived_lineages=all_data_derived_lineages,\n        all_control_flow_lineages=all_control_flow_lineages,\n        input_data=input_data,\n        dimensionality_reference_property=dimensionality_reference_property,\n    )\n    if output_dimensionality_offset < 0:\n        result_dimensionality = reference_lineage[:output_dimensionality_offset]\n        return result_dimensionality, []\n    if output_dimensionality_offset == 0:\n        return reference_lineage, control_flow_lineage_support\n    reference_lineage.append(step_selector)\n    return reference_lineage, []\n",
    "optimized_function_code": "from typing import List, Optional, Tuple\n\nfrom inference.core.workflows.errors import AssumptionError\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import \\\n    StepInputData\n\n\ndef establish_batch_oriented_step_lineage(\n    step_selector: str,\n    all_data_derived_lineages: List[List[str]],\n    all_control_flow_lineages: List[List[str]],\n    input_data: StepInputData,\n    dimensionality_reference_property: Optional[str],\n    output_dimensionality_offset: int,\n) -> Tuple[List[str], List[str]]:\n    reference_lineage, control_flow_lineage_support = get_reference_lineage(\n        step_selector=step_selector,\n        all_data_derived_lineages=all_data_derived_lineages,\n        all_control_flow_lineages=all_control_flow_lineages,\n        input_data=input_data,\n        dimensionality_reference_property=dimensionality_reference_property,\n    )\n    if output_dimensionality_offset < 0:\n        result_dimensionality = reference_lineage[:output_dimensionality_offset]\n        return result_dimensionality, []\n    if output_dimensionality_offset == 0:\n        return reference_lineage, control_flow_lineage_support\n    reference_lineage.append(step_selector)\n    return reference_lineage, []\n\n\ndef get_reference_lineage(\n    step_selector: str,\n    all_data_derived_lineages: List[List[str]],\n    all_control_flow_lineages: List[List[str]],\n    input_data: StepInputData,\n    dimensionality_reference_property: Optional[str],\n) -> Tuple[List[str], List[str]]:\n    if not all_data_derived_lineages:\n        if len(all_control_flow_lineages) == 1:\n            # Return two separate shallow copies to match original behavior\n            return list(all_control_flow_lineages[0]), list(all_control_flow_lineages[0])\n        # Multiple control-flow lineages and no data-derived lineage: pick the shortest.\n        # Mask intersection in the executor (get_masks_intersection_up_to_dimension) truncates\n        # each branch's indices to [:dimension] and intersects. Only at the minimum lineage\n        # length do all branches have comparable indices; at a higher dimension, longer-lineage\n        # indices would not match shorter ones, giving empty or wrong intersections.\n        if not all_control_flow_lineages:\n            # Match original behavior where min() on empty would raise ValueError\n            raise ValueError(\"min() arg is an empty sequence\")\n        # Single-pass scan to find the unique shortest lineage without constructing intermediate lists\n        min_lineage_len = None\n        candidate = None\n        match_count = 0\n        for _lineage in all_control_flow_lineages:\n            l = len(_lineage)\n            if min_lineage_len is None or l < min_lineage_len:\n                min_lineage_len = l\n                candidate = _lineage\n                match_count = 1\n            elif l == min_lineage_len:\n                match_count += 1\n        if match_count == 1:\n            return list(candidate), list(candidate)\n        else:\n            raise AssumptionError(\n                \"SAFE-GUARD - multiple control-flow lineages with same minimum length \"\n                \"and no data-derived lineage; unique shortest lineage required.\"\n            )\n    if len(all_data_derived_lineages) == 1:\n        return list(all_data_derived_lineages[0]), []\n    if dimensionality_reference_property not in input_data:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` expected dimensionality_reference_property \"\n            f\"presence to be verified at earlier stages, which did not happen as expected. \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    property_data = input_data[dimensionality_reference_property]\n    if property_data.is_compound_input():\n        lineage = None\n        for nested_element in property_data.iterate_through_definitions():\n            if nested_element.is_batch_oriented():\n                lineage = list(nested_element.data_lineage)\n                return lineage, []\n        if lineage is None:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n                f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if not property_data.is_batch_oriented():\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n            f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    return list(property_data.data_lineage), []",
    "optimized_raw_markdown": "```python:inference/core/workflows/execution_engine/v1/compiler/graph_constructor.py\nfrom typing import List, Optional, Tuple\n\nfrom inference.core.workflows.errors import AssumptionError\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import \\\n    StepInputData\n\n\ndef establish_batch_oriented_step_lineage(\n    step_selector: str,\n    all_data_derived_lineages: List[List[str]],\n    all_control_flow_lineages: List[List[str]],\n    input_data: StepInputData,\n    dimensionality_reference_property: Optional[str],\n    output_dimensionality_offset: int,\n) -> Tuple[List[str], List[str]]:\n    reference_lineage, control_flow_lineage_support = get_reference_lineage(\n        step_selector=step_selector,\n        all_data_derived_lineages=all_data_derived_lineages,\n        all_control_flow_lineages=all_control_flow_lineages,\n        input_data=input_data,\n        dimensionality_reference_property=dimensionality_reference_property,\n    )\n    if output_dimensionality_offset < 0:\n        result_dimensionality = reference_lineage[:output_dimensionality_offset]\n        return result_dimensionality, []\n    if output_dimensionality_offset == 0:\n        return reference_lineage, control_flow_lineage_support\n    reference_lineage.append(step_selector)\n    return reference_lineage, []\n\n\ndef get_reference_lineage(\n    step_selector: str,\n    all_data_derived_lineages: List[List[str]],\n    all_control_flow_lineages: List[List[str]],\n    input_data: StepInputData,\n    dimensionality_reference_property: Optional[str],\n) -> Tuple[List[str], List[str]]:\n    if not all_data_derived_lineages:\n        if len(all_control_flow_lineages) == 1:\n            # Return two separate shallow copies to match original behavior\n            return list(all_control_flow_lineages[0]), list(all_control_flow_lineages[0])\n        # Multiple control-flow lineages and no data-derived lineage: pick the shortest.\n        # Mask intersection in the executor (get_masks_intersection_up_to_dimension) truncates\n        # each branch's indices to [:dimension] and intersects. Only at the minimum lineage\n        # length do all branches have comparable indices; at a higher dimension, longer-lineage\n        # indices would not match shorter ones, giving empty or wrong intersections.\n        if not all_control_flow_lineages:\n            # Match original behavior where min() on empty would raise ValueError\n            raise ValueError(\"min() arg is an empty sequence\")\n        # Single-pass scan to find the unique shortest lineage without constructing intermediate lists\n        min_lineage_len = None\n        candidate = None\n        match_count = 0\n        for _lineage in all_control_flow_lineages:\n            l = len(_lineage)\n            if min_lineage_len is None or l < min_lineage_len:\n                min_lineage_len = l\n                candidate = _lineage\n                match_count = 1\n            elif l == min_lineage_len:\n                match_count += 1\n        if match_count == 1:\n            return list(candidate), list(candidate)\n        else:\n            raise AssumptionError(\n                \"SAFE-GUARD - multiple control-flow lineages with same minimum length \"\n                \"and no data-derived lineage; unique shortest lineage required.\"\n            )\n    if len(all_data_derived_lineages) == 1:\n        return list(all_data_derived_lineages[0]), []\n    if dimensionality_reference_property not in input_data:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` expected dimensionality_reference_property \"\n            f\"presence to be verified at earlier stages, which did not happen as expected. \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    property_data = input_data[dimensionality_reference_property]\n    if property_data.is_compound_input():\n        lineage = None\n        for nested_element in property_data.iterate_through_definitions():\n            if nested_element.is_batch_oriented():\n                lineage = list(nested_element.data_lineage)\n                return lineage, []\n        if lineage is None:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n                f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if not property_data.is_batch_oriented():\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n            f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    return list(property_data.data_lineage), []\n```",
    "optimized_function_only": "def establish_batch_oriented_step_lineage(\n    step_selector: str,\n    all_data_derived_lineages: List[List[str]],\n    all_control_flow_lineages: List[List[str]],\n    input_data: StepInputData,\n    dimensionality_reference_property: Optional[str],\n    output_dimensionality_offset: int,\n) -> Tuple[List[str], List[str]]:\n    reference_lineage, control_flow_lineage_support = get_reference_lineage(\n        step_selector=step_selector,\n        all_data_derived_lineages=all_data_derived_lineages,\n        all_control_flow_lineages=all_control_flow_lineages,\n        input_data=input_data,\n        dimensionality_reference_property=dimensionality_reference_property,\n    )\n    if output_dimensionality_offset < 0:\n        result_dimensionality = reference_lineage[:output_dimensionality_offset]\n        return result_dimensionality, []\n    if output_dimensionality_offset == 0:\n        return reference_lineage, control_flow_lineage_support\n    reference_lineage.append(step_selector)\n    return reference_lineage, []\n",
    "original_file_content": "import itertools\nfrom collections import defaultdict\nfrom copy import copy, deepcopy\nfrom typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union\nfrom uuid import uuid4\n\nimport networkx as nx\nfrom networkx import DiGraph\n\nfrom inference.core import logger\nfrom inference.core.workflows.errors import (\n    AssumptionError,\n    BlockInterfaceError,\n    ControlFlowDefinitionError,\n    ExecutionGraphStructureError,\n    InvalidReferenceTargetError,\n    StepInputDimensionalityError,\n    StepInputLineageError,\n    WorkflowBlockError,\n)\nfrom inference.core.workflows.execution_engine.constants import (\n    NODE_COMPILATION_OUTPUT_PROPERTY,\n    PARSED_NODE_INPUT_SELECTORS_PROPERTY,\n    TOP_LEVEL_LINEAGES_KEY,\n    WORKFLOW_INPUT_BATCH_LINEAGE_ID,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    InputType,\n    JsonField,\n    OutputDefinition,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    STEP_AS_SELECTED_ELEMENT,\n    Kind,\n)\nfrom inference.core.workflows.execution_engine.introspection.entities import (\n    ParsedSelector,\n)\nfrom inference.core.workflows.execution_engine.introspection.selectors_parser import (\n    get_step_selectors,\n)\nfrom inference.core.workflows.execution_engine.profiling.core import (\n    WorkflowsProfiler,\n    execution_phase,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import (\n    AutoBatchCastingConfig,\n    CompoundStepInputDefinition,\n    DictOfStepInputDefinitions,\n    DynamicStepInputDefinition,\n    ExecutionGraphNode,\n    InputDimensionalitySpecification,\n    InputNode,\n    ListOfStepInputDefinitions,\n    NodeCategory,\n    NodeInputCategory,\n    OutputNode,\n    ParameterSpecification,\n    ParsedWorkflowDefinition,\n    PropertyPredecessorDefinition,\n    StaticStepInputDefinition,\n    StepInputData,\n    StepInputDefinition,\n    StepNode,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.graph_traversal import (\n    traverse_graph_ensuring_parents_are_reached_first,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.reference_type_checker import (\n    validate_reference_kinds,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import (\n    construct_input_selector,\n    construct_output_selector,\n    construct_step_selector,\n    get_last_chunk_of_selector,\n    get_nodes_of_specific_category,\n    get_step_selector_from_its_output,\n    identify_lineage,\n    is_control_flow_step,\n    is_input_node,\n    is_input_selector,\n    is_output_node,\n    is_step_node,\n    is_step_output_selector,\n    is_step_selector,\n    node_as,\n)\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nNODE_DEFINITION_KEY = \"definition\"\nSTEP_INPUT_SELECTORS_PROPERTY = \"step_input_selectors\"\nEXCLUDED_FIELDS = {\"type\", \"name\"}\n\n\n@execution_phase(\n    name=\"execution_graph_creation\",\n    categories=[\"execution_engine_operation\"],\n)\ndef prepare_execution_graph(\n    workflow_definition: ParsedWorkflowDefinition,\n    profiler: Optional[WorkflowsProfiler] = None,\n) -> DiGraph:\n    execution_graph = construct_graph(\n        workflow_definition=workflow_definition,\n    )\n    if not nx.is_directed_acyclic_graph(execution_graph):\n        raise ExecutionGraphStructureError(\n            public_message=f\"Detected cycle in execution graph. This means that there is output from one \"\n            f\"step that is connected to input of other step creating loop in the graph that would \"\n            f\"never end if executed.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    return denote_data_flow_in_workflow(\n        execution_graph=execution_graph,\n        parsed_workflow_definition=workflow_definition,\n    )\n\n\ndef construct_graph(\n    workflow_definition: ParsedWorkflowDefinition,\n) -> DiGraph:\n    execution_graph = nx.DiGraph()\n    execution_graph = add_input_nodes_for_graph(\n        inputs=workflow_definition.inputs,\n        execution_graph=execution_graph,\n    )\n    execution_graph = add_steps_nodes_for_graph(\n        steps=workflow_definition.steps,\n        execution_graph=execution_graph,\n    )\n    execution_graph = add_output_nodes_for_graph(\n        outputs=workflow_definition.outputs,\n        execution_graph=execution_graph,\n    )\n    execution_graph = add_steps_edges(\n        workflow_definition=workflow_definition,\n        execution_graph=execution_graph,\n    )\n    return add_edges_for_outputs(\n        workflow_definition=workflow_definition,\n        execution_graph=execution_graph,\n    )\n\n\ndef add_input_nodes_for_graph(\n    inputs: List[InputType],\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for input_spec in inputs:\n        input_selector = construct_input_selector(input_name=input_spec.name)\n        if input_spec.is_batch_oriented():\n            if input_spec.dimensionality < 1:\n                raise ExecutionGraphStructureError(\n                    public_message=f\"Detected batch oriented input `{input_spec.name}` with \"\n                    f\"declared dimensionality `{input_spec.dimensionality}` which is below \"\n                    f\"one (one is minimum dimensionality of the batch). Fix input definition in\"\n                    f\"your Workflow.\",\n                    context=\"workflow_compilation | execution_graph_construction\",\n                )\n            data_lineage = [WORKFLOW_INPUT_BATCH_LINEAGE_ID]\n            for _ in range(input_spec.dimensionality - 1):\n                # TODO: this may end up being a bug - with ability for multi-step debugging, if we will\n                #  ever have a situation that there will be multiple step outputs with nested\n                #  dimensionality with the same lineage, this re-construction method will\n                #  assign a different lineage identifier, causing the inputs being non-composable in\n                #  a single execution branch\n                data_lineage.append(f\"{uuid4()}\")\n        else:\n            data_lineage = []\n        compilation_output = InputNode(\n            node_category=NodeCategory.INPUT_NODE,\n            name=input_spec.name,\n            selector=input_selector,\n            data_lineage=data_lineage,\n            input_manifest=input_spec,\n        )\n        execution_graph.add_node(\n            input_selector,\n            **{\n                NODE_COMPILATION_OUTPUT_PROPERTY: compilation_output,\n            },\n        )\n    return execution_graph\n\n\ndef add_steps_nodes_for_graph(\n    steps: List[WorkflowBlockManifest],\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for step in steps:\n        step_selector = construct_step_selector(step_name=step.name)\n        compilation_output = StepNode(\n            node_category=NodeCategory.STEP_NODE,\n            name=step.name,\n            selector=step_selector,\n            data_lineage=[],\n            step_manifest=step,\n        )\n        execution_graph.add_node(\n            step_selector,\n            **{\n                NODE_COMPILATION_OUTPUT_PROPERTY: compilation_output,\n            },\n        )\n    return execution_graph\n\n\ndef add_output_nodes_for_graph(\n    outputs: List[JsonField],\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for output_spec in outputs:\n        output_selector = construct_output_selector(name=output_spec.name)\n        compilation_output = OutputNode(\n            node_category=NodeCategory.OUTPUT_NODE,\n            name=output_spec.name,\n            selector=output_selector,\n            data_lineage=[],\n            output_manifest=output_spec,\n        )\n        execution_graph.add_node(\n            output_selector,\n            **{\n                NODE_COMPILATION_OUTPUT_PROPERTY: compilation_output,\n            },\n        )\n    return execution_graph\n\n\ndef add_steps_edges(\n    workflow_definition: ParsedWorkflowDefinition,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for step in workflow_definition.steps:\n        source_step_selector = construct_step_selector(step_name=step.name)\n        step_selectors = get_step_selectors(step_manifest=step)\n        execution_graph.nodes[source_step_selector][\n            PARSED_NODE_INPUT_SELECTORS_PROPERTY\n        ] = step_selectors\n        execution_graph = add_edges_for_step(\n            execution_graph=execution_graph,\n            source_step_selector=source_step_selector,\n            target_step_parsed_selectors=step_selectors,\n        )\n    return execution_graph\n\n\ndef add_edges_for_step(\n    execution_graph: DiGraph,\n    source_step_selector: str,\n    target_step_parsed_selectors: List[ParsedSelector],\n) -> DiGraph:\n    for target_step_parsed_selector in target_step_parsed_selectors:\n        execution_graph = add_edge_for_step(\n            execution_graph=execution_graph,\n            source_step_selector=source_step_selector,\n            target_step_parsed_selector=target_step_parsed_selector,\n        )\n    return execution_graph\n\n\ndef add_edge_for_step(\n    execution_graph: DiGraph,\n    source_step_selector: str,\n    target_step_parsed_selector: ParsedSelector,\n) -> DiGraph:\n    target_step_selector = get_step_selector_from_its_output(\n        step_output_selector=target_step_parsed_selector.value\n    )\n    verify_edge_is_created_between_existing_nodes(\n        execution_graph=execution_graph,\n        start=source_step_selector,\n        end=target_step_selector,\n    )\n    if is_step_selector(target_step_parsed_selector.value):\n        return establish_control_flow_edge(\n            source_step_selector=source_step_selector,\n            target_step_parsed_selector=target_step_parsed_selector,\n            execution_graph=execution_graph,\n        )\n    if is_input_selector(target_step_parsed_selector.value):\n        input_node_compilation_data = node_as(\n            execution_graph=execution_graph,\n            node=target_step_parsed_selector.value,\n            expected_type=InputNode,\n        )\n        actual_input_kind = input_node_compilation_data.input_manifest.kind\n    else:\n        other_step_compilation_data = node_as(\n            execution_graph=execution_graph,\n            node=target_step_selector,\n            expected_type=StepNode,\n        )\n        source_step_compilation_data = node_as(\n            execution_graph=execution_graph,\n            node=source_step_selector,\n            expected_type=StepNode,\n        )\n        actual_input_kind = get_kind_of_value_provided_in_step_output(\n            step_manifest=other_step_compilation_data.step_manifest,\n            step_property=get_last_chunk_of_selector(\n                selector=target_step_parsed_selector.value\n            ),\n            source_step_manifest=source_step_compilation_data.step_manifest,\n        )\n    expected_input_kind = list(\n        itertools.chain.from_iterable(\n            ref.kind\n            for ref in target_step_parsed_selector.definition.allowed_references\n        )\n    )\n    error_message = (\n        f\"Failed to validate reference provided for step: {source_step_selector} regarding property: \"\n        f\"{target_step_parsed_selector.definition.property_name} with value: {target_step_parsed_selector.value}. \"\n        f\"Allowed kinds of references for this property: {list(set(e.name for e in expected_input_kind))}. \"\n        f\"Types of output for referred property: \"\n        f\"{list(set(a.name if isinstance(a, Kind) else a for a in actual_input_kind))}\"\n    )\n    validate_reference_kinds(\n        expected=expected_input_kind,\n        actual=actual_input_kind,\n        error_message=error_message,\n    )\n    if execution_graph.has_edge(target_step_selector, source_step_selector):\n        edge_data = execution_graph.edges[(target_step_selector, source_step_selector)]\n        if STEP_INPUT_SELECTORS_PROPERTY not in edge_data:\n            edge_data[STEP_INPUT_SELECTORS_PROPERTY] = []\n        edge_data[STEP_INPUT_SELECTORS_PROPERTY].append(\n            target_step_parsed_selector,\n        )\n    else:\n        execution_graph.add_edge(\n            target_step_selector,\n            source_step_selector,\n            **{STEP_INPUT_SELECTORS_PROPERTY: [target_step_parsed_selector]},\n        )\n    return execution_graph\n\n\ndef establish_control_flow_edge(\n    source_step_selector: str,\n    target_step_parsed_selector: ParsedSelector,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    if not step_definition_allows_control_flow_references(\n        parsed_selector=target_step_parsed_selector\n    ):\n        raise ExecutionGraphStructureError(\n            public_message=f\"Detected reference to other step in manifest of step {source_step_selector}. \"\n            f\"This is not allowed, as step manifest does not define any properties of type `StepSelector` \"\n            f\"allowing for defining connections between steps that represent flow control in `workflows`.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    target_step_selector = get_step_selector_from_its_output(\n        step_output_selector=target_step_parsed_selector.value\n    )\n    source_compilation_data = node_as(\n        execution_graph=execution_graph,\n        node=source_step_selector,\n        expected_type=StepNode,\n    )\n    target_compilation_data = node_as(\n        execution_graph=execution_graph,\n        node=target_step_selector,\n        expected_type=StepNode,\n    )\n    nodes_categories = {\n        source_compilation_data.node_category,\n        target_compilation_data.node_category,\n    }\n    if nodes_categories != {NodeCategory.STEP_NODE}:\n        raise ExecutionGraphStructureError(\n            public_message=f\"Attempted to create flow-control connection between workflow nodes: \"\n            f\"{source_step_selector} and {target_step_selector}, one of which is not denoted\"\n            f\"as step node.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    execution_graph.add_edge(\n        source_step_selector,\n        target_step_selector,\n    )\n    if target_step_selector in source_compilation_data.child_execution_branches:\n        raise ExecutionGraphStructureError(\n            public_message=f\"While establishing flow-control connection between source `{source_step_selector}` \"\n            f\"and target `{target_step_selector}` it was discovered that source step defines\"\n            f\"control flow transition into target one more than once, which is not allowed as \"\n            f\"that situation creates ambiguity in selecting execution branch.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    execution_branch_name = f\"Branch[{source_step_selector} -> {target_step_parsed_selector.definition.property_name}]\"\n    source_compilation_data.child_execution_branches[target_step_selector] = (\n        execution_branch_name\n    )\n    target_compilation_data.execution_branches_impacting_inputs.add(\n        execution_branch_name\n    )\n    return execution_graph\n\n\ndef step_definition_allows_control_flow_references(\n    parsed_selector: ParsedSelector,\n) -> bool:\n    return any(\n        definition.selected_element == STEP_AS_SELECTED_ELEMENT\n        for definition in parsed_selector.definition.allowed_references\n    )\n\n\ndef get_kind_of_value_provided_in_step_output(\n    step_manifest: WorkflowBlockManifest,\n    step_property: str,\n    source_step_manifest: WorkflowBlockManifest,\n) -> List[Kind]:\n    referred_node_outputs = step_manifest.get_actual_outputs()\n    actual_kind = []\n    matched_property = False\n    for output in referred_node_outputs:\n        if output.name != step_property:\n            continue\n        matched_property = True\n        actual_kind.extend(output.kind)\n    if not matched_property:\n        property_name = get_property_with_invalid_selector(\n            manifest=source_step_manifest,\n            step_property=step_property,\n        )\n        raise ExecutionGraphStructureError(\n            public_message=f\"Found reference to non-existing property `{step_property}` of step `{step_manifest.name}`.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=source_step_manifest.name,\n                    block_type=source_step_manifest.type,\n                    property_name=property_name,\n                    property_details=f\"'{step_manifest.name}.{step_property}' is an invalid reference\",\n                )\n            ],\n        )\n    return actual_kind\n\n\ndef add_edges_for_step_inputs(\n    execution_graph: DiGraph,\n    input_selectors: Set[str],\n    step_selector: str,\n) -> DiGraph:\n    for input_selector in input_selectors:\n        if is_step_output_selector(selector_or_value=input_selector):\n            input_selector = get_step_selector_from_its_output(\n                step_output_selector=input_selector\n            )\n        verify_edge_is_created_between_existing_nodes(\n            execution_graph=execution_graph,\n            start=input_selector,\n            end=step_selector,\n        )\n        execution_graph.add_edge(input_selector, step_selector)\n    return execution_graph\n\n\ndef add_edges_for_outputs(\n    workflow_definition: ParsedWorkflowDefinition,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for output in workflow_definition.outputs:\n        node_selector = output.selector\n        if is_step_output_selector(selector_or_value=node_selector):\n            node_selector = get_step_selector_from_its_output(\n                step_output_selector=node_selector\n            )\n        output_selector = construct_output_selector(name=output.name)\n        verify_edge_is_created_between_existing_nodes(\n            execution_graph=execution_graph,\n            start=node_selector,\n            end=output_selector,\n        )\n        output_node_manifest = node_as(\n            execution_graph=execution_graph,\n            node=output_selector,\n            expected_type=OutputNode,\n        )\n        if is_step_output_selector(selector_or_value=output.selector):\n            step_manifest = execution_graph.nodes[node_selector][\n                NODE_COMPILATION_OUTPUT_PROPERTY\n            ].step_manifest\n            step_outputs = step_manifest.get_actual_outputs()\n            denote_output_node_kind_based_on_step_outputs(\n                output_selector=output.selector,\n                step_outputs=step_outputs,\n                output_node_manifest=output_node_manifest,\n            )\n        else:\n            input_manifest = node_as(\n                execution_graph=execution_graph,\n                node=node_selector,\n                expected_type=InputNode,\n            ).input_manifest\n            output_node_manifest.kind = copy(input_manifest.kind)\n        execution_graph.add_edge(node_selector, output_selector)\n    return execution_graph\n\n\ndef verify_edge_is_created_between_existing_nodes(\n    execution_graph: DiGraph,\n    start: str,\n    end: str,\n) -> None:\n    if not execution_graph.has_node(start) or not execution_graph.has_node(end):\n        invalid_block = start if not execution_graph.has_node(start) else end\n        referencing_block = end if invalid_block == start else start\n\n        step_type = None\n        property_name = None\n        if execution_graph.has_node(referencing_block):\n            if is_step_node(execution_graph, referencing_block):\n                step_manifest = node_as(\n                    execution_graph=execution_graph,\n                    node=referencing_block,\n                    expected_type=StepNode,\n                ).step_manifest\n                step_type = step_manifest.type\n                property_name = get_property_with_invalid_selector(\n                    manifest=step_manifest,\n                    step_property=invalid_block,\n                )\n\n        block_id = (\n            \"$outputs\"\n            if referencing_block.startswith(\"$outputs.\")\n            else get_last_chunk_of_selector(selector=referencing_block)\n        )\n        property_name = (\n            get_last_chunk_of_selector(selector=referencing_block)\n            if referencing_block.startswith(\"$outputs.\")\n            else property_name\n        )\n\n        is_input = is_input_selector(selector_or_value=invalid_block)\n        raise InvalidReferenceTargetError(\n            public_message=f\"Workflow references '{invalid_block}' which points to a non-existent {is_input and 'input parameter' or 'block'}.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=block_id,\n                    block_type=step_type,\n                    property_name=property_name,\n                    property_details=f\"Invalid reference to {invalid_block}\",\n                ),\n            ],\n        )\n\n\ndef denote_output_node_kind_based_on_step_outputs(\n    output_selector: str,\n    step_outputs: List[OutputDefinition],\n    output_node_manifest: OutputNode,\n) -> None:\n    selected_output_name = get_last_chunk_of_selector(selector=output_selector)\n    kinds_for_outputs = {output.name: output.kind for output in step_outputs}\n\n    if selected_output_name == \"*\":\n        output_node_manifest.kind = deepcopy(kinds_for_outputs)\n        return None\n    if selected_output_name not in kinds_for_outputs:\n        output_name = output_node_manifest.output_manifest.name\n\n        raise InvalidReferenceTargetError(\n            public_message=f\"Workflow output references '{output_selector}' which points to a non-existent block property.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=\"$outputs\",\n                    property_name=output_name,\n                    property_details=f\"Invalid reference to {output_selector}\",\n                ),\n            ],\n        )\n    output_node_manifest.kind = copy(kinds_for_outputs[selected_output_name])\n    return None\n\n\ndef denote_data_flow_in_workflow(\n    execution_graph: DiGraph,\n    parsed_workflow_definition: ParsedWorkflowDefinition,\n) -> nx.DiGraph:\n    block_manifest_by_step_name = {\n        step.name: step for step in parsed_workflow_definition.steps\n    }\n    super_input_node = \"<super-input>\"\n    execution_graph = add_super_input_node_in_execution_graph(\n        execution_graph=execution_graph,\n        super_input_node=super_input_node,\n    )\n    execution_graph.nodes[super_input_node][NODE_COMPILATION_OUTPUT_PROPERTY] = (\n        InputNode(\n            node_category=NodeCategory.INPUT_NODE,\n            name=super_input_node,\n            selector=f\"$inputs.{super_input_node}\",\n            data_lineage=[],\n            input_manifest=None,  # this is expected never to be reached\n        )\n    )\n    top_level_data_lineage = set()\n    for node in traverse_graph_ensuring_parents_are_reached_first(\n        graph=execution_graph,\n        start_node=super_input_node,\n    ):\n        execution_graph = denote_data_flow_for_node(\n            execution_graph=execution_graph,\n            node=node,\n            block_manifest_by_step_name=block_manifest_by_step_name,\n            on_top_level_lineage_denoted=lambda element: top_level_data_lineage.add(\n                element\n            ),\n        )\n    execution_graph.remove_node(super_input_node)\n    execution_graph.graph[TOP_LEVEL_LINEAGES_KEY] = top_level_data_lineage\n    return execution_graph\n\n\ndef denote_data_flow_for_node(\n    execution_graph: DiGraph,\n    node: str,\n    block_manifest_by_step_name: Dict[str, WorkflowBlockManifest],\n    on_top_level_lineage_denoted: Callable[[str], None],\n) -> DiGraph:\n    if is_input_node(execution_graph=execution_graph, node=node):\n        # everything already set there, in the previous stage of compilation\n        return execution_graph\n    if is_step_node(execution_graph=execution_graph, node=node):\n        step_name = get_last_chunk_of_selector(selector=node)\n        if step_name not in block_manifest_by_step_name:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler expected manifest for the step: {step_name} to be registered \"\n                f\"but this condition is not met. This is most likely the bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | retrieving_predecessors_for_output\",\n            )\n        manifest = block_manifest_by_step_name[step_name]\n        return denote_data_flow_for_step(\n            execution_graph=execution_graph,\n            node=node,\n            manifest=manifest,\n            on_top_level_lineage_denoted=on_top_level_lineage_denoted,\n        )\n    if is_output_node(execution_graph=execution_graph, node=node):\n        # output is allowed to have exactly one predecessor\n        output_predecessors = list(execution_graph.predecessors(node))\n        if len(output_predecessors) != 1:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler expected each output in compiled graph to have one predecessor, \"\n                f\"but this condition is not met for node {node}. This is most likely the bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | retrieving_predecessors_for_output\",\n            )\n        predecessor_node = output_predecessors[0]\n        predecessor_node_data = node_as(\n            execution_graph=execution_graph,\n            node=predecessor_node,\n            expected_type=ExecutionGraphNode,\n        )\n        predecessor_node_lineage = predecessor_node_data.data_lineage\n        output_node_data = node_as(\n            execution_graph=execution_graph,\n            node=node,\n            expected_type=OutputNode,\n        )\n        output_node_data.data_lineage = predecessor_node_lineage\n        return execution_graph\n    raise AssumptionError(\n        f\"Workflow Compiler encountered node: {node} which cannot be classified as known node type. \"\n        f\"This is most likely the bug. Contact Roboflow team through github issues \"\n        f\"(https://github.com/roboflow/inference/issues) providing full \"\n        f\"context of the problem - including workflow definition you use.\",\n        context=\"workflow_compilation | execution_graph_construction | denoting_data_flow_for_step\",\n    )\n\n\ndef denote_data_flow_for_step(\n    execution_graph: DiGraph,\n    node: str,\n    manifest: WorkflowBlockManifest,\n    on_top_level_lineage_denoted: Callable[[str], None],\n) -> DiGraph:\n    all_control_flow_predecessors, all_non_control_flow_predecessors = (\n        separate_control_flow_predecessors_from_data_providers(\n            execution_graph=execution_graph, node=node\n        )\n    )\n    input_data = build_input_data_for_step(\n        manifest=manifest,\n        step_node=node,\n        data_providing_predecessors=all_non_control_flow_predecessors,\n        execution_graph=execution_graph,\n    )\n    step_name = get_last_chunk_of_selector(node)\n    step_node_data = node_as(\n        execution_graph=execution_graph,\n        node=node,\n        expected_type=StepNode,\n    )\n    parsed_step_input_selectors: List[ParsedSelector] = execution_graph.nodes[node][\n        PARSED_NODE_INPUT_SELECTORS_PROPERTY\n    ]\n    batch_compatibility_of_properties = retrieve_batch_compatibility_of_input_selectors(\n        input_selectors=parsed_step_input_selectors\n    )\n    scalar_parameters_to_be_batched = (\n        verify_declared_batch_compatibility_against_actual_inputs(\n            node=node,\n            step_node_data=step_node_data,\n            input_data=input_data,\n            batch_compatibility_of_properties=batch_compatibility_of_properties,\n        )\n    )\n    input_dimensionality_offsets = manifest.get_input_dimensionality_offsets()\n    verify_step_input_dimensionality_offsets(\n        step_name=step_name,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n    )\n    inputs_dimensionalities = get_inputs_dimensionalities(\n        step_name=step_name,\n        step_type=manifest.type,\n        input_data=input_data,\n        scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n    )\n    logger.debug(\n        f\"For step: {node}, detected the following input dimensionalities: {inputs_dimensionalities}\"\n    )\n    parameters_with_batch_inputs = grab_parameters_defining_batch_inputs(\n        inputs_dimensionalities=inputs_dimensionalities,\n    )\n    dimensionality_reference_property = manifest.get_dimensionality_reference_property()\n    output_dimensionality_offset = manifest.get_output_dimensionality_offset()\n    verify_step_input_dimensionality_offsets(\n        step_name=step_name,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n    )\n    verify_output_offset(\n        step_name=step_name,\n        parameters_with_batch_inputs=parameters_with_batch_inputs,\n        dimensionality_reference_property=dimensionality_reference_property,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n        output_dimensionality_offset=output_dimensionality_offset,\n    )\n    verify_input_data_dimensionality(\n        step_name=step_name,\n        step_type=manifest.type,\n        dimensionality_reference_property=dimensionality_reference_property,\n        inputs_dimensionalities=inputs_dimensionalities,\n        dimensionality_offstes=input_dimensionality_offsets,\n    )\n    all_data_derived_lineages = get_input_data_lineage_excluding_auto_batch_casting(\n        step_name=step_name,\n        input_data=input_data,\n        scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n    )\n    all_control_flow_lineages = get_lineage_derived_from_control_flow(\n        control_flow_steps_selectors=all_control_flow_predecessors,\n        execution_graph=execution_graph,\n    )\n    verify_compatibility_of_input_data_lineage_with_control_flow_lineage(\n        step_name=step_name,\n        inputs_lineage=all_data_derived_lineages,\n        control_flow_steps_selectors=all_control_flow_predecessors,\n        execution_graph=execution_graph,\n    )\n    step_node_data.input_data = input_data\n    step_node_data.dimensionality_reference_property = dimensionality_reference_property\n    step_node_data.control_flow_lineage_dims = [\n        len(_lineage) for _lineage in all_control_flow_lineages if _lineage\n    ]\n    step_node_data.batch_oriented_parameters = parameters_with_batch_inputs\n    if not all_data_derived_lineages and not all_control_flow_lineages:\n        if manifest.get_output_dimensionality_offset() > 0:\n            # brave decision to open a Pandora box\n            data_lineage = [node]\n        else:\n            data_lineage = []\n        control_flow_lineage_support = []\n    else:\n        data_lineage, control_flow_lineage_support = (\n            establish_batch_oriented_step_lineage(\n                step_selector=node,\n                all_data_derived_lineages=all_data_derived_lineages,\n                all_control_flow_lineages=all_control_flow_lineages,\n                input_data=input_data,\n                dimensionality_reference_property=dimensionality_reference_property,\n                output_dimensionality_offset=output_dimensionality_offset,\n            )\n        )\n    step_node_data.step_execution_dimensionality = (\n        establish_step_execution_dimensionality(\n            inputs_dimensionalities=inputs_dimensionalities,\n            control_flow_lineage_support=control_flow_lineage_support,\n            output_dimensionality_offset=output_dimensionality_offset,\n        )\n    )\n    lineage_supports = get_lineage_support_for_auto_batch_casted_parameters(\n        input_dimensionalities=inputs_dimensionalities,\n        all_lineages_of_batch_parameters=all_data_derived_lineages,\n        scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n    )\n    step_node_data.auto_batch_casting_lineage_supports = lineage_supports\n    step_node_data.control_flow_lineage_support = control_flow_lineage_support\n    if data_lineage:\n        on_top_level_lineage_denoted(data_lineage[0])\n    step_node_data.data_lineage = data_lineage\n    return execution_graph\n\n\ndef _collect_unique_control_flow_lineages_with_step_mapping(\n    control_flow_steps_selectors: List[str],\n    execution_graph: nx.DiGraph,\n) -> Tuple[List[List[str]], Dict[int, List[str]]]:\n    \"\"\"\n    Collect data lineages from control flow steps and deduplicate by lineage id.\n\n    For each given control flow step selector, reads its data_lineage from the\n    execution graph. Returns unique non-empty lineages (by identify_lineage id)\n    and a mapping from lineage id to every step selector that produced that\n    lineage (used e.g. for error reporting when lineage is incompatible).\n\n    Args:\n        control_flow_steps_selectors: Step selectors (node ids) of control\n            flow steps whose data_lineage is to be collected.\n        execution_graph: The workflow execution graph containing step nodes\n            and their data_lineage.\n\n    Returns:\n        A tuple of (unique_lineages, lineage_id_to_step_selectors):\n        - unique_lineages: list of distinct non-empty data lineages.\n        - lineage_id_to_step_selectors: map from lineage id to list of step\n          selectors whose data_lineage has that id (includes empty lineages).\n    \"\"\"\n    unique_lineages: List[List[str]] = []\n    seen_lineage_ids: Set[int] = set()\n    lineage_id_to_step_selectors: Dict[int, List[str]] = defaultdict(list)\n\n    for step_selector in control_flow_steps_selectors:\n        step_data = node_as(\n            execution_graph=execution_graph,\n            node=step_selector,\n            expected_type=StepNode,\n        )\n        lineage = step_data.data_lineage\n        lineage_id = identify_lineage(lineage)\n        lineage_id_to_step_selectors[lineage_id].append(step_selector)\n        if lineage and lineage_id not in seen_lineage_ids:\n            seen_lineage_ids.add(lineage_id)\n            unique_lineages.append(lineage)\n\n    return unique_lineages, dict(lineage_id_to_step_selectors)\n\n\ndef get_lineage_derived_from_control_flow(\n    control_flow_steps_selectors: List[str],\n    execution_graph: nx.DiGraph,\n) -> List[List[str]]:\n    \"\"\"\n    Return unique non-empty data lineages from the given control flow steps.\n\n    Each lineage is taken from the step's data_lineage in the execution graph.\n    Lineages are deduplicated by lineage id (see identify_lineage); empty\n    lineages are omitted. Used when establishing batch-oriented step lineage.\n\n    Args:\n        control_flow_steps_selectors: Step selectors (node ids) of control\n            flow steps whose data_lineage is to be collected.\n        execution_graph: The workflow execution graph containing step nodes\n            and their data_lineage.\n\n    Returns:\n        List of distinct non-empty data lineages, one per unique lineage id.\n    \"\"\"\n    unique_lineages, _ = _collect_unique_control_flow_lineages_with_step_mapping(\n        control_flow_steps_selectors=control_flow_steps_selectors,\n        execution_graph=execution_graph,\n    )\n    return unique_lineages\n\n\ndef separate_control_flow_predecessors_from_data_providers(\n    execution_graph: DiGraph,\n    node: str,\n) -> Tuple[List[str], List[str]]:\n    all_predecessors = list(execution_graph.predecessors(node))\n    all_control_flow_predecessors = [\n        predecessor\n        for predecessor in all_predecessors\n        if is_control_flow_step(execution_graph=execution_graph, node=predecessor)\n    ]\n    all_non_control_flow_predecessors = [\n        predecessor\n        for predecessor in all_predecessors\n        if not is_control_flow_step(execution_graph=execution_graph, node=predecessor)\n    ]\n    return all_control_flow_predecessors, all_non_control_flow_predecessors\n\n\ndef build_input_data_for_step(\n    manifest: WorkflowBlockManifest,\n    step_node: str,\n    data_providing_predecessors: List[str],\n    execution_graph: DiGraph,\n) -> StepInputData:\n    predecessors_by_property_name = get_predecessors_for_step_manifest_properties(\n        execution_graph=execution_graph,\n        step_node=step_node,\n        data_providing_predecessors=data_providing_predecessors,\n    )\n    manifest_fields_values = get_manifest_fields_values(step_manifest=manifest)\n    result = {}\n    for name, value in manifest_fields_values.items():\n        result[name] = build_input_property(\n            step_node=step_node,\n            manifest_property_name=name,\n            manifest_property_value=value,\n            predecessors_by_property_name=predecessors_by_property_name,\n            execution_graph=execution_graph,\n        )\n    return result\n\n\ndef get_predecessors_for_step_manifest_properties(\n    execution_graph: DiGraph, step_node: str, data_providing_predecessors: List[str]\n) -> Dict[str, List[PropertyPredecessorDefinition]]:\n    predecessors_by_property_name = defaultdict(list)\n    for predecessor in data_providing_predecessors:\n        edge_data = execution_graph.edges[(predecessor, step_node)]\n        # STEP_INPUT_SELECTORS_PROPERTY is optional, as special <super-input> node may be directly\n        # connected to step\n        selectors_associated_to_edge: List[ParsedSelector] = edge_data.get(\n            STEP_INPUT_SELECTORS_PROPERTY, []\n        )\n        for selector_associated_to_edge in selectors_associated_to_edge:\n            definition = PropertyPredecessorDefinition(\n                predecessor_selector=predecessor,\n                parsed_selector=selector_associated_to_edge,\n            )\n            predecessors_by_property_name[\n                selector_associated_to_edge.definition.property_name\n            ].append(definition)\n    return predecessors_by_property_name\n\n\ndef build_input_property(\n    step_node: str,\n    manifest_property_name: str,\n    manifest_property_value: Any,\n    predecessors_by_property_name: Dict[str, List[PropertyPredecessorDefinition]],\n    execution_graph: DiGraph,\n) -> Union[StepInputDefinition, CompoundStepInputDefinition]:\n    if manifest_property_name not in predecessors_by_property_name:\n        return StaticStepInputDefinition(\n            parameter_specification=ParameterSpecification(\n                parameter_name=manifest_property_name,\n            ),\n            category=NodeInputCategory.STATIC_VALUE,\n            value=manifest_property_value,\n        )\n    if isinstance(manifest_property_value, dict):\n        return build_nested_dictionary_for_input_property(\n            step_node=step_node,\n            manifest_property_name=manifest_property_name,\n            manifest_property_value=manifest_property_value,\n            predecessors_definitions=predecessors_by_property_name[\n                manifest_property_name\n            ],\n            execution_graph=execution_graph,\n        )\n    if isinstance(manifest_property_value, list):\n        return build_nested_list_for_input_property(\n            step_node=step_node,\n            manifest_property_name=manifest_property_name,\n            manifest_property_value=manifest_property_value,\n            predecessors_definitions=predecessors_by_property_name[\n                manifest_property_name\n            ],\n            execution_graph=execution_graph,\n        )\n    matching_predecessors_data = predecessors_by_property_name[manifest_property_name]\n    if len(matching_predecessors_data) != 1:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler deduced that property `{manifest_property_name}` of step `{step_node}` \"\n            f\"should be fed with data coming from exactly one execution graph node, but found \"\n            f\"{len(matching_predecessors_data)} data sources. This is most likely the bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n        )\n    predecessor_selector, predecessor_parsed_selector = (\n        matching_predecessors_data[0].predecessor_selector,\n        matching_predecessors_data[0].parsed_selector,\n    )\n    if is_input_node(execution_graph=execution_graph, node=predecessor_selector):\n        predecessor_node_data = node_as(\n            execution_graph=execution_graph,\n            node=matching_predecessors_data[0].predecessor_selector,\n            expected_type=InputNode,\n        )\n        category = (\n            NodeInputCategory.BATCH_INPUT_PARAMETER\n            if predecessor_node_data.is_batch_oriented()\n            else NodeInputCategory.NON_BATCH_INPUT_PARAMETER\n        )\n        return DynamicStepInputDefinition(\n            parameter_specification=ParameterSpecification(\n                parameter_name=manifest_property_name,\n            ),\n            category=category,\n            data_lineage=predecessor_node_data.data_lineage,\n            selector=predecessor_node_data.selector,\n        )\n    if is_step_node(execution_graph=execution_graph, node=predecessor_selector):\n        predecessor_node_data = node_as(\n            execution_graph=execution_graph,\n            node=matching_predecessors_data[0].predecessor_selector,\n            expected_type=StepNode,\n        )\n        category = (\n            NodeInputCategory.BATCH_STEP_OUTPUT\n            if predecessor_node_data.output_dimensionality > 0\n            else NodeInputCategory.NON_BATCH_STEP_OUTPUT\n        )\n        return DynamicStepInputDefinition(\n            parameter_specification=ParameterSpecification(\n                parameter_name=manifest_property_name,\n            ),\n            category=category,\n            data_lineage=predecessor_node_data.data_lineage,\n            selector=predecessor_parsed_selector.value,\n        )\n    raise AssumptionError(\n        public_message=f\"Workflow Compiler for property `{manifest_property_name}` of step `{step_node}` \"\n        f\"found data providing predecessor `{predecessor_selector}` which has unsupported step type.\"\n        f\"This is most likely the bug. \"\n        f\"Contact Roboflow team through github issues \"\n        f\"(https://github.com/roboflow/inference/issues) providing full \"\n        f\"context of the problem - including workflow definition you use.\",\n        context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n    )\n\n\ndef build_nested_dictionary_for_input_property(\n    step_node: str,\n    manifest_property_name: str,\n    manifest_property_value: dict,\n    predecessors_definitions: List[PropertyPredecessorDefinition],\n    execution_graph: DiGraph,\n) -> DictOfStepInputDefinitions:\n    nested_property_name2data: Dict[Optional[str], PropertyPredecessorDefinition] = {\n        predecessor_definition.parsed_selector.key: predecessor_definition\n        for predecessor_definition in predecessors_definitions\n    }\n    result = {}\n    for nested_dict_key, nested_dict_value in manifest_property_value.items():\n        if nested_dict_key not in nested_property_name2data:\n            result[nested_dict_key] = StaticStepInputDefinition(\n                parameter_specification=ParameterSpecification(\n                    parameter_name=manifest_property_name,\n                    nested_element_key=nested_dict_key,\n                ),\n                category=NodeInputCategory.STATIC_VALUE,\n                value=nested_dict_value,\n            )\n            continue\n        referred_node_selector = nested_property_name2data[\n            nested_dict_key\n        ].predecessor_selector\n        referred_node_parsed_selector = nested_property_name2data[\n            nested_dict_key\n        ].parsed_selector\n        if is_input_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=InputNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_INPUT_PARAMETER\n                if predecessor_node_data.is_batch_oriented()\n                else NodeInputCategory.NON_BATCH_INPUT_PARAMETER\n            )\n            result[nested_dict_key] = DynamicStepInputDefinition(\n                parameter_specification=ParameterSpecification(\n                    parameter_name=manifest_property_name,\n                    nested_element_key=nested_dict_key,\n                ),\n                category=category,\n                data_lineage=predecessor_node_data.data_lineage,\n                selector=predecessor_node_data.selector,\n            )\n            continue\n        if is_step_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=StepNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_STEP_OUTPUT\n                if predecessor_node_data.output_dimensionality > 0\n                else NodeInputCategory.NON_BATCH_STEP_OUTPUT\n            )\n            result[nested_dict_key] = DynamicStepInputDefinition(\n                parameter_specification=ParameterSpecification(\n                    parameter_name=manifest_property_name,\n                    nested_element_key=nested_dict_key,\n                ),\n                category=category,\n                data_lineage=predecessor_node_data.data_lineage,\n                selector=referred_node_parsed_selector.value,\n            )\n            continue\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for property `{manifest_property_name}` of step `{step_node}` \"\n            f\"found data providing predecessor `{referred_node_selector}` which has \"\n            f\"unsupported step type (key: {nested_dict_key} of nested data dictionary). \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n        )\n    return DictOfStepInputDefinitions(\n        name=manifest_property_name,\n        nested_definitions=result,\n    )\n\n\ndef get_manifest_fields_values(step_manifest: WorkflowBlockManifest) -> Dict[str, Any]:\n    result = {}\n    for field in step_manifest.model_fields:\n        if field in EXCLUDED_FIELDS:\n            continue\n        result[field] = getattr(step_manifest, field)\n    return result\n\n\ndef build_nested_list_for_input_property(\n    step_node: str,\n    manifest_property_name: str,\n    manifest_property_value: list,\n    predecessors_definitions: List[PropertyPredecessorDefinition],\n    execution_graph: DiGraph,\n) -> ListOfStepInputDefinitions:\n    nested_index2data: Dict[Optional[int], PropertyPredecessorDefinition] = {\n        e.parsed_selector.index: e for e in predecessors_definitions\n    }\n    result = []\n    for index, element in enumerate(manifest_property_value):\n        if index not in nested_index2data:\n            result.append(\n                StaticStepInputDefinition(\n                    parameter_specification=ParameterSpecification(\n                        parameter_name=manifest_property_name,\n                        nested_element_index=index,\n                    ),\n                    category=NodeInputCategory.STATIC_VALUE,\n                    value=element,\n                )\n            )\n            continue\n        referred_node_selector = nested_index2data[index].predecessor_selector\n        referred_node_parsed_selector = nested_index2data[index].parsed_selector\n        if is_input_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=InputNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_INPUT_PARAMETER\n                if predecessor_node_data.is_batch_oriented()\n                else NodeInputCategory.NON_BATCH_INPUT_PARAMETER\n            )\n            result.append(\n                DynamicStepInputDefinition(\n                    parameter_specification=ParameterSpecification(\n                        parameter_name=manifest_property_name,\n                        nested_element_index=index,\n                    ),\n                    category=category,\n                    data_lineage=predecessor_node_data.data_lineage,\n                    selector=predecessor_node_data.selector,\n                )\n            )\n            continue\n        if is_step_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=StepNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_STEP_OUTPUT\n                if predecessor_node_data.output_dimensionality > 0\n                else NodeInputCategory.NON_BATCH_STEP_OUTPUT\n            )\n            result.append(\n                DynamicStepInputDefinition(\n                    parameter_specification=ParameterSpecification(\n                        parameter_name=manifest_property_name,\n                        nested_element_index=index,\n                    ),\n                    category=category,\n                    data_lineage=predecessor_node_data.data_lineage,\n                    selector=referred_node_parsed_selector.value,\n                )\n            )\n            continue\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for property `{manifest_property_name}` of step `{step_node}` \"\n            f\"found data providing predecessor `{referred_node_selector}` which has \"\n            f\"unsupported step type (index: {index} of nested data list). \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n        )\n    return ListOfStepInputDefinitions(\n        name=manifest_property_name,\n        nested_definitions=result,\n    )\n\n\ndef verify_step_input_dimensionality_offsets(\n    step_name: str,\n    input_dimensionality_offsets: Dict[str, int],\n) -> None:\n    min_offset, max_offset = None, None\n    for offset in input_dimensionality_offsets.values():\n        if min_offset is None or offset < min_offset:\n            min_offset = offset\n        if max_offset is None or offset > max_offset:\n            max_offset = offset\n    if min_offset is None or max_offset is None:\n        return None\n    if min_offset < 0 or max_offset < 0:\n        raise BlockInterfaceError(\n            public_message=f\"Offsets could not be negative, but block defining step: {step_name} defines that values.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_input_offset_definitions\",\n        )\n    if abs(max_offset - min_offset) > 1:\n        raise BlockInterfaceError(\n            public_message=\"Offsets of input parameters could not differ more than 1, but block defining step {step_name} \"\n            f\"violates that rule.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_input_offset_definitions\",\n        )\n\n\ndef verify_output_offset(\n    step_name: str,\n    parameters_with_batch_inputs: Set[str],\n    input_dimensionality_offsets: Dict[str, int],\n    dimensionality_reference_property: Optional[str],\n    output_dimensionality_offset: int,\n) -> None:\n    if not parameters_with_batch_inputs and output_dimensionality_offset < 0:\n        raise StepInputDimensionalityError(\n            public_message=f\"Block defining step {step_name} defines negative dimensionality offset while only \"\n            f\"scalar inputs being provided - the block cannot run as there is no dimension to collapse.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if (\n        dimensionality_reference_property is not None\n        and dimensionality_reference_property not in parameters_with_batch_inputs\n    ):\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} defines dimensionality reference property \"\n            f\"which is not in scope of parameters bring batch-oriented input, which makes it impossible \"\n            f\"to use as reference for output dimensionality.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if output_dimensionality_offset not in {-1, 0, 1}:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} defines output dimensionality offset \"\n            f\"being {output_dimensionality_offset}, whereas it is only possible for that offset being \"\n            f\"in set [-1, 0, 1].\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    different_offsets = {o for o in input_dimensionality_offsets.values()}\n    if len(parameters_with_batch_inputs) != len(input_dimensionality_offsets):\n        # assumption of default offset being zero - and this one does not need to be manifested\n        # by block\n        different_offsets.add(0)\n    if 0 not in different_offsets and parameters_with_batch_inputs:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} explicitly defines input dimensionalities offsets\"\n            f\"with {input_dimensionality_offsets}, but the definition lack 0-level input, which is \"\n            f\"not allowed, as in this scenario offsets could be adjusted to include 0\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if len(different_offsets) > 1 and dimensionality_reference_property is None:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} explicitly defines input dimensionality \"\n            f\"offsets {input_dimensionality_offsets}. In this scenario it is required to provide dimensionality \"\n            f\"reference property.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if len(different_offsets) > 1 and output_dimensionality_offset != 0:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} explicitly defines input dimensionality \"\n            f\"offsets {input_dimensionality_offsets} and output dimensionality offset {output_dimensionality_offset} \"\n            f\"where the latter is not 0, but for inputs differing with dimensionality it is only possible to keep \"\n            f\"output dimensionality the same and point reference parameter.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n\n\ndef verify_input_data_dimensionality(\n    step_name: str,\n    step_type: str,\n    dimensionality_reference_property: Optional[str],\n    inputs_dimensionalities: Dict[str, Set[int]],\n    dimensionality_offstes: Dict[str, int],\n) -> None:\n    parameter_name2dimensionality_specification = (\n        grab_input_data_dimensionality_specifications(\n            step_name=step_name,\n            inputs_dimensionalities=inputs_dimensionalities,\n            dimensionality_offstes=dimensionality_offstes,\n        )\n    )\n    if not parameter_name2dimensionality_specification:\n        # nothing to check if no batch-oriented inputs\n        return None\n    different_dimensionalities_of_parameters = {\n        specification.actual_dimensionality\n        for specification in parameter_name2dimensionality_specification.values()\n    }\n    if dimensionality_reference_property is None:\n        if len(different_dimensionalities_of_parameters) > 1:\n            parameter2dimensionality = {\n                k: e.actual_dimensionality\n                for k, e in parameter_name2dimensionality_specification.items()\n            }\n            raise StepInputDimensionalityError(\n                public_message=f\"Block defining step {step_name} does not define dimensionality reference property, \"\n                f\"which means that all batch-oriented parameters must be at the same dimensionality level, \"\n                f\"but detected the following dimensionalities for parameters {parameter2dimensionality}\",\n                context=\"workflow_compilation | execution_graph_construction | denoting_step_inputs_dimensionality\",\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=step_name,\n                        block_type=step_type,\n                        block_details=f\"Dimensionality of input parameters doesn't match: {parameter2dimensionality}\",\n                    )\n                ],\n            )\n        return None\n    reference_specification = parameter_name2dimensionality_specification[\n        dimensionality_reference_property\n    ]\n    expected_dimensionalities = {\n        property_name: (e.expected_offset - reference_specification.expected_offset)\n        + reference_specification.actual_dimensionality\n        for property_name, e in parameter_name2dimensionality_specification.items()\n    }\n    if any(dim <= 0 for dim in expected_dimensionalities.values()):\n        raise StepInputDimensionalityError(\n            public_message=f\"Given the definition of block defining step {step_name} and data provided, \"\n            f\"the block would expect batch input dimensionality to be 0 or below, which is invalid.\",\n            context=\"workflow_compilation | execution_graph_construction | denoting_step_inputs_dimensionality\",\n        )\n    for property_name, expected_dimensionality in expected_dimensionalities.items():\n        actual_dimensionality = parameter_name2dimensionality_specification[\n            property_name\n        ].actual_dimensionality\n        if actual_dimensionality != expected_dimensionality:\n            raise StepInputDimensionalityError(\n                public_message=f\"Data fed into step `{step_name}` property `{property_name}` has \"\n                f\"actual dimensionality {actual_dimensionality}, \"\n                f\"when expected was {expected_dimensionality}\",\n                context=\"workflow_compilation | execution_graph_construction | denoting_step_inputs_dimensionality\",\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=step_name,\n                        block_type=step_type,\n                        property_name=property_name,\n                        property_details=f\"Expected dimensionality {expected_dimensionality}, but received dimensionality {actual_dimensionality}\",\n                    )\n                ],\n            )\n    return None\n\n\ndef grab_input_data_dimensionality_specifications(\n    step_name: str,\n    inputs_dimensionalities: Dict[str, Set[int]],\n    dimensionality_offstes: Dict[str, int],\n) -> Dict[str, InputDimensionalitySpecification]:\n    result = {}\n    for parameter_name, dimensionality in inputs_dimensionalities.items():\n        parameter_offset = dimensionality_offstes.get(parameter_name, 0)\n        non_zero_dimensionalities_for_parameter = {d for d in dimensionality if d > 0}\n        if len(non_zero_dimensionalities_for_parameter) > 1:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler for step: `{step_name}` and parameter: {parameter_name}\"\n                f\"found multiple different values of actual input dimensionalities: \"\n                f\"`{non_zero_dimensionalities_for_parameter}` which should be detected and addresses \"\n                f\"at earlier stages of compilation.\"\n                f\"This is most likely the bug. Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n            )\n        if non_zero_dimensionalities_for_parameter:\n            actual_dimensionality = next(iter(non_zero_dimensionalities_for_parameter))\n            result[parameter_name] = InputDimensionalitySpecification(\n                actual_dimensionality=actual_dimensionality,\n                expected_offset=parameter_offset,\n            )\n    return result\n\n\ndef verify_compatibility_of_input_data_lineage_with_control_flow_lineage(\n    step_name: str,\n    inputs_lineage: List[List[str]],\n    control_flow_steps_selectors: List[str],\n    execution_graph: DiGraph,\n) -> None:\n    \"\"\"\n    Ensure control flow steps' data lineage is compatible with the step's inputs.\n\n    Control flow steps that affect this step must operate on data that is\n    compatible with the data fed to the step; otherwise the step could never\n    execute. Compares unique control flow lineages against input lineage\n    prefixes and raises ControlFlowDefinitionError if any control flow lineage\n    is not covered by the inputs.\n\n    If inputs_lineage is empty, there is no sense to verify compatibility. The lineage of the\n    step should be established based on the control flow lineages.\n\n    Args:\n        step_name: Name of the step being verified (used in error messages).\n        inputs_lineage: Data lineages derived from the step's input data.\n        control_flow_steps_selectors: Step selectors of control flow steps\n            that affect this step's execution.\n        execution_graph: The workflow execution graph.\n\n    Raises:\n        ControlFlowDefinitionError: When a control flow step's lineage is not\n            compatible with the step's input lineage (step would never execute).\n    \"\"\"\n    (\n        batch_oriented_control_flow_lineages,\n        lineage_id2control_flow_steps,\n    ) = _collect_unique_control_flow_lineages_with_step_mapping(\n        control_flow_steps_selectors=control_flow_steps_selectors,\n        execution_graph=execution_graph,\n    )\n    if not inputs_lineage:\n        return\n\n    all_input_lineage_prefixes = get_all_batch_lineage_prefixes(lineages=inputs_lineage)\n    all_input_lineage_prefixes_hashes = {\n        identify_lineage(lineage=lineage) for lineage in all_input_lineage_prefixes\n    }\n    for control_flow_lineage in batch_oriented_control_flow_lineages:\n        control_flow_lineage_id = identify_lineage(lineage=control_flow_lineage)\n        if control_flow_lineage_id not in all_input_lineage_prefixes_hashes:\n            problematic_flow_control_steps = lineage_id2control_flow_steps[\n                control_flow_lineage_id\n            ]\n            raise ControlFlowDefinitionError(\n                public_message=f\"Step {step_name} execution is impacted by control flow outcome of the following \"\n                f\"steps {problematic_flow_control_steps} which make decision based on data that is \"\n                f\"not compatible with data fed to the step {step_name} - which would cause the step \"\n                f\"to never execute. This behaviour is invalid and prevented upfront by Workflows compiler.\",\n                context=\"workflow_compilation | execution_graph_construction | verification_of_control_flow_lineage\",\n            )\n\n\ndef get_all_batch_lineage_prefixes(lineages: List[List[str]]) -> List[List[str]]:\n    result = []\n    already_spotted = set()\n    for lineage in lineages:\n        lineage_prefixes = get_batch_lineage_prefixes(lineage=lineage)\n        for lineage_prefix in lineage_prefixes:\n            lineage_prefix_id = identify_lineage(lineage=lineage_prefix)\n            if lineage_prefix_id not in already_spotted:\n                already_spotted.add(lineage_prefix_id)\n                result.append(lineage_prefix)\n    return result\n\n\ndef get_batch_lineage_prefixes(lineage: List[str]) -> List[List[str]]:\n    if not lineage:\n        return []\n    result = []\n    prefix = []\n    for i in range(len(lineage)):\n        prefix.append(lineage[i])\n        result.append(copy(prefix))\n    return result\n\n\ndef get_inputs_dimensionalities(\n    step_name: str,\n    step_type: str,\n    input_data: StepInputData,\n    scalar_parameters_to_be_batched: Set[str],\n    input_dimensionality_offsets: Dict[str, int],\n) -> Dict[str, Set[int]]:\n    result = defaultdict(set)\n    dimensionalities_spotted = set()\n    offset_parameters = {\n        parameter: value\n        for parameter, value in input_dimensionality_offsets.items()\n        if value > 0\n    }\n    non_offset_parameters_dimensionality_values = set()\n    for property_name, input_definition in input_data.items():\n        if property_name in offset_parameters:\n            continue\n        if input_definition.is_compound_input():\n            for value in input_definition.iterate_through_definitions():\n                if value.is_batch_oriented():\n                    non_offset_parameters_dimensionality_values.add(\n                        value.get_dimensionality()\n                    )\n        elif input_definition.is_batch_oriented():\n            non_offset_parameters_dimensionality_values.add(\n                input_definition.get_dimensionality()\n            )\n    if len(non_offset_parameters_dimensionality_values) > 1:\n        raise StepInputDimensionalityError(\n            public_message=f\"For step {step_name} attempted to plug input data that are in different dimensions, \"\n            f\"whereas block defines the inputs to be equal in that terms.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_input_data\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=step_name,\n                    block_type=step_type,\n                    block_details=f\"Dimensionality of input parameters differs by more than 1. Detected dimensions: {dict(result)}\",\n                )\n            ],\n        )\n    non_offset_parameters_dimensionality_value = (\n        non_offset_parameters_dimensionality_values.pop()\n        if len(non_offset_parameters_dimensionality_values) > 0\n        else 1\n    )\n    for property_name, input_definition in input_data.items():\n        if input_definition.is_compound_input():\n            result[property_name] = get_compound_input_dimensionality(\n                step_name=step_name,\n                step_type=step_type,\n                property_name=property_name,\n                input_definition=input_definition,\n                scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n                non_offset_parameters_dimensionality_value=non_offset_parameters_dimensionality_value,\n                offset_parameters=offset_parameters,\n            )\n        else:\n            if property_name in scalar_parameters_to_be_batched:\n                if property_name not in offset_parameters:\n                    result[property_name] = {non_offset_parameters_dimensionality_value}\n                else:\n                    result[property_name] = (\n                        non_offset_parameters_dimensionality_value\n                        + offset_parameters[property_name]\n                    )\n            else:\n                result[property_name] = {input_definition.get_dimensionality()}\n        dimensionalities_spotted.update(result[property_name])\n    non_zero_dimensionalities_spotted = {d for d in dimensionalities_spotted if d != 0}\n    if len(non_zero_dimensionalities_spotted) > 0:\n        min_dim, max_dim = min(non_zero_dimensionalities_spotted), max(\n            non_zero_dimensionalities_spotted\n        )\n        if abs(max_dim - min_dim) > 1:\n            raise StepInputDimensionalityError(\n                public_message=f\"For step {step_name} attempted to plug input data differing in dimensionality more than 1\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_input_data\",\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=step_name,\n                        block_type=step_type,\n                        block_details=f\"Dimensionality of input parameters differs by more than 1. Detected dimensions: {dict(result)}\",\n                    )\n                ],\n            )\n    return result\n\n\ndef get_compound_input_dimensionality(\n    step_name: str,\n    property_name: str,\n    step_type: str,\n    input_definition: CompoundStepInputDefinition,\n    scalar_parameters_to_be_batched: Set[str],\n    offset_parameters: Dict[str, int],\n    non_offset_parameters_dimensionality_value: int,\n) -> Set[int]:\n    dimensionalities_spotted = set()\n    for definition in input_definition.iterate_through_definitions():\n        if (\n            property_name not in scalar_parameters_to_be_batched\n            or definition.is_batch_oriented()\n        ):\n            dimensionalities_spotted.add(definition.get_dimensionality())\n        elif property_name not in offset_parameters:\n            dimensionalities_spotted.add(non_offset_parameters_dimensionality_value)\n        else:\n            dimensionalities_spotted.add(\n                non_offset_parameters_dimensionality_value\n                + offset_parameters[property_name]\n            )\n    non_zero_dimensionalities = {e for e in dimensionalities_spotted if e != 0}\n    if len(non_zero_dimensionalities) > 1:\n        raise StepInputDimensionalityError(\n            public_message=f\"While evaluating compound property {property_name} of step {step_name}, \"\n            f\"detected multiple inputs of differing batch dimensionalities: {non_zero_dimensionalities}\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_input_data\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=step_name,\n                    block_type=step_type,\n                    property_name=property_name,\n                    property_details=f\"Detected multiple inputs of differing batch dimensionalities: {non_zero_dimensionalities}\",\n                )\n            ],\n        )\n    return dimensionalities_spotted\n\n\ndef grab_parameters_defining_batch_inputs(\n    inputs_dimensionalities: Dict[str, Set[int]],\n) -> Set[str]:\n    result = set()\n    for paremeter, dimensionalities in inputs_dimensionalities.items():\n        batch_dimensionalities = {d for d in dimensionalities if d > 0}\n        if len(batch_dimensionalities):\n            result.add(paremeter)\n    return result\n\n\ndef retrieve_batch_compatibility_of_input_selectors(\n    input_selectors: List[ParsedSelector],\n) -> Dict[str, Set[bool]]:\n    batch_compatibility_of_properties = defaultdict(set)\n    for parsed_selector in input_selectors:\n        for reference in parsed_selector.definition.allowed_references:\n            batch_compatibility_of_properties[\n                parsed_selector.definition.property_name\n            ].update(reference.points_to_batch)\n    return batch_compatibility_of_properties\n\n\ndef verify_declared_batch_compatibility_against_actual_inputs(\n    node: str,\n    step_node_data: StepNode,\n    input_data: StepInputData,\n    batch_compatibility_of_properties: Dict[str, Set[bool]],\n) -> Set[str]:\n    scalar_parameters_to_be_batched = set()\n    parameters_accepting_batches_and_scalars = set(\n        step_node_data.step_manifest.get_parameters_accepting_batches_and_scalars()\n    )\n    hardcoded_inputs_to_be_batch_compatible = set(\n        step_node_data.step_manifest.get_parameters_enforcing_auto_batch_casting()\n        + step_node_data.step_manifest.get_parameters_accepting_batches()\n    )\n    for property_name, input_definition in input_data.items():\n        if property_name not in batch_compatibility_of_properties:\n            actual_input_is_batch = {False}\n            if property_name in parameters_accepting_batches_and_scalars:\n                batch_compatibility = {True, False}\n            elif property_name in hardcoded_inputs_to_be_batch_compatible:\n                batch_compatibility = {True}\n            else:\n                continue\n        elif input_definition.is_compound_input():\n            actual_input_is_batch = {\n                element.is_batch_oriented()\n                for element in input_definition.iterate_through_definitions()\n            }\n            batch_compatibility = batch_compatibility_of_properties[property_name]\n        else:\n            actual_input_is_batch = {input_definition.is_batch_oriented()}\n            batch_compatibility = batch_compatibility_of_properties[property_name]\n        step_accepts_batch_input = step_node_data.step_manifest.accepts_batch_input()\n        if (\n            step_accepts_batch_input\n            and batch_compatibility == {False}\n            and True in actual_input_is_batch\n        ):\n            raise ExecutionGraphStructureError(\n                public_message=f\"Detected invalid reference plugged \"\n                f\"into property `{property_name}` of step `{node}` - the step \"\n                f\"property do not accept batch-oriented inputs, yet the input selector \"\n                f\"holds one - this indicates the problem with \"\n                f\"construction of your Workflow - usually the problem occurs when non-batch oriented \"\n                f\"step inputs are filled with outputs of batch-oriented steps or batch-oriented inputs.\",\n                context=\"workflow_compilation | execution_graph_construction\",\n            )\n        if batch_compatibility == {True} and False in actual_input_is_batch:\n            scalar_parameters_to_be_batched.add(property_name)\n    return scalar_parameters_to_be_batched\n\n\ndef get_input_data_lineage_excluding_auto_batch_casting(\n    step_name: str,\n    input_data: StepInputData,\n    scalar_parameters_to_be_batched: Set[str],\n) -> List[List[str]]:\n    lineage_deduplication_set = set()\n    lineages = []\n    for property_name, input_definition in input_data.items():\n        new_lineages_detected_within_property_data = get_lineage_for_input_property(\n            step_name=step_name,\n            property_name=property_name,\n            input_definition=input_definition,\n            lineage_deduplication_set=lineage_deduplication_set,\n        )\n        if (\n            property_name in scalar_parameters_to_be_batched\n            and len(new_lineages_detected_within_property_data) == 0\n        ):\n            continue\n        lineages.extend(new_lineages_detected_within_property_data)\n    if not lineages:\n        return lineages\n    verify_lineages(step_name=step_name, detected_lineages=lineages)\n    return lineages\n\n\ndef get_lineage_support_for_auto_batch_casted_parameters(\n    input_dimensionalities: Dict[str, Set[int]],\n    scalar_parameters_to_be_batched: Set[str],\n    all_lineages_of_batch_parameters: List[List[str]],\n) -> Dict[str, AutoBatchCastingConfig]:\n    longest_lineage_support = find_longest_lineage_support(\n        all_lineages_of_batch_parameters=all_lineages_of_batch_parameters,\n    )\n    result = {}\n    for parameter_name in scalar_parameters_to_be_batched:\n        parameter_dimensionality = max(input_dimensionalities[parameter_name])\n        if longest_lineage_support is None:\n            lineage_support = None\n        else:\n            lineage_support = longest_lineage_support[:parameter_dimensionality]\n        result[parameter_name] = AutoBatchCastingConfig(\n            casted_dimensionality=parameter_dimensionality,\n            lineage_support=lineage_support,\n        )\n    return result\n\n\ndef find_longest_lineage_support(\n    all_lineages_of_batch_parameters: List[List[str]],\n) -> Optional[List[str]]:\n    longest_longest_lineage_support = []\n    for lineage in all_lineages_of_batch_parameters:\n        if len(lineage) > len(longest_longest_lineage_support):\n            longest_longest_lineage_support = lineage\n    if len(longest_longest_lineage_support) == 0:\n        return None\n    return longest_longest_lineage_support\n\n\ndef get_lineage_for_input_property(\n    step_name: str,\n    property_name: str,\n    input_definition: Union[StepInputDefinition, CompoundStepInputDefinition],\n    lineage_deduplication_set: Set[int],\n) -> List[List[str]]:\n    if input_definition.is_compound_input():\n        return get_lineage_from_compound_input(\n            step_name=step_name,\n            property_name=property_name,\n            input_definition=input_definition,\n            lineage_deduplication_set=lineage_deduplication_set,\n        )\n    lineages = []\n    if input_definition.is_batch_oriented():\n        lineage = input_definition.data_lineage\n        lineage_id = identify_lineage(lineage=lineage)\n        if lineage_id not in lineage_deduplication_set:\n            lineage_deduplication_set.add(lineage_id)\n            lineages.append(lineage)\n    return lineages\n\n\ndef get_lineage_from_compound_input(\n    step_name: str,\n    property_name: str,\n    input_definition: Union[StepInputDefinition, CompoundStepInputDefinition],\n    lineage_deduplication_set: Set[int],\n) -> List[List[str]]:\n    lineages = []\n    for nested_element in input_definition.iterate_through_definitions():\n        if nested_element.is_batch_oriented():\n            lineage = nested_element.data_lineage\n            lineage_id = identify_lineage(lineage=lineage)\n            if lineage_id not in lineage_deduplication_set:\n                lineage_deduplication_set.add(lineage_id)\n                lineages.append(lineage)\n    if len(lineages) > 1:\n        raise StepInputLineageError(\n            public_message=f\"Input data provided for step: `{step_name}` comes with multiple different lineages \"\n            f\"{lineages} for property `{property_name}` accepting \"\n            f\"multiple selectors, which is not allowed.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    return lineages\n\n\ndef verify_lineages(step_name: str, detected_lineages: List[List[str]]) -> None:\n    lineages_by_length = defaultdict(list)\n    for lineage in detected_lineages:\n        lineages_by_length[len(lineage)].append(lineage)\n    if len(lineages_by_length) > 2:\n        raise StepInputLineageError(\n            public_message=f\"Input data provided for step: `{step_name}` comes with lineages at more than two \"\n            f\"dimensionality levels, which should not be possible.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    lineage_lengths = sorted(lineages_by_length.keys())\n    for lineage_length in lineage_lengths:\n        if len(lineages_by_length[lineage_length]) > 1:\n            raise StepInputLineageError(\n                public_message=f\"Among step `{step_name}` inputs found different lineages at the same  \"\n                f\"dimensionality levels dimensionality.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if len(lineages_by_length[lineage_lengths[-1]]) > 1 and len(lineage_lengths) < 2:\n        raise StepInputLineageError(\n            public_message=f\"If lineage differ at the last level, then Execution Engine requires at least one \"\n            f\"higher-dimension  input that will come with common lineage, but this is not the \"\n            f\"case for step {step_name}.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    if len(lineage_lengths) == 2:\n        reference_lineage = lineages_by_length[lineage_lengths[0]][0]\n        if reference_lineage != lineages_by_length[lineage_lengths[1]][0][:-1]:\n            raise StepInputLineageError(\n                public_message=f\"Step `{step_name}` inputs does not share common lineage. Differing element: \"\n                f\"{lineages_by_length[lineage_lengths[1]][0]}, \"\n                f\"reference lineage prefix: {reference_lineage}\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n\n\ndef establish_step_execution_dimensionality(\n    inputs_dimensionalities: Dict[str, Set[int]],\n    control_flow_lineage_support: List[str],\n    output_dimensionality_offset: int,\n) -> int:\n    \"\"\"\n    Determine how many batch dimensions (execution slices) a step runs with.\n\n    Used during workflow compilation in denote_data_flow_for_step. The result\n    is stored on StepNode.step_execution_dimensionality and consumed at\n    execution time to:\n    - Drive how many times the step is executed (which batch indices/slices).\n    - Align and expand inputs (e.g. auto-batch casting) to match this size.\n    - Validate that parameter dimensionalities are compatible (runtime checks\n      in step_input_assembler and manager).\n\n    Logic:\n    - If no input has non-zero dimensionality but the step is gated by\n      control flow (control_flow_lineage_support non-empty), the\n      dimensionality is the number of control-flow branches.\n    - Otherwise, the minimum non-zero input dimensionality is used; if\n      output_dimensionality_offset < 0 (step reduces batch dimension),\n      one is subtracted.\n\n    Args:\n        inputs_dimensionalities: Per-input sets of dimensionalities (from\n            get_inputs_dimensionalities).\n        control_flow_lineage_support: Lineage identifiers for control-flow\n            branches that gate this step (from establish_batch_oriented_step_lineage).\n        output_dimensionality_offset: Block's output dimensionality offset\n            (positive = expand, negative = reduce batch dimension).\n\n    Returns:\n        The number of batch dimensions (execution slices) for this step.\n    \"\"\"\n    step_execution_dimensionality = 0\n    non_zero_dimensionalities = {\n        dimensionality\n        for dimensionalities in inputs_dimensionalities.values()\n        for dimensionality in dimensionalities\n        if dimensionality > 0\n    }\n    if len(non_zero_dimensionalities) == 0 and len(control_flow_lineage_support) > 0:\n        return len(control_flow_lineage_support)\n    if len(non_zero_dimensionalities) > 0:\n        step_execution_dimensionality = min(non_zero_dimensionalities)\n        if output_dimensionality_offset < 0:\n            step_execution_dimensionality -= 1\n    return step_execution_dimensionality\n\n\ndef establish_batch_oriented_step_lineage(\n    step_selector: str,\n    all_data_derived_lineages: List[List[str]],\n    all_control_flow_lineages: List[List[str]],\n    input_data: StepInputData,\n    dimensionality_reference_property: Optional[str],\n    output_dimensionality_offset: int,\n) -> Tuple[List[str], List[str]]:\n    reference_lineage, control_flow_lineage_support = get_reference_lineage(\n        step_selector=step_selector,\n        all_data_derived_lineages=all_data_derived_lineages,\n        all_control_flow_lineages=all_control_flow_lineages,\n        input_data=input_data,\n        dimensionality_reference_property=dimensionality_reference_property,\n    )\n    if output_dimensionality_offset < 0:\n        result_dimensionality = reference_lineage[:output_dimensionality_offset]\n        return result_dimensionality, []\n    if output_dimensionality_offset == 0:\n        return reference_lineage, control_flow_lineage_support\n    reference_lineage.append(step_selector)\n    return reference_lineage, []\n\n\ndef get_reference_lineage(\n    step_selector: str,\n    all_data_derived_lineages: List[List[str]],\n    all_control_flow_lineages: List[List[str]],\n    input_data: StepInputData,\n    dimensionality_reference_property: Optional[str],\n) -> Tuple[List[str], List[str]]:\n    if not all_data_derived_lineages:\n        if len(all_control_flow_lineages) == 1:\n            return copy(all_control_flow_lineages[0]), copy(\n                all_control_flow_lineages[0]\n            )\n        # Multiple control-flow lineages and no data-derived lineage: pick the deepest.\n        max_lineage_len = max(len(lineage) for lineage in all_control_flow_lineages)\n        lineages_matching_max_len = [\n            _lineage\n            for _lineage in all_control_flow_lineages\n            if len(_lineage) == max_lineage_len\n        ]\n        if len(lineages_matching_max_len) == 1:\n            return copy(lineages_matching_max_len[0]), copy(\n                lineages_matching_max_len[0]\n            )\n        else:\n            raise AssumptionError(\n                public_message=f\"Multiple control-flow lineages at the same level for step `{step_selector}` \"\n                f\"and no data-derived lineage; unique lineage level required. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if len(all_data_derived_lineages) == 1:\n        return copy(all_data_derived_lineages[0]), []\n    if dimensionality_reference_property not in input_data:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` expected dimensionality_reference_property \"\n            f\"presence to be verified at earlier stages, which did not happen as expected. \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    property_data = input_data[dimensionality_reference_property]\n    if property_data.is_compound_input():\n        lineage = None\n        for nested_element in property_data.iterate_through_definitions():\n            if nested_element.is_batch_oriented():\n                lineage = copy(nested_element.data_lineage)\n                return lineage, []\n        if lineage is None:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n                f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if not property_data.is_batch_oriented():\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n            f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    return copy(property_data.data_lineage), []\n\n\ndef get_property_with_invalid_selector(\n    manifest: WorkflowBlockManifest, step_property: str\n) -> Optional[str]:\n    property_name = None\n    for key, value in manifest.__dict__.items():\n        if isinstance(value, str) and step_property in value:\n            property_name = key\n            break\n    return property_name\n\n\ndef add_super_input_node_in_execution_graph(\n    execution_graph: DiGraph,\n    super_input_node: str,\n) -> DiGraph:\n    nodes_to_attach_super_input_into = get_nodes_of_specific_category(\n        execution_graph=execution_graph,\n        category=NodeCategory.INPUT_NODE,\n    )\n    step_nodes_without_predecessors = [\n        node\n        for node in execution_graph.nodes\n        if not list(execution_graph.predecessors(node))\n    ]\n    nodes_to_attach_super_input_into.update(step_nodes_without_predecessors)\n    execution_graph.add_node(super_input_node)\n    for node in nodes_to_attach_super_input_into:\n        execution_graph.add_edge(super_input_node, node)\n    return execution_graph\n",
    "patch": null
  },
  {
    "trace_id": "d1ff5e3c-ff86-4b74-8de3-bed228663969",
    "function_name": "ExecutionDataManager._register_control_flow_output_for_non_simd_step",
    "file_path": "inference/core/workflows/execution_engine/v1/executor/execution_data_manager/manager.py",
    "speedup_x": 1.6508911930995671,
    "review_quality": "high",
    "pre_optimization_commit": "90243bdc6278ef7d17b6db09dc1eb5b0d155b4be",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def _register_control_flow_output_for_non_simd_step(\n        self,\n        step_node: StepNode,\n        output: FlowControl,\n    ) -> None:\n        if not step_node.child_execution_branches:\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Error in execution engine. Step: {step_node.name} \"\n                f\"which is not flow-control step attempted to register FlowControl output. \"\n                f\"This is most likely bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_output_registration\",\n            )\n        selected_steps = output.context\n        if not isinstance(selected_steps, list):\n            selected_steps = {selected_steps}\n        else:\n            selected_steps = set(selected_steps)\n        selected_execution_branches = set()\n        for target_step, branch_name in step_node.child_execution_branches.items():\n            if target_step in selected_steps:\n                selected_execution_branches.add(branch_name)\n        for branch_name in step_node.child_execution_branches.values():\n            mask = branch_name in selected_execution_branches\n            logger.debug(f\"NON-SIMD flow control -> {branch_name}: {mask}\")\n            self._branching_manager.register_non_batch_mask(\n                execution_branch=branch_name,\n                mask=mask,\n            )\n        return None\n",
    "optimized_function_code": "from typing import Any, Dict\n\nfrom inference.core import logger\nfrom inference.core.workflows.errors import ExecutionEngineRuntimeError\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import \\\n    StepNode\nfrom inference.core.workflows.execution_engine.v1.entities import FlowControl\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.branching_manager import \\\n    BranchingManager\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.dynamic_batches_manager import \\\n    DynamicBatchesManager\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.execution_cache import \\\n    ExecutionCache\nfrom networkx import DiGraph\n\n\nclass ExecutionDataManager:\n\n    def __init__(\n        self,\n        execution_graph: DiGraph,\n        runtime_parameters: Dict[str, Any],\n        execution_cache: ExecutionCache,\n        dynamic_batches_manager: DynamicBatchesManager,\n        branching_manager: BranchingManager,\n    ):\n        self._execution_graph = execution_graph\n        self._runtime_parameters = runtime_parameters\n        self._execution_cache = execution_cache\n        self._dynamic_batches_manager = dynamic_batches_manager\n        self._branching_manager = branching_manager\n\n    def _register_control_flow_output_for_non_simd_step(\n        self,\n        step_node: StepNode,\n        output: FlowControl,\n    ) -> None:\n        if not step_node.child_execution_branches:\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Error in execution engine. Step: {step_node.name} \"\n                f\"which is not flow-control step attempted to register FlowControl output. \"\n                f\"This is most likely bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_output_registration\",\n            )\n        selected_steps = output.context\n        if not isinstance(selected_steps, list):\n            selected_steps = {selected_steps}\n        else:\n            selected_steps = set(selected_steps)\n        selected_execution_branches = set()\n        for target_step, branch_name in step_node.child_execution_branches.items():\n            if target_step in selected_steps:\n                selected_execution_branches.add(branch_name)\n        \n        debug_enabled = logger.isEnabledFor(10)  # 10 is DEBUG level\n        for branch_name in step_node.child_execution_branches.values():\n            mask = branch_name in selected_execution_branches\n            if debug_enabled:\n                logger.debug(f\"NON-SIMD flow control -> {branch_name}: {mask}\")\n            self._branching_manager.register_non_batch_mask(\n                execution_branch=branch_name,\n                mask=mask,\n            )\n        return None",
    "optimized_raw_markdown": "```python:inference/core/workflows/execution_engine/v1/executor/execution_data_manager/branching_manager.py\nfrom typing import Dict, Set, Union\n\nfrom inference.core.workflows.errors import ExecutionEngineRuntimeError\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.dynamic_batches_manager import \\\n    DynamicBatchIndex\n\n\nclass BranchingManager:\n\n    def __init__(self, masks: Dict[str, Union[Set[DynamicBatchIndex], bool]]):\n        self._masks = masks\n        self._batch_compatibility = {\n            branch_name: not isinstance(mask, bool)\n            for branch_name, mask in masks.items()\n        }\n\n    def register_non_batch_mask(self, execution_branch: str, mask: bool) -> None:\n        if execution_branch in self._masks:\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Attempted to re-register maks for execution branch: {execution_branch}. \"\n                f\"This is most likely a bug. Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n        self._batch_compatibility[execution_branch] = False\n        self._masks[execution_branch] = mask\n```\n```python:inference/core/workflows/execution_engine/v1/executor/execution_data_manager/manager.py\nfrom typing import Any, Dict\n\nfrom inference.core import logger\nfrom inference.core.workflows.errors import ExecutionEngineRuntimeError\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import \\\n    StepNode\nfrom inference.core.workflows.execution_engine.v1.entities import FlowControl\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.branching_manager import \\\n    BranchingManager\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.dynamic_batches_manager import \\\n    DynamicBatchesManager\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.execution_cache import \\\n    ExecutionCache\nfrom networkx import DiGraph\n\n\nclass ExecutionDataManager:\n\n    def __init__(\n        self,\n        execution_graph: DiGraph,\n        runtime_parameters: Dict[str, Any],\n        execution_cache: ExecutionCache,\n        dynamic_batches_manager: DynamicBatchesManager,\n        branching_manager: BranchingManager,\n    ):\n        self._execution_graph = execution_graph\n        self._runtime_parameters = runtime_parameters\n        self._execution_cache = execution_cache\n        self._dynamic_batches_manager = dynamic_batches_manager\n        self._branching_manager = branching_manager\n\n    def _register_control_flow_output_for_non_simd_step(\n        self,\n        step_node: StepNode,\n        output: FlowControl,\n    ) -> None:\n        if not step_node.child_execution_branches:\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Error in execution engine. Step: {step_node.name} \"\n                f\"which is not flow-control step attempted to register FlowControl output. \"\n                f\"This is most likely bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_output_registration\",\n            )\n        selected_steps = output.context\n        if not isinstance(selected_steps, list):\n            selected_steps = {selected_steps}\n        else:\n            selected_steps = set(selected_steps)\n        selected_execution_branches = set()\n        for target_step, branch_name in step_node.child_execution_branches.items():\n            if target_step in selected_steps:\n                selected_execution_branches.add(branch_name)\n        \n        debug_enabled = logger.isEnabledFor(10)  # 10 is DEBUG level\n        for branch_name in step_node.child_execution_branches.values():\n            mask = branch_name in selected_execution_branches\n            if debug_enabled:\n                logger.debug(f\"NON-SIMD flow control -> {branch_name}: {mask}\")\n            self._branching_manager.register_non_batch_mask(\n                execution_branch=branch_name,\n                mask=mask,\n            )\n        return None\n```",
    "optimized_function_only": "    def _register_control_flow_output_for_non_simd_step(\n        self,\n        step_node: StepNode,\n        output: FlowControl,\n    ) -> None:\n        if not step_node.child_execution_branches:\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Error in execution engine. Step: {step_node.name} \"\n                f\"which is not flow-control step attempted to register FlowControl output. \"\n                f\"This is most likely bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_output_registration\",\n            )\n        selected_steps = output.context\n        if not isinstance(selected_steps, list):\n            selected_steps = {selected_steps}\n        else:\n            selected_steps = set(selected_steps)\n        selected_execution_branches = set()\n        for target_step, branch_name in step_node.child_execution_branches.items():\n            if target_step in selected_steps:\n                selected_execution_branches.add(branch_name)\n        \n        debug_enabled = logger.isEnabledFor(10)  # 10 is DEBUG level\n        for branch_name in step_node.child_execution_branches.values():\n            mask = branch_name in selected_execution_branches\n            if debug_enabled:\n                logger.debug(f\"NON-SIMD flow control -> {branch_name}: {mask}\")\n            self._branching_manager.register_non_batch_mask(\n                execution_branch=branch_name,\n                mask=mask,\n            )\n        return None",
    "original_file_content": "from typing import Any, Dict, Generator, List, Optional, Tuple, Union\n\nfrom networkx import DiGraph\n\nfrom inference.core import logger\nfrom inference.core.workflows.errors import AssumptionError, ExecutionEngineRuntimeError\nfrom inference.core.workflows.execution_engine.constants import (\n    NODE_COMPILATION_OUTPUT_PROPERTY,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import (\n    CompoundStepInputDefinition,\n    DynamicStepInputDefinition,\n    InputNode,\n    StepNode,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import (\n    get_last_chunk_of_selector,\n    get_step_selector_from_its_output,\n    is_input_selector,\n    is_selector,\n    is_step_output_selector,\n    is_step_selector,\n    node_as,\n)\nfrom inference.core.workflows.execution_engine.v1.entities import FlowControl\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.branching_manager import (\n    BranchingManager,\n)\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.dynamic_batches_manager import (\n    DynamicBatchesManager,\n    DynamicBatchIndex,\n)\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.execution_cache import (\n    ExecutionCache,\n)\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.step_input_assembler import (\n    BatchModeSIMDStepInput,\n    NonBatchModeSIMDStepInput,\n    construct_non_simd_step_input,\n    construct_simd_step_input,\n    iterate_over_simd_step_input,\n)\nfrom inference.core.workflows.prototypes.block import BlockResult\n\n\nclass ExecutionDataManager:\n\n    @classmethod\n    def init(\n        cls,\n        execution_graph: DiGraph,\n        runtime_parameters: Dict[str, Any],\n    ) -> \"ExecutionDataManager\":\n        execution_cache = ExecutionCache.init(execution_graph=execution_graph)\n        dynamic_batches_manager = DynamicBatchesManager.init(\n            execution_graph=execution_graph,\n            runtime_parameters=runtime_parameters,\n        )\n        branching_manager = BranchingManager.init()\n        return cls(\n            execution_graph=execution_graph,\n            runtime_parameters=runtime_parameters,\n            execution_cache=execution_cache,\n            dynamic_batches_manager=dynamic_batches_manager,\n            branching_manager=branching_manager,\n        )\n\n    def __init__(\n        self,\n        execution_graph: DiGraph,\n        runtime_parameters: Dict[str, Any],\n        execution_cache: ExecutionCache,\n        dynamic_batches_manager: DynamicBatchesManager,\n        branching_manager: BranchingManager,\n    ):\n        self._execution_graph = execution_graph\n        self._runtime_parameters = runtime_parameters\n        self._execution_cache = execution_cache\n        self._dynamic_batches_manager = dynamic_batches_manager\n        self._branching_manager = branching_manager\n\n    def all_inputs_impacting_step_are_registered(self, step_selector: str) -> bool:\n        step_node_data: StepNode = self._execution_graph.nodes[step_selector][\n            NODE_COMPILATION_OUTPUT_PROPERTY\n        ]\n        all_batch_oriented_parameters_registered = (\n            are_all_batch_oriented_parameters_registered(\n                step_node_data=step_node_data,\n                execution_cache=self._execution_cache,\n            )\n        )\n        all_execution_branches_registered = all(\n            self._branching_manager.is_execution_branch_registered(\n                execution_branch=execution_branch\n            )\n            for execution_branch in step_node_data.execution_branches_impacting_inputs\n        )\n        return (\n            all_batch_oriented_parameters_registered\n            and all_execution_branches_registered\n        )\n\n    def get_non_simd_step_input(self, step_selector: str) -> Optional[Dict[str, Any]]:\n        if self.is_step_simd(step_selector=step_selector):\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Error in execution engine. In context of SIMD step: {step_selector} attempts to \"\n                f\"get non-simd input. This is most likely bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_output_registration\",\n            )\n        step_node: StepNode = self._execution_graph.nodes[step_selector][\n            NODE_COMPILATION_OUTPUT_PROPERTY\n        ]\n        return construct_non_simd_step_input(\n            step_node=step_node,\n            runtime_parameters=self._runtime_parameters,\n            execution_cache=self._execution_cache,\n            branching_manager=self._branching_manager,\n        )\n\n    def register_non_simd_step_output(\n        self, step_selector: str, output: Union[Dict[str, Any], FlowControl, list]\n    ) -> None:\n        if self.is_step_simd(step_selector=step_selector):\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Error in execution engine. In context of SIMD step: {step_selector} attempts to \"\n                f\"register non-simd output. This is most likely bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_output_registration\",\n            )\n        step_name = get_last_chunk_of_selector(selector=step_selector)\n        step_node = node_as(\n            execution_graph=self._execution_graph,\n            node=step_selector,\n            expected_type=StepNode,\n        )\n        if step_node.output_dimensionality == 1:\n            # we only allow +1 dim increase for now, so it is fine to only handle this case\n            indices = [(i,) for i in range(len(output))]\n            self._dynamic_batches_manager.register_element_indices_for_lineage(\n                lineage=step_node.data_lineage,\n                indices=indices,\n            )\n            if step_node.child_execution_branches:\n                if not all(isinstance(element, FlowControl) for element in output):\n                    raise ExecutionEngineRuntimeError(\n                        public_message=f\"Error in execution engine. Flow control step {step_name} \"\n                        f\"expected to only produce FlowControl objects. This is most likely bug. \"\n                        f\"Contact Roboflow team through github issues \"\n                        f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                        f\"the problem - including workflow definition you use.\",\n                        context=\"workflow_execution | step_output_registration\",\n                    )\n                self._register_control_flow_output_for_simd_step(\n                    step_node=step_node,\n                    indices=indices,\n                    outputs=output,\n                )\n                return None\n            self._execution_cache.register_batch_of_step_outputs(\n                step_name=step_name,\n                indices=indices,\n                outputs=output,\n            )\n            return None\n        if isinstance(output, list):\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Error in execution engine. Non-SIMD step {step_name} \"\n                f\"produced list of results which is not expected. This is most likely bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_output_registration\",\n            )\n        if isinstance(output, FlowControl):\n            self._register_control_flow_output_for_non_simd_step(\n                step_node=step_node,\n                output=output,\n            )\n            return None\n        self._execution_cache.register_non_batch_step_outputs(\n            step_name=step_name,\n            outputs=output,\n        )\n\n    def get_simd_step_input(\n        self,\n        step_selector: str,\n    ) -> BatchModeSIMDStepInput:\n        if not self.is_step_simd(step_selector=step_selector):\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Error in execution engine. In context of non-SIMD step: {step_selector} attempts to \"\n                f\"get SIMD step input. This is most likely bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | getting_workflow_data\",\n            )\n        step_node = node_as(\n            execution_graph=self._execution_graph,\n            node=step_selector,\n            expected_type=StepNode,\n        )\n        return construct_simd_step_input(\n            step_node=step_node,\n            runtime_parameters=self._runtime_parameters,\n            execution_cache=self._execution_cache,\n            dynamic_batches_manager=self._dynamic_batches_manager,\n            branching_manager=self._branching_manager,\n        )\n\n    def iterate_over_simd_step_input(\n        self, step_selector: str\n    ) -> Generator[NonBatchModeSIMDStepInput, None, None]:\n        if not self.is_step_simd(step_selector=step_selector):\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Error in execution engine. In context of non-SIMD step: {step_selector} attempts to \"\n                f\"get SIMD step input. This is most likely bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | getting_workflow_data\",\n            )\n        step_node = node_as(\n            execution_graph=self._execution_graph,\n            node=step_selector,\n            expected_type=StepNode,\n        )\n        yield from iterate_over_simd_step_input(\n            step_node=step_node,\n            runtime_parameters=self._runtime_parameters,\n            execution_cache=self._execution_cache,\n            dynamic_batches_manager=self._dynamic_batches_manager,\n            branching_manager=self._branching_manager,\n        )\n\n    def register_simd_step_output(\n        self,\n        step_selector: str,\n        indices: List[DynamicBatchIndex],\n        outputs: BlockResult,\n    ) -> None:\n        if not self.is_step_simd(step_selector=step_selector):\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Error in execution engine. In context of non-SIMD step: {step_selector} attempts to \"\n                f\"register SIMD step input. This is most likely bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_output_registration\",\n            )\n        step_node = node_as(\n            execution_graph=self._execution_graph,\n            node=step_selector,\n            expected_type=StepNode,\n        )\n\n        step_name = get_last_chunk_of_selector(selector=step_selector)\n        if step_node.output_dimensionality == 0:\n            # SIMD step collapsing into scalar (can happen for auto-batch casting of parameters)\n            if isinstance(outputs, list):\n                if len(outputs) == 0:\n                    # termination of the computation as in NON-SIMD case\n                    return None\n                if len(outputs) != 1:\n                    raise ExecutionEngineRuntimeError(\n                        public_message=f\"Error in execution engine. In context of SIMD step: {step_selector} attempts to \"\n                        f\"register output which should collapse into a scalar, but detected batched output \"\n                        f\"with more than a single element (or incompatible output), \"\n                        f\"making the operation not possible. This is most likely bug (either a block or \"\n                        f\"Execution Engine is faulty). Contact Roboflow team through github issues \"\n                        f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                        f\"the problem - including workflow definition you use.\",\n                        context=\"workflow_execution | step_output_registration\",\n                    )\n                output = outputs[0]\n            else:\n                output = outputs\n            if isinstance(output, FlowControl):\n                self._register_control_flow_output_for_non_simd_step(\n                    step_node=step_node,\n                    output=output,\n                )\n                return None\n            self._execution_cache.register_non_batch_step_outputs(\n                step_name=step_name,\n                outputs=output,\n            )\n            return None\n        if (\n            step_node.output_dimensionality - step_node.step_execution_dimensionality\n            == 0\n            and step_node.step_manifest.get_output_dimensionality_offset() > 0\n        ):\n            # artificial increase in output dimensionality due to ABC which should be unwrapped\n            if isinstance(outputs, list) and len(outputs) == 0:\n                self._dynamic_batches_manager.register_element_indices_for_lineage(\n                    lineage=step_node.data_lineage,\n                    indices=indices,\n                )\n                if step_node.child_execution_branches:\n                    if not all(isinstance(element, FlowControl) for element in outputs):\n                        raise ExecutionEngineRuntimeError(\n                            public_message=f\"Error in execution engine. Flow control step {step_name} \"\n                            f\"expected to only produce FlowControl objects. This is most likely bug. \"\n                            f\"Contact Roboflow team through github issues \"\n                            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                            f\"the problem - including workflow definition you use.\",\n                            context=\"workflow_execution | step_output_registration\",\n                        )\n                    self._register_control_flow_output_for_simd_step(\n                        step_node=step_node,\n                        indices=indices,\n                        outputs=outputs,\n                    )\n                    return None\n                self._execution_cache.register_batch_of_step_outputs(\n                    step_name=step_name,\n                    indices=indices,\n                    outputs=outputs,\n                )\n                return None\n            if not isinstance(outputs, list) or len(outputs) != 1:\n                raise AssumptionError(\n                    public_message=f\"Error in execution engine. In context of SIMD step: {step_selector} attempts to \"\n                    f\"register output which should be nested, 1-element batch, but detected batched \"\n                    f\"output with more than a single element (or incompatible output), \"\n                    f\"making the operation not possible. This is most likely bug (either a block or \"\n                    f\"Execution Engine is faulty). Contact Roboflow team through github issues \"\n                    f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                    f\"the problem - including workflow definition you use.\",\n                    context=\"workflow_execution | step_output_registration\",\n                )\n            index_base = indices[0][:-1]\n            outputs = outputs[0]\n            indices = [index_base + (i,) for i in range(len(outputs))]\n            self._dynamic_batches_manager.register_element_indices_for_lineage(\n                lineage=step_node.data_lineage,\n                indices=indices,\n            )\n        elif (\n            step_node.output_dimensionality - step_node.step_execution_dimensionality\n        ) > 0:\n            # increase in dimensionality\n            indices, outputs = flatten_nested_output(\n                step_selector=step_selector, indices=indices, outputs=outputs\n            )\n            self._dynamic_batches_manager.register_element_indices_for_lineage(\n                lineage=step_node.data_lineage,\n                indices=indices,\n            )\n        if step_node.child_execution_branches:\n            if not all(isinstance(element, FlowControl) for element in outputs):\n                raise ExecutionEngineRuntimeError(\n                    public_message=f\"Error in execution engine. Flow control step {step_name} \"\n                    f\"expected to only produce FlowControl objects. This is most likely bug. \"\n                    f\"Contact Roboflow team through github issues \"\n                    f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                    f\"the problem - including workflow definition you use.\",\n                    context=\"workflow_execution | step_output_registration\",\n                )\n            self._register_control_flow_output_for_simd_step(\n                step_node=step_node,\n                indices=indices,\n                outputs=outputs,\n            )\n            return None\n        self._execution_cache.register_batch_of_step_outputs(\n            step_name=step_name,\n            indices=indices,\n            outputs=outputs,\n        )\n\n    def get_selector_indices(self, selector: str) -> Optional[List[DynamicBatchIndex]]:\n        selector_lineage = []\n        if not is_selector(selector_or_value=selector):\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Error in execution engine. Attempted to get indices for: {selector}, \"\n                f\"which is not recognised as valid selector. This is most likely bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_output_registration\",\n            )\n        potential_step_selector = get_step_selector_from_its_output(\n            step_output_selector=selector\n        )\n        if is_input_selector(selector_or_value=selector):\n            if self.does_input_represent_batch(input_selector=selector):\n                input_node: InputNode = self._execution_graph.nodes[selector][\n                    NODE_COMPILATION_OUTPUT_PROPERTY\n                ]\n                selector_lineage = input_node.data_lineage\n        elif is_step_selector(selector_or_value=potential_step_selector):\n            if self.does_step_produce_batches(step_selector=potential_step_selector):\n                step_node_data: StepNode = self._execution_graph.nodes[\n                    potential_step_selector\n                ][NODE_COMPILATION_OUTPUT_PROPERTY]\n                selector_lineage = step_node_data.data_lineage\n        else:\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Error in execution engine. Attempted to get indices for: {selector}, \"\n                f\"which is not recognised as neither input selector or step selector. \"\n                f\"This is most likely bug. Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | getting_workflow_data_indices\",\n            )\n        if not selector_lineage:\n            return None\n        return self.get_lineage_indices(lineage=selector_lineage)\n\n    def get_lineage_indices(self, lineage: List[str]) -> List[DynamicBatchIndex]:\n        if not self._dynamic_batches_manager.is_lineage_registered(lineage=lineage):\n            return []\n        return self._dynamic_batches_manager.get_indices_for_data_lineage(\n            lineage=lineage\n        )\n\n    def get_non_batch_data(self, selector: str) -> Any:\n        if not is_selector(selector_or_value=selector):\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Error in execution engine. Attempted to get value of: {selector}, \"\n                f\"which is not recognised as valid selector. This is most likely bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_output_registration\",\n            )\n        potential_step_selector = get_step_selector_from_its_output(\n            step_output_selector=selector\n        )\n        if is_input_selector(\n            selector_or_value=selector\n        ) and not self.does_input_represent_batch(input_selector=selector):\n            input_name = get_last_chunk_of_selector(selector=selector)\n            return self._runtime_parameters[input_name]\n        elif is_step_selector(selector_or_value=potential_step_selector):\n            step_node_data = node_as(\n                execution_graph=self._execution_graph,\n                node=potential_step_selector,\n                expected_type=StepNode,\n            )\n            if step_node_data.output_dimensionality != 0:\n                raise ExecutionEngineRuntimeError(\n                    public_message=f\"Error in execution engine. Attempted to get value of: {selector}, \"\n                    f\"which was supposed to be registered as scalar output, but in fact Execution \"\n                    f\"Engine denoted the output as batched one (with dimensionality: \"\n                    f\"{step_node_data.output_dimensionality}). \"\n                    f\"This is most likely bug. Contact Roboflow team through github issues \"\n                    f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                    f\"the problem - including workflow definition you use.\",\n                    context=\"workflow_execution | getting_workflow_data\",\n                )\n            step_name = get_last_chunk_of_selector(selector=potential_step_selector)\n            if selector.endswith(\".*\"):\n                return self._execution_cache.get_all_non_batch_step_outputs(\n                    step_name=step_name,\n                )\n            return self._execution_cache.get_non_batch_output(selector=selector)\n        else:\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Error in execution engine. Attempted to get value of: {selector}, \"\n                f\"which is not recognised as neither input selector or step selector. \"\n                f\"This is most likely bug. Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | getting_workflow_data\",\n            )\n\n    def get_batch_data(\n        self, selector: str, indices: List[DynamicBatchIndex]\n    ) -> List[Any]:\n        if not is_selector(selector_or_value=selector):\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Error in execution engine. Attempted to get value of: {selector}, \"\n                f\"which is not recognised as valid selector. This is most likely bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | getting_workflow_data\",\n            )\n        potential_step_selector = get_step_selector_from_its_output(\n            step_output_selector=selector\n        )\n        if is_input_selector(\n            selector_or_value=selector\n        ) and self.does_input_represent_batch(input_selector=selector):\n            input_name = get_last_chunk_of_selector(selector=selector)\n            input_data = self._runtime_parameters[input_name]\n            # simplification: assumption that we can only request dim-1 batch from inputs\n            requested_indices = {i[0] for i in indices}\n            return [\n                data_element if idx in requested_indices else None\n                for idx, data_element in enumerate(input_data)\n            ]\n        elif is_step_selector(\n            selector_or_value=potential_step_selector\n        ) and self.does_step_produce_batches(step_selector=potential_step_selector):\n            step_name = get_last_chunk_of_selector(selector=potential_step_selector)\n            if selector.endswith(\".*\"):\n                return self._execution_cache.get_all_batch_step_outputs(\n                    step_name=step_name,\n                    batch_elements_indices=indices,\n                )\n            return self._execution_cache.get_batch_output(\n                selector=selector,\n                batch_elements_indices=indices,\n            )\n        else:\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Error in execution engine. Attempted to get value of: {selector}, \"\n                f\"which is not recognised as neither input selector or step selector. \"\n                f\"This is most likely bug. Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_output_registration\",\n            )\n\n    def is_step_simd(self, step_selector: str) -> bool:\n        step_node_data = node_as(\n            execution_graph=self._execution_graph,\n            node=step_selector,\n            expected_type=StepNode,\n        )\n        return step_node_data.is_batch_oriented()\n\n    def does_step_produce_batches(self, step_selector: str) -> bool:\n        step_node_data = node_as(\n            execution_graph=self._execution_graph,\n            node=step_selector,\n            expected_type=StepNode,\n        )\n        return step_node_data.output_dimensionality > 0\n\n    def does_input_represent_batch(self, input_selector: str) -> bool:\n        input_node = node_as(\n            execution_graph=self._execution_graph,\n            node=input_selector,\n            expected_type=InputNode,\n        )\n        return input_node.is_batch_oriented()\n\n    def _register_control_flow_output_for_non_simd_step(\n        self,\n        step_node: StepNode,\n        output: FlowControl,\n    ) -> None:\n        if not step_node.child_execution_branches:\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Error in execution engine. Step: {step_node.name} \"\n                f\"which is not flow-control step attempted to register FlowControl output. \"\n                f\"This is most likely bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_output_registration\",\n            )\n        selected_steps = output.context\n        if not isinstance(selected_steps, list):\n            selected_steps = {selected_steps}\n        else:\n            selected_steps = set(selected_steps)\n        selected_execution_branches = set()\n        for target_step, branch_name in step_node.child_execution_branches.items():\n            if target_step in selected_steps:\n                selected_execution_branches.add(branch_name)\n        for branch_name in step_node.child_execution_branches.values():\n            mask = branch_name in selected_execution_branches\n            logger.debug(f\"NON-SIMD flow control -> {branch_name}: {mask}\")\n            self._branching_manager.register_non_batch_mask(\n                execution_branch=branch_name,\n                mask=mask,\n            )\n        return None\n\n    def _register_control_flow_output_for_simd_step(\n        self,\n        step_node: StepNode,\n        indices: List[DynamicBatchIndex],\n        outputs: List[FlowControl],\n    ) -> None:\n        all_branches_masks = {\n            branch_name: set()\n            for branch_name in step_node.child_execution_branches.values()\n        }\n        for output_index, output in zip(indices, outputs):\n            selected_steps = output.context\n            if selected_steps is None:\n                selected_steps = []\n            if not isinstance(selected_steps, list):\n                selected_steps = {selected_steps}\n            else:\n                selected_steps = set(selected_steps)\n            for selected_step in selected_steps:\n                branch_for_step = step_node.child_execution_branches.get(selected_step)\n                if branch_for_step is None:\n                    raise ExecutionEngineRuntimeError(\n                        public_message=f\"Error in execution engine. Handing with step: {step_node.name} output \"\n                        f\"Cannot find execution branch for selected step {selected_step}\"\n                        f\"This is most likely bug. \"\n                        f\"Contact Roboflow team through github issues \"\n                        f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                        f\"the problem - including workflow definition you use.\",\n                        context=\"workflow_execution | step_output_registration\",\n                    )\n                all_branches_masks[branch_for_step].add(output_index)\n        for branch_name, mask in all_branches_masks.items():\n            logger.debug(f\"SIMD flow control -> {branch_name}: {mask}\")\n            self._branching_manager.register_batch_oriented_mask(\n                execution_branch=branch_name,\n                mask=mask,\n            )\n\n\ndef are_all_batch_oriented_parameters_registered(\n    step_node_data: StepNode,\n    execution_cache: ExecutionCache,\n) -> bool:\n    for batch_oriented_parameter in step_node_data.batch_oriented_parameters:\n        parameter = step_node_data.input_data[batch_oriented_parameter]\n        if not parameter.is_compound_input():\n            if not is_dynamic_step_input_registered(\n                dynamic_input=parameter,\n                execution_cache=execution_cache,\n            ):\n                return False\n        else:\n            if not are_all_compound_inputs_registered(\n                compound_input=parameter,\n                execution_cache=execution_cache,\n            ):\n                return False\n    return True\n\n\ndef are_all_compound_inputs_registered(\n    compound_input: CompoundStepInputDefinition,\n    execution_cache: ExecutionCache,\n) -> bool:\n    for step_input in compound_input.iterate_through_definitions():\n        if not step_input.is_batch_oriented():\n            continue\n        if not is_dynamic_step_input_registered(\n            dynamic_input=step_input,  # type: ignore\n            execution_cache=execution_cache,\n        ):\n            return False\n    return True\n\n\ndef is_dynamic_step_input_registered(\n    dynamic_input: DynamicStepInputDefinition,\n    execution_cache: ExecutionCache,\n) -> bool:\n    selector = dynamic_input.selector\n    if is_input_selector(selector_or_value=selector):\n        return True\n    if is_step_output_selector(selector_or_value=selector):\n        step_selector = get_step_selector_from_its_output(step_output_selector=selector)\n        step_name = get_last_chunk_of_selector(selector=step_selector)\n        return execution_cache.is_step_output_data_registered(step_name=step_name)\n    raise ExecutionEngineRuntimeError(\n        public_message=f\"Error in execution engine. Not recognised type of selector: {selector}. \"\n        f\"This is most likely bug. \"\n        f\"Contact Roboflow team through github issues \"\n        f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n        f\"the problem - including workflow definition you use.\",\n        context=\"workflow_execution | assembling_step_inputs\",\n    )\n\n\ndef flatten_nested_output(\n    step_selector: str,\n    indices: List[DynamicBatchIndex],\n    outputs: BlockResult,\n) -> Tuple[List[DynamicBatchIndex], List[Union[Dict[str, Any], FlowControl]]]:\n    flattened_index, flattened_output = [], []\n    for index, output_element in zip(indices, outputs):\n        if not isinstance(output_element, list):\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Error in execution engine. Handing with step: {step_selector} output \"\n                f\"it was expected that the output is nested list, but the condition \"\n                f\"is not met. This is most likely bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_output_registration\",\n            )\n        for nested_index, nested_element_of_output_element in enumerate(output_element):\n            flattened_index.append(index + (nested_index,))\n            flattened_output.append(nested_element_of_output_element)\n    return flattened_index, flattened_output\n",
    "patch": null
  },
  {
    "trace_id": "a4721d04-7b76-4555-8131-6387a4e69f0d",
    "function_name": "is_control_flow_step",
    "file_path": "inference/core/workflows/execution_engine/v1/compiler/utils.py",
    "speedup_x": 0.3374125467644379,
    "review_quality": "high",
    "pre_optimization_commit": "90243bdc6278ef7d17b6db09dc1eb5b0d155b4be",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def is_control_flow_step(execution_graph: DiGraph, node: str) -> bool:\n    if not is_step_node(execution_graph=execution_graph, node=node):\n        return False\n    return execution_graph.nodes[node][NODE_COMPILATION_OUTPUT_PROPERTY].controls_flow()\n",
    "optimized_function_code": "from inference.core.workflows.execution_engine.constants import \\\n    NODE_COMPILATION_OUTPUT_PROPERTY\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import \\\n    NodeCategory\nfrom networkx import DiGraph\n\n\ndef is_control_flow_step(execution_graph: DiGraph, node: str) -> bool:\n    # Retrieve the compilation output property once to avoid repeated dict lookups\n    node_prop = execution_graph.nodes[node][NODE_COMPILATION_OUTPUT_PROPERTY]\n    if node_prop.node_category is not NodeCategory.STEP_NODE:\n        return False\n    return node_prop.controls_flow()\n\n\n\n\ndef is_step_node(execution_graph: DiGraph, node: str) -> bool:\n    node_prop = execution_graph.nodes[node][NODE_COMPILATION_OUTPUT_PROPERTY]\n    return node_prop.node_category is NodeCategory.STEP_NODE",
    "optimized_raw_markdown": "```python:inference/core/workflows/execution_engine/v1/compiler/utils.py\nfrom inference.core.workflows.execution_engine.constants import \\\n    NODE_COMPILATION_OUTPUT_PROPERTY\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import \\\n    NodeCategory\nfrom networkx import DiGraph\n\n\ndef is_control_flow_step(execution_graph: DiGraph, node: str) -> bool:\n    # Retrieve the compilation output property once to avoid repeated dict lookups\n    node_prop = execution_graph.nodes[node][NODE_COMPILATION_OUTPUT_PROPERTY]\n    if node_prop.node_category is not NodeCategory.STEP_NODE:\n        return False\n    return node_prop.controls_flow()\n\n\n\n\ndef is_step_node(execution_graph: DiGraph, node: str) -> bool:\n    node_prop = execution_graph.nodes[node][NODE_COMPILATION_OUTPUT_PROPERTY]\n    return node_prop.node_category is NodeCategory.STEP_NODE\n```",
    "optimized_function_only": "def is_control_flow_step(execution_graph: DiGraph, node: str) -> bool:\n    # Retrieve the compilation output property once to avoid repeated dict lookups\n    node_prop = execution_graph.nodes[node][NODE_COMPILATION_OUTPUT_PROPERTY]\n    if node_prop.node_category is not NodeCategory.STEP_NODE:\n        return False\n    return node_prop.controls_flow()\n",
    "original_file_content": "from typing import Any, List, Set, Type, TypeVar\n\nfrom networkx import DiGraph\n\nfrom inference.core.workflows.errors import AssumptionError\nfrom inference.core.workflows.execution_engine.constants import (\n    NODE_COMPILATION_OUTPUT_PROPERTY,\n)\nfrom inference.core.workflows.execution_engine.entities.base import InputType, JsonField\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import (\n    ExecutionGraphNode,\n    NodeCategory,\n)\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nNodeTypeVar = TypeVar(\"NodeTypeVar\", bound=ExecutionGraphNode)\n\n\ndef get_input_parameters_selectors(inputs: List[InputType]) -> Set[str]:\n    return {\n        construct_input_selector(input_name=input_definition.name)\n        for input_definition in inputs\n    }\n\n\ndef construct_input_selector(input_name: str) -> str:\n    return f\"$inputs.{input_name}\"\n\n\ndef get_steps_selectors(steps: List[WorkflowBlockManifest]) -> Set[str]:\n    return {construct_step_selector(step_name=step.name) for step in steps}\n\n\ndef construct_step_selector(step_name: str) -> str:\n    return f\"$steps.{step_name}\"\n\n\ndef get_output_selectors(outputs: List[JsonField]) -> Set[str]:\n    return {construct_output_selector(name=output.name) for output in outputs}\n\n\ndef construct_output_selector(name: str) -> str:\n    return f\"$outputs.{name}\"\n\n\ndef is_input_selector(selector_or_value: Any) -> bool:\n    if not is_selector(selector_or_value=selector_or_value):\n        return False\n    return selector_or_value.startswith(\"$inputs\")\n\n\ndef is_step_selector(selector_or_value: Any) -> bool:\n    if not is_selector(selector_or_value=selector_or_value):\n        return False\n    return (\n        selector_or_value.startswith(\"$steps.\")\n        and len(selector_or_value.split(\".\")) == 2\n    )\n\n\ndef is_step_output_selector(selector_or_value: Any) -> bool:\n    if not is_selector(selector_or_value=selector_or_value):\n        return False\n    return (\n        selector_or_value.startswith(\"$steps.\")\n        and len(selector_or_value.split(\".\")) == 3\n    )\n\n\ndef get_step_selector_from_its_output(step_output_selector: str) -> str:\n    return \".\".join(step_output_selector.split(\".\")[:2])\n\n\ndef get_nodes_of_specific_category(\n    execution_graph: DiGraph, category: NodeCategory\n) -> Set[str]:\n    return {\n        node[0]\n        for node in execution_graph.nodes(data=True)\n        if node[1][NODE_COMPILATION_OUTPUT_PROPERTY].node_category is category\n    }\n\n\ndef get_last_chunk_of_selector(selector: str) -> str:\n    return selector.split(\".\")[-1]\n\n\ndef is_control_flow_step(execution_graph: DiGraph, node: str) -> bool:\n    if not is_step_node(execution_graph=execution_graph, node=node):\n        return False\n    return execution_graph.nodes[node][NODE_COMPILATION_OUTPUT_PROPERTY].controls_flow()\n\n\ndef is_input_node(execution_graph: DiGraph, node: str) -> bool:\n    return (\n        execution_graph.nodes[node][NODE_COMPILATION_OUTPUT_PROPERTY].node_category\n        is NodeCategory.INPUT_NODE\n    )\n\n\ndef is_step_node(execution_graph: DiGraph, node: str) -> bool:\n    return (\n        execution_graph.nodes[node][NODE_COMPILATION_OUTPUT_PROPERTY].node_category\n        is NodeCategory.STEP_NODE\n    )\n\n\ndef is_output_node(execution_graph: DiGraph, node: str) -> bool:\n    return (\n        execution_graph.nodes[node][NODE_COMPILATION_OUTPUT_PROPERTY].node_category\n        is NodeCategory.OUTPUT_NODE\n    )\n\n\ndef is_selector(selector_or_value: Any) -> bool:\n    return str(selector_or_value).startswith(\"$\")\n\n\ndef identify_lineage(lineage: List[str]) -> int:\n    return sum(hash(e) for e in lineage)\n\n\ndef node_as(\n    execution_graph: DiGraph, node: str, expected_type: Type[NodeTypeVar]\n) -> NodeTypeVar:\n    if node not in execution_graph.nodes:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler expected node: {node} to be present in execution graph, \"\n            f\"but condition failed to be met. This is most likely the bug. Contact Roboflow team \"\n            f\"through github issues (https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | retrieving_compiled_node\",\n        )\n    if NODE_COMPILATION_OUTPUT_PROPERTY not in execution_graph.nodes[node]:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler expected key: {NODE_COMPILATION_OUTPUT_PROPERTY} to be present \"\n            f\"for node {node} in execution graph, \"\n            f\"but condition failed to be met. This is most likely the bug. Contact Roboflow team \"\n            f\"through github issues (https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | retrieving_compiled_node\",\n        )\n    node_data: ExecutionGraphNode = execution_graph.nodes[node][\n        NODE_COMPILATION_OUTPUT_PROPERTY\n    ]\n    if not isinstance(node_data, expected_type):\n        node_data_type = type(node_data)\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler expected compilation output for node {node}\"\n            f\"to be {expected_type}, but found: {node_data_type}. \"\n            f\"This is most likely the bug. Contact Roboflow team \"\n            f\"through github issues (https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | retrieving_compiled_node\",\n        )\n    return node_data\n",
    "patch": null
  },
  {
    "trace_id": "27917af9-868e-4ceb-b6be-e2695443295a",
    "function_name": "establish_step_execution_dimensionality",
    "file_path": "inference/core/workflows/execution_engine/v1/compiler/graph_constructor.py",
    "speedup_x": 1.3698571068731296,
    "review_quality": "high",
    "pre_optimization_commit": "90243bdc6278ef7d17b6db09dc1eb5b0d155b4be",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def establish_step_execution_dimensionality(\n    inputs_dimensionalities: Dict[str, Set[int]],\n    control_flow_lineage_support: List[str],\n    output_dimensionality_offset: int,\n) -> int:\n    \"\"\"\n    Determine how many batch dimensions (execution slices) a step runs with.\n\n    Used during workflow compilation in denote_data_flow_for_step. The result\n    is stored on StepNode.step_execution_dimensionality and consumed at\n    execution time to:\n    - Drive how many times the step is executed (which batch indices/slices).\n    - Align and expand inputs (e.g. auto-batch casting) to match this size.\n    - Validate that parameter dimensionalities are compatible (runtime checks\n      in step_input_assembler and manager).\n\n    Logic:\n    - If no input has non-zero dimensionality but the step is gated by\n      control flow (control_flow_lineage_support non-empty), the\n      dimensionality is the number of control-flow branches.\n    - Otherwise, the minimum non-zero input dimensionality is used; if\n      output_dimensionality_offset < 0 (step reduces batch dimension),\n      one is subtracted.\n\n    Args:\n        inputs_dimensionalities: Per-input sets of dimensionalities (from\n            get_inputs_dimensionalities).\n        control_flow_lineage_support: Lineage identifiers for control-flow\n            branches that gate this step (from establish_batch_oriented_step_lineage).\n        output_dimensionality_offset: Block's output dimensionality offset\n            (positive = expand, negative = reduce batch dimension).\n\n    Returns:\n        The number of batch dimensions (execution slices) for this step.\n    \"\"\"\n    step_execution_dimensionality = 0\n    non_zero_dimensionalities = {\n        dimensionality\n        for dimensionalities in inputs_dimensionalities.values()\n        for dimensionality in dimensionalities\n        if dimensionality > 0\n    }\n    if len(non_zero_dimensionalities) == 0 and len(control_flow_lineage_support) > 0:\n        return len(control_flow_lineage_support)\n    if len(non_zero_dimensionalities) > 0:\n        step_execution_dimensionality = min(non_zero_dimensionalities)\n        if output_dimensionality_offset < 0:\n            step_execution_dimensionality -= 1\n    return step_execution_dimensionality\n",
    "optimized_function_code": "from typing import Dict, List, Set\n\n\ndef establish_step_execution_dimensionality(\n    inputs_dimensionalities: Dict[str, Set[int]],\n    control_flow_lineage_support: List[str],\n    output_dimensionality_offset: int,\n) -> int:\n    \"\"\"\n    Determine how many batch dimensions (execution slices) a step runs with.\n\n    Used during workflow compilation in denote_data_flow_for_step. The result\n    is stored on StepNode.step_execution_dimensionality and consumed at\n    execution time to:\n    - Drive how many times the step is executed (which batch indices/slices).\n    - Align and expand inputs (e.g. auto-batch casting) to match this size.\n    - Validate that parameter dimensionalities are compatible (runtime checks\n      in step_input_assembler and manager).\n\n    Logic:\n    - If no input has non-zero dimensionality but the step is gated by\n      control flow (control_flow_lineage_support non-empty), the\n      dimensionality is the number of control-flow branches.\n    - Otherwise, the minimum non-zero input dimensionality is used; if\n      output_dimensionality_offset < 0 (step reduces batch dimension),\n      one is subtracted.\n\n    Args:\n        inputs_dimensionalities: Per-input sets of dimensionalities (from\n            get_inputs_dimensionalities).\n        control_flow_lineage_support: Lineage identifiers for control-flow\n            branches that gate this step (from establish_batch_oriented_step_lineage).\n        output_dimensionality_offset: Block's output dimensionality offset\n            (positive = expand, negative = reduce batch dimension).\n\n    Returns:\n        The number of batch dimensions (execution slices) for this step.\n    \"\"\"\n    step_execution_dimensionality = 0\n    # Find the smallest positive dimensionality without building a set.\n    min_positive = None\n    outer_break = False\n    for dimensionalities in inputs_dimensionalities.values():\n        for dimensionality in dimensionalities:\n            if dimensionality > 0:\n                if min_positive is None or dimensionality < min_positive:\n                    min_positive = dimensionality\n                    # Minimum possible positive dimensionality is 1; we can stop early.\n                    if min_positive == 1:\n                        outer_break = True\n                        break\n        if outer_break:\n            break\n\n    if min_positive is None and len(control_flow_lineage_support) > 0:\n        return len(control_flow_lineage_support)\n    if min_positive is not None:\n        step_execution_dimensionality = min_positive\n        if output_dimensionality_offset < 0:\n            step_execution_dimensionality -= 1\n    return step_execution_dimensionality",
    "optimized_raw_markdown": "```python:inference/core/workflows/execution_engine/v1/compiler/graph_constructor.py\nfrom typing import Dict, List, Set\n\n\ndef establish_step_execution_dimensionality(\n    inputs_dimensionalities: Dict[str, Set[int]],\n    control_flow_lineage_support: List[str],\n    output_dimensionality_offset: int,\n) -> int:\n    \"\"\"\n    Determine how many batch dimensions (execution slices) a step runs with.\n\n    Used during workflow compilation in denote_data_flow_for_step. The result\n    is stored on StepNode.step_execution_dimensionality and consumed at\n    execution time to:\n    - Drive how many times the step is executed (which batch indices/slices).\n    - Align and expand inputs (e.g. auto-batch casting) to match this size.\n    - Validate that parameter dimensionalities are compatible (runtime checks\n      in step_input_assembler and manager).\n\n    Logic:\n    - If no input has non-zero dimensionality but the step is gated by\n      control flow (control_flow_lineage_support non-empty), the\n      dimensionality is the number of control-flow branches.\n    - Otherwise, the minimum non-zero input dimensionality is used; if\n      output_dimensionality_offset < 0 (step reduces batch dimension),\n      one is subtracted.\n\n    Args:\n        inputs_dimensionalities: Per-input sets of dimensionalities (from\n            get_inputs_dimensionalities).\n        control_flow_lineage_support: Lineage identifiers for control-flow\n            branches that gate this step (from establish_batch_oriented_step_lineage).\n        output_dimensionality_offset: Block's output dimensionality offset\n            (positive = expand, negative = reduce batch dimension).\n\n    Returns:\n        The number of batch dimensions (execution slices) for this step.\n    \"\"\"\n    step_execution_dimensionality = 0\n    # Find the smallest positive dimensionality without building a set.\n    min_positive = None\n    outer_break = False\n    for dimensionalities in inputs_dimensionalities.values():\n        for dimensionality in dimensionalities:\n            if dimensionality > 0:\n                if min_positive is None or dimensionality < min_positive:\n                    min_positive = dimensionality\n                    # Minimum possible positive dimensionality is 1; we can stop early.\n                    if min_positive == 1:\n                        outer_break = True\n                        break\n        if outer_break:\n            break\n\n    if min_positive is None and len(control_flow_lineage_support) > 0:\n        return len(control_flow_lineage_support)\n    if min_positive is not None:\n        step_execution_dimensionality = min_positive\n        if output_dimensionality_offset < 0:\n            step_execution_dimensionality -= 1\n    return step_execution_dimensionality\n```",
    "optimized_function_only": "def establish_step_execution_dimensionality(\n    inputs_dimensionalities: Dict[str, Set[int]],\n    control_flow_lineage_support: List[str],\n    output_dimensionality_offset: int,\n) -> int:\n    \"\"\"\n    Determine how many batch dimensions (execution slices) a step runs with.\n\n    Used during workflow compilation in denote_data_flow_for_step. The result\n    is stored on StepNode.step_execution_dimensionality and consumed at\n    execution time to:\n    - Drive how many times the step is executed (which batch indices/slices).\n    - Align and expand inputs (e.g. auto-batch casting) to match this size.\n    - Validate that parameter dimensionalities are compatible (runtime checks\n      in step_input_assembler and manager).\n\n    Logic:\n    - If no input has non-zero dimensionality but the step is gated by\n      control flow (control_flow_lineage_support non-empty), the\n      dimensionality is the number of control-flow branches.\n    - Otherwise, the minimum non-zero input dimensionality is used; if\n      output_dimensionality_offset < 0 (step reduces batch dimension),\n      one is subtracted.\n\n    Args:\n        inputs_dimensionalities: Per-input sets of dimensionalities (from\n            get_inputs_dimensionalities).\n        control_flow_lineage_support: Lineage identifiers for control-flow\n            branches that gate this step (from establish_batch_oriented_step_lineage).\n        output_dimensionality_offset: Block's output dimensionality offset\n            (positive = expand, negative = reduce batch dimension).\n\n    Returns:\n        The number of batch dimensions (execution slices) for this step.\n    \"\"\"\n    step_execution_dimensionality = 0\n    # Find the smallest positive dimensionality without building a set.\n    min_positive = None\n    outer_break = False\n    for dimensionalities in inputs_dimensionalities.values():\n        for dimensionality in dimensionalities:\n            if dimensionality > 0:\n                if min_positive is None or dimensionality < min_positive:\n                    min_positive = dimensionality\n                    # Minimum possible positive dimensionality is 1; we can stop early.\n                    if min_positive == 1:\n                        outer_break = True\n                        break\n        if outer_break:\n            break\n\n    if min_positive is None and len(control_flow_lineage_support) > 0:\n        return len(control_flow_lineage_support)\n    if min_positive is not None:\n        step_execution_dimensionality = min_positive\n        if output_dimensionality_offset < 0:\n            step_execution_dimensionality -= 1\n    return step_execution_dimensionality",
    "original_file_content": "import itertools\nfrom collections import defaultdict\nfrom copy import copy, deepcopy\nfrom typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union\nfrom uuid import uuid4\n\nimport networkx as nx\nfrom networkx import DiGraph\n\nfrom inference.core import logger\nfrom inference.core.workflows.errors import (\n    AssumptionError,\n    BlockInterfaceError,\n    ControlFlowDefinitionError,\n    ExecutionGraphStructureError,\n    InvalidReferenceTargetError,\n    StepInputDimensionalityError,\n    StepInputLineageError,\n    WorkflowBlockError,\n)\nfrom inference.core.workflows.execution_engine.constants import (\n    NODE_COMPILATION_OUTPUT_PROPERTY,\n    PARSED_NODE_INPUT_SELECTORS_PROPERTY,\n    TOP_LEVEL_LINEAGES_KEY,\n    WORKFLOW_INPUT_BATCH_LINEAGE_ID,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    InputType,\n    JsonField,\n    OutputDefinition,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    STEP_AS_SELECTED_ELEMENT,\n    Kind,\n)\nfrom inference.core.workflows.execution_engine.introspection.entities import (\n    ParsedSelector,\n)\nfrom inference.core.workflows.execution_engine.introspection.selectors_parser import (\n    get_step_selectors,\n)\nfrom inference.core.workflows.execution_engine.profiling.core import (\n    WorkflowsProfiler,\n    execution_phase,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import (\n    AutoBatchCastingConfig,\n    CompoundStepInputDefinition,\n    DictOfStepInputDefinitions,\n    DynamicStepInputDefinition,\n    ExecutionGraphNode,\n    InputDimensionalitySpecification,\n    InputNode,\n    ListOfStepInputDefinitions,\n    NodeCategory,\n    NodeInputCategory,\n    OutputNode,\n    ParameterSpecification,\n    ParsedWorkflowDefinition,\n    PropertyPredecessorDefinition,\n    StaticStepInputDefinition,\n    StepInputData,\n    StepInputDefinition,\n    StepNode,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.graph_traversal import (\n    traverse_graph_ensuring_parents_are_reached_first,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.reference_type_checker import (\n    validate_reference_kinds,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import (\n    construct_input_selector,\n    construct_output_selector,\n    construct_step_selector,\n    get_last_chunk_of_selector,\n    get_nodes_of_specific_category,\n    get_step_selector_from_its_output,\n    identify_lineage,\n    is_control_flow_step,\n    is_input_node,\n    is_input_selector,\n    is_output_node,\n    is_step_node,\n    is_step_output_selector,\n    is_step_selector,\n    node_as,\n)\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nNODE_DEFINITION_KEY = \"definition\"\nSTEP_INPUT_SELECTORS_PROPERTY = \"step_input_selectors\"\nEXCLUDED_FIELDS = {\"type\", \"name\"}\n\n\n@execution_phase(\n    name=\"execution_graph_creation\",\n    categories=[\"execution_engine_operation\"],\n)\ndef prepare_execution_graph(\n    workflow_definition: ParsedWorkflowDefinition,\n    profiler: Optional[WorkflowsProfiler] = None,\n) -> DiGraph:\n    execution_graph = construct_graph(\n        workflow_definition=workflow_definition,\n    )\n    if not nx.is_directed_acyclic_graph(execution_graph):\n        raise ExecutionGraphStructureError(\n            public_message=f\"Detected cycle in execution graph. This means that there is output from one \"\n            f\"step that is connected to input of other step creating loop in the graph that would \"\n            f\"never end if executed.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    return denote_data_flow_in_workflow(\n        execution_graph=execution_graph,\n        parsed_workflow_definition=workflow_definition,\n    )\n\n\ndef construct_graph(\n    workflow_definition: ParsedWorkflowDefinition,\n) -> DiGraph:\n    execution_graph = nx.DiGraph()\n    execution_graph = add_input_nodes_for_graph(\n        inputs=workflow_definition.inputs,\n        execution_graph=execution_graph,\n    )\n    execution_graph = add_steps_nodes_for_graph(\n        steps=workflow_definition.steps,\n        execution_graph=execution_graph,\n    )\n    execution_graph = add_output_nodes_for_graph(\n        outputs=workflow_definition.outputs,\n        execution_graph=execution_graph,\n    )\n    execution_graph = add_steps_edges(\n        workflow_definition=workflow_definition,\n        execution_graph=execution_graph,\n    )\n    return add_edges_for_outputs(\n        workflow_definition=workflow_definition,\n        execution_graph=execution_graph,\n    )\n\n\ndef add_input_nodes_for_graph(\n    inputs: List[InputType],\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for input_spec in inputs:\n        input_selector = construct_input_selector(input_name=input_spec.name)\n        if input_spec.is_batch_oriented():\n            if input_spec.dimensionality < 1:\n                raise ExecutionGraphStructureError(\n                    public_message=f\"Detected batch oriented input `{input_spec.name}` with \"\n                    f\"declared dimensionality `{input_spec.dimensionality}` which is below \"\n                    f\"one (one is minimum dimensionality of the batch). Fix input definition in\"\n                    f\"your Workflow.\",\n                    context=\"workflow_compilation | execution_graph_construction\",\n                )\n            data_lineage = [WORKFLOW_INPUT_BATCH_LINEAGE_ID]\n            for _ in range(input_spec.dimensionality - 1):\n                # TODO: this may end up being a bug - with ability for multi-step debugging, if we will\n                #  ever have a situation that there will be multiple step outputs with nested\n                #  dimensionality with the same lineage, this re-construction method will\n                #  assign a different lineage identifier, causing the inputs being non-composable in\n                #  a single execution branch\n                data_lineage.append(f\"{uuid4()}\")\n        else:\n            data_lineage = []\n        compilation_output = InputNode(\n            node_category=NodeCategory.INPUT_NODE,\n            name=input_spec.name,\n            selector=input_selector,\n            data_lineage=data_lineage,\n            input_manifest=input_spec,\n        )\n        execution_graph.add_node(\n            input_selector,\n            **{\n                NODE_COMPILATION_OUTPUT_PROPERTY: compilation_output,\n            },\n        )\n    return execution_graph\n\n\ndef add_steps_nodes_for_graph(\n    steps: List[WorkflowBlockManifest],\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for step in steps:\n        step_selector = construct_step_selector(step_name=step.name)\n        compilation_output = StepNode(\n            node_category=NodeCategory.STEP_NODE,\n            name=step.name,\n            selector=step_selector,\n            data_lineage=[],\n            step_manifest=step,\n        )\n        execution_graph.add_node(\n            step_selector,\n            **{\n                NODE_COMPILATION_OUTPUT_PROPERTY: compilation_output,\n            },\n        )\n    return execution_graph\n\n\ndef add_output_nodes_for_graph(\n    outputs: List[JsonField],\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for output_spec in outputs:\n        output_selector = construct_output_selector(name=output_spec.name)\n        compilation_output = OutputNode(\n            node_category=NodeCategory.OUTPUT_NODE,\n            name=output_spec.name,\n            selector=output_selector,\n            data_lineage=[],\n            output_manifest=output_spec,\n        )\n        execution_graph.add_node(\n            output_selector,\n            **{\n                NODE_COMPILATION_OUTPUT_PROPERTY: compilation_output,\n            },\n        )\n    return execution_graph\n\n\ndef add_steps_edges(\n    workflow_definition: ParsedWorkflowDefinition,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for step in workflow_definition.steps:\n        source_step_selector = construct_step_selector(step_name=step.name)\n        step_selectors = get_step_selectors(step_manifest=step)\n        execution_graph.nodes[source_step_selector][\n            PARSED_NODE_INPUT_SELECTORS_PROPERTY\n        ] = step_selectors\n        execution_graph = add_edges_for_step(\n            execution_graph=execution_graph,\n            source_step_selector=source_step_selector,\n            target_step_parsed_selectors=step_selectors,\n        )\n    return execution_graph\n\n\ndef add_edges_for_step(\n    execution_graph: DiGraph,\n    source_step_selector: str,\n    target_step_parsed_selectors: List[ParsedSelector],\n) -> DiGraph:\n    for target_step_parsed_selector in target_step_parsed_selectors:\n        execution_graph = add_edge_for_step(\n            execution_graph=execution_graph,\n            source_step_selector=source_step_selector,\n            target_step_parsed_selector=target_step_parsed_selector,\n        )\n    return execution_graph\n\n\ndef add_edge_for_step(\n    execution_graph: DiGraph,\n    source_step_selector: str,\n    target_step_parsed_selector: ParsedSelector,\n) -> DiGraph:\n    target_step_selector = get_step_selector_from_its_output(\n        step_output_selector=target_step_parsed_selector.value\n    )\n    verify_edge_is_created_between_existing_nodes(\n        execution_graph=execution_graph,\n        start=source_step_selector,\n        end=target_step_selector,\n    )\n    if is_step_selector(target_step_parsed_selector.value):\n        return establish_control_flow_edge(\n            source_step_selector=source_step_selector,\n            target_step_parsed_selector=target_step_parsed_selector,\n            execution_graph=execution_graph,\n        )\n    if is_input_selector(target_step_parsed_selector.value):\n        input_node_compilation_data = node_as(\n            execution_graph=execution_graph,\n            node=target_step_parsed_selector.value,\n            expected_type=InputNode,\n        )\n        actual_input_kind = input_node_compilation_data.input_manifest.kind\n    else:\n        other_step_compilation_data = node_as(\n            execution_graph=execution_graph,\n            node=target_step_selector,\n            expected_type=StepNode,\n        )\n        source_step_compilation_data = node_as(\n            execution_graph=execution_graph,\n            node=source_step_selector,\n            expected_type=StepNode,\n        )\n        actual_input_kind = get_kind_of_value_provided_in_step_output(\n            step_manifest=other_step_compilation_data.step_manifest,\n            step_property=get_last_chunk_of_selector(\n                selector=target_step_parsed_selector.value\n            ),\n            source_step_manifest=source_step_compilation_data.step_manifest,\n        )\n    expected_input_kind = list(\n        itertools.chain.from_iterable(\n            ref.kind\n            for ref in target_step_parsed_selector.definition.allowed_references\n        )\n    )\n    error_message = (\n        f\"Failed to validate reference provided for step: {source_step_selector} regarding property: \"\n        f\"{target_step_parsed_selector.definition.property_name} with value: {target_step_parsed_selector.value}. \"\n        f\"Allowed kinds of references for this property: {list(set(e.name for e in expected_input_kind))}. \"\n        f\"Types of output for referred property: \"\n        f\"{list(set(a.name if isinstance(a, Kind) else a for a in actual_input_kind))}\"\n    )\n    validate_reference_kinds(\n        expected=expected_input_kind,\n        actual=actual_input_kind,\n        error_message=error_message,\n    )\n    if execution_graph.has_edge(target_step_selector, source_step_selector):\n        edge_data = execution_graph.edges[(target_step_selector, source_step_selector)]\n        if STEP_INPUT_SELECTORS_PROPERTY not in edge_data:\n            edge_data[STEP_INPUT_SELECTORS_PROPERTY] = []\n        edge_data[STEP_INPUT_SELECTORS_PROPERTY].append(\n            target_step_parsed_selector,\n        )\n    else:\n        execution_graph.add_edge(\n            target_step_selector,\n            source_step_selector,\n            **{STEP_INPUT_SELECTORS_PROPERTY: [target_step_parsed_selector]},\n        )\n    return execution_graph\n\n\ndef establish_control_flow_edge(\n    source_step_selector: str,\n    target_step_parsed_selector: ParsedSelector,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    if not step_definition_allows_control_flow_references(\n        parsed_selector=target_step_parsed_selector\n    ):\n        raise ExecutionGraphStructureError(\n            public_message=f\"Detected reference to other step in manifest of step {source_step_selector}. \"\n            f\"This is not allowed, as step manifest does not define any properties of type `StepSelector` \"\n            f\"allowing for defining connections between steps that represent flow control in `workflows`.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    target_step_selector = get_step_selector_from_its_output(\n        step_output_selector=target_step_parsed_selector.value\n    )\n    source_compilation_data = node_as(\n        execution_graph=execution_graph,\n        node=source_step_selector,\n        expected_type=StepNode,\n    )\n    target_compilation_data = node_as(\n        execution_graph=execution_graph,\n        node=target_step_selector,\n        expected_type=StepNode,\n    )\n    nodes_categories = {\n        source_compilation_data.node_category,\n        target_compilation_data.node_category,\n    }\n    if nodes_categories != {NodeCategory.STEP_NODE}:\n        raise ExecutionGraphStructureError(\n            public_message=f\"Attempted to create flow-control connection between workflow nodes: \"\n            f\"{source_step_selector} and {target_step_selector}, one of which is not denoted\"\n            f\"as step node.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    execution_graph.add_edge(\n        source_step_selector,\n        target_step_selector,\n    )\n    if target_step_selector in source_compilation_data.child_execution_branches:\n        raise ExecutionGraphStructureError(\n            public_message=f\"While establishing flow-control connection between source `{source_step_selector}` \"\n            f\"and target `{target_step_selector}` it was discovered that source step defines\"\n            f\"control flow transition into target one more than once, which is not allowed as \"\n            f\"that situation creates ambiguity in selecting execution branch.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    execution_branch_name = f\"Branch[{source_step_selector} -> {target_step_parsed_selector.definition.property_name}]\"\n    source_compilation_data.child_execution_branches[target_step_selector] = (\n        execution_branch_name\n    )\n    target_compilation_data.execution_branches_impacting_inputs.add(\n        execution_branch_name\n    )\n    return execution_graph\n\n\ndef step_definition_allows_control_flow_references(\n    parsed_selector: ParsedSelector,\n) -> bool:\n    return any(\n        definition.selected_element == STEP_AS_SELECTED_ELEMENT\n        for definition in parsed_selector.definition.allowed_references\n    )\n\n\ndef get_kind_of_value_provided_in_step_output(\n    step_manifest: WorkflowBlockManifest,\n    step_property: str,\n    source_step_manifest: WorkflowBlockManifest,\n) -> List[Kind]:\n    referred_node_outputs = step_manifest.get_actual_outputs()\n    actual_kind = []\n    matched_property = False\n    for output in referred_node_outputs:\n        if output.name != step_property:\n            continue\n        matched_property = True\n        actual_kind.extend(output.kind)\n    if not matched_property:\n        property_name = get_property_with_invalid_selector(\n            manifest=source_step_manifest,\n            step_property=step_property,\n        )\n        raise ExecutionGraphStructureError(\n            public_message=f\"Found reference to non-existing property `{step_property}` of step `{step_manifest.name}`.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=source_step_manifest.name,\n                    block_type=source_step_manifest.type,\n                    property_name=property_name,\n                    property_details=f\"'{step_manifest.name}.{step_property}' is an invalid reference\",\n                )\n            ],\n        )\n    return actual_kind\n\n\ndef add_edges_for_step_inputs(\n    execution_graph: DiGraph,\n    input_selectors: Set[str],\n    step_selector: str,\n) -> DiGraph:\n    for input_selector in input_selectors:\n        if is_step_output_selector(selector_or_value=input_selector):\n            input_selector = get_step_selector_from_its_output(\n                step_output_selector=input_selector\n            )\n        verify_edge_is_created_between_existing_nodes(\n            execution_graph=execution_graph,\n            start=input_selector,\n            end=step_selector,\n        )\n        execution_graph.add_edge(input_selector, step_selector)\n    return execution_graph\n\n\ndef add_edges_for_outputs(\n    workflow_definition: ParsedWorkflowDefinition,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for output in workflow_definition.outputs:\n        node_selector = output.selector\n        if is_step_output_selector(selector_or_value=node_selector):\n            node_selector = get_step_selector_from_its_output(\n                step_output_selector=node_selector\n            )\n        output_selector = construct_output_selector(name=output.name)\n        verify_edge_is_created_between_existing_nodes(\n            execution_graph=execution_graph,\n            start=node_selector,\n            end=output_selector,\n        )\n        output_node_manifest = node_as(\n            execution_graph=execution_graph,\n            node=output_selector,\n            expected_type=OutputNode,\n        )\n        if is_step_output_selector(selector_or_value=output.selector):\n            step_manifest = execution_graph.nodes[node_selector][\n                NODE_COMPILATION_OUTPUT_PROPERTY\n            ].step_manifest\n            step_outputs = step_manifest.get_actual_outputs()\n            denote_output_node_kind_based_on_step_outputs(\n                output_selector=output.selector,\n                step_outputs=step_outputs,\n                output_node_manifest=output_node_manifest,\n            )\n        else:\n            input_manifest = node_as(\n                execution_graph=execution_graph,\n                node=node_selector,\n                expected_type=InputNode,\n            ).input_manifest\n            output_node_manifest.kind = copy(input_manifest.kind)\n        execution_graph.add_edge(node_selector, output_selector)\n    return execution_graph\n\n\ndef verify_edge_is_created_between_existing_nodes(\n    execution_graph: DiGraph,\n    start: str,\n    end: str,\n) -> None:\n    if not execution_graph.has_node(start) or not execution_graph.has_node(end):\n        invalid_block = start if not execution_graph.has_node(start) else end\n        referencing_block = end if invalid_block == start else start\n\n        step_type = None\n        property_name = None\n        if execution_graph.has_node(referencing_block):\n            if is_step_node(execution_graph, referencing_block):\n                step_manifest = node_as(\n                    execution_graph=execution_graph,\n                    node=referencing_block,\n                    expected_type=StepNode,\n                ).step_manifest\n                step_type = step_manifest.type\n                property_name = get_property_with_invalid_selector(\n                    manifest=step_manifest,\n                    step_property=invalid_block,\n                )\n\n        block_id = (\n            \"$outputs\"\n            if referencing_block.startswith(\"$outputs.\")\n            else get_last_chunk_of_selector(selector=referencing_block)\n        )\n        property_name = (\n            get_last_chunk_of_selector(selector=referencing_block)\n            if referencing_block.startswith(\"$outputs.\")\n            else property_name\n        )\n\n        is_input = is_input_selector(selector_or_value=invalid_block)\n        raise InvalidReferenceTargetError(\n            public_message=f\"Workflow references '{invalid_block}' which points to a non-existent {is_input and 'input parameter' or 'block'}.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=block_id,\n                    block_type=step_type,\n                    property_name=property_name,\n                    property_details=f\"Invalid reference to {invalid_block}\",\n                ),\n            ],\n        )\n\n\ndef denote_output_node_kind_based_on_step_outputs(\n    output_selector: str,\n    step_outputs: List[OutputDefinition],\n    output_node_manifest: OutputNode,\n) -> None:\n    selected_output_name = get_last_chunk_of_selector(selector=output_selector)\n    kinds_for_outputs = {output.name: output.kind for output in step_outputs}\n\n    if selected_output_name == \"*\":\n        output_node_manifest.kind = deepcopy(kinds_for_outputs)\n        return None\n    if selected_output_name not in kinds_for_outputs:\n        output_name = output_node_manifest.output_manifest.name\n\n        raise InvalidReferenceTargetError(\n            public_message=f\"Workflow output references '{output_selector}' which points to a non-existent block property.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=\"$outputs\",\n                    property_name=output_name,\n                    property_details=f\"Invalid reference to {output_selector}\",\n                ),\n            ],\n        )\n    output_node_manifest.kind = copy(kinds_for_outputs[selected_output_name])\n    return None\n\n\ndef denote_data_flow_in_workflow(\n    execution_graph: DiGraph,\n    parsed_workflow_definition: ParsedWorkflowDefinition,\n) -> nx.DiGraph:\n    block_manifest_by_step_name = {\n        step.name: step for step in parsed_workflow_definition.steps\n    }\n    super_input_node = \"<super-input>\"\n    execution_graph = add_super_input_node_in_execution_graph(\n        execution_graph=execution_graph,\n        super_input_node=super_input_node,\n    )\n    execution_graph.nodes[super_input_node][NODE_COMPILATION_OUTPUT_PROPERTY] = (\n        InputNode(\n            node_category=NodeCategory.INPUT_NODE,\n            name=super_input_node,\n            selector=f\"$inputs.{super_input_node}\",\n            data_lineage=[],\n            input_manifest=None,  # this is expected never to be reached\n        )\n    )\n    top_level_data_lineage = set()\n    for node in traverse_graph_ensuring_parents_are_reached_first(\n        graph=execution_graph,\n        start_node=super_input_node,\n    ):\n        execution_graph = denote_data_flow_for_node(\n            execution_graph=execution_graph,\n            node=node,\n            block_manifest_by_step_name=block_manifest_by_step_name,\n            on_top_level_lineage_denoted=lambda element: top_level_data_lineage.add(\n                element\n            ),\n        )\n    execution_graph.remove_node(super_input_node)\n    execution_graph.graph[TOP_LEVEL_LINEAGES_KEY] = top_level_data_lineage\n    return execution_graph\n\n\ndef denote_data_flow_for_node(\n    execution_graph: DiGraph,\n    node: str,\n    block_manifest_by_step_name: Dict[str, WorkflowBlockManifest],\n    on_top_level_lineage_denoted: Callable[[str], None],\n) -> DiGraph:\n    if is_input_node(execution_graph=execution_graph, node=node):\n        # everything already set there, in the previous stage of compilation\n        return execution_graph\n    if is_step_node(execution_graph=execution_graph, node=node):\n        step_name = get_last_chunk_of_selector(selector=node)\n        if step_name not in block_manifest_by_step_name:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler expected manifest for the step: {step_name} to be registered \"\n                f\"but this condition is not met. This is most likely the bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | retrieving_predecessors_for_output\",\n            )\n        manifest = block_manifest_by_step_name[step_name]\n        return denote_data_flow_for_step(\n            execution_graph=execution_graph,\n            node=node,\n            manifest=manifest,\n            on_top_level_lineage_denoted=on_top_level_lineage_denoted,\n        )\n    if is_output_node(execution_graph=execution_graph, node=node):\n        # output is allowed to have exactly one predecessor\n        output_predecessors = list(execution_graph.predecessors(node))\n        if len(output_predecessors) != 1:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler expected each output in compiled graph to have one predecessor, \"\n                f\"but this condition is not met for node {node}. This is most likely the bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | retrieving_predecessors_for_output\",\n            )\n        predecessor_node = output_predecessors[0]\n        predecessor_node_data = node_as(\n            execution_graph=execution_graph,\n            node=predecessor_node,\n            expected_type=ExecutionGraphNode,\n        )\n        predecessor_node_lineage = predecessor_node_data.data_lineage\n        output_node_data = node_as(\n            execution_graph=execution_graph,\n            node=node,\n            expected_type=OutputNode,\n        )\n        output_node_data.data_lineage = predecessor_node_lineage\n        return execution_graph\n    raise AssumptionError(\n        f\"Workflow Compiler encountered node: {node} which cannot be classified as known node type. \"\n        f\"This is most likely the bug. Contact Roboflow team through github issues \"\n        f\"(https://github.com/roboflow/inference/issues) providing full \"\n        f\"context of the problem - including workflow definition you use.\",\n        context=\"workflow_compilation | execution_graph_construction | denoting_data_flow_for_step\",\n    )\n\n\ndef denote_data_flow_for_step(\n    execution_graph: DiGraph,\n    node: str,\n    manifest: WorkflowBlockManifest,\n    on_top_level_lineage_denoted: Callable[[str], None],\n) -> DiGraph:\n    all_control_flow_predecessors, all_non_control_flow_predecessors = (\n        separate_control_flow_predecessors_from_data_providers(\n            execution_graph=execution_graph, node=node\n        )\n    )\n    input_data = build_input_data_for_step(\n        manifest=manifest,\n        step_node=node,\n        data_providing_predecessors=all_non_control_flow_predecessors,\n        execution_graph=execution_graph,\n    )\n    step_name = get_last_chunk_of_selector(node)\n    step_node_data = node_as(\n        execution_graph=execution_graph,\n        node=node,\n        expected_type=StepNode,\n    )\n    parsed_step_input_selectors: List[ParsedSelector] = execution_graph.nodes[node][\n        PARSED_NODE_INPUT_SELECTORS_PROPERTY\n    ]\n    batch_compatibility_of_properties = retrieve_batch_compatibility_of_input_selectors(\n        input_selectors=parsed_step_input_selectors\n    )\n    scalar_parameters_to_be_batched = (\n        verify_declared_batch_compatibility_against_actual_inputs(\n            node=node,\n            step_node_data=step_node_data,\n            input_data=input_data,\n            batch_compatibility_of_properties=batch_compatibility_of_properties,\n        )\n    )\n    input_dimensionality_offsets = manifest.get_input_dimensionality_offsets()\n    verify_step_input_dimensionality_offsets(\n        step_name=step_name,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n    )\n    inputs_dimensionalities = get_inputs_dimensionalities(\n        step_name=step_name,\n        step_type=manifest.type,\n        input_data=input_data,\n        scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n    )\n    logger.debug(\n        f\"For step: {node}, detected the following input dimensionalities: {inputs_dimensionalities}\"\n    )\n    parameters_with_batch_inputs = grab_parameters_defining_batch_inputs(\n        inputs_dimensionalities=inputs_dimensionalities,\n    )\n    dimensionality_reference_property = manifest.get_dimensionality_reference_property()\n    output_dimensionality_offset = manifest.get_output_dimensionality_offset()\n    verify_step_input_dimensionality_offsets(\n        step_name=step_name,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n    )\n    verify_output_offset(\n        step_name=step_name,\n        parameters_with_batch_inputs=parameters_with_batch_inputs,\n        dimensionality_reference_property=dimensionality_reference_property,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n        output_dimensionality_offset=output_dimensionality_offset,\n    )\n    verify_input_data_dimensionality(\n        step_name=step_name,\n        step_type=manifest.type,\n        dimensionality_reference_property=dimensionality_reference_property,\n        inputs_dimensionalities=inputs_dimensionalities,\n        dimensionality_offstes=input_dimensionality_offsets,\n    )\n    all_data_derived_lineages = get_input_data_lineage_excluding_auto_batch_casting(\n        step_name=step_name,\n        input_data=input_data,\n        scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n    )\n    all_control_flow_lineages = get_lineage_derived_from_control_flow(\n        control_flow_steps_selectors=all_control_flow_predecessors,\n        execution_graph=execution_graph,\n    )\n    verify_compatibility_of_input_data_lineage_with_control_flow_lineage(\n        step_name=step_name,\n        inputs_lineage=all_data_derived_lineages,\n        control_flow_steps_selectors=all_control_flow_predecessors,\n        execution_graph=execution_graph,\n    )\n    step_node_data.input_data = input_data\n    step_node_data.dimensionality_reference_property = dimensionality_reference_property\n    step_node_data.control_flow_lineage_dims = [\n        len(_lineage) for _lineage in all_control_flow_lineages if _lineage\n    ]\n    step_node_data.batch_oriented_parameters = parameters_with_batch_inputs\n    if not all_data_derived_lineages and not all_control_flow_lineages:\n        if manifest.get_output_dimensionality_offset() > 0:\n            # brave decision to open a Pandora box\n            data_lineage = [node]\n        else:\n            data_lineage = []\n        control_flow_lineage_support = []\n    else:\n        data_lineage, control_flow_lineage_support = (\n            establish_batch_oriented_step_lineage(\n                step_selector=node,\n                all_data_derived_lineages=all_data_derived_lineages,\n                all_control_flow_lineages=all_control_flow_lineages,\n                input_data=input_data,\n                dimensionality_reference_property=dimensionality_reference_property,\n                output_dimensionality_offset=output_dimensionality_offset,\n            )\n        )\n    step_node_data.step_execution_dimensionality = (\n        establish_step_execution_dimensionality(\n            inputs_dimensionalities=inputs_dimensionalities,\n            control_flow_lineage_support=control_flow_lineage_support,\n            output_dimensionality_offset=output_dimensionality_offset,\n        )\n    )\n    lineage_supports = get_lineage_support_for_auto_batch_casted_parameters(\n        input_dimensionalities=inputs_dimensionalities,\n        all_lineages_of_batch_parameters=all_data_derived_lineages,\n        scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n    )\n    step_node_data.auto_batch_casting_lineage_supports = lineage_supports\n    step_node_data.control_flow_lineage_support = control_flow_lineage_support\n    if data_lineage:\n        on_top_level_lineage_denoted(data_lineage[0])\n    step_node_data.data_lineage = data_lineage\n    return execution_graph\n\n\ndef _collect_unique_control_flow_lineages_with_step_mapping(\n    control_flow_steps_selectors: List[str],\n    execution_graph: nx.DiGraph,\n) -> Tuple[List[List[str]], Dict[int, List[str]]]:\n    \"\"\"\n    Collect data lineages from control flow steps and deduplicate by lineage id.\n\n    For each given control flow step selector, reads its data_lineage from the\n    execution graph. Returns unique non-empty lineages (by identify_lineage id)\n    and a mapping from lineage id to every step selector that produced that\n    lineage (used e.g. for error reporting when lineage is incompatible).\n\n    Args:\n        control_flow_steps_selectors: Step selectors (node ids) of control\n            flow steps whose data_lineage is to be collected.\n        execution_graph: The workflow execution graph containing step nodes\n            and their data_lineage.\n\n    Returns:\n        A tuple of (unique_lineages, lineage_id_to_step_selectors):\n        - unique_lineages: list of distinct non-empty data lineages.\n        - lineage_id_to_step_selectors: map from lineage id to list of step\n          selectors whose data_lineage has that id (includes empty lineages).\n    \"\"\"\n    unique_lineages: List[List[str]] = []\n    seen_lineage_ids: Set[int] = set()\n    lineage_id_to_step_selectors: Dict[int, List[str]] = defaultdict(list)\n\n    for step_selector in control_flow_steps_selectors:\n        step_data = node_as(\n            execution_graph=execution_graph,\n            node=step_selector,\n            expected_type=StepNode,\n        )\n        lineage = step_data.data_lineage\n        lineage_id = identify_lineage(lineage)\n        lineage_id_to_step_selectors[lineage_id].append(step_selector)\n        if lineage and lineage_id not in seen_lineage_ids:\n            seen_lineage_ids.add(lineage_id)\n            unique_lineages.append(lineage)\n\n    return unique_lineages, dict(lineage_id_to_step_selectors)\n\n\ndef get_lineage_derived_from_control_flow(\n    control_flow_steps_selectors: List[str],\n    execution_graph: nx.DiGraph,\n) -> List[List[str]]:\n    \"\"\"\n    Return unique non-empty data lineages from the given control flow steps.\n\n    Each lineage is taken from the step's data_lineage in the execution graph.\n    Lineages are deduplicated by lineage id (see identify_lineage); empty\n    lineages are omitted. Used when establishing batch-oriented step lineage.\n\n    Args:\n        control_flow_steps_selectors: Step selectors (node ids) of control\n            flow steps whose data_lineage is to be collected.\n        execution_graph: The workflow execution graph containing step nodes\n            and their data_lineage.\n\n    Returns:\n        List of distinct non-empty data lineages, one per unique lineage id.\n    \"\"\"\n    unique_lineages, _ = _collect_unique_control_flow_lineages_with_step_mapping(\n        control_flow_steps_selectors=control_flow_steps_selectors,\n        execution_graph=execution_graph,\n    )\n    return unique_lineages\n\n\ndef separate_control_flow_predecessors_from_data_providers(\n    execution_graph: DiGraph,\n    node: str,\n) -> Tuple[List[str], List[str]]:\n    all_predecessors = list(execution_graph.predecessors(node))\n    all_control_flow_predecessors = [\n        predecessor\n        for predecessor in all_predecessors\n        if is_control_flow_step(execution_graph=execution_graph, node=predecessor)\n    ]\n    all_non_control_flow_predecessors = [\n        predecessor\n        for predecessor in all_predecessors\n        if not is_control_flow_step(execution_graph=execution_graph, node=predecessor)\n    ]\n    return all_control_flow_predecessors, all_non_control_flow_predecessors\n\n\ndef build_input_data_for_step(\n    manifest: WorkflowBlockManifest,\n    step_node: str,\n    data_providing_predecessors: List[str],\n    execution_graph: DiGraph,\n) -> StepInputData:\n    predecessors_by_property_name = get_predecessors_for_step_manifest_properties(\n        execution_graph=execution_graph,\n        step_node=step_node,\n        data_providing_predecessors=data_providing_predecessors,\n    )\n    manifest_fields_values = get_manifest_fields_values(step_manifest=manifest)\n    result = {}\n    for name, value in manifest_fields_values.items():\n        result[name] = build_input_property(\n            step_node=step_node,\n            manifest_property_name=name,\n            manifest_property_value=value,\n            predecessors_by_property_name=predecessors_by_property_name,\n            execution_graph=execution_graph,\n        )\n    return result\n\n\ndef get_predecessors_for_step_manifest_properties(\n    execution_graph: DiGraph, step_node: str, data_providing_predecessors: List[str]\n) -> Dict[str, List[PropertyPredecessorDefinition]]:\n    predecessors_by_property_name = defaultdict(list)\n    for predecessor in data_providing_predecessors:\n        edge_data = execution_graph.edges[(predecessor, step_node)]\n        # STEP_INPUT_SELECTORS_PROPERTY is optional, as special <super-input> node may be directly\n        # connected to step\n        selectors_associated_to_edge: List[ParsedSelector] = edge_data.get(\n            STEP_INPUT_SELECTORS_PROPERTY, []\n        )\n        for selector_associated_to_edge in selectors_associated_to_edge:\n            definition = PropertyPredecessorDefinition(\n                predecessor_selector=predecessor,\n                parsed_selector=selector_associated_to_edge,\n            )\n            predecessors_by_property_name[\n                selector_associated_to_edge.definition.property_name\n            ].append(definition)\n    return predecessors_by_property_name\n\n\ndef build_input_property(\n    step_node: str,\n    manifest_property_name: str,\n    manifest_property_value: Any,\n    predecessors_by_property_name: Dict[str, List[PropertyPredecessorDefinition]],\n    execution_graph: DiGraph,\n) -> Union[StepInputDefinition, CompoundStepInputDefinition]:\n    if manifest_property_name not in predecessors_by_property_name:\n        return StaticStepInputDefinition(\n            parameter_specification=ParameterSpecification(\n                parameter_name=manifest_property_name,\n            ),\n            category=NodeInputCategory.STATIC_VALUE,\n            value=manifest_property_value,\n        )\n    if isinstance(manifest_property_value, dict):\n        return build_nested_dictionary_for_input_property(\n            step_node=step_node,\n            manifest_property_name=manifest_property_name,\n            manifest_property_value=manifest_property_value,\n            predecessors_definitions=predecessors_by_property_name[\n                manifest_property_name\n            ],\n            execution_graph=execution_graph,\n        )\n    if isinstance(manifest_property_value, list):\n        return build_nested_list_for_input_property(\n            step_node=step_node,\n            manifest_property_name=manifest_property_name,\n            manifest_property_value=manifest_property_value,\n            predecessors_definitions=predecessors_by_property_name[\n                manifest_property_name\n            ],\n            execution_graph=execution_graph,\n        )\n    matching_predecessors_data = predecessors_by_property_name[manifest_property_name]\n    if len(matching_predecessors_data) != 1:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler deduced that property `{manifest_property_name}` of step `{step_node}` \"\n            f\"should be fed with data coming from exactly one execution graph node, but found \"\n            f\"{len(matching_predecessors_data)} data sources. This is most likely the bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n        )\n    predecessor_selector, predecessor_parsed_selector = (\n        matching_predecessors_data[0].predecessor_selector,\n        matching_predecessors_data[0].parsed_selector,\n    )\n    if is_input_node(execution_graph=execution_graph, node=predecessor_selector):\n        predecessor_node_data = node_as(\n            execution_graph=execution_graph,\n            node=matching_predecessors_data[0].predecessor_selector,\n            expected_type=InputNode,\n        )\n        category = (\n            NodeInputCategory.BATCH_INPUT_PARAMETER\n            if predecessor_node_data.is_batch_oriented()\n            else NodeInputCategory.NON_BATCH_INPUT_PARAMETER\n        )\n        return DynamicStepInputDefinition(\n            parameter_specification=ParameterSpecification(\n                parameter_name=manifest_property_name,\n            ),\n            category=category,\n            data_lineage=predecessor_node_data.data_lineage,\n            selector=predecessor_node_data.selector,\n        )\n    if is_step_node(execution_graph=execution_graph, node=predecessor_selector):\n        predecessor_node_data = node_as(\n            execution_graph=execution_graph,\n            node=matching_predecessors_data[0].predecessor_selector,\n            expected_type=StepNode,\n        )\n        category = (\n            NodeInputCategory.BATCH_STEP_OUTPUT\n            if predecessor_node_data.output_dimensionality > 0\n            else NodeInputCategory.NON_BATCH_STEP_OUTPUT\n        )\n        return DynamicStepInputDefinition(\n            parameter_specification=ParameterSpecification(\n                parameter_name=manifest_property_name,\n            ),\n            category=category,\n            data_lineage=predecessor_node_data.data_lineage,\n            selector=predecessor_parsed_selector.value,\n        )\n    raise AssumptionError(\n        public_message=f\"Workflow Compiler for property `{manifest_property_name}` of step `{step_node}` \"\n        f\"found data providing predecessor `{predecessor_selector}` which has unsupported step type.\"\n        f\"This is most likely the bug. \"\n        f\"Contact Roboflow team through github issues \"\n        f\"(https://github.com/roboflow/inference/issues) providing full \"\n        f\"context of the problem - including workflow definition you use.\",\n        context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n    )\n\n\ndef build_nested_dictionary_for_input_property(\n    step_node: str,\n    manifest_property_name: str,\n    manifest_property_value: dict,\n    predecessors_definitions: List[PropertyPredecessorDefinition],\n    execution_graph: DiGraph,\n) -> DictOfStepInputDefinitions:\n    nested_property_name2data: Dict[Optional[str], PropertyPredecessorDefinition] = {\n        predecessor_definition.parsed_selector.key: predecessor_definition\n        for predecessor_definition in predecessors_definitions\n    }\n    result = {}\n    for nested_dict_key, nested_dict_value in manifest_property_value.items():\n        if nested_dict_key not in nested_property_name2data:\n            result[nested_dict_key] = StaticStepInputDefinition(\n                parameter_specification=ParameterSpecification(\n                    parameter_name=manifest_property_name,\n                    nested_element_key=nested_dict_key,\n                ),\n                category=NodeInputCategory.STATIC_VALUE,\n                value=nested_dict_value,\n            )\n            continue\n        referred_node_selector = nested_property_name2data[\n            nested_dict_key\n        ].predecessor_selector\n        referred_node_parsed_selector = nested_property_name2data[\n            nested_dict_key\n        ].parsed_selector\n        if is_input_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=InputNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_INPUT_PARAMETER\n                if predecessor_node_data.is_batch_oriented()\n                else NodeInputCategory.NON_BATCH_INPUT_PARAMETER\n            )\n            result[nested_dict_key] = DynamicStepInputDefinition(\n                parameter_specification=ParameterSpecification(\n                    parameter_name=manifest_property_name,\n                    nested_element_key=nested_dict_key,\n                ),\n                category=category,\n                data_lineage=predecessor_node_data.data_lineage,\n                selector=predecessor_node_data.selector,\n            )\n            continue\n        if is_step_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=StepNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_STEP_OUTPUT\n                if predecessor_node_data.output_dimensionality > 0\n                else NodeInputCategory.NON_BATCH_STEP_OUTPUT\n            )\n            result[nested_dict_key] = DynamicStepInputDefinition(\n                parameter_specification=ParameterSpecification(\n                    parameter_name=manifest_property_name,\n                    nested_element_key=nested_dict_key,\n                ),\n                category=category,\n                data_lineage=predecessor_node_data.data_lineage,\n                selector=referred_node_parsed_selector.value,\n            )\n            continue\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for property `{manifest_property_name}` of step `{step_node}` \"\n            f\"found data providing predecessor `{referred_node_selector}` which has \"\n            f\"unsupported step type (key: {nested_dict_key} of nested data dictionary). \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n        )\n    return DictOfStepInputDefinitions(\n        name=manifest_property_name,\n        nested_definitions=result,\n    )\n\n\ndef get_manifest_fields_values(step_manifest: WorkflowBlockManifest) -> Dict[str, Any]:\n    result = {}\n    for field in step_manifest.model_fields:\n        if field in EXCLUDED_FIELDS:\n            continue\n        result[field] = getattr(step_manifest, field)\n    return result\n\n\ndef build_nested_list_for_input_property(\n    step_node: str,\n    manifest_property_name: str,\n    manifest_property_value: list,\n    predecessors_definitions: List[PropertyPredecessorDefinition],\n    execution_graph: DiGraph,\n) -> ListOfStepInputDefinitions:\n    nested_index2data: Dict[Optional[int], PropertyPredecessorDefinition] = {\n        e.parsed_selector.index: e for e in predecessors_definitions\n    }\n    result = []\n    for index, element in enumerate(manifest_property_value):\n        if index not in nested_index2data:\n            result.append(\n                StaticStepInputDefinition(\n                    parameter_specification=ParameterSpecification(\n                        parameter_name=manifest_property_name,\n                        nested_element_index=index,\n                    ),\n                    category=NodeInputCategory.STATIC_VALUE,\n                    value=element,\n                )\n            )\n            continue\n        referred_node_selector = nested_index2data[index].predecessor_selector\n        referred_node_parsed_selector = nested_index2data[index].parsed_selector\n        if is_input_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=InputNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_INPUT_PARAMETER\n                if predecessor_node_data.is_batch_oriented()\n                else NodeInputCategory.NON_BATCH_INPUT_PARAMETER\n            )\n            result.append(\n                DynamicStepInputDefinition(\n                    parameter_specification=ParameterSpecification(\n                        parameter_name=manifest_property_name,\n                        nested_element_index=index,\n                    ),\n                    category=category,\n                    data_lineage=predecessor_node_data.data_lineage,\n                    selector=predecessor_node_data.selector,\n                )\n            )\n            continue\n        if is_step_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=StepNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_STEP_OUTPUT\n                if predecessor_node_data.output_dimensionality > 0\n                else NodeInputCategory.NON_BATCH_STEP_OUTPUT\n            )\n            result.append(\n                DynamicStepInputDefinition(\n                    parameter_specification=ParameterSpecification(\n                        parameter_name=manifest_property_name,\n                        nested_element_index=index,\n                    ),\n                    category=category,\n                    data_lineage=predecessor_node_data.data_lineage,\n                    selector=referred_node_parsed_selector.value,\n                )\n            )\n            continue\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for property `{manifest_property_name}` of step `{step_node}` \"\n            f\"found data providing predecessor `{referred_node_selector}` which has \"\n            f\"unsupported step type (index: {index} of nested data list). \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n        )\n    return ListOfStepInputDefinitions(\n        name=manifest_property_name,\n        nested_definitions=result,\n    )\n\n\ndef verify_step_input_dimensionality_offsets(\n    step_name: str,\n    input_dimensionality_offsets: Dict[str, int],\n) -> None:\n    min_offset, max_offset = None, None\n    for offset in input_dimensionality_offsets.values():\n        if min_offset is None or offset < min_offset:\n            min_offset = offset\n        if max_offset is None or offset > max_offset:\n            max_offset = offset\n    if min_offset is None or max_offset is None:\n        return None\n    if min_offset < 0 or max_offset < 0:\n        raise BlockInterfaceError(\n            public_message=f\"Offsets could not be negative, but block defining step: {step_name} defines that values.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_input_offset_definitions\",\n        )\n    if abs(max_offset - min_offset) > 1:\n        raise BlockInterfaceError(\n            public_message=\"Offsets of input parameters could not differ more than 1, but block defining step {step_name} \"\n            f\"violates that rule.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_input_offset_definitions\",\n        )\n\n\ndef verify_output_offset(\n    step_name: str,\n    parameters_with_batch_inputs: Set[str],\n    input_dimensionality_offsets: Dict[str, int],\n    dimensionality_reference_property: Optional[str],\n    output_dimensionality_offset: int,\n) -> None:\n    if not parameters_with_batch_inputs and output_dimensionality_offset < 0:\n        raise StepInputDimensionalityError(\n            public_message=f\"Block defining step {step_name} defines negative dimensionality offset while only \"\n            f\"scalar inputs being provided - the block cannot run as there is no dimension to collapse.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if (\n        dimensionality_reference_property is not None\n        and dimensionality_reference_property not in parameters_with_batch_inputs\n    ):\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} defines dimensionality reference property \"\n            f\"which is not in scope of parameters bring batch-oriented input, which makes it impossible \"\n            f\"to use as reference for output dimensionality.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if output_dimensionality_offset not in {-1, 0, 1}:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} defines output dimensionality offset \"\n            f\"being {output_dimensionality_offset}, whereas it is only possible for that offset being \"\n            f\"in set [-1, 0, 1].\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    different_offsets = {o for o in input_dimensionality_offsets.values()}\n    if len(parameters_with_batch_inputs) != len(input_dimensionality_offsets):\n        # assumption of default offset being zero - and this one does not need to be manifested\n        # by block\n        different_offsets.add(0)\n    if 0 not in different_offsets and parameters_with_batch_inputs:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} explicitly defines input dimensionalities offsets\"\n            f\"with {input_dimensionality_offsets}, but the definition lack 0-level input, which is \"\n            f\"not allowed, as in this scenario offsets could be adjusted to include 0\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if len(different_offsets) > 1 and dimensionality_reference_property is None:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} explicitly defines input dimensionality \"\n            f\"offsets {input_dimensionality_offsets}. In this scenario it is required to provide dimensionality \"\n            f\"reference property.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if len(different_offsets) > 1 and output_dimensionality_offset != 0:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} explicitly defines input dimensionality \"\n            f\"offsets {input_dimensionality_offsets} and output dimensionality offset {output_dimensionality_offset} \"\n            f\"where the latter is not 0, but for inputs differing with dimensionality it is only possible to keep \"\n            f\"output dimensionality the same and point reference parameter.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n\n\ndef verify_input_data_dimensionality(\n    step_name: str,\n    step_type: str,\n    dimensionality_reference_property: Optional[str],\n    inputs_dimensionalities: Dict[str, Set[int]],\n    dimensionality_offstes: Dict[str, int],\n) -> None:\n    parameter_name2dimensionality_specification = (\n        grab_input_data_dimensionality_specifications(\n            step_name=step_name,\n            inputs_dimensionalities=inputs_dimensionalities,\n            dimensionality_offstes=dimensionality_offstes,\n        )\n    )\n    if not parameter_name2dimensionality_specification:\n        # nothing to check if no batch-oriented inputs\n        return None\n    different_dimensionalities_of_parameters = {\n        specification.actual_dimensionality\n        for specification in parameter_name2dimensionality_specification.values()\n    }\n    if dimensionality_reference_property is None:\n        if len(different_dimensionalities_of_parameters) > 1:\n            parameter2dimensionality = {\n                k: e.actual_dimensionality\n                for k, e in parameter_name2dimensionality_specification.items()\n            }\n            raise StepInputDimensionalityError(\n                public_message=f\"Block defining step {step_name} does not define dimensionality reference property, \"\n                f\"which means that all batch-oriented parameters must be at the same dimensionality level, \"\n                f\"but detected the following dimensionalities for parameters {parameter2dimensionality}\",\n                context=\"workflow_compilation | execution_graph_construction | denoting_step_inputs_dimensionality\",\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=step_name,\n                        block_type=step_type,\n                        block_details=f\"Dimensionality of input parameters doesn't match: {parameter2dimensionality}\",\n                    )\n                ],\n            )\n        return None\n    reference_specification = parameter_name2dimensionality_specification[\n        dimensionality_reference_property\n    ]\n    expected_dimensionalities = {\n        property_name: (e.expected_offset - reference_specification.expected_offset)\n        + reference_specification.actual_dimensionality\n        for property_name, e in parameter_name2dimensionality_specification.items()\n    }\n    if any(dim <= 0 for dim in expected_dimensionalities.values()):\n        raise StepInputDimensionalityError(\n            public_message=f\"Given the definition of block defining step {step_name} and data provided, \"\n            f\"the block would expect batch input dimensionality to be 0 or below, which is invalid.\",\n            context=\"workflow_compilation | execution_graph_construction | denoting_step_inputs_dimensionality\",\n        )\n    for property_name, expected_dimensionality in expected_dimensionalities.items():\n        actual_dimensionality = parameter_name2dimensionality_specification[\n            property_name\n        ].actual_dimensionality\n        if actual_dimensionality != expected_dimensionality:\n            raise StepInputDimensionalityError(\n                public_message=f\"Data fed into step `{step_name}` property `{property_name}` has \"\n                f\"actual dimensionality {actual_dimensionality}, \"\n                f\"when expected was {expected_dimensionality}\",\n                context=\"workflow_compilation | execution_graph_construction | denoting_step_inputs_dimensionality\",\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=step_name,\n                        block_type=step_type,\n                        property_name=property_name,\n                        property_details=f\"Expected dimensionality {expected_dimensionality}, but received dimensionality {actual_dimensionality}\",\n                    )\n                ],\n            )\n    return None\n\n\ndef grab_input_data_dimensionality_specifications(\n    step_name: str,\n    inputs_dimensionalities: Dict[str, Set[int]],\n    dimensionality_offstes: Dict[str, int],\n) -> Dict[str, InputDimensionalitySpecification]:\n    result = {}\n    for parameter_name, dimensionality in inputs_dimensionalities.items():\n        parameter_offset = dimensionality_offstes.get(parameter_name, 0)\n        non_zero_dimensionalities_for_parameter = {d for d in dimensionality if d > 0}\n        if len(non_zero_dimensionalities_for_parameter) > 1:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler for step: `{step_name}` and parameter: {parameter_name}\"\n                f\"found multiple different values of actual input dimensionalities: \"\n                f\"`{non_zero_dimensionalities_for_parameter}` which should be detected and addresses \"\n                f\"at earlier stages of compilation.\"\n                f\"This is most likely the bug. Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n            )\n        if non_zero_dimensionalities_for_parameter:\n            actual_dimensionality = next(iter(non_zero_dimensionalities_for_parameter))\n            result[parameter_name] = InputDimensionalitySpecification(\n                actual_dimensionality=actual_dimensionality,\n                expected_offset=parameter_offset,\n            )\n    return result\n\n\ndef verify_compatibility_of_input_data_lineage_with_control_flow_lineage(\n    step_name: str,\n    inputs_lineage: List[List[str]],\n    control_flow_steps_selectors: List[str],\n    execution_graph: DiGraph,\n) -> None:\n    \"\"\"\n    Ensure control flow steps' data lineage is compatible with the step's inputs.\n\n    Control flow steps that affect this step must operate on data that is\n    compatible with the data fed to the step; otherwise the step could never\n    execute. Compares unique control flow lineages against input lineage\n    prefixes and raises ControlFlowDefinitionError if any control flow lineage\n    is not covered by the inputs.\n\n    If inputs_lineage is empty, there is no sense to verify compatibility. The lineage of the\n    step should be established based on the control flow lineages.\n\n    Args:\n        step_name: Name of the step being verified (used in error messages).\n        inputs_lineage: Data lineages derived from the step's input data.\n        control_flow_steps_selectors: Step selectors of control flow steps\n            that affect this step's execution.\n        execution_graph: The workflow execution graph.\n\n    Raises:\n        ControlFlowDefinitionError: When a control flow step's lineage is not\n            compatible with the step's input lineage (step would never execute).\n    \"\"\"\n    (\n        batch_oriented_control_flow_lineages,\n        lineage_id2control_flow_steps,\n    ) = _collect_unique_control_flow_lineages_with_step_mapping(\n        control_flow_steps_selectors=control_flow_steps_selectors,\n        execution_graph=execution_graph,\n    )\n    if not inputs_lineage:\n        return\n\n    all_input_lineage_prefixes = get_all_batch_lineage_prefixes(lineages=inputs_lineage)\n    all_input_lineage_prefixes_hashes = {\n        identify_lineage(lineage=lineage) for lineage in all_input_lineage_prefixes\n    }\n    for control_flow_lineage in batch_oriented_control_flow_lineages:\n        control_flow_lineage_id = identify_lineage(lineage=control_flow_lineage)\n        if control_flow_lineage_id not in all_input_lineage_prefixes_hashes:\n            problematic_flow_control_steps = lineage_id2control_flow_steps[\n                control_flow_lineage_id\n            ]\n            raise ControlFlowDefinitionError(\n                public_message=f\"Step {step_name} execution is impacted by control flow outcome of the following \"\n                f\"steps {problematic_flow_control_steps} which make decision based on data that is \"\n                f\"not compatible with data fed to the step {step_name} - which would cause the step \"\n                f\"to never execute. This behaviour is invalid and prevented upfront by Workflows compiler.\",\n                context=\"workflow_compilation | execution_graph_construction | verification_of_control_flow_lineage\",\n            )\n\n\ndef get_all_batch_lineage_prefixes(lineages: List[List[str]]) -> List[List[str]]:\n    result = []\n    already_spotted = set()\n    for lineage in lineages:\n        lineage_prefixes = get_batch_lineage_prefixes(lineage=lineage)\n        for lineage_prefix in lineage_prefixes:\n            lineage_prefix_id = identify_lineage(lineage=lineage_prefix)\n            if lineage_prefix_id not in already_spotted:\n                already_spotted.add(lineage_prefix_id)\n                result.append(lineage_prefix)\n    return result\n\n\ndef get_batch_lineage_prefixes(lineage: List[str]) -> List[List[str]]:\n    if not lineage:\n        return []\n    result = []\n    prefix = []\n    for i in range(len(lineage)):\n        prefix.append(lineage[i])\n        result.append(copy(prefix))\n    return result\n\n\ndef get_inputs_dimensionalities(\n    step_name: str,\n    step_type: str,\n    input_data: StepInputData,\n    scalar_parameters_to_be_batched: Set[str],\n    input_dimensionality_offsets: Dict[str, int],\n) -> Dict[str, Set[int]]:\n    result = defaultdict(set)\n    dimensionalities_spotted = set()\n    offset_parameters = {\n        parameter: value\n        for parameter, value in input_dimensionality_offsets.items()\n        if value > 0\n    }\n    non_offset_parameters_dimensionality_values = set()\n    for property_name, input_definition in input_data.items():\n        if property_name in offset_parameters:\n            continue\n        if input_definition.is_compound_input():\n            for value in input_definition.iterate_through_definitions():\n                if value.is_batch_oriented():\n                    non_offset_parameters_dimensionality_values.add(\n                        value.get_dimensionality()\n                    )\n        elif input_definition.is_batch_oriented():\n            non_offset_parameters_dimensionality_values.add(\n                input_definition.get_dimensionality()\n            )\n    if len(non_offset_parameters_dimensionality_values) > 1:\n        raise StepInputDimensionalityError(\n            public_message=f\"For step {step_name} attempted to plug input data that are in different dimensions, \"\n            f\"whereas block defines the inputs to be equal in that terms.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_input_data\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=step_name,\n                    block_type=step_type,\n                    block_details=f\"Dimensionality of input parameters differs by more than 1. Detected dimensions: {dict(result)}\",\n                )\n            ],\n        )\n    non_offset_parameters_dimensionality_value = (\n        non_offset_parameters_dimensionality_values.pop()\n        if len(non_offset_parameters_dimensionality_values) > 0\n        else 1\n    )\n    for property_name, input_definition in input_data.items():\n        if input_definition.is_compound_input():\n            result[property_name] = get_compound_input_dimensionality(\n                step_name=step_name,\n                step_type=step_type,\n                property_name=property_name,\n                input_definition=input_definition,\n                scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n                non_offset_parameters_dimensionality_value=non_offset_parameters_dimensionality_value,\n                offset_parameters=offset_parameters,\n            )\n        else:\n            if property_name in scalar_parameters_to_be_batched:\n                if property_name not in offset_parameters:\n                    result[property_name] = {non_offset_parameters_dimensionality_value}\n                else:\n                    result[property_name] = (\n                        non_offset_parameters_dimensionality_value\n                        + offset_parameters[property_name]\n                    )\n            else:\n                result[property_name] = {input_definition.get_dimensionality()}\n        dimensionalities_spotted.update(result[property_name])\n    non_zero_dimensionalities_spotted = {d for d in dimensionalities_spotted if d != 0}\n    if len(non_zero_dimensionalities_spotted) > 0:\n        min_dim, max_dim = min(non_zero_dimensionalities_spotted), max(\n            non_zero_dimensionalities_spotted\n        )\n        if abs(max_dim - min_dim) > 1:\n            raise StepInputDimensionalityError(\n                public_message=f\"For step {step_name} attempted to plug input data differing in dimensionality more than 1\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_input_data\",\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=step_name,\n                        block_type=step_type,\n                        block_details=f\"Dimensionality of input parameters differs by more than 1. Detected dimensions: {dict(result)}\",\n                    )\n                ],\n            )\n    return result\n\n\ndef get_compound_input_dimensionality(\n    step_name: str,\n    property_name: str,\n    step_type: str,\n    input_definition: CompoundStepInputDefinition,\n    scalar_parameters_to_be_batched: Set[str],\n    offset_parameters: Dict[str, int],\n    non_offset_parameters_dimensionality_value: int,\n) -> Set[int]:\n    dimensionalities_spotted = set()\n    for definition in input_definition.iterate_through_definitions():\n        if (\n            property_name not in scalar_parameters_to_be_batched\n            or definition.is_batch_oriented()\n        ):\n            dimensionalities_spotted.add(definition.get_dimensionality())\n        elif property_name not in offset_parameters:\n            dimensionalities_spotted.add(non_offset_parameters_dimensionality_value)\n        else:\n            dimensionalities_spotted.add(\n                non_offset_parameters_dimensionality_value\n                + offset_parameters[property_name]\n            )\n    non_zero_dimensionalities = {e for e in dimensionalities_spotted if e != 0}\n    if len(non_zero_dimensionalities) > 1:\n        raise StepInputDimensionalityError(\n            public_message=f\"While evaluating compound property {property_name} of step {step_name}, \"\n            f\"detected multiple inputs of differing batch dimensionalities: {non_zero_dimensionalities}\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_input_data\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=step_name,\n                    block_type=step_type,\n                    property_name=property_name,\n                    property_details=f\"Detected multiple inputs of differing batch dimensionalities: {non_zero_dimensionalities}\",\n                )\n            ],\n        )\n    return dimensionalities_spotted\n\n\ndef grab_parameters_defining_batch_inputs(\n    inputs_dimensionalities: Dict[str, Set[int]],\n) -> Set[str]:\n    result = set()\n    for paremeter, dimensionalities in inputs_dimensionalities.items():\n        batch_dimensionalities = {d for d in dimensionalities if d > 0}\n        if len(batch_dimensionalities):\n            result.add(paremeter)\n    return result\n\n\ndef retrieve_batch_compatibility_of_input_selectors(\n    input_selectors: List[ParsedSelector],\n) -> Dict[str, Set[bool]]:\n    batch_compatibility_of_properties = defaultdict(set)\n    for parsed_selector in input_selectors:\n        for reference in parsed_selector.definition.allowed_references:\n            batch_compatibility_of_properties[\n                parsed_selector.definition.property_name\n            ].update(reference.points_to_batch)\n    return batch_compatibility_of_properties\n\n\ndef verify_declared_batch_compatibility_against_actual_inputs(\n    node: str,\n    step_node_data: StepNode,\n    input_data: StepInputData,\n    batch_compatibility_of_properties: Dict[str, Set[bool]],\n) -> Set[str]:\n    scalar_parameters_to_be_batched = set()\n    parameters_accepting_batches_and_scalars = set(\n        step_node_data.step_manifest.get_parameters_accepting_batches_and_scalars()\n    )\n    hardcoded_inputs_to_be_batch_compatible = set(\n        step_node_data.step_manifest.get_parameters_enforcing_auto_batch_casting()\n        + step_node_data.step_manifest.get_parameters_accepting_batches()\n    )\n    for property_name, input_definition in input_data.items():\n        if property_name not in batch_compatibility_of_properties:\n            actual_input_is_batch = {False}\n            if property_name in parameters_accepting_batches_and_scalars:\n                batch_compatibility = {True, False}\n            elif property_name in hardcoded_inputs_to_be_batch_compatible:\n                batch_compatibility = {True}\n            else:\n                continue\n        elif input_definition.is_compound_input():\n            actual_input_is_batch = {\n                element.is_batch_oriented()\n                for element in input_definition.iterate_through_definitions()\n            }\n            batch_compatibility = batch_compatibility_of_properties[property_name]\n        else:\n            actual_input_is_batch = {input_definition.is_batch_oriented()}\n            batch_compatibility = batch_compatibility_of_properties[property_name]\n        step_accepts_batch_input = step_node_data.step_manifest.accepts_batch_input()\n        if (\n            step_accepts_batch_input\n            and batch_compatibility == {False}\n            and True in actual_input_is_batch\n        ):\n            raise ExecutionGraphStructureError(\n                public_message=f\"Detected invalid reference plugged \"\n                f\"into property `{property_name}` of step `{node}` - the step \"\n                f\"property do not accept batch-oriented inputs, yet the input selector \"\n                f\"holds one - this indicates the problem with \"\n                f\"construction of your Workflow - usually the problem occurs when non-batch oriented \"\n                f\"step inputs are filled with outputs of batch-oriented steps or batch-oriented inputs.\",\n                context=\"workflow_compilation | execution_graph_construction\",\n            )\n        if batch_compatibility == {True} and False in actual_input_is_batch:\n            scalar_parameters_to_be_batched.add(property_name)\n    return scalar_parameters_to_be_batched\n\n\ndef get_input_data_lineage_excluding_auto_batch_casting(\n    step_name: str,\n    input_data: StepInputData,\n    scalar_parameters_to_be_batched: Set[str],\n) -> List[List[str]]:\n    lineage_deduplication_set = set()\n    lineages = []\n    for property_name, input_definition in input_data.items():\n        new_lineages_detected_within_property_data = get_lineage_for_input_property(\n            step_name=step_name,\n            property_name=property_name,\n            input_definition=input_definition,\n            lineage_deduplication_set=lineage_deduplication_set,\n        )\n        if (\n            property_name in scalar_parameters_to_be_batched\n            and len(new_lineages_detected_within_property_data) == 0\n        ):\n            continue\n        lineages.extend(new_lineages_detected_within_property_data)\n    if not lineages:\n        return lineages\n    verify_lineages(step_name=step_name, detected_lineages=lineages)\n    return lineages\n\n\ndef get_lineage_support_for_auto_batch_casted_parameters(\n    input_dimensionalities: Dict[str, Set[int]],\n    scalar_parameters_to_be_batched: Set[str],\n    all_lineages_of_batch_parameters: List[List[str]],\n) -> Dict[str, AutoBatchCastingConfig]:\n    longest_lineage_support = find_longest_lineage_support(\n        all_lineages_of_batch_parameters=all_lineages_of_batch_parameters,\n    )\n    result = {}\n    for parameter_name in scalar_parameters_to_be_batched:\n        parameter_dimensionality = max(input_dimensionalities[parameter_name])\n        if longest_lineage_support is None:\n            lineage_support = None\n        else:\n            lineage_support = longest_lineage_support[:parameter_dimensionality]\n        result[parameter_name] = AutoBatchCastingConfig(\n            casted_dimensionality=parameter_dimensionality,\n            lineage_support=lineage_support,\n        )\n    return result\n\n\ndef find_longest_lineage_support(\n    all_lineages_of_batch_parameters: List[List[str]],\n) -> Optional[List[str]]:\n    longest_longest_lineage_support = []\n    for lineage in all_lineages_of_batch_parameters:\n        if len(lineage) > len(longest_longest_lineage_support):\n            longest_longest_lineage_support = lineage\n    if len(longest_longest_lineage_support) == 0:\n        return None\n    return longest_longest_lineage_support\n\n\ndef get_lineage_for_input_property(\n    step_name: str,\n    property_name: str,\n    input_definition: Union[StepInputDefinition, CompoundStepInputDefinition],\n    lineage_deduplication_set: Set[int],\n) -> List[List[str]]:\n    if input_definition.is_compound_input():\n        return get_lineage_from_compound_input(\n            step_name=step_name,\n            property_name=property_name,\n            input_definition=input_definition,\n            lineage_deduplication_set=lineage_deduplication_set,\n        )\n    lineages = []\n    if input_definition.is_batch_oriented():\n        lineage = input_definition.data_lineage\n        lineage_id = identify_lineage(lineage=lineage)\n        if lineage_id not in lineage_deduplication_set:\n            lineage_deduplication_set.add(lineage_id)\n            lineages.append(lineage)\n    return lineages\n\n\ndef get_lineage_from_compound_input(\n    step_name: str,\n    property_name: str,\n    input_definition: Union[StepInputDefinition, CompoundStepInputDefinition],\n    lineage_deduplication_set: Set[int],\n) -> List[List[str]]:\n    lineages = []\n    for nested_element in input_definition.iterate_through_definitions():\n        if nested_element.is_batch_oriented():\n            lineage = nested_element.data_lineage\n            lineage_id = identify_lineage(lineage=lineage)\n            if lineage_id not in lineage_deduplication_set:\n                lineage_deduplication_set.add(lineage_id)\n                lineages.append(lineage)\n    if len(lineages) > 1:\n        raise StepInputLineageError(\n            public_message=f\"Input data provided for step: `{step_name}` comes with multiple different lineages \"\n            f\"{lineages} for property `{property_name}` accepting \"\n            f\"multiple selectors, which is not allowed.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    return lineages\n\n\ndef verify_lineages(step_name: str, detected_lineages: List[List[str]]) -> None:\n    lineages_by_length = defaultdict(list)\n    for lineage in detected_lineages:\n        lineages_by_length[len(lineage)].append(lineage)\n    if len(lineages_by_length) > 2:\n        raise StepInputLineageError(\n            public_message=f\"Input data provided for step: `{step_name}` comes with lineages at more than two \"\n            f\"dimensionality levels, which should not be possible.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    lineage_lengths = sorted(lineages_by_length.keys())\n    for lineage_length in lineage_lengths:\n        if len(lineages_by_length[lineage_length]) > 1:\n            raise StepInputLineageError(\n                public_message=f\"Among step `{step_name}` inputs found different lineages at the same  \"\n                f\"dimensionality levels dimensionality.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if len(lineages_by_length[lineage_lengths[-1]]) > 1 and len(lineage_lengths) < 2:\n        raise StepInputLineageError(\n            public_message=f\"If lineage differ at the last level, then Execution Engine requires at least one \"\n            f\"higher-dimension  input that will come with common lineage, but this is not the \"\n            f\"case for step {step_name}.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    if len(lineage_lengths) == 2:\n        reference_lineage = lineages_by_length[lineage_lengths[0]][0]\n        if reference_lineage != lineages_by_length[lineage_lengths[1]][0][:-1]:\n            raise StepInputLineageError(\n                public_message=f\"Step `{step_name}` inputs does not share common lineage. Differing element: \"\n                f\"{lineages_by_length[lineage_lengths[1]][0]}, \"\n                f\"reference lineage prefix: {reference_lineage}\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n\n\ndef establish_step_execution_dimensionality(\n    inputs_dimensionalities: Dict[str, Set[int]],\n    control_flow_lineage_support: List[str],\n    output_dimensionality_offset: int,\n) -> int:\n    \"\"\"\n    Determine how many batch dimensions (execution slices) a step runs with.\n\n    Used during workflow compilation in denote_data_flow_for_step. The result\n    is stored on StepNode.step_execution_dimensionality and consumed at\n    execution time to:\n    - Drive how many times the step is executed (which batch indices/slices).\n    - Align and expand inputs (e.g. auto-batch casting) to match this size.\n    - Validate that parameter dimensionalities are compatible (runtime checks\n      in step_input_assembler and manager).\n\n    Logic:\n    - If no input has non-zero dimensionality but the step is gated by\n      control flow (control_flow_lineage_support non-empty), the\n      dimensionality is the number of control-flow branches.\n    - Otherwise, the minimum non-zero input dimensionality is used; if\n      output_dimensionality_offset < 0 (step reduces batch dimension),\n      one is subtracted.\n\n    Args:\n        inputs_dimensionalities: Per-input sets of dimensionalities (from\n            get_inputs_dimensionalities).\n        control_flow_lineage_support: Lineage identifiers for control-flow\n            branches that gate this step (from establish_batch_oriented_step_lineage).\n        output_dimensionality_offset: Block's output dimensionality offset\n            (positive = expand, negative = reduce batch dimension).\n\n    Returns:\n        The number of batch dimensions (execution slices) for this step.\n    \"\"\"\n    step_execution_dimensionality = 0\n    non_zero_dimensionalities = {\n        dimensionality\n        for dimensionalities in inputs_dimensionalities.values()\n        for dimensionality in dimensionalities\n        if dimensionality > 0\n    }\n    if len(non_zero_dimensionalities) == 0 and len(control_flow_lineage_support) > 0:\n        return len(control_flow_lineage_support)\n    if len(non_zero_dimensionalities) > 0:\n        step_execution_dimensionality = min(non_zero_dimensionalities)\n        if output_dimensionality_offset < 0:\n            step_execution_dimensionality -= 1\n    return step_execution_dimensionality\n\n\ndef establish_batch_oriented_step_lineage(\n    step_selector: str,\n    all_data_derived_lineages: List[List[str]],\n    all_control_flow_lineages: List[List[str]],\n    input_data: StepInputData,\n    dimensionality_reference_property: Optional[str],\n    output_dimensionality_offset: int,\n) -> Tuple[List[str], List[str]]:\n    reference_lineage, control_flow_lineage_support = get_reference_lineage(\n        step_selector=step_selector,\n        all_data_derived_lineages=all_data_derived_lineages,\n        all_control_flow_lineages=all_control_flow_lineages,\n        input_data=input_data,\n        dimensionality_reference_property=dimensionality_reference_property,\n    )\n    if output_dimensionality_offset < 0:\n        result_dimensionality = reference_lineage[:output_dimensionality_offset]\n        return result_dimensionality, []\n    if output_dimensionality_offset == 0:\n        return reference_lineage, control_flow_lineage_support\n    reference_lineage.append(step_selector)\n    return reference_lineage, []\n\n\ndef get_reference_lineage(\n    step_selector: str,\n    all_data_derived_lineages: List[List[str]],\n    all_control_flow_lineages: List[List[str]],\n    input_data: StepInputData,\n    dimensionality_reference_property: Optional[str],\n) -> Tuple[List[str], List[str]]:\n    if not all_data_derived_lineages:\n        if len(all_control_flow_lineages) == 1:\n            return copy(all_control_flow_lineages[0]), copy(\n                all_control_flow_lineages[0]\n            )\n        # Multiple control-flow lineages and no data-derived lineage: pick the deepest.\n        max_lineage_len = max(len(lineage) for lineage in all_control_flow_lineages)\n        lineages_matching_max_len = [\n            _lineage\n            for _lineage in all_control_flow_lineages\n            if len(_lineage) == max_lineage_len\n        ]\n        if len(lineages_matching_max_len) == 1:\n            return copy(lineages_matching_max_len[0]), copy(\n                lineages_matching_max_len[0]\n            )\n        else:\n            raise AssumptionError(\n                public_message=f\"Multiple control-flow lineages at the same level for step `{step_selector}` \"\n                f\"and no data-derived lineage; unique lineage level required. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if len(all_data_derived_lineages) == 1:\n        return copy(all_data_derived_lineages[0]), []\n    if dimensionality_reference_property not in input_data:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` expected dimensionality_reference_property \"\n            f\"presence to be verified at earlier stages, which did not happen as expected. \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    property_data = input_data[dimensionality_reference_property]\n    if property_data.is_compound_input():\n        lineage = None\n        for nested_element in property_data.iterate_through_definitions():\n            if nested_element.is_batch_oriented():\n                lineage = copy(nested_element.data_lineage)\n                return lineage, []\n        if lineage is None:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n                f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if not property_data.is_batch_oriented():\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n            f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    return copy(property_data.data_lineage), []\n\n\ndef get_property_with_invalid_selector(\n    manifest: WorkflowBlockManifest, step_property: str\n) -> Optional[str]:\n    property_name = None\n    for key, value in manifest.__dict__.items():\n        if isinstance(value, str) and step_property in value:\n            property_name = key\n            break\n    return property_name\n\n\ndef add_super_input_node_in_execution_graph(\n    execution_graph: DiGraph,\n    super_input_node: str,\n) -> DiGraph:\n    nodes_to_attach_super_input_into = get_nodes_of_specific_category(\n        execution_graph=execution_graph,\n        category=NodeCategory.INPUT_NODE,\n    )\n    step_nodes_without_predecessors = [\n        node\n        for node in execution_graph.nodes\n        if not list(execution_graph.predecessors(node))\n    ]\n    nodes_to_attach_super_input_into.update(step_nodes_without_predecessors)\n    execution_graph.add_node(super_input_node)\n    for node in nodes_to_attach_super_input_into:\n        execution_graph.add_edge(super_input_node, node)\n    return execution_graph\n",
    "patch": null
  },
  {
    "trace_id": "44eda0f3-16be-47af-b158-beeac0b8a87d",
    "function_name": "get_lineage_derived_from_control_flow",
    "file_path": "inference/core/workflows/execution_engine/v1/compiler/graph_constructor.py",
    "speedup_x": 0.2492806696311797,
    "review_quality": "high",
    "pre_optimization_commit": "90243bdc6278ef7d17b6db09dc1eb5b0d155b4be",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def get_lineage_derived_from_control_flow(\n    control_flow_steps_selectors: List[str],\n    execution_graph: nx.DiGraph,\n) -> List[List[str]]:\n    \"\"\"\n    Return unique non-empty data lineages from the given control flow steps.\n\n    Each lineage is taken from the step's data_lineage in the execution graph.\n    Lineages are deduplicated by lineage id (see identify_lineage); empty\n    lineages are omitted. Used when establishing batch-oriented step lineage.\n\n    Args:\n        control_flow_steps_selectors: Step selectors (node ids) of control\n            flow steps whose data_lineage is to be collected.\n        execution_graph: The workflow execution graph containing step nodes\n            and their data_lineage.\n\n    Returns:\n        List of distinct non-empty data lineages, one per unique lineage id.\n    \"\"\"\n    unique_lineages, _ = _collect_unique_control_flow_lineages_with_step_mapping(\n        control_flow_steps_selectors=control_flow_steps_selectors,\n        execution_graph=execution_graph,\n    )\n    return unique_lineages\n",
    "optimized_function_code": "from typing import Dict, List, Set, Tuple\n\nimport networkx as nx\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import \\\n    StepNode\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import (\n    identify_lineage, node_as)\n\n\ndef _collect_unique_control_flow_lineages_with_step_mapping(\n    control_flow_steps_selectors: List[str],\n    execution_graph: nx.DiGraph,\n) -> Tuple[List[List[str]], Dict[int, List[str]]]:\n    \"\"\"\n    Collect data lineages from control flow steps and deduplicate by lineage id.\n\n    For each given control flow step selector, reads its data_lineage from the\n    execution graph. Returns unique non-empty lineages (by identify_lineage id)\n    and a mapping from lineage id to every step selector that produced that\n    lineage (used e.g. for error reporting when lineage is incompatible).\n\n    Args:\n        control_flow_steps_selectors: Step selectors (node ids) of control\n            flow steps whose data_lineage is to be collected.\n        execution_graph: The workflow execution graph containing step nodes\n            and their data_lineage.\n\n    Returns:\n        A tuple of (unique_lineages, lineage_id_to_step_selectors):\n        - unique_lineages: list of distinct non-empty data lineages.\n        - lineage_id_to_step_selectors: map from lineage id to list of step\n          selectors whose data_lineage has that id (includes empty lineages).\n    \"\"\"\n    unique_lineages: List[List[str]] = []\n    # Use plain dict and avoid separate seen set to reduce allocations\n    lineage_id_to_step_selectors: Dict[int, List[str]] = {}\n\n\n    for step_selector in control_flow_steps_selectors:\n        step_data = node_as(\n            execution_graph=execution_graph,\n            node=step_selector,\n            expected_type=StepNode,\n        )\n        lineage = step_data.data_lineage\n        lineage_id = identify_lineage(lineage)\n        # If we encounter a non-empty lineage for the first time, record it.\n        if lineage and lineage_id not in lineage_id_to_step_selectors:\n            lineage_id_to_step_selectors[lineage_id] = []\n            unique_lineages.append(lineage)\n        # Append the step selector to the mapping, creating the list if needed.\n        try:\n            lineage_id_to_step_selectors[lineage_id].append(step_selector)\n        except KeyError:\n            lineage_id_to_step_selectors[lineage_id] = [step_selector]\n\n    return unique_lineages, lineage_id_to_step_selectors\n\n\n\n\ndef get_lineage_derived_from_control_flow(\n    control_flow_steps_selectors: List[str],\n    execution_graph: nx.DiGraph,\n) -> List[List[str]]:\n    \"\"\"\n    Return unique non-empty data lineages from the given control flow steps.\n\n    Each lineage is taken from the step's data_lineage in the execution graph.\n    Lineages are deduplicated by lineage id (see identify_lineage); empty\n    lineages are omitted. Used when establishing batch-oriented step lineage.\n\n    Args:\n        control_flow_steps_selectors: Step selectors (node ids) of control\n            flow steps whose data_lineage is to be collected.\n        execution_graph: The workflow execution graph containing step nodes\n            and their data_lineage.\n\n    Returns:\n        List of distinct non-empty data lineages, one per unique lineage id.\n    \"\"\"\n    unique_lineages, _ = _collect_unique_control_flow_lineages_with_step_mapping(\n        control_flow_steps_selectors=control_flow_steps_selectors,\n        execution_graph=execution_graph,\n    )\n    return unique_lineages",
    "optimized_raw_markdown": "```python:inference/core/workflows/execution_engine/v1/compiler/graph_constructor.py\nfrom typing import Dict, List, Set, Tuple\n\nimport networkx as nx\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import \\\n    StepNode\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import (\n    identify_lineage, node_as)\n\n\ndef _collect_unique_control_flow_lineages_with_step_mapping(\n    control_flow_steps_selectors: List[str],\n    execution_graph: nx.DiGraph,\n) -> Tuple[List[List[str]], Dict[int, List[str]]]:\n    \"\"\"\n    Collect data lineages from control flow steps and deduplicate by lineage id.\n\n    For each given control flow step selector, reads its data_lineage from the\n    execution graph. Returns unique non-empty lineages (by identify_lineage id)\n    and a mapping from lineage id to every step selector that produced that\n    lineage (used e.g. for error reporting when lineage is incompatible).\n\n    Args:\n        control_flow_steps_selectors: Step selectors (node ids) of control\n            flow steps whose data_lineage is to be collected.\n        execution_graph: The workflow execution graph containing step nodes\n            and their data_lineage.\n\n    Returns:\n        A tuple of (unique_lineages, lineage_id_to_step_selectors):\n        - unique_lineages: list of distinct non-empty data lineages.\n        - lineage_id_to_step_selectors: map from lineage id to list of step\n          selectors whose data_lineage has that id (includes empty lineages).\n    \"\"\"\n    unique_lineages: List[List[str]] = []\n    # Use plain dict and avoid separate seen set to reduce allocations\n    lineage_id_to_step_selectors: Dict[int, List[str]] = {}\n\n\n    for step_selector in control_flow_steps_selectors:\n        step_data = node_as(\n            execution_graph=execution_graph,\n            node=step_selector,\n            expected_type=StepNode,\n        )\n        lineage = step_data.data_lineage\n        lineage_id = identify_lineage(lineage)\n        # If we encounter a non-empty lineage for the first time, record it.\n        if lineage and lineage_id not in lineage_id_to_step_selectors:\n            lineage_id_to_step_selectors[lineage_id] = []\n            unique_lineages.append(lineage)\n        # Append the step selector to the mapping, creating the list if needed.\n        try:\n            lineage_id_to_step_selectors[lineage_id].append(step_selector)\n        except KeyError:\n            lineage_id_to_step_selectors[lineage_id] = [step_selector]\n\n    return unique_lineages, lineage_id_to_step_selectors\n\n\n\n\ndef get_lineage_derived_from_control_flow(\n    control_flow_steps_selectors: List[str],\n    execution_graph: nx.DiGraph,\n) -> List[List[str]]:\n    \"\"\"\n    Return unique non-empty data lineages from the given control flow steps.\n\n    Each lineage is taken from the step's data_lineage in the execution graph.\n    Lineages are deduplicated by lineage id (see identify_lineage); empty\n    lineages are omitted. Used when establishing batch-oriented step lineage.\n\n    Args:\n        control_flow_steps_selectors: Step selectors (node ids) of control\n            flow steps whose data_lineage is to be collected.\n        execution_graph: The workflow execution graph containing step nodes\n            and their data_lineage.\n\n    Returns:\n        List of distinct non-empty data lineages, one per unique lineage id.\n    \"\"\"\n    unique_lineages, _ = _collect_unique_control_flow_lineages_with_step_mapping(\n        control_flow_steps_selectors=control_flow_steps_selectors,\n        execution_graph=execution_graph,\n    )\n    return unique_lineages\n```",
    "optimized_function_only": "def get_lineage_derived_from_control_flow(\n    control_flow_steps_selectors: List[str],\n    execution_graph: nx.DiGraph,\n) -> List[List[str]]:\n    \"\"\"\n    Return unique non-empty data lineages from the given control flow steps.\n\n    Each lineage is taken from the step's data_lineage in the execution graph.\n    Lineages are deduplicated by lineage id (see identify_lineage); empty\n    lineages are omitted. Used when establishing batch-oriented step lineage.\n\n    Args:\n        control_flow_steps_selectors: Step selectors (node ids) of control\n            flow steps whose data_lineage is to be collected.\n        execution_graph: The workflow execution graph containing step nodes\n            and their data_lineage.\n\n    Returns:\n        List of distinct non-empty data lineages, one per unique lineage id.\n    \"\"\"\n    unique_lineages, _ = _collect_unique_control_flow_lineages_with_step_mapping(\n        control_flow_steps_selectors=control_flow_steps_selectors,\n        execution_graph=execution_graph,\n    )\n    return unique_lineages",
    "original_file_content": "import itertools\nfrom collections import defaultdict\nfrom copy import copy, deepcopy\nfrom typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union\nfrom uuid import uuid4\n\nimport networkx as nx\nfrom networkx import DiGraph\n\nfrom inference.core import logger\nfrom inference.core.workflows.errors import (\n    AssumptionError,\n    BlockInterfaceError,\n    ControlFlowDefinitionError,\n    ExecutionGraphStructureError,\n    InvalidReferenceTargetError,\n    StepInputDimensionalityError,\n    StepInputLineageError,\n    WorkflowBlockError,\n)\nfrom inference.core.workflows.execution_engine.constants import (\n    NODE_COMPILATION_OUTPUT_PROPERTY,\n    PARSED_NODE_INPUT_SELECTORS_PROPERTY,\n    TOP_LEVEL_LINEAGES_KEY,\n    WORKFLOW_INPUT_BATCH_LINEAGE_ID,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    InputType,\n    JsonField,\n    OutputDefinition,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    STEP_AS_SELECTED_ELEMENT,\n    Kind,\n)\nfrom inference.core.workflows.execution_engine.introspection.entities import (\n    ParsedSelector,\n)\nfrom inference.core.workflows.execution_engine.introspection.selectors_parser import (\n    get_step_selectors,\n)\nfrom inference.core.workflows.execution_engine.profiling.core import (\n    WorkflowsProfiler,\n    execution_phase,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import (\n    AutoBatchCastingConfig,\n    CompoundStepInputDefinition,\n    DictOfStepInputDefinitions,\n    DynamicStepInputDefinition,\n    ExecutionGraphNode,\n    InputDimensionalitySpecification,\n    InputNode,\n    ListOfStepInputDefinitions,\n    NodeCategory,\n    NodeInputCategory,\n    OutputNode,\n    ParameterSpecification,\n    ParsedWorkflowDefinition,\n    PropertyPredecessorDefinition,\n    StaticStepInputDefinition,\n    StepInputData,\n    StepInputDefinition,\n    StepNode,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.graph_traversal import (\n    traverse_graph_ensuring_parents_are_reached_first,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.reference_type_checker import (\n    validate_reference_kinds,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import (\n    construct_input_selector,\n    construct_output_selector,\n    construct_step_selector,\n    get_last_chunk_of_selector,\n    get_nodes_of_specific_category,\n    get_step_selector_from_its_output,\n    identify_lineage,\n    is_control_flow_step,\n    is_input_node,\n    is_input_selector,\n    is_output_node,\n    is_step_node,\n    is_step_output_selector,\n    is_step_selector,\n    node_as,\n)\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nNODE_DEFINITION_KEY = \"definition\"\nSTEP_INPUT_SELECTORS_PROPERTY = \"step_input_selectors\"\nEXCLUDED_FIELDS = {\"type\", \"name\"}\n\n\n@execution_phase(\n    name=\"execution_graph_creation\",\n    categories=[\"execution_engine_operation\"],\n)\ndef prepare_execution_graph(\n    workflow_definition: ParsedWorkflowDefinition,\n    profiler: Optional[WorkflowsProfiler] = None,\n) -> DiGraph:\n    execution_graph = construct_graph(\n        workflow_definition=workflow_definition,\n    )\n    if not nx.is_directed_acyclic_graph(execution_graph):\n        raise ExecutionGraphStructureError(\n            public_message=f\"Detected cycle in execution graph. This means that there is output from one \"\n            f\"step that is connected to input of other step creating loop in the graph that would \"\n            f\"never end if executed.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    return denote_data_flow_in_workflow(\n        execution_graph=execution_graph,\n        parsed_workflow_definition=workflow_definition,\n    )\n\n\ndef construct_graph(\n    workflow_definition: ParsedWorkflowDefinition,\n) -> DiGraph:\n    execution_graph = nx.DiGraph()\n    execution_graph = add_input_nodes_for_graph(\n        inputs=workflow_definition.inputs,\n        execution_graph=execution_graph,\n    )\n    execution_graph = add_steps_nodes_for_graph(\n        steps=workflow_definition.steps,\n        execution_graph=execution_graph,\n    )\n    execution_graph = add_output_nodes_for_graph(\n        outputs=workflow_definition.outputs,\n        execution_graph=execution_graph,\n    )\n    execution_graph = add_steps_edges(\n        workflow_definition=workflow_definition,\n        execution_graph=execution_graph,\n    )\n    return add_edges_for_outputs(\n        workflow_definition=workflow_definition,\n        execution_graph=execution_graph,\n    )\n\n\ndef add_input_nodes_for_graph(\n    inputs: List[InputType],\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for input_spec in inputs:\n        input_selector = construct_input_selector(input_name=input_spec.name)\n        if input_spec.is_batch_oriented():\n            if input_spec.dimensionality < 1:\n                raise ExecutionGraphStructureError(\n                    public_message=f\"Detected batch oriented input `{input_spec.name}` with \"\n                    f\"declared dimensionality `{input_spec.dimensionality}` which is below \"\n                    f\"one (one is minimum dimensionality of the batch). Fix input definition in\"\n                    f\"your Workflow.\",\n                    context=\"workflow_compilation | execution_graph_construction\",\n                )\n            data_lineage = [WORKFLOW_INPUT_BATCH_LINEAGE_ID]\n            for _ in range(input_spec.dimensionality - 1):\n                # TODO: this may end up being a bug - with ability for multi-step debugging, if we will\n                #  ever have a situation that there will be multiple step outputs with nested\n                #  dimensionality with the same lineage, this re-construction method will\n                #  assign a different lineage identifier, causing the inputs being non-composable in\n                #  a single execution branch\n                data_lineage.append(f\"{uuid4()}\")\n        else:\n            data_lineage = []\n        compilation_output = InputNode(\n            node_category=NodeCategory.INPUT_NODE,\n            name=input_spec.name,\n            selector=input_selector,\n            data_lineage=data_lineage,\n            input_manifest=input_spec,\n        )\n        execution_graph.add_node(\n            input_selector,\n            **{\n                NODE_COMPILATION_OUTPUT_PROPERTY: compilation_output,\n            },\n        )\n    return execution_graph\n\n\ndef add_steps_nodes_for_graph(\n    steps: List[WorkflowBlockManifest],\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for step in steps:\n        step_selector = construct_step_selector(step_name=step.name)\n        compilation_output = StepNode(\n            node_category=NodeCategory.STEP_NODE,\n            name=step.name,\n            selector=step_selector,\n            data_lineage=[],\n            step_manifest=step,\n        )\n        execution_graph.add_node(\n            step_selector,\n            **{\n                NODE_COMPILATION_OUTPUT_PROPERTY: compilation_output,\n            },\n        )\n    return execution_graph\n\n\ndef add_output_nodes_for_graph(\n    outputs: List[JsonField],\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for output_spec in outputs:\n        output_selector = construct_output_selector(name=output_spec.name)\n        compilation_output = OutputNode(\n            node_category=NodeCategory.OUTPUT_NODE,\n            name=output_spec.name,\n            selector=output_selector,\n            data_lineage=[],\n            output_manifest=output_spec,\n        )\n        execution_graph.add_node(\n            output_selector,\n            **{\n                NODE_COMPILATION_OUTPUT_PROPERTY: compilation_output,\n            },\n        )\n    return execution_graph\n\n\ndef add_steps_edges(\n    workflow_definition: ParsedWorkflowDefinition,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for step in workflow_definition.steps:\n        source_step_selector = construct_step_selector(step_name=step.name)\n        step_selectors = get_step_selectors(step_manifest=step)\n        execution_graph.nodes[source_step_selector][\n            PARSED_NODE_INPUT_SELECTORS_PROPERTY\n        ] = step_selectors\n        execution_graph = add_edges_for_step(\n            execution_graph=execution_graph,\n            source_step_selector=source_step_selector,\n            target_step_parsed_selectors=step_selectors,\n        )\n    return execution_graph\n\n\ndef add_edges_for_step(\n    execution_graph: DiGraph,\n    source_step_selector: str,\n    target_step_parsed_selectors: List[ParsedSelector],\n) -> DiGraph:\n    for target_step_parsed_selector in target_step_parsed_selectors:\n        execution_graph = add_edge_for_step(\n            execution_graph=execution_graph,\n            source_step_selector=source_step_selector,\n            target_step_parsed_selector=target_step_parsed_selector,\n        )\n    return execution_graph\n\n\ndef add_edge_for_step(\n    execution_graph: DiGraph,\n    source_step_selector: str,\n    target_step_parsed_selector: ParsedSelector,\n) -> DiGraph:\n    target_step_selector = get_step_selector_from_its_output(\n        step_output_selector=target_step_parsed_selector.value\n    )\n    verify_edge_is_created_between_existing_nodes(\n        execution_graph=execution_graph,\n        start=source_step_selector,\n        end=target_step_selector,\n    )\n    if is_step_selector(target_step_parsed_selector.value):\n        return establish_control_flow_edge(\n            source_step_selector=source_step_selector,\n            target_step_parsed_selector=target_step_parsed_selector,\n            execution_graph=execution_graph,\n        )\n    if is_input_selector(target_step_parsed_selector.value):\n        input_node_compilation_data = node_as(\n            execution_graph=execution_graph,\n            node=target_step_parsed_selector.value,\n            expected_type=InputNode,\n        )\n        actual_input_kind = input_node_compilation_data.input_manifest.kind\n    else:\n        other_step_compilation_data = node_as(\n            execution_graph=execution_graph,\n            node=target_step_selector,\n            expected_type=StepNode,\n        )\n        source_step_compilation_data = node_as(\n            execution_graph=execution_graph,\n            node=source_step_selector,\n            expected_type=StepNode,\n        )\n        actual_input_kind = get_kind_of_value_provided_in_step_output(\n            step_manifest=other_step_compilation_data.step_manifest,\n            step_property=get_last_chunk_of_selector(\n                selector=target_step_parsed_selector.value\n            ),\n            source_step_manifest=source_step_compilation_data.step_manifest,\n        )\n    expected_input_kind = list(\n        itertools.chain.from_iterable(\n            ref.kind\n            for ref in target_step_parsed_selector.definition.allowed_references\n        )\n    )\n    error_message = (\n        f\"Failed to validate reference provided for step: {source_step_selector} regarding property: \"\n        f\"{target_step_parsed_selector.definition.property_name} with value: {target_step_parsed_selector.value}. \"\n        f\"Allowed kinds of references for this property: {list(set(e.name for e in expected_input_kind))}. \"\n        f\"Types of output for referred property: \"\n        f\"{list(set(a.name if isinstance(a, Kind) else a for a in actual_input_kind))}\"\n    )\n    validate_reference_kinds(\n        expected=expected_input_kind,\n        actual=actual_input_kind,\n        error_message=error_message,\n    )\n    if execution_graph.has_edge(target_step_selector, source_step_selector):\n        edge_data = execution_graph.edges[(target_step_selector, source_step_selector)]\n        if STEP_INPUT_SELECTORS_PROPERTY not in edge_data:\n            edge_data[STEP_INPUT_SELECTORS_PROPERTY] = []\n        edge_data[STEP_INPUT_SELECTORS_PROPERTY].append(\n            target_step_parsed_selector,\n        )\n    else:\n        execution_graph.add_edge(\n            target_step_selector,\n            source_step_selector,\n            **{STEP_INPUT_SELECTORS_PROPERTY: [target_step_parsed_selector]},\n        )\n    return execution_graph\n\n\ndef establish_control_flow_edge(\n    source_step_selector: str,\n    target_step_parsed_selector: ParsedSelector,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    if not step_definition_allows_control_flow_references(\n        parsed_selector=target_step_parsed_selector\n    ):\n        raise ExecutionGraphStructureError(\n            public_message=f\"Detected reference to other step in manifest of step {source_step_selector}. \"\n            f\"This is not allowed, as step manifest does not define any properties of type `StepSelector` \"\n            f\"allowing for defining connections between steps that represent flow control in `workflows`.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    target_step_selector = get_step_selector_from_its_output(\n        step_output_selector=target_step_parsed_selector.value\n    )\n    source_compilation_data = node_as(\n        execution_graph=execution_graph,\n        node=source_step_selector,\n        expected_type=StepNode,\n    )\n    target_compilation_data = node_as(\n        execution_graph=execution_graph,\n        node=target_step_selector,\n        expected_type=StepNode,\n    )\n    nodes_categories = {\n        source_compilation_data.node_category,\n        target_compilation_data.node_category,\n    }\n    if nodes_categories != {NodeCategory.STEP_NODE}:\n        raise ExecutionGraphStructureError(\n            public_message=f\"Attempted to create flow-control connection between workflow nodes: \"\n            f\"{source_step_selector} and {target_step_selector}, one of which is not denoted\"\n            f\"as step node.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    execution_graph.add_edge(\n        source_step_selector,\n        target_step_selector,\n    )\n    if target_step_selector in source_compilation_data.child_execution_branches:\n        raise ExecutionGraphStructureError(\n            public_message=f\"While establishing flow-control connection between source `{source_step_selector}` \"\n            f\"and target `{target_step_selector}` it was discovered that source step defines\"\n            f\"control flow transition into target one more than once, which is not allowed as \"\n            f\"that situation creates ambiguity in selecting execution branch.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    execution_branch_name = f\"Branch[{source_step_selector} -> {target_step_parsed_selector.definition.property_name}]\"\n    source_compilation_data.child_execution_branches[target_step_selector] = (\n        execution_branch_name\n    )\n    target_compilation_data.execution_branches_impacting_inputs.add(\n        execution_branch_name\n    )\n    return execution_graph\n\n\ndef step_definition_allows_control_flow_references(\n    parsed_selector: ParsedSelector,\n) -> bool:\n    return any(\n        definition.selected_element == STEP_AS_SELECTED_ELEMENT\n        for definition in parsed_selector.definition.allowed_references\n    )\n\n\ndef get_kind_of_value_provided_in_step_output(\n    step_manifest: WorkflowBlockManifest,\n    step_property: str,\n    source_step_manifest: WorkflowBlockManifest,\n) -> List[Kind]:\n    referred_node_outputs = step_manifest.get_actual_outputs()\n    actual_kind = []\n    matched_property = False\n    for output in referred_node_outputs:\n        if output.name != step_property:\n            continue\n        matched_property = True\n        actual_kind.extend(output.kind)\n    if not matched_property:\n        property_name = get_property_with_invalid_selector(\n            manifest=source_step_manifest,\n            step_property=step_property,\n        )\n        raise ExecutionGraphStructureError(\n            public_message=f\"Found reference to non-existing property `{step_property}` of step `{step_manifest.name}`.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=source_step_manifest.name,\n                    block_type=source_step_manifest.type,\n                    property_name=property_name,\n                    property_details=f\"'{step_manifest.name}.{step_property}' is an invalid reference\",\n                )\n            ],\n        )\n    return actual_kind\n\n\ndef add_edges_for_step_inputs(\n    execution_graph: DiGraph,\n    input_selectors: Set[str],\n    step_selector: str,\n) -> DiGraph:\n    for input_selector in input_selectors:\n        if is_step_output_selector(selector_or_value=input_selector):\n            input_selector = get_step_selector_from_its_output(\n                step_output_selector=input_selector\n            )\n        verify_edge_is_created_between_existing_nodes(\n            execution_graph=execution_graph,\n            start=input_selector,\n            end=step_selector,\n        )\n        execution_graph.add_edge(input_selector, step_selector)\n    return execution_graph\n\n\ndef add_edges_for_outputs(\n    workflow_definition: ParsedWorkflowDefinition,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for output in workflow_definition.outputs:\n        node_selector = output.selector\n        if is_step_output_selector(selector_or_value=node_selector):\n            node_selector = get_step_selector_from_its_output(\n                step_output_selector=node_selector\n            )\n        output_selector = construct_output_selector(name=output.name)\n        verify_edge_is_created_between_existing_nodes(\n            execution_graph=execution_graph,\n            start=node_selector,\n            end=output_selector,\n        )\n        output_node_manifest = node_as(\n            execution_graph=execution_graph,\n            node=output_selector,\n            expected_type=OutputNode,\n        )\n        if is_step_output_selector(selector_or_value=output.selector):\n            step_manifest = execution_graph.nodes[node_selector][\n                NODE_COMPILATION_OUTPUT_PROPERTY\n            ].step_manifest\n            step_outputs = step_manifest.get_actual_outputs()\n            denote_output_node_kind_based_on_step_outputs(\n                output_selector=output.selector,\n                step_outputs=step_outputs,\n                output_node_manifest=output_node_manifest,\n            )\n        else:\n            input_manifest = node_as(\n                execution_graph=execution_graph,\n                node=node_selector,\n                expected_type=InputNode,\n            ).input_manifest\n            output_node_manifest.kind = copy(input_manifest.kind)\n        execution_graph.add_edge(node_selector, output_selector)\n    return execution_graph\n\n\ndef verify_edge_is_created_between_existing_nodes(\n    execution_graph: DiGraph,\n    start: str,\n    end: str,\n) -> None:\n    if not execution_graph.has_node(start) or not execution_graph.has_node(end):\n        invalid_block = start if not execution_graph.has_node(start) else end\n        referencing_block = end if invalid_block == start else start\n\n        step_type = None\n        property_name = None\n        if execution_graph.has_node(referencing_block):\n            if is_step_node(execution_graph, referencing_block):\n                step_manifest = node_as(\n                    execution_graph=execution_graph,\n                    node=referencing_block,\n                    expected_type=StepNode,\n                ).step_manifest\n                step_type = step_manifest.type\n                property_name = get_property_with_invalid_selector(\n                    manifest=step_manifest,\n                    step_property=invalid_block,\n                )\n\n        block_id = (\n            \"$outputs\"\n            if referencing_block.startswith(\"$outputs.\")\n            else get_last_chunk_of_selector(selector=referencing_block)\n        )\n        property_name = (\n            get_last_chunk_of_selector(selector=referencing_block)\n            if referencing_block.startswith(\"$outputs.\")\n            else property_name\n        )\n\n        is_input = is_input_selector(selector_or_value=invalid_block)\n        raise InvalidReferenceTargetError(\n            public_message=f\"Workflow references '{invalid_block}' which points to a non-existent {is_input and 'input parameter' or 'block'}.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=block_id,\n                    block_type=step_type,\n                    property_name=property_name,\n                    property_details=f\"Invalid reference to {invalid_block}\",\n                ),\n            ],\n        )\n\n\ndef denote_output_node_kind_based_on_step_outputs(\n    output_selector: str,\n    step_outputs: List[OutputDefinition],\n    output_node_manifest: OutputNode,\n) -> None:\n    selected_output_name = get_last_chunk_of_selector(selector=output_selector)\n    kinds_for_outputs = {output.name: output.kind for output in step_outputs}\n\n    if selected_output_name == \"*\":\n        output_node_manifest.kind = deepcopy(kinds_for_outputs)\n        return None\n    if selected_output_name not in kinds_for_outputs:\n        output_name = output_node_manifest.output_manifest.name\n\n        raise InvalidReferenceTargetError(\n            public_message=f\"Workflow output references '{output_selector}' which points to a non-existent block property.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=\"$outputs\",\n                    property_name=output_name,\n                    property_details=f\"Invalid reference to {output_selector}\",\n                ),\n            ],\n        )\n    output_node_manifest.kind = copy(kinds_for_outputs[selected_output_name])\n    return None\n\n\ndef denote_data_flow_in_workflow(\n    execution_graph: DiGraph,\n    parsed_workflow_definition: ParsedWorkflowDefinition,\n) -> nx.DiGraph:\n    block_manifest_by_step_name = {\n        step.name: step for step in parsed_workflow_definition.steps\n    }\n    super_input_node = \"<super-input>\"\n    execution_graph = add_super_input_node_in_execution_graph(\n        execution_graph=execution_graph,\n        super_input_node=super_input_node,\n    )\n    execution_graph.nodes[super_input_node][NODE_COMPILATION_OUTPUT_PROPERTY] = (\n        InputNode(\n            node_category=NodeCategory.INPUT_NODE,\n            name=super_input_node,\n            selector=f\"$inputs.{super_input_node}\",\n            data_lineage=[],\n            input_manifest=None,  # this is expected never to be reached\n        )\n    )\n    top_level_data_lineage = set()\n    for node in traverse_graph_ensuring_parents_are_reached_first(\n        graph=execution_graph,\n        start_node=super_input_node,\n    ):\n        execution_graph = denote_data_flow_for_node(\n            execution_graph=execution_graph,\n            node=node,\n            block_manifest_by_step_name=block_manifest_by_step_name,\n            on_top_level_lineage_denoted=lambda element: top_level_data_lineage.add(\n                element\n            ),\n        )\n    execution_graph.remove_node(super_input_node)\n    execution_graph.graph[TOP_LEVEL_LINEAGES_KEY] = top_level_data_lineage\n    return execution_graph\n\n\ndef denote_data_flow_for_node(\n    execution_graph: DiGraph,\n    node: str,\n    block_manifest_by_step_name: Dict[str, WorkflowBlockManifest],\n    on_top_level_lineage_denoted: Callable[[str], None],\n) -> DiGraph:\n    if is_input_node(execution_graph=execution_graph, node=node):\n        # everything already set there, in the previous stage of compilation\n        return execution_graph\n    if is_step_node(execution_graph=execution_graph, node=node):\n        step_name = get_last_chunk_of_selector(selector=node)\n        if step_name not in block_manifest_by_step_name:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler expected manifest for the step: {step_name} to be registered \"\n                f\"but this condition is not met. This is most likely the bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | retrieving_predecessors_for_output\",\n            )\n        manifest = block_manifest_by_step_name[step_name]\n        return denote_data_flow_for_step(\n            execution_graph=execution_graph,\n            node=node,\n            manifest=manifest,\n            on_top_level_lineage_denoted=on_top_level_lineage_denoted,\n        )\n    if is_output_node(execution_graph=execution_graph, node=node):\n        # output is allowed to have exactly one predecessor\n        output_predecessors = list(execution_graph.predecessors(node))\n        if len(output_predecessors) != 1:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler expected each output in compiled graph to have one predecessor, \"\n                f\"but this condition is not met for node {node}. This is most likely the bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | retrieving_predecessors_for_output\",\n            )\n        predecessor_node = output_predecessors[0]\n        predecessor_node_data = node_as(\n            execution_graph=execution_graph,\n            node=predecessor_node,\n            expected_type=ExecutionGraphNode,\n        )\n        predecessor_node_lineage = predecessor_node_data.data_lineage\n        output_node_data = node_as(\n            execution_graph=execution_graph,\n            node=node,\n            expected_type=OutputNode,\n        )\n        output_node_data.data_lineage = predecessor_node_lineage\n        return execution_graph\n    raise AssumptionError(\n        f\"Workflow Compiler encountered node: {node} which cannot be classified as known node type. \"\n        f\"This is most likely the bug. Contact Roboflow team through github issues \"\n        f\"(https://github.com/roboflow/inference/issues) providing full \"\n        f\"context of the problem - including workflow definition you use.\",\n        context=\"workflow_compilation | execution_graph_construction | denoting_data_flow_for_step\",\n    )\n\n\ndef denote_data_flow_for_step(\n    execution_graph: DiGraph,\n    node: str,\n    manifest: WorkflowBlockManifest,\n    on_top_level_lineage_denoted: Callable[[str], None],\n) -> DiGraph:\n    all_control_flow_predecessors, all_non_control_flow_predecessors = (\n        separate_control_flow_predecessors_from_data_providers(\n            execution_graph=execution_graph, node=node\n        )\n    )\n    input_data = build_input_data_for_step(\n        manifest=manifest,\n        step_node=node,\n        data_providing_predecessors=all_non_control_flow_predecessors,\n        execution_graph=execution_graph,\n    )\n    step_name = get_last_chunk_of_selector(node)\n    step_node_data = node_as(\n        execution_graph=execution_graph,\n        node=node,\n        expected_type=StepNode,\n    )\n    parsed_step_input_selectors: List[ParsedSelector] = execution_graph.nodes[node][\n        PARSED_NODE_INPUT_SELECTORS_PROPERTY\n    ]\n    batch_compatibility_of_properties = retrieve_batch_compatibility_of_input_selectors(\n        input_selectors=parsed_step_input_selectors\n    )\n    scalar_parameters_to_be_batched = (\n        verify_declared_batch_compatibility_against_actual_inputs(\n            node=node,\n            step_node_data=step_node_data,\n            input_data=input_data,\n            batch_compatibility_of_properties=batch_compatibility_of_properties,\n        )\n    )\n    input_dimensionality_offsets = manifest.get_input_dimensionality_offsets()\n    verify_step_input_dimensionality_offsets(\n        step_name=step_name,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n    )\n    inputs_dimensionalities = get_inputs_dimensionalities(\n        step_name=step_name,\n        step_type=manifest.type,\n        input_data=input_data,\n        scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n    )\n    logger.debug(\n        f\"For step: {node}, detected the following input dimensionalities: {inputs_dimensionalities}\"\n    )\n    parameters_with_batch_inputs = grab_parameters_defining_batch_inputs(\n        inputs_dimensionalities=inputs_dimensionalities,\n    )\n    dimensionality_reference_property = manifest.get_dimensionality_reference_property()\n    output_dimensionality_offset = manifest.get_output_dimensionality_offset()\n    verify_step_input_dimensionality_offsets(\n        step_name=step_name,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n    )\n    verify_output_offset(\n        step_name=step_name,\n        parameters_with_batch_inputs=parameters_with_batch_inputs,\n        dimensionality_reference_property=dimensionality_reference_property,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n        output_dimensionality_offset=output_dimensionality_offset,\n    )\n    verify_input_data_dimensionality(\n        step_name=step_name,\n        step_type=manifest.type,\n        dimensionality_reference_property=dimensionality_reference_property,\n        inputs_dimensionalities=inputs_dimensionalities,\n        dimensionality_offstes=input_dimensionality_offsets,\n    )\n    all_data_derived_lineages = get_input_data_lineage_excluding_auto_batch_casting(\n        step_name=step_name,\n        input_data=input_data,\n        scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n    )\n    all_control_flow_lineages = get_lineage_derived_from_control_flow(\n        control_flow_steps_selectors=all_control_flow_predecessors,\n        execution_graph=execution_graph,\n    )\n    verify_compatibility_of_input_data_lineage_with_control_flow_lineage(\n        step_name=step_name,\n        inputs_lineage=all_data_derived_lineages,\n        control_flow_steps_selectors=all_control_flow_predecessors,\n        execution_graph=execution_graph,\n    )\n    step_node_data.input_data = input_data\n    step_node_data.dimensionality_reference_property = dimensionality_reference_property\n    step_node_data.control_flow_lineage_dims = [\n        len(_lineage) for _lineage in all_control_flow_lineages if _lineage\n    ]\n    step_node_data.batch_oriented_parameters = parameters_with_batch_inputs\n    if not all_data_derived_lineages and not all_control_flow_lineages:\n        if manifest.get_output_dimensionality_offset() > 0:\n            # brave decision to open a Pandora box\n            data_lineage = [node]\n        else:\n            data_lineage = []\n        control_flow_lineage_support = []\n    else:\n        data_lineage, control_flow_lineage_support = (\n            establish_batch_oriented_step_lineage(\n                step_selector=node,\n                all_data_derived_lineages=all_data_derived_lineages,\n                all_control_flow_lineages=all_control_flow_lineages,\n                input_data=input_data,\n                dimensionality_reference_property=dimensionality_reference_property,\n                output_dimensionality_offset=output_dimensionality_offset,\n            )\n        )\n    step_node_data.step_execution_dimensionality = (\n        establish_step_execution_dimensionality(\n            inputs_dimensionalities=inputs_dimensionalities,\n            control_flow_lineage_support=control_flow_lineage_support,\n            output_dimensionality_offset=output_dimensionality_offset,\n        )\n    )\n    lineage_supports = get_lineage_support_for_auto_batch_casted_parameters(\n        input_dimensionalities=inputs_dimensionalities,\n        all_lineages_of_batch_parameters=all_data_derived_lineages,\n        scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n    )\n    step_node_data.auto_batch_casting_lineage_supports = lineage_supports\n    step_node_data.control_flow_lineage_support = control_flow_lineage_support\n    if data_lineage:\n        on_top_level_lineage_denoted(data_lineage[0])\n    step_node_data.data_lineage = data_lineage\n    return execution_graph\n\n\ndef _collect_unique_control_flow_lineages_with_step_mapping(\n    control_flow_steps_selectors: List[str],\n    execution_graph: nx.DiGraph,\n) -> Tuple[List[List[str]], Dict[int, List[str]]]:\n    \"\"\"\n    Collect data lineages from control flow steps and deduplicate by lineage id.\n\n    For each given control flow step selector, reads its data_lineage from the\n    execution graph. Returns unique non-empty lineages (by identify_lineage id)\n    and a mapping from lineage id to every step selector that produced that\n    lineage (used e.g. for error reporting when lineage is incompatible).\n\n    Args:\n        control_flow_steps_selectors: Step selectors (node ids) of control\n            flow steps whose data_lineage is to be collected.\n        execution_graph: The workflow execution graph containing step nodes\n            and their data_lineage.\n\n    Returns:\n        A tuple of (unique_lineages, lineage_id_to_step_selectors):\n        - unique_lineages: list of distinct non-empty data lineages.\n        - lineage_id_to_step_selectors: map from lineage id to list of step\n          selectors whose data_lineage has that id (includes empty lineages).\n    \"\"\"\n    unique_lineages: List[List[str]] = []\n    seen_lineage_ids: Set[int] = set()\n    lineage_id_to_step_selectors: Dict[int, List[str]] = defaultdict(list)\n\n    for step_selector in control_flow_steps_selectors:\n        step_data = node_as(\n            execution_graph=execution_graph,\n            node=step_selector,\n            expected_type=StepNode,\n        )\n        lineage = step_data.data_lineage\n        lineage_id = identify_lineage(lineage)\n        lineage_id_to_step_selectors[lineage_id].append(step_selector)\n        if lineage and lineage_id not in seen_lineage_ids:\n            seen_lineage_ids.add(lineage_id)\n            unique_lineages.append(lineage)\n\n    return unique_lineages, dict(lineage_id_to_step_selectors)\n\n\ndef get_lineage_derived_from_control_flow(\n    control_flow_steps_selectors: List[str],\n    execution_graph: nx.DiGraph,\n) -> List[List[str]]:\n    \"\"\"\n    Return unique non-empty data lineages from the given control flow steps.\n\n    Each lineage is taken from the step's data_lineage in the execution graph.\n    Lineages are deduplicated by lineage id (see identify_lineage); empty\n    lineages are omitted. Used when establishing batch-oriented step lineage.\n\n    Args:\n        control_flow_steps_selectors: Step selectors (node ids) of control\n            flow steps whose data_lineage is to be collected.\n        execution_graph: The workflow execution graph containing step nodes\n            and their data_lineage.\n\n    Returns:\n        List of distinct non-empty data lineages, one per unique lineage id.\n    \"\"\"\n    unique_lineages, _ = _collect_unique_control_flow_lineages_with_step_mapping(\n        control_flow_steps_selectors=control_flow_steps_selectors,\n        execution_graph=execution_graph,\n    )\n    return unique_lineages\n\n\ndef separate_control_flow_predecessors_from_data_providers(\n    execution_graph: DiGraph,\n    node: str,\n) -> Tuple[List[str], List[str]]:\n    all_predecessors = list(execution_graph.predecessors(node))\n    all_control_flow_predecessors = [\n        predecessor\n        for predecessor in all_predecessors\n        if is_control_flow_step(execution_graph=execution_graph, node=predecessor)\n    ]\n    all_non_control_flow_predecessors = [\n        predecessor\n        for predecessor in all_predecessors\n        if not is_control_flow_step(execution_graph=execution_graph, node=predecessor)\n    ]\n    return all_control_flow_predecessors, all_non_control_flow_predecessors\n\n\ndef build_input_data_for_step(\n    manifest: WorkflowBlockManifest,\n    step_node: str,\n    data_providing_predecessors: List[str],\n    execution_graph: DiGraph,\n) -> StepInputData:\n    predecessors_by_property_name = get_predecessors_for_step_manifest_properties(\n        execution_graph=execution_graph,\n        step_node=step_node,\n        data_providing_predecessors=data_providing_predecessors,\n    )\n    manifest_fields_values = get_manifest_fields_values(step_manifest=manifest)\n    result = {}\n    for name, value in manifest_fields_values.items():\n        result[name] = build_input_property(\n            step_node=step_node,\n            manifest_property_name=name,\n            manifest_property_value=value,\n            predecessors_by_property_name=predecessors_by_property_name,\n            execution_graph=execution_graph,\n        )\n    return result\n\n\ndef get_predecessors_for_step_manifest_properties(\n    execution_graph: DiGraph, step_node: str, data_providing_predecessors: List[str]\n) -> Dict[str, List[PropertyPredecessorDefinition]]:\n    predecessors_by_property_name = defaultdict(list)\n    for predecessor in data_providing_predecessors:\n        edge_data = execution_graph.edges[(predecessor, step_node)]\n        # STEP_INPUT_SELECTORS_PROPERTY is optional, as special <super-input> node may be directly\n        # connected to step\n        selectors_associated_to_edge: List[ParsedSelector] = edge_data.get(\n            STEP_INPUT_SELECTORS_PROPERTY, []\n        )\n        for selector_associated_to_edge in selectors_associated_to_edge:\n            definition = PropertyPredecessorDefinition(\n                predecessor_selector=predecessor,\n                parsed_selector=selector_associated_to_edge,\n            )\n            predecessors_by_property_name[\n                selector_associated_to_edge.definition.property_name\n            ].append(definition)\n    return predecessors_by_property_name\n\n\ndef build_input_property(\n    step_node: str,\n    manifest_property_name: str,\n    manifest_property_value: Any,\n    predecessors_by_property_name: Dict[str, List[PropertyPredecessorDefinition]],\n    execution_graph: DiGraph,\n) -> Union[StepInputDefinition, CompoundStepInputDefinition]:\n    if manifest_property_name not in predecessors_by_property_name:\n        return StaticStepInputDefinition(\n            parameter_specification=ParameterSpecification(\n                parameter_name=manifest_property_name,\n            ),\n            category=NodeInputCategory.STATIC_VALUE,\n            value=manifest_property_value,\n        )\n    if isinstance(manifest_property_value, dict):\n        return build_nested_dictionary_for_input_property(\n            step_node=step_node,\n            manifest_property_name=manifest_property_name,\n            manifest_property_value=manifest_property_value,\n            predecessors_definitions=predecessors_by_property_name[\n                manifest_property_name\n            ],\n            execution_graph=execution_graph,\n        )\n    if isinstance(manifest_property_value, list):\n        return build_nested_list_for_input_property(\n            step_node=step_node,\n            manifest_property_name=manifest_property_name,\n            manifest_property_value=manifest_property_value,\n            predecessors_definitions=predecessors_by_property_name[\n                manifest_property_name\n            ],\n            execution_graph=execution_graph,\n        )\n    matching_predecessors_data = predecessors_by_property_name[manifest_property_name]\n    if len(matching_predecessors_data) != 1:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler deduced that property `{manifest_property_name}` of step `{step_node}` \"\n            f\"should be fed with data coming from exactly one execution graph node, but found \"\n            f\"{len(matching_predecessors_data)} data sources. This is most likely the bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n        )\n    predecessor_selector, predecessor_parsed_selector = (\n        matching_predecessors_data[0].predecessor_selector,\n        matching_predecessors_data[0].parsed_selector,\n    )\n    if is_input_node(execution_graph=execution_graph, node=predecessor_selector):\n        predecessor_node_data = node_as(\n            execution_graph=execution_graph,\n            node=matching_predecessors_data[0].predecessor_selector,\n            expected_type=InputNode,\n        )\n        category = (\n            NodeInputCategory.BATCH_INPUT_PARAMETER\n            if predecessor_node_data.is_batch_oriented()\n            else NodeInputCategory.NON_BATCH_INPUT_PARAMETER\n        )\n        return DynamicStepInputDefinition(\n            parameter_specification=ParameterSpecification(\n                parameter_name=manifest_property_name,\n            ),\n            category=category,\n            data_lineage=predecessor_node_data.data_lineage,\n            selector=predecessor_node_data.selector,\n        )\n    if is_step_node(execution_graph=execution_graph, node=predecessor_selector):\n        predecessor_node_data = node_as(\n            execution_graph=execution_graph,\n            node=matching_predecessors_data[0].predecessor_selector,\n            expected_type=StepNode,\n        )\n        category = (\n            NodeInputCategory.BATCH_STEP_OUTPUT\n            if predecessor_node_data.output_dimensionality > 0\n            else NodeInputCategory.NON_BATCH_STEP_OUTPUT\n        )\n        return DynamicStepInputDefinition(\n            parameter_specification=ParameterSpecification(\n                parameter_name=manifest_property_name,\n            ),\n            category=category,\n            data_lineage=predecessor_node_data.data_lineage,\n            selector=predecessor_parsed_selector.value,\n        )\n    raise AssumptionError(\n        public_message=f\"Workflow Compiler for property `{manifest_property_name}` of step `{step_node}` \"\n        f\"found data providing predecessor `{predecessor_selector}` which has unsupported step type.\"\n        f\"This is most likely the bug. \"\n        f\"Contact Roboflow team through github issues \"\n        f\"(https://github.com/roboflow/inference/issues) providing full \"\n        f\"context of the problem - including workflow definition you use.\",\n        context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n    )\n\n\ndef build_nested_dictionary_for_input_property(\n    step_node: str,\n    manifest_property_name: str,\n    manifest_property_value: dict,\n    predecessors_definitions: List[PropertyPredecessorDefinition],\n    execution_graph: DiGraph,\n) -> DictOfStepInputDefinitions:\n    nested_property_name2data: Dict[Optional[str], PropertyPredecessorDefinition] = {\n        predecessor_definition.parsed_selector.key: predecessor_definition\n        for predecessor_definition in predecessors_definitions\n    }\n    result = {}\n    for nested_dict_key, nested_dict_value in manifest_property_value.items():\n        if nested_dict_key not in nested_property_name2data:\n            result[nested_dict_key] = StaticStepInputDefinition(\n                parameter_specification=ParameterSpecification(\n                    parameter_name=manifest_property_name,\n                    nested_element_key=nested_dict_key,\n                ),\n                category=NodeInputCategory.STATIC_VALUE,\n                value=nested_dict_value,\n            )\n            continue\n        referred_node_selector = nested_property_name2data[\n            nested_dict_key\n        ].predecessor_selector\n        referred_node_parsed_selector = nested_property_name2data[\n            nested_dict_key\n        ].parsed_selector\n        if is_input_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=InputNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_INPUT_PARAMETER\n                if predecessor_node_data.is_batch_oriented()\n                else NodeInputCategory.NON_BATCH_INPUT_PARAMETER\n            )\n            result[nested_dict_key] = DynamicStepInputDefinition(\n                parameter_specification=ParameterSpecification(\n                    parameter_name=manifest_property_name,\n                    nested_element_key=nested_dict_key,\n                ),\n                category=category,\n                data_lineage=predecessor_node_data.data_lineage,\n                selector=predecessor_node_data.selector,\n            )\n            continue\n        if is_step_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=StepNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_STEP_OUTPUT\n                if predecessor_node_data.output_dimensionality > 0\n                else NodeInputCategory.NON_BATCH_STEP_OUTPUT\n            )\n            result[nested_dict_key] = DynamicStepInputDefinition(\n                parameter_specification=ParameterSpecification(\n                    parameter_name=manifest_property_name,\n                    nested_element_key=nested_dict_key,\n                ),\n                category=category,\n                data_lineage=predecessor_node_data.data_lineage,\n                selector=referred_node_parsed_selector.value,\n            )\n            continue\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for property `{manifest_property_name}` of step `{step_node}` \"\n            f\"found data providing predecessor `{referred_node_selector}` which has \"\n            f\"unsupported step type (key: {nested_dict_key} of nested data dictionary). \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n        )\n    return DictOfStepInputDefinitions(\n        name=manifest_property_name,\n        nested_definitions=result,\n    )\n\n\ndef get_manifest_fields_values(step_manifest: WorkflowBlockManifest) -> Dict[str, Any]:\n    result = {}\n    for field in step_manifest.model_fields:\n        if field in EXCLUDED_FIELDS:\n            continue\n        result[field] = getattr(step_manifest, field)\n    return result\n\n\ndef build_nested_list_for_input_property(\n    step_node: str,\n    manifest_property_name: str,\n    manifest_property_value: list,\n    predecessors_definitions: List[PropertyPredecessorDefinition],\n    execution_graph: DiGraph,\n) -> ListOfStepInputDefinitions:\n    nested_index2data: Dict[Optional[int], PropertyPredecessorDefinition] = {\n        e.parsed_selector.index: e for e in predecessors_definitions\n    }\n    result = []\n    for index, element in enumerate(manifest_property_value):\n        if index not in nested_index2data:\n            result.append(\n                StaticStepInputDefinition(\n                    parameter_specification=ParameterSpecification(\n                        parameter_name=manifest_property_name,\n                        nested_element_index=index,\n                    ),\n                    category=NodeInputCategory.STATIC_VALUE,\n                    value=element,\n                )\n            )\n            continue\n        referred_node_selector = nested_index2data[index].predecessor_selector\n        referred_node_parsed_selector = nested_index2data[index].parsed_selector\n        if is_input_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=InputNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_INPUT_PARAMETER\n                if predecessor_node_data.is_batch_oriented()\n                else NodeInputCategory.NON_BATCH_INPUT_PARAMETER\n            )\n            result.append(\n                DynamicStepInputDefinition(\n                    parameter_specification=ParameterSpecification(\n                        parameter_name=manifest_property_name,\n                        nested_element_index=index,\n                    ),\n                    category=category,\n                    data_lineage=predecessor_node_data.data_lineage,\n                    selector=predecessor_node_data.selector,\n                )\n            )\n            continue\n        if is_step_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=StepNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_STEP_OUTPUT\n                if predecessor_node_data.output_dimensionality > 0\n                else NodeInputCategory.NON_BATCH_STEP_OUTPUT\n            )\n            result.append(\n                DynamicStepInputDefinition(\n                    parameter_specification=ParameterSpecification(\n                        parameter_name=manifest_property_name,\n                        nested_element_index=index,\n                    ),\n                    category=category,\n                    data_lineage=predecessor_node_data.data_lineage,\n                    selector=referred_node_parsed_selector.value,\n                )\n            )\n            continue\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for property `{manifest_property_name}` of step `{step_node}` \"\n            f\"found data providing predecessor `{referred_node_selector}` which has \"\n            f\"unsupported step type (index: {index} of nested data list). \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n        )\n    return ListOfStepInputDefinitions(\n        name=manifest_property_name,\n        nested_definitions=result,\n    )\n\n\ndef verify_step_input_dimensionality_offsets(\n    step_name: str,\n    input_dimensionality_offsets: Dict[str, int],\n) -> None:\n    min_offset, max_offset = None, None\n    for offset in input_dimensionality_offsets.values():\n        if min_offset is None or offset < min_offset:\n            min_offset = offset\n        if max_offset is None or offset > max_offset:\n            max_offset = offset\n    if min_offset is None or max_offset is None:\n        return None\n    if min_offset < 0 or max_offset < 0:\n        raise BlockInterfaceError(\n            public_message=f\"Offsets could not be negative, but block defining step: {step_name} defines that values.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_input_offset_definitions\",\n        )\n    if abs(max_offset - min_offset) > 1:\n        raise BlockInterfaceError(\n            public_message=\"Offsets of input parameters could not differ more than 1, but block defining step {step_name} \"\n            f\"violates that rule.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_input_offset_definitions\",\n        )\n\n\ndef verify_output_offset(\n    step_name: str,\n    parameters_with_batch_inputs: Set[str],\n    input_dimensionality_offsets: Dict[str, int],\n    dimensionality_reference_property: Optional[str],\n    output_dimensionality_offset: int,\n) -> None:\n    if not parameters_with_batch_inputs and output_dimensionality_offset < 0:\n        raise StepInputDimensionalityError(\n            public_message=f\"Block defining step {step_name} defines negative dimensionality offset while only \"\n            f\"scalar inputs being provided - the block cannot run as there is no dimension to collapse.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if (\n        dimensionality_reference_property is not None\n        and dimensionality_reference_property not in parameters_with_batch_inputs\n    ):\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} defines dimensionality reference property \"\n            f\"which is not in scope of parameters bring batch-oriented input, which makes it impossible \"\n            f\"to use as reference for output dimensionality.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if output_dimensionality_offset not in {-1, 0, 1}:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} defines output dimensionality offset \"\n            f\"being {output_dimensionality_offset}, whereas it is only possible for that offset being \"\n            f\"in set [-1, 0, 1].\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    different_offsets = {o for o in input_dimensionality_offsets.values()}\n    if len(parameters_with_batch_inputs) != len(input_dimensionality_offsets):\n        # assumption of default offset being zero - and this one does not need to be manifested\n        # by block\n        different_offsets.add(0)\n    if 0 not in different_offsets and parameters_with_batch_inputs:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} explicitly defines input dimensionalities offsets\"\n            f\"with {input_dimensionality_offsets}, but the definition lack 0-level input, which is \"\n            f\"not allowed, as in this scenario offsets could be adjusted to include 0\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if len(different_offsets) > 1 and dimensionality_reference_property is None:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} explicitly defines input dimensionality \"\n            f\"offsets {input_dimensionality_offsets}. In this scenario it is required to provide dimensionality \"\n            f\"reference property.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if len(different_offsets) > 1 and output_dimensionality_offset != 0:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} explicitly defines input dimensionality \"\n            f\"offsets {input_dimensionality_offsets} and output dimensionality offset {output_dimensionality_offset} \"\n            f\"where the latter is not 0, but for inputs differing with dimensionality it is only possible to keep \"\n            f\"output dimensionality the same and point reference parameter.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n\n\ndef verify_input_data_dimensionality(\n    step_name: str,\n    step_type: str,\n    dimensionality_reference_property: Optional[str],\n    inputs_dimensionalities: Dict[str, Set[int]],\n    dimensionality_offstes: Dict[str, int],\n) -> None:\n    parameter_name2dimensionality_specification = (\n        grab_input_data_dimensionality_specifications(\n            step_name=step_name,\n            inputs_dimensionalities=inputs_dimensionalities,\n            dimensionality_offstes=dimensionality_offstes,\n        )\n    )\n    if not parameter_name2dimensionality_specification:\n        # nothing to check if no batch-oriented inputs\n        return None\n    different_dimensionalities_of_parameters = {\n        specification.actual_dimensionality\n        for specification in parameter_name2dimensionality_specification.values()\n    }\n    if dimensionality_reference_property is None:\n        if len(different_dimensionalities_of_parameters) > 1:\n            parameter2dimensionality = {\n                k: e.actual_dimensionality\n                for k, e in parameter_name2dimensionality_specification.items()\n            }\n            raise StepInputDimensionalityError(\n                public_message=f\"Block defining step {step_name} does not define dimensionality reference property, \"\n                f\"which means that all batch-oriented parameters must be at the same dimensionality level, \"\n                f\"but detected the following dimensionalities for parameters {parameter2dimensionality}\",\n                context=\"workflow_compilation | execution_graph_construction | denoting_step_inputs_dimensionality\",\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=step_name,\n                        block_type=step_type,\n                        block_details=f\"Dimensionality of input parameters doesn't match: {parameter2dimensionality}\",\n                    )\n                ],\n            )\n        return None\n    reference_specification = parameter_name2dimensionality_specification[\n        dimensionality_reference_property\n    ]\n    expected_dimensionalities = {\n        property_name: (e.expected_offset - reference_specification.expected_offset)\n        + reference_specification.actual_dimensionality\n        for property_name, e in parameter_name2dimensionality_specification.items()\n    }\n    if any(dim <= 0 for dim in expected_dimensionalities.values()):\n        raise StepInputDimensionalityError(\n            public_message=f\"Given the definition of block defining step {step_name} and data provided, \"\n            f\"the block would expect batch input dimensionality to be 0 or below, which is invalid.\",\n            context=\"workflow_compilation | execution_graph_construction | denoting_step_inputs_dimensionality\",\n        )\n    for property_name, expected_dimensionality in expected_dimensionalities.items():\n        actual_dimensionality = parameter_name2dimensionality_specification[\n            property_name\n        ].actual_dimensionality\n        if actual_dimensionality != expected_dimensionality:\n            raise StepInputDimensionalityError(\n                public_message=f\"Data fed into step `{step_name}` property `{property_name}` has \"\n                f\"actual dimensionality {actual_dimensionality}, \"\n                f\"when expected was {expected_dimensionality}\",\n                context=\"workflow_compilation | execution_graph_construction | denoting_step_inputs_dimensionality\",\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=step_name,\n                        block_type=step_type,\n                        property_name=property_name,\n                        property_details=f\"Expected dimensionality {expected_dimensionality}, but received dimensionality {actual_dimensionality}\",\n                    )\n                ],\n            )\n    return None\n\n\ndef grab_input_data_dimensionality_specifications(\n    step_name: str,\n    inputs_dimensionalities: Dict[str, Set[int]],\n    dimensionality_offstes: Dict[str, int],\n) -> Dict[str, InputDimensionalitySpecification]:\n    result = {}\n    for parameter_name, dimensionality in inputs_dimensionalities.items():\n        parameter_offset = dimensionality_offstes.get(parameter_name, 0)\n        non_zero_dimensionalities_for_parameter = {d for d in dimensionality if d > 0}\n        if len(non_zero_dimensionalities_for_parameter) > 1:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler for step: `{step_name}` and parameter: {parameter_name}\"\n                f\"found multiple different values of actual input dimensionalities: \"\n                f\"`{non_zero_dimensionalities_for_parameter}` which should be detected and addresses \"\n                f\"at earlier stages of compilation.\"\n                f\"This is most likely the bug. Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n            )\n        if non_zero_dimensionalities_for_parameter:\n            actual_dimensionality = next(iter(non_zero_dimensionalities_for_parameter))\n            result[parameter_name] = InputDimensionalitySpecification(\n                actual_dimensionality=actual_dimensionality,\n                expected_offset=parameter_offset,\n            )\n    return result\n\n\ndef verify_compatibility_of_input_data_lineage_with_control_flow_lineage(\n    step_name: str,\n    inputs_lineage: List[List[str]],\n    control_flow_steps_selectors: List[str],\n    execution_graph: DiGraph,\n) -> None:\n    \"\"\"\n    Ensure control flow steps' data lineage is compatible with the step's inputs.\n\n    Control flow steps that affect this step must operate on data that is\n    compatible with the data fed to the step; otherwise the step could never\n    execute. Compares unique control flow lineages against input lineage\n    prefixes and raises ControlFlowDefinitionError if any control flow lineage\n    is not covered by the inputs.\n\n    If inputs_lineage is empty, there is no sense to verify compatibility. The lineage of the\n    step should be established based on the control flow lineages.\n\n    Args:\n        step_name: Name of the step being verified (used in error messages).\n        inputs_lineage: Data lineages derived from the step's input data.\n        control_flow_steps_selectors: Step selectors of control flow steps\n            that affect this step's execution.\n        execution_graph: The workflow execution graph.\n\n    Raises:\n        ControlFlowDefinitionError: When a control flow step's lineage is not\n            compatible with the step's input lineage (step would never execute).\n    \"\"\"\n    (\n        batch_oriented_control_flow_lineages,\n        lineage_id2control_flow_steps,\n    ) = _collect_unique_control_flow_lineages_with_step_mapping(\n        control_flow_steps_selectors=control_flow_steps_selectors,\n        execution_graph=execution_graph,\n    )\n    if not inputs_lineage:\n        return\n\n    all_input_lineage_prefixes = get_all_batch_lineage_prefixes(lineages=inputs_lineage)\n    all_input_lineage_prefixes_hashes = {\n        identify_lineage(lineage=lineage) for lineage in all_input_lineage_prefixes\n    }\n    for control_flow_lineage in batch_oriented_control_flow_lineages:\n        control_flow_lineage_id = identify_lineage(lineage=control_flow_lineage)\n        if control_flow_lineage_id not in all_input_lineage_prefixes_hashes:\n            problematic_flow_control_steps = lineage_id2control_flow_steps[\n                control_flow_lineage_id\n            ]\n            raise ControlFlowDefinitionError(\n                public_message=f\"Step {step_name} execution is impacted by control flow outcome of the following \"\n                f\"steps {problematic_flow_control_steps} which make decision based on data that is \"\n                f\"not compatible with data fed to the step {step_name} - which would cause the step \"\n                f\"to never execute. This behaviour is invalid and prevented upfront by Workflows compiler.\",\n                context=\"workflow_compilation | execution_graph_construction | verification_of_control_flow_lineage\",\n            )\n\n\ndef get_all_batch_lineage_prefixes(lineages: List[List[str]]) -> List[List[str]]:\n    result = []\n    already_spotted = set()\n    for lineage in lineages:\n        lineage_prefixes = get_batch_lineage_prefixes(lineage=lineage)\n        for lineage_prefix in lineage_prefixes:\n            lineage_prefix_id = identify_lineage(lineage=lineage_prefix)\n            if lineage_prefix_id not in already_spotted:\n                already_spotted.add(lineage_prefix_id)\n                result.append(lineage_prefix)\n    return result\n\n\ndef get_batch_lineage_prefixes(lineage: List[str]) -> List[List[str]]:\n    if not lineage:\n        return []\n    result = []\n    prefix = []\n    for i in range(len(lineage)):\n        prefix.append(lineage[i])\n        result.append(copy(prefix))\n    return result\n\n\ndef get_inputs_dimensionalities(\n    step_name: str,\n    step_type: str,\n    input_data: StepInputData,\n    scalar_parameters_to_be_batched: Set[str],\n    input_dimensionality_offsets: Dict[str, int],\n) -> Dict[str, Set[int]]:\n    result = defaultdict(set)\n    dimensionalities_spotted = set()\n    offset_parameters = {\n        parameter: value\n        for parameter, value in input_dimensionality_offsets.items()\n        if value > 0\n    }\n    non_offset_parameters_dimensionality_values = set()\n    for property_name, input_definition in input_data.items():\n        if property_name in offset_parameters:\n            continue\n        if input_definition.is_compound_input():\n            for value in input_definition.iterate_through_definitions():\n                if value.is_batch_oriented():\n                    non_offset_parameters_dimensionality_values.add(\n                        value.get_dimensionality()\n                    )\n        elif input_definition.is_batch_oriented():\n            non_offset_parameters_dimensionality_values.add(\n                input_definition.get_dimensionality()\n            )\n    if len(non_offset_parameters_dimensionality_values) > 1:\n        raise StepInputDimensionalityError(\n            public_message=f\"For step {step_name} attempted to plug input data that are in different dimensions, \"\n            f\"whereas block defines the inputs to be equal in that terms.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_input_data\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=step_name,\n                    block_type=step_type,\n                    block_details=f\"Dimensionality of input parameters differs by more than 1. Detected dimensions: {dict(result)}\",\n                )\n            ],\n        )\n    non_offset_parameters_dimensionality_value = (\n        non_offset_parameters_dimensionality_values.pop()\n        if len(non_offset_parameters_dimensionality_values) > 0\n        else 1\n    )\n    for property_name, input_definition in input_data.items():\n        if input_definition.is_compound_input():\n            result[property_name] = get_compound_input_dimensionality(\n                step_name=step_name,\n                step_type=step_type,\n                property_name=property_name,\n                input_definition=input_definition,\n                scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n                non_offset_parameters_dimensionality_value=non_offset_parameters_dimensionality_value,\n                offset_parameters=offset_parameters,\n            )\n        else:\n            if property_name in scalar_parameters_to_be_batched:\n                if property_name not in offset_parameters:\n                    result[property_name] = {non_offset_parameters_dimensionality_value}\n                else:\n                    result[property_name] = (\n                        non_offset_parameters_dimensionality_value\n                        + offset_parameters[property_name]\n                    )\n            else:\n                result[property_name] = {input_definition.get_dimensionality()}\n        dimensionalities_spotted.update(result[property_name])\n    non_zero_dimensionalities_spotted = {d for d in dimensionalities_spotted if d != 0}\n    if len(non_zero_dimensionalities_spotted) > 0:\n        min_dim, max_dim = min(non_zero_dimensionalities_spotted), max(\n            non_zero_dimensionalities_spotted\n        )\n        if abs(max_dim - min_dim) > 1:\n            raise StepInputDimensionalityError(\n                public_message=f\"For step {step_name} attempted to plug input data differing in dimensionality more than 1\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_input_data\",\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=step_name,\n                        block_type=step_type,\n                        block_details=f\"Dimensionality of input parameters differs by more than 1. Detected dimensions: {dict(result)}\",\n                    )\n                ],\n            )\n    return result\n\n\ndef get_compound_input_dimensionality(\n    step_name: str,\n    property_name: str,\n    step_type: str,\n    input_definition: CompoundStepInputDefinition,\n    scalar_parameters_to_be_batched: Set[str],\n    offset_parameters: Dict[str, int],\n    non_offset_parameters_dimensionality_value: int,\n) -> Set[int]:\n    dimensionalities_spotted = set()\n    for definition in input_definition.iterate_through_definitions():\n        if (\n            property_name not in scalar_parameters_to_be_batched\n            or definition.is_batch_oriented()\n        ):\n            dimensionalities_spotted.add(definition.get_dimensionality())\n        elif property_name not in offset_parameters:\n            dimensionalities_spotted.add(non_offset_parameters_dimensionality_value)\n        else:\n            dimensionalities_spotted.add(\n                non_offset_parameters_dimensionality_value\n                + offset_parameters[property_name]\n            )\n    non_zero_dimensionalities = {e for e in dimensionalities_spotted if e != 0}\n    if len(non_zero_dimensionalities) > 1:\n        raise StepInputDimensionalityError(\n            public_message=f\"While evaluating compound property {property_name} of step {step_name}, \"\n            f\"detected multiple inputs of differing batch dimensionalities: {non_zero_dimensionalities}\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_input_data\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=step_name,\n                    block_type=step_type,\n                    property_name=property_name,\n                    property_details=f\"Detected multiple inputs of differing batch dimensionalities: {non_zero_dimensionalities}\",\n                )\n            ],\n        )\n    return dimensionalities_spotted\n\n\ndef grab_parameters_defining_batch_inputs(\n    inputs_dimensionalities: Dict[str, Set[int]],\n) -> Set[str]:\n    result = set()\n    for paremeter, dimensionalities in inputs_dimensionalities.items():\n        batch_dimensionalities = {d for d in dimensionalities if d > 0}\n        if len(batch_dimensionalities):\n            result.add(paremeter)\n    return result\n\n\ndef retrieve_batch_compatibility_of_input_selectors(\n    input_selectors: List[ParsedSelector],\n) -> Dict[str, Set[bool]]:\n    batch_compatibility_of_properties = defaultdict(set)\n    for parsed_selector in input_selectors:\n        for reference in parsed_selector.definition.allowed_references:\n            batch_compatibility_of_properties[\n                parsed_selector.definition.property_name\n            ].update(reference.points_to_batch)\n    return batch_compatibility_of_properties\n\n\ndef verify_declared_batch_compatibility_against_actual_inputs(\n    node: str,\n    step_node_data: StepNode,\n    input_data: StepInputData,\n    batch_compatibility_of_properties: Dict[str, Set[bool]],\n) -> Set[str]:\n    scalar_parameters_to_be_batched = set()\n    parameters_accepting_batches_and_scalars = set(\n        step_node_data.step_manifest.get_parameters_accepting_batches_and_scalars()\n    )\n    hardcoded_inputs_to_be_batch_compatible = set(\n        step_node_data.step_manifest.get_parameters_enforcing_auto_batch_casting()\n        + step_node_data.step_manifest.get_parameters_accepting_batches()\n    )\n    for property_name, input_definition in input_data.items():\n        if property_name not in batch_compatibility_of_properties:\n            actual_input_is_batch = {False}\n            if property_name in parameters_accepting_batches_and_scalars:\n                batch_compatibility = {True, False}\n            elif property_name in hardcoded_inputs_to_be_batch_compatible:\n                batch_compatibility = {True}\n            else:\n                continue\n        elif input_definition.is_compound_input():\n            actual_input_is_batch = {\n                element.is_batch_oriented()\n                for element in input_definition.iterate_through_definitions()\n            }\n            batch_compatibility = batch_compatibility_of_properties[property_name]\n        else:\n            actual_input_is_batch = {input_definition.is_batch_oriented()}\n            batch_compatibility = batch_compatibility_of_properties[property_name]\n        step_accepts_batch_input = step_node_data.step_manifest.accepts_batch_input()\n        if (\n            step_accepts_batch_input\n            and batch_compatibility == {False}\n            and True in actual_input_is_batch\n        ):\n            raise ExecutionGraphStructureError(\n                public_message=f\"Detected invalid reference plugged \"\n                f\"into property `{property_name}` of step `{node}` - the step \"\n                f\"property do not accept batch-oriented inputs, yet the input selector \"\n                f\"holds one - this indicates the problem with \"\n                f\"construction of your Workflow - usually the problem occurs when non-batch oriented \"\n                f\"step inputs are filled with outputs of batch-oriented steps or batch-oriented inputs.\",\n                context=\"workflow_compilation | execution_graph_construction\",\n            )\n        if batch_compatibility == {True} and False in actual_input_is_batch:\n            scalar_parameters_to_be_batched.add(property_name)\n    return scalar_parameters_to_be_batched\n\n\ndef get_input_data_lineage_excluding_auto_batch_casting(\n    step_name: str,\n    input_data: StepInputData,\n    scalar_parameters_to_be_batched: Set[str],\n) -> List[List[str]]:\n    lineage_deduplication_set = set()\n    lineages = []\n    for property_name, input_definition in input_data.items():\n        new_lineages_detected_within_property_data = get_lineage_for_input_property(\n            step_name=step_name,\n            property_name=property_name,\n            input_definition=input_definition,\n            lineage_deduplication_set=lineage_deduplication_set,\n        )\n        if (\n            property_name in scalar_parameters_to_be_batched\n            and len(new_lineages_detected_within_property_data) == 0\n        ):\n            continue\n        lineages.extend(new_lineages_detected_within_property_data)\n    if not lineages:\n        return lineages\n    verify_lineages(step_name=step_name, detected_lineages=lineages)\n    return lineages\n\n\ndef get_lineage_support_for_auto_batch_casted_parameters(\n    input_dimensionalities: Dict[str, Set[int]],\n    scalar_parameters_to_be_batched: Set[str],\n    all_lineages_of_batch_parameters: List[List[str]],\n) -> Dict[str, AutoBatchCastingConfig]:\n    longest_lineage_support = find_longest_lineage_support(\n        all_lineages_of_batch_parameters=all_lineages_of_batch_parameters,\n    )\n    result = {}\n    for parameter_name in scalar_parameters_to_be_batched:\n        parameter_dimensionality = max(input_dimensionalities[parameter_name])\n        if longest_lineage_support is None:\n            lineage_support = None\n        else:\n            lineage_support = longest_lineage_support[:parameter_dimensionality]\n        result[parameter_name] = AutoBatchCastingConfig(\n            casted_dimensionality=parameter_dimensionality,\n            lineage_support=lineage_support,\n        )\n    return result\n\n\ndef find_longest_lineage_support(\n    all_lineages_of_batch_parameters: List[List[str]],\n) -> Optional[List[str]]:\n    longest_longest_lineage_support = []\n    for lineage in all_lineages_of_batch_parameters:\n        if len(lineage) > len(longest_longest_lineage_support):\n            longest_longest_lineage_support = lineage\n    if len(longest_longest_lineage_support) == 0:\n        return None\n    return longest_longest_lineage_support\n\n\ndef get_lineage_for_input_property(\n    step_name: str,\n    property_name: str,\n    input_definition: Union[StepInputDefinition, CompoundStepInputDefinition],\n    lineage_deduplication_set: Set[int],\n) -> List[List[str]]:\n    if input_definition.is_compound_input():\n        return get_lineage_from_compound_input(\n            step_name=step_name,\n            property_name=property_name,\n            input_definition=input_definition,\n            lineage_deduplication_set=lineage_deduplication_set,\n        )\n    lineages = []\n    if input_definition.is_batch_oriented():\n        lineage = input_definition.data_lineage\n        lineage_id = identify_lineage(lineage=lineage)\n        if lineage_id not in lineage_deduplication_set:\n            lineage_deduplication_set.add(lineage_id)\n            lineages.append(lineage)\n    return lineages\n\n\ndef get_lineage_from_compound_input(\n    step_name: str,\n    property_name: str,\n    input_definition: Union[StepInputDefinition, CompoundStepInputDefinition],\n    lineage_deduplication_set: Set[int],\n) -> List[List[str]]:\n    lineages = []\n    for nested_element in input_definition.iterate_through_definitions():\n        if nested_element.is_batch_oriented():\n            lineage = nested_element.data_lineage\n            lineage_id = identify_lineage(lineage=lineage)\n            if lineage_id not in lineage_deduplication_set:\n                lineage_deduplication_set.add(lineage_id)\n                lineages.append(lineage)\n    if len(lineages) > 1:\n        raise StepInputLineageError(\n            public_message=f\"Input data provided for step: `{step_name}` comes with multiple different lineages \"\n            f\"{lineages} for property `{property_name}` accepting \"\n            f\"multiple selectors, which is not allowed.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    return lineages\n\n\ndef verify_lineages(step_name: str, detected_lineages: List[List[str]]) -> None:\n    lineages_by_length = defaultdict(list)\n    for lineage in detected_lineages:\n        lineages_by_length[len(lineage)].append(lineage)\n    if len(lineages_by_length) > 2:\n        raise StepInputLineageError(\n            public_message=f\"Input data provided for step: `{step_name}` comes with lineages at more than two \"\n            f\"dimensionality levels, which should not be possible.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    lineage_lengths = sorted(lineages_by_length.keys())\n    for lineage_length in lineage_lengths:\n        if len(lineages_by_length[lineage_length]) > 1:\n            raise StepInputLineageError(\n                public_message=f\"Among step `{step_name}` inputs found different lineages at the same  \"\n                f\"dimensionality levels dimensionality.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if len(lineages_by_length[lineage_lengths[-1]]) > 1 and len(lineage_lengths) < 2:\n        raise StepInputLineageError(\n            public_message=f\"If lineage differ at the last level, then Execution Engine requires at least one \"\n            f\"higher-dimension  input that will come with common lineage, but this is not the \"\n            f\"case for step {step_name}.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    if len(lineage_lengths) == 2:\n        reference_lineage = lineages_by_length[lineage_lengths[0]][0]\n        if reference_lineage != lineages_by_length[lineage_lengths[1]][0][:-1]:\n            raise StepInputLineageError(\n                public_message=f\"Step `{step_name}` inputs does not share common lineage. Differing element: \"\n                f\"{lineages_by_length[lineage_lengths[1]][0]}, \"\n                f\"reference lineage prefix: {reference_lineage}\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n\n\ndef establish_step_execution_dimensionality(\n    inputs_dimensionalities: Dict[str, Set[int]],\n    control_flow_lineage_support: List[str],\n    output_dimensionality_offset: int,\n) -> int:\n    \"\"\"\n    Determine how many batch dimensions (execution slices) a step runs with.\n\n    Used during workflow compilation in denote_data_flow_for_step. The result\n    is stored on StepNode.step_execution_dimensionality and consumed at\n    execution time to:\n    - Drive how many times the step is executed (which batch indices/slices).\n    - Align and expand inputs (e.g. auto-batch casting) to match this size.\n    - Validate that parameter dimensionalities are compatible (runtime checks\n      in step_input_assembler and manager).\n\n    Logic:\n    - If no input has non-zero dimensionality but the step is gated by\n      control flow (control_flow_lineage_support non-empty), the\n      dimensionality is the number of control-flow branches.\n    - Otherwise, the minimum non-zero input dimensionality is used; if\n      output_dimensionality_offset < 0 (step reduces batch dimension),\n      one is subtracted.\n\n    Args:\n        inputs_dimensionalities: Per-input sets of dimensionalities (from\n            get_inputs_dimensionalities).\n        control_flow_lineage_support: Lineage identifiers for control-flow\n            branches that gate this step (from establish_batch_oriented_step_lineage).\n        output_dimensionality_offset: Block's output dimensionality offset\n            (positive = expand, negative = reduce batch dimension).\n\n    Returns:\n        The number of batch dimensions (execution slices) for this step.\n    \"\"\"\n    step_execution_dimensionality = 0\n    non_zero_dimensionalities = {\n        dimensionality\n        for dimensionalities in inputs_dimensionalities.values()\n        for dimensionality in dimensionalities\n        if dimensionality > 0\n    }\n    if len(non_zero_dimensionalities) == 0 and len(control_flow_lineage_support) > 0:\n        return len(control_flow_lineage_support)\n    if len(non_zero_dimensionalities) > 0:\n        step_execution_dimensionality = min(non_zero_dimensionalities)\n        if output_dimensionality_offset < 0:\n            step_execution_dimensionality -= 1\n    return step_execution_dimensionality\n\n\ndef establish_batch_oriented_step_lineage(\n    step_selector: str,\n    all_data_derived_lineages: List[List[str]],\n    all_control_flow_lineages: List[List[str]],\n    input_data: StepInputData,\n    dimensionality_reference_property: Optional[str],\n    output_dimensionality_offset: int,\n) -> Tuple[List[str], List[str]]:\n    reference_lineage, control_flow_lineage_support = get_reference_lineage(\n        step_selector=step_selector,\n        all_data_derived_lineages=all_data_derived_lineages,\n        all_control_flow_lineages=all_control_flow_lineages,\n        input_data=input_data,\n        dimensionality_reference_property=dimensionality_reference_property,\n    )\n    if output_dimensionality_offset < 0:\n        result_dimensionality = reference_lineage[:output_dimensionality_offset]\n        return result_dimensionality, []\n    if output_dimensionality_offset == 0:\n        return reference_lineage, control_flow_lineage_support\n    reference_lineage.append(step_selector)\n    return reference_lineage, []\n\n\ndef get_reference_lineage(\n    step_selector: str,\n    all_data_derived_lineages: List[List[str]],\n    all_control_flow_lineages: List[List[str]],\n    input_data: StepInputData,\n    dimensionality_reference_property: Optional[str],\n) -> Tuple[List[str], List[str]]:\n    if not all_data_derived_lineages:\n        if len(all_control_flow_lineages) == 1:\n            return copy(all_control_flow_lineages[0]), copy(\n                all_control_flow_lineages[0]\n            )\n        # Multiple control-flow lineages and no data-derived lineage: pick the deepest.\n        max_lineage_len = max(len(lineage) for lineage in all_control_flow_lineages)\n        lineages_matching_max_len = [\n            _lineage\n            for _lineage in all_control_flow_lineages\n            if len(_lineage) == max_lineage_len\n        ]\n        if len(lineages_matching_max_len) == 1:\n            return copy(lineages_matching_max_len[0]), copy(\n                lineages_matching_max_len[0]\n            )\n        else:\n            raise AssumptionError(\n                public_message=f\"Multiple control-flow lineages at the same level for step `{step_selector}` \"\n                f\"and no data-derived lineage; unique lineage level required. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if len(all_data_derived_lineages) == 1:\n        return copy(all_data_derived_lineages[0]), []\n    if dimensionality_reference_property not in input_data:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` expected dimensionality_reference_property \"\n            f\"presence to be verified at earlier stages, which did not happen as expected. \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    property_data = input_data[dimensionality_reference_property]\n    if property_data.is_compound_input():\n        lineage = None\n        for nested_element in property_data.iterate_through_definitions():\n            if nested_element.is_batch_oriented():\n                lineage = copy(nested_element.data_lineage)\n                return lineage, []\n        if lineage is None:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n                f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if not property_data.is_batch_oriented():\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n            f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    return copy(property_data.data_lineage), []\n\n\ndef get_property_with_invalid_selector(\n    manifest: WorkflowBlockManifest, step_property: str\n) -> Optional[str]:\n    property_name = None\n    for key, value in manifest.__dict__.items():\n        if isinstance(value, str) and step_property in value:\n            property_name = key\n            break\n    return property_name\n\n\ndef add_super_input_node_in_execution_graph(\n    execution_graph: DiGraph,\n    super_input_node: str,\n) -> DiGraph:\n    nodes_to_attach_super_input_into = get_nodes_of_specific_category(\n        execution_graph=execution_graph,\n        category=NodeCategory.INPUT_NODE,\n    )\n    step_nodes_without_predecessors = [\n        node\n        for node in execution_graph.nodes\n        if not list(execution_graph.predecessors(node))\n    ]\n    nodes_to_attach_super_input_into.update(step_nodes_without_predecessors)\n    execution_graph.add_node(super_input_node)\n    for node in nodes_to_attach_super_input_into:\n        execution_graph.add_edge(super_input_node, node)\n    return execution_graph\n",
    "patch": null
  },
  {
    "trace_id": "5779b128-2cab-4bc0-804d-3bf40871ee8c",
    "function_name": "verify_compatibility_of_input_data_lineage_with_control_flow_lineage",
    "file_path": "inference/core/workflows/execution_engine/v1/compiler/graph_constructor.py",
    "speedup_x": 1.1129910869973443,
    "review_quality": "high",
    "pre_optimization_commit": "90243bdc6278ef7d17b6db09dc1eb5b0d155b4be",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def verify_compatibility_of_input_data_lineage_with_control_flow_lineage(\n    step_name: str,\n    inputs_lineage: List[List[str]],\n    control_flow_steps_selectors: List[str],\n    execution_graph: DiGraph,\n) -> None:\n    \"\"\"\n    Ensure control flow steps' data lineage is compatible with the step's inputs.\n\n    Control flow steps that affect this step must operate on data that is\n    compatible with the data fed to the step; otherwise the step could never\n    execute. Compares unique control flow lineages against input lineage\n    prefixes and raises ControlFlowDefinitionError if any control flow lineage\n    is not covered by the inputs.\n\n    If inputs_lineage is empty, there is no sense to verify compatibility. The lineage of the\n    step should be established based on the control flow lineages.\n\n    Args:\n        step_name: Name of the step being verified (used in error messages).\n        inputs_lineage: Data lineages derived from the step's input data.\n        control_flow_steps_selectors: Step selectors of control flow steps\n            that affect this step's execution.\n        execution_graph: The workflow execution graph.\n\n    Raises:\n        ControlFlowDefinitionError: When a control flow step's lineage is not\n            compatible with the step's input lineage (step would never execute).\n    \"\"\"\n    (\n        batch_oriented_control_flow_lineages,\n        lineage_id2control_flow_steps,\n    ) = _collect_unique_control_flow_lineages_with_step_mapping(\n        control_flow_steps_selectors=control_flow_steps_selectors,\n        execution_graph=execution_graph,\n    )\n    if not inputs_lineage:\n        return\n\n    all_input_lineage_prefixes = get_all_batch_lineage_prefixes(lineages=inputs_lineage)\n    all_input_lineage_prefixes_hashes = {\n        identify_lineage(lineage=lineage) for lineage in all_input_lineage_prefixes\n    }\n    for control_flow_lineage in batch_oriented_control_flow_lineages:\n        control_flow_lineage_id = identify_lineage(lineage=control_flow_lineage)\n        if control_flow_lineage_id not in all_input_lineage_prefixes_hashes:\n            problematic_flow_control_steps = lineage_id2control_flow_steps[\n                control_flow_lineage_id\n            ]\n            raise ControlFlowDefinitionError(\n                public_message=f\"Step {step_name} execution is impacted by control flow outcome of the following \"\n                f\"steps {problematic_flow_control_steps} which make decision based on data that is \"\n                f\"not compatible with data fed to the step {step_name} - which would cause the step \"\n                f\"to never execute. This behaviour is invalid and prevented upfront by Workflows compiler.\",\n                context=\"workflow_compilation | execution_graph_construction | verification_of_control_flow_lineage\",\n            )\n",
    "optimized_function_code": "from collections import defaultdict\nfrom typing import Dict, List, Set, Tuple\n\nimport networkx as nx\nfrom inference.core.workflows.errors import ControlFlowDefinitionError\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import \\\n    StepNode\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import (\n    identify_lineage, node_as)\nfrom networkx import DiGraph\n\n\ndef _collect_unique_control_flow_lineages_with_step_mapping(\n    control_flow_steps_selectors: List[str],\n    execution_graph: nx.DiGraph,\n) -> Tuple[List[List[str]], Dict[int, List[str]]]:\n    \"\"\"\n    Collect data lineages from control flow steps and deduplicate by lineage id.\n\n    For each given control flow step selector, reads its data_lineage from the\n    execution graph. Returns unique non-empty lineages (by identify_lineage id)\n    and a mapping from lineage id to every step selector that produced that\n    lineage (used e.g. for error reporting when lineage is incompatible).\n\n    Args:\n        control_flow_steps_selectors: Step selectors (node ids) of control\n            flow steps whose data_lineage is to be collected.\n        execution_graph: The workflow execution graph containing step nodes\n            and their data_lineage.\n\n    Returns:\n        A tuple of (unique_lineages, lineage_id_to_step_selectors):\n        - unique_lineages: list of distinct non-empty data lineages.\n        - lineage_id_to_step_selectors: map from lineage id to list of step\n          selectors whose data_lineage has that id (includes empty lineages).\n    \"\"\"\n    unique_lineages: List[List[str]] = []\n    seen_lineage_ids: Set[int] = set()\n    lineage_id_to_step_selectors: Dict[int, List[str]] = defaultdict(list)\n\n    for step_selector in control_flow_steps_selectors:\n        step_data = node_as(\n            execution_graph=execution_graph,\n            node=step_selector,\n            expected_type=StepNode,\n        )\n        lineage = step_data.data_lineage\n        lineage_id = identify_lineage(lineage)\n        lineage_id_to_step_selectors[lineage_id].append(step_selector)\n        if lineage and lineage_id not in seen_lineage_ids:\n            seen_lineage_ids.add(lineage_id)\n            unique_lineages.append(lineage)\n\n    return unique_lineages, dict(lineage_id_to_step_selectors)\n\n\ndef verify_compatibility_of_input_data_lineage_with_control_flow_lineage(\n    step_name: str,\n    inputs_lineage: List[List[str]],\n    control_flow_steps_selectors: List[str],\n    execution_graph: DiGraph,\n) -> None:\n    \"\"\"\n    Ensure control flow steps' data lineage is compatible with the step's inputs.\n\n    Control flow steps that affect this step must operate on data that is\n    compatible with the data fed to the step; otherwise the step could never\n    execute. Compares unique control flow lineages against input lineage\n    prefixes and raises ControlFlowDefinitionError if any control flow lineage\n    is not covered by the inputs.\n\n    If inputs_lineage is empty, there is no sense to verify compatibility. The lineage of the\n    step should be established based on the control flow lineages.\n\n    Args:\n        step_name: Name of the step being verified (used in error messages).\n        inputs_lineage: Data lineages derived from the step's input data.\n        control_flow_steps_selectors: Step selectors of control flow steps\n            that affect this step's execution.\n        execution_graph: The workflow execution graph.\n\n    Raises:\n        ControlFlowDefinitionError: When a control flow step's lineage is not\n            compatible with the step's input lineage (step would never execute).\n    \"\"\"\n    if not inputs_lineage:\n        return\n\n    (\n        batch_oriented_control_flow_lineages,\n        lineage_id2control_flow_steps,\n    ) = _collect_unique_control_flow_lineages_with_step_mapping(\n        control_flow_steps_selectors=control_flow_steps_selectors,\n        execution_graph=execution_graph,\n    )\n\n    all_input_lineage_prefixes_hashes = set()\n    for lineage in inputs_lineage:\n        prefix_hash = 0\n        for element in lineage:\n            prefix_hash += hash(element)\n            all_input_lineage_prefixes_hashes.add(prefix_hash)\n\n    for control_flow_lineage in batch_oriented_control_flow_lineages:\n        control_flow_lineage_id = identify_lineage(lineage=control_flow_lineage)\n        if control_flow_lineage_id not in all_input_lineage_prefixes_hashes:\n            problematic_flow_control_steps = lineage_id2control_flow_steps[\n                control_flow_lineage_id\n            ]\n            raise ControlFlowDefinitionError(\n                public_message=f\"Step {step_name} execution is impacted by control flow outcome of the following \"\n                f\"steps {problematic_flow_control_steps} which make decision based on data that is \"\n                f\"not compatible with data fed to the step {step_name} - which would cause the step \"\n                f\"to never execute. This behaviour is invalid and prevented upfront by Workflows compiler.\",\n                context=\"workflow_compilation | execution_graph_construction | verification_of_control_flow_lineage\",\n            )\n\n\ndef get_all_batch_lineage_prefixes(lineages: List[List[str]]) -> List[List[str]]:\n    result = []\n    already_spotted = set()\n    for lineage in lineages:\n        prefix = []\n        prefix_hash = 0\n        for element in lineage:\n            prefix.append(element)\n            prefix_hash += hash(element)\n            if prefix_hash not in already_spotted:\n                already_spotted.add(prefix_hash)\n                result.append(prefix[:])\n    return result",
    "optimized_raw_markdown": "```python:inference/core/workflows/execution_engine/v1/compiler/graph_constructor.py\nfrom collections import defaultdict\nfrom typing import Dict, List, Set, Tuple\n\nimport networkx as nx\nfrom inference.core.workflows.errors import ControlFlowDefinitionError\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import \\\n    StepNode\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import (\n    identify_lineage, node_as)\nfrom networkx import DiGraph\n\n\ndef _collect_unique_control_flow_lineages_with_step_mapping(\n    control_flow_steps_selectors: List[str],\n    execution_graph: nx.DiGraph,\n) -> Tuple[List[List[str]], Dict[int, List[str]]]:\n    \"\"\"\n    Collect data lineages from control flow steps and deduplicate by lineage id.\n\n    For each given control flow step selector, reads its data_lineage from the\n    execution graph. Returns unique non-empty lineages (by identify_lineage id)\n    and a mapping from lineage id to every step selector that produced that\n    lineage (used e.g. for error reporting when lineage is incompatible).\n\n    Args:\n        control_flow_steps_selectors: Step selectors (node ids) of control\n            flow steps whose data_lineage is to be collected.\n        execution_graph: The workflow execution graph containing step nodes\n            and their data_lineage.\n\n    Returns:\n        A tuple of (unique_lineages, lineage_id_to_step_selectors):\n        - unique_lineages: list of distinct non-empty data lineages.\n        - lineage_id_to_step_selectors: map from lineage id to list of step\n          selectors whose data_lineage has that id (includes empty lineages).\n    \"\"\"\n    unique_lineages: List[List[str]] = []\n    seen_lineage_ids: Set[int] = set()\n    lineage_id_to_step_selectors: Dict[int, List[str]] = defaultdict(list)\n\n    for step_selector in control_flow_steps_selectors:\n        step_data = node_as(\n            execution_graph=execution_graph,\n            node=step_selector,\n            expected_type=StepNode,\n        )\n        lineage = step_data.data_lineage\n        lineage_id = identify_lineage(lineage)\n        lineage_id_to_step_selectors[lineage_id].append(step_selector)\n        if lineage and lineage_id not in seen_lineage_ids:\n            seen_lineage_ids.add(lineage_id)\n            unique_lineages.append(lineage)\n\n    return unique_lineages, dict(lineage_id_to_step_selectors)\n\n\ndef verify_compatibility_of_input_data_lineage_with_control_flow_lineage(\n    step_name: str,\n    inputs_lineage: List[List[str]],\n    control_flow_steps_selectors: List[str],\n    execution_graph: DiGraph,\n) -> None:\n    \"\"\"\n    Ensure control flow steps' data lineage is compatible with the step's inputs.\n\n    Control flow steps that affect this step must operate on data that is\n    compatible with the data fed to the step; otherwise the step could never\n    execute. Compares unique control flow lineages against input lineage\n    prefixes and raises ControlFlowDefinitionError if any control flow lineage\n    is not covered by the inputs.\n\n    If inputs_lineage is empty, there is no sense to verify compatibility. The lineage of the\n    step should be established based on the control flow lineages.\n\n    Args:\n        step_name: Name of the step being verified (used in error messages).\n        inputs_lineage: Data lineages derived from the step's input data.\n        control_flow_steps_selectors: Step selectors of control flow steps\n            that affect this step's execution.\n        execution_graph: The workflow execution graph.\n\n    Raises:\n        ControlFlowDefinitionError: When a control flow step's lineage is not\n            compatible with the step's input lineage (step would never execute).\n    \"\"\"\n    if not inputs_lineage:\n        return\n\n    (\n        batch_oriented_control_flow_lineages,\n        lineage_id2control_flow_steps,\n    ) = _collect_unique_control_flow_lineages_with_step_mapping(\n        control_flow_steps_selectors=control_flow_steps_selectors,\n        execution_graph=execution_graph,\n    )\n\n    all_input_lineage_prefixes_hashes = set()\n    for lineage in inputs_lineage:\n        prefix_hash = 0\n        for element in lineage:\n            prefix_hash += hash(element)\n            all_input_lineage_prefixes_hashes.add(prefix_hash)\n\n    for control_flow_lineage in batch_oriented_control_flow_lineages:\n        control_flow_lineage_id = identify_lineage(lineage=control_flow_lineage)\n        if control_flow_lineage_id not in all_input_lineage_prefixes_hashes:\n            problematic_flow_control_steps = lineage_id2control_flow_steps[\n                control_flow_lineage_id\n            ]\n            raise ControlFlowDefinitionError(\n                public_message=f\"Step {step_name} execution is impacted by control flow outcome of the following \"\n                f\"steps {problematic_flow_control_steps} which make decision based on data that is \"\n                f\"not compatible with data fed to the step {step_name} - which would cause the step \"\n                f\"to never execute. This behaviour is invalid and prevented upfront by Workflows compiler.\",\n                context=\"workflow_compilation | execution_graph_construction | verification_of_control_flow_lineage\",\n            )\n\n\ndef get_all_batch_lineage_prefixes(lineages: List[List[str]]) -> List[List[str]]:\n    result = []\n    already_spotted = set()\n    for lineage in lineages:\n        prefix = []\n        prefix_hash = 0\n        for element in lineage:\n            prefix.append(element)\n            prefix_hash += hash(element)\n            if prefix_hash not in already_spotted:\n                already_spotted.add(prefix_hash)\n                result.append(prefix[:])\n    return result\n```\n```python:inference/core/workflows/execution_engine/v1/compiler/utils.py\nfrom copy import copy\nfrom typing import List\n\n\ndef get_batch_lineage_prefixes(lineage: List[str]) -> List[List[str]]:\n    if not lineage:\n        return []\n    result = []\n    prefix = []\n    for element in lineage:\n        prefix.append(element)\n        result.append(copy(prefix))\n    return result\n```",
    "optimized_function_only": "def verify_compatibility_of_input_data_lineage_with_control_flow_lineage(\n    step_name: str,\n    inputs_lineage: List[List[str]],\n    control_flow_steps_selectors: List[str],\n    execution_graph: DiGraph,\n) -> None:\n    \"\"\"\n    Ensure control flow steps' data lineage is compatible with the step's inputs.\n\n    Control flow steps that affect this step must operate on data that is\n    compatible with the data fed to the step; otherwise the step could never\n    execute. Compares unique control flow lineages against input lineage\n    prefixes and raises ControlFlowDefinitionError if any control flow lineage\n    is not covered by the inputs.\n\n    If inputs_lineage is empty, there is no sense to verify compatibility. The lineage of the\n    step should be established based on the control flow lineages.\n\n    Args:\n        step_name: Name of the step being verified (used in error messages).\n        inputs_lineage: Data lineages derived from the step's input data.\n        control_flow_steps_selectors: Step selectors of control flow steps\n            that affect this step's execution.\n        execution_graph: The workflow execution graph.\n\n    Raises:\n        ControlFlowDefinitionError: When a control flow step's lineage is not\n            compatible with the step's input lineage (step would never execute).\n    \"\"\"\n    if not inputs_lineage:\n        return\n\n    (\n        batch_oriented_control_flow_lineages,\n        lineage_id2control_flow_steps,\n    ) = _collect_unique_control_flow_lineages_with_step_mapping(\n        control_flow_steps_selectors=control_flow_steps_selectors,\n        execution_graph=execution_graph,\n    )\n\n    all_input_lineage_prefixes_hashes = set()\n    for lineage in inputs_lineage:\n        prefix_hash = 0\n        for element in lineage:\n            prefix_hash += hash(element)\n            all_input_lineage_prefixes_hashes.add(prefix_hash)\n\n    for control_flow_lineage in batch_oriented_control_flow_lineages:\n        control_flow_lineage_id = identify_lineage(lineage=control_flow_lineage)\n        if control_flow_lineage_id not in all_input_lineage_prefixes_hashes:\n            problematic_flow_control_steps = lineage_id2control_flow_steps[\n                control_flow_lineage_id\n            ]\n            raise ControlFlowDefinitionError(\n                public_message=f\"Step {step_name} execution is impacted by control flow outcome of the following \"\n                f\"steps {problematic_flow_control_steps} which make decision based on data that is \"\n                f\"not compatible with data fed to the step {step_name} - which would cause the step \"\n                f\"to never execute. This behaviour is invalid and prevented upfront by Workflows compiler.\",\n                context=\"workflow_compilation | execution_graph_construction | verification_of_control_flow_lineage\",\n            )\n",
    "original_file_content": "import itertools\nfrom collections import defaultdict\nfrom copy import copy, deepcopy\nfrom typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union\nfrom uuid import uuid4\n\nimport networkx as nx\nfrom networkx import DiGraph\n\nfrom inference.core import logger\nfrom inference.core.workflows.errors import (\n    AssumptionError,\n    BlockInterfaceError,\n    ControlFlowDefinitionError,\n    ExecutionGraphStructureError,\n    InvalidReferenceTargetError,\n    StepInputDimensionalityError,\n    StepInputLineageError,\n    WorkflowBlockError,\n)\nfrom inference.core.workflows.execution_engine.constants import (\n    NODE_COMPILATION_OUTPUT_PROPERTY,\n    PARSED_NODE_INPUT_SELECTORS_PROPERTY,\n    TOP_LEVEL_LINEAGES_KEY,\n    WORKFLOW_INPUT_BATCH_LINEAGE_ID,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    InputType,\n    JsonField,\n    OutputDefinition,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    STEP_AS_SELECTED_ELEMENT,\n    Kind,\n)\nfrom inference.core.workflows.execution_engine.introspection.entities import (\n    ParsedSelector,\n)\nfrom inference.core.workflows.execution_engine.introspection.selectors_parser import (\n    get_step_selectors,\n)\nfrom inference.core.workflows.execution_engine.profiling.core import (\n    WorkflowsProfiler,\n    execution_phase,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import (\n    AutoBatchCastingConfig,\n    CompoundStepInputDefinition,\n    DictOfStepInputDefinitions,\n    DynamicStepInputDefinition,\n    ExecutionGraphNode,\n    InputDimensionalitySpecification,\n    InputNode,\n    ListOfStepInputDefinitions,\n    NodeCategory,\n    NodeInputCategory,\n    OutputNode,\n    ParameterSpecification,\n    ParsedWorkflowDefinition,\n    PropertyPredecessorDefinition,\n    StaticStepInputDefinition,\n    StepInputData,\n    StepInputDefinition,\n    StepNode,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.graph_traversal import (\n    traverse_graph_ensuring_parents_are_reached_first,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.reference_type_checker import (\n    validate_reference_kinds,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import (\n    construct_input_selector,\n    construct_output_selector,\n    construct_step_selector,\n    get_last_chunk_of_selector,\n    get_nodes_of_specific_category,\n    get_step_selector_from_its_output,\n    identify_lineage,\n    is_control_flow_step,\n    is_input_node,\n    is_input_selector,\n    is_output_node,\n    is_step_node,\n    is_step_output_selector,\n    is_step_selector,\n    node_as,\n)\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nNODE_DEFINITION_KEY = \"definition\"\nSTEP_INPUT_SELECTORS_PROPERTY = \"step_input_selectors\"\nEXCLUDED_FIELDS = {\"type\", \"name\"}\n\n\n@execution_phase(\n    name=\"execution_graph_creation\",\n    categories=[\"execution_engine_operation\"],\n)\ndef prepare_execution_graph(\n    workflow_definition: ParsedWorkflowDefinition,\n    profiler: Optional[WorkflowsProfiler] = None,\n) -> DiGraph:\n    execution_graph = construct_graph(\n        workflow_definition=workflow_definition,\n    )\n    if not nx.is_directed_acyclic_graph(execution_graph):\n        raise ExecutionGraphStructureError(\n            public_message=f\"Detected cycle in execution graph. This means that there is output from one \"\n            f\"step that is connected to input of other step creating loop in the graph that would \"\n            f\"never end if executed.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    return denote_data_flow_in_workflow(\n        execution_graph=execution_graph,\n        parsed_workflow_definition=workflow_definition,\n    )\n\n\ndef construct_graph(\n    workflow_definition: ParsedWorkflowDefinition,\n) -> DiGraph:\n    execution_graph = nx.DiGraph()\n    execution_graph = add_input_nodes_for_graph(\n        inputs=workflow_definition.inputs,\n        execution_graph=execution_graph,\n    )\n    execution_graph = add_steps_nodes_for_graph(\n        steps=workflow_definition.steps,\n        execution_graph=execution_graph,\n    )\n    execution_graph = add_output_nodes_for_graph(\n        outputs=workflow_definition.outputs,\n        execution_graph=execution_graph,\n    )\n    execution_graph = add_steps_edges(\n        workflow_definition=workflow_definition,\n        execution_graph=execution_graph,\n    )\n    return add_edges_for_outputs(\n        workflow_definition=workflow_definition,\n        execution_graph=execution_graph,\n    )\n\n\ndef add_input_nodes_for_graph(\n    inputs: List[InputType],\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for input_spec in inputs:\n        input_selector = construct_input_selector(input_name=input_spec.name)\n        if input_spec.is_batch_oriented():\n            if input_spec.dimensionality < 1:\n                raise ExecutionGraphStructureError(\n                    public_message=f\"Detected batch oriented input `{input_spec.name}` with \"\n                    f\"declared dimensionality `{input_spec.dimensionality}` which is below \"\n                    f\"one (one is minimum dimensionality of the batch). Fix input definition in\"\n                    f\"your Workflow.\",\n                    context=\"workflow_compilation | execution_graph_construction\",\n                )\n            data_lineage = [WORKFLOW_INPUT_BATCH_LINEAGE_ID]\n            for _ in range(input_spec.dimensionality - 1):\n                # TODO: this may end up being a bug - with ability for multi-step debugging, if we will\n                #  ever have a situation that there will be multiple step outputs with nested\n                #  dimensionality with the same lineage, this re-construction method will\n                #  assign a different lineage identifier, causing the inputs being non-composable in\n                #  a single execution branch\n                data_lineage.append(f\"{uuid4()}\")\n        else:\n            data_lineage = []\n        compilation_output = InputNode(\n            node_category=NodeCategory.INPUT_NODE,\n            name=input_spec.name,\n            selector=input_selector,\n            data_lineage=data_lineage,\n            input_manifest=input_spec,\n        )\n        execution_graph.add_node(\n            input_selector,\n            **{\n                NODE_COMPILATION_OUTPUT_PROPERTY: compilation_output,\n            },\n        )\n    return execution_graph\n\n\ndef add_steps_nodes_for_graph(\n    steps: List[WorkflowBlockManifest],\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for step in steps:\n        step_selector = construct_step_selector(step_name=step.name)\n        compilation_output = StepNode(\n            node_category=NodeCategory.STEP_NODE,\n            name=step.name,\n            selector=step_selector,\n            data_lineage=[],\n            step_manifest=step,\n        )\n        execution_graph.add_node(\n            step_selector,\n            **{\n                NODE_COMPILATION_OUTPUT_PROPERTY: compilation_output,\n            },\n        )\n    return execution_graph\n\n\ndef add_output_nodes_for_graph(\n    outputs: List[JsonField],\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for output_spec in outputs:\n        output_selector = construct_output_selector(name=output_spec.name)\n        compilation_output = OutputNode(\n            node_category=NodeCategory.OUTPUT_NODE,\n            name=output_spec.name,\n            selector=output_selector,\n            data_lineage=[],\n            output_manifest=output_spec,\n        )\n        execution_graph.add_node(\n            output_selector,\n            **{\n                NODE_COMPILATION_OUTPUT_PROPERTY: compilation_output,\n            },\n        )\n    return execution_graph\n\n\ndef add_steps_edges(\n    workflow_definition: ParsedWorkflowDefinition,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for step in workflow_definition.steps:\n        source_step_selector = construct_step_selector(step_name=step.name)\n        step_selectors = get_step_selectors(step_manifest=step)\n        execution_graph.nodes[source_step_selector][\n            PARSED_NODE_INPUT_SELECTORS_PROPERTY\n        ] = step_selectors\n        execution_graph = add_edges_for_step(\n            execution_graph=execution_graph,\n            source_step_selector=source_step_selector,\n            target_step_parsed_selectors=step_selectors,\n        )\n    return execution_graph\n\n\ndef add_edges_for_step(\n    execution_graph: DiGraph,\n    source_step_selector: str,\n    target_step_parsed_selectors: List[ParsedSelector],\n) -> DiGraph:\n    for target_step_parsed_selector in target_step_parsed_selectors:\n        execution_graph = add_edge_for_step(\n            execution_graph=execution_graph,\n            source_step_selector=source_step_selector,\n            target_step_parsed_selector=target_step_parsed_selector,\n        )\n    return execution_graph\n\n\ndef add_edge_for_step(\n    execution_graph: DiGraph,\n    source_step_selector: str,\n    target_step_parsed_selector: ParsedSelector,\n) -> DiGraph:\n    target_step_selector = get_step_selector_from_its_output(\n        step_output_selector=target_step_parsed_selector.value\n    )\n    verify_edge_is_created_between_existing_nodes(\n        execution_graph=execution_graph,\n        start=source_step_selector,\n        end=target_step_selector,\n    )\n    if is_step_selector(target_step_parsed_selector.value):\n        return establish_control_flow_edge(\n            source_step_selector=source_step_selector,\n            target_step_parsed_selector=target_step_parsed_selector,\n            execution_graph=execution_graph,\n        )\n    if is_input_selector(target_step_parsed_selector.value):\n        input_node_compilation_data = node_as(\n            execution_graph=execution_graph,\n            node=target_step_parsed_selector.value,\n            expected_type=InputNode,\n        )\n        actual_input_kind = input_node_compilation_data.input_manifest.kind\n    else:\n        other_step_compilation_data = node_as(\n            execution_graph=execution_graph,\n            node=target_step_selector,\n            expected_type=StepNode,\n        )\n        source_step_compilation_data = node_as(\n            execution_graph=execution_graph,\n            node=source_step_selector,\n            expected_type=StepNode,\n        )\n        actual_input_kind = get_kind_of_value_provided_in_step_output(\n            step_manifest=other_step_compilation_data.step_manifest,\n            step_property=get_last_chunk_of_selector(\n                selector=target_step_parsed_selector.value\n            ),\n            source_step_manifest=source_step_compilation_data.step_manifest,\n        )\n    expected_input_kind = list(\n        itertools.chain.from_iterable(\n            ref.kind\n            for ref in target_step_parsed_selector.definition.allowed_references\n        )\n    )\n    error_message = (\n        f\"Failed to validate reference provided for step: {source_step_selector} regarding property: \"\n        f\"{target_step_parsed_selector.definition.property_name} with value: {target_step_parsed_selector.value}. \"\n        f\"Allowed kinds of references for this property: {list(set(e.name for e in expected_input_kind))}. \"\n        f\"Types of output for referred property: \"\n        f\"{list(set(a.name if isinstance(a, Kind) else a for a in actual_input_kind))}\"\n    )\n    validate_reference_kinds(\n        expected=expected_input_kind,\n        actual=actual_input_kind,\n        error_message=error_message,\n    )\n    if execution_graph.has_edge(target_step_selector, source_step_selector):\n        edge_data = execution_graph.edges[(target_step_selector, source_step_selector)]\n        if STEP_INPUT_SELECTORS_PROPERTY not in edge_data:\n            edge_data[STEP_INPUT_SELECTORS_PROPERTY] = []\n        edge_data[STEP_INPUT_SELECTORS_PROPERTY].append(\n            target_step_parsed_selector,\n        )\n    else:\n        execution_graph.add_edge(\n            target_step_selector,\n            source_step_selector,\n            **{STEP_INPUT_SELECTORS_PROPERTY: [target_step_parsed_selector]},\n        )\n    return execution_graph\n\n\ndef establish_control_flow_edge(\n    source_step_selector: str,\n    target_step_parsed_selector: ParsedSelector,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    if not step_definition_allows_control_flow_references(\n        parsed_selector=target_step_parsed_selector\n    ):\n        raise ExecutionGraphStructureError(\n            public_message=f\"Detected reference to other step in manifest of step {source_step_selector}. \"\n            f\"This is not allowed, as step manifest does not define any properties of type `StepSelector` \"\n            f\"allowing for defining connections between steps that represent flow control in `workflows`.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    target_step_selector = get_step_selector_from_its_output(\n        step_output_selector=target_step_parsed_selector.value\n    )\n    source_compilation_data = node_as(\n        execution_graph=execution_graph,\n        node=source_step_selector,\n        expected_type=StepNode,\n    )\n    target_compilation_data = node_as(\n        execution_graph=execution_graph,\n        node=target_step_selector,\n        expected_type=StepNode,\n    )\n    nodes_categories = {\n        source_compilation_data.node_category,\n        target_compilation_data.node_category,\n    }\n    if nodes_categories != {NodeCategory.STEP_NODE}:\n        raise ExecutionGraphStructureError(\n            public_message=f\"Attempted to create flow-control connection between workflow nodes: \"\n            f\"{source_step_selector} and {target_step_selector}, one of which is not denoted\"\n            f\"as step node.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    execution_graph.add_edge(\n        source_step_selector,\n        target_step_selector,\n    )\n    if target_step_selector in source_compilation_data.child_execution_branches:\n        raise ExecutionGraphStructureError(\n            public_message=f\"While establishing flow-control connection between source `{source_step_selector}` \"\n            f\"and target `{target_step_selector}` it was discovered that source step defines\"\n            f\"control flow transition into target one more than once, which is not allowed as \"\n            f\"that situation creates ambiguity in selecting execution branch.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    execution_branch_name = f\"Branch[{source_step_selector} -> {target_step_parsed_selector.definition.property_name}]\"\n    source_compilation_data.child_execution_branches[target_step_selector] = (\n        execution_branch_name\n    )\n    target_compilation_data.execution_branches_impacting_inputs.add(\n        execution_branch_name\n    )\n    return execution_graph\n\n\ndef step_definition_allows_control_flow_references(\n    parsed_selector: ParsedSelector,\n) -> bool:\n    return any(\n        definition.selected_element == STEP_AS_SELECTED_ELEMENT\n        for definition in parsed_selector.definition.allowed_references\n    )\n\n\ndef get_kind_of_value_provided_in_step_output(\n    step_manifest: WorkflowBlockManifest,\n    step_property: str,\n    source_step_manifest: WorkflowBlockManifest,\n) -> List[Kind]:\n    referred_node_outputs = step_manifest.get_actual_outputs()\n    actual_kind = []\n    matched_property = False\n    for output in referred_node_outputs:\n        if output.name != step_property:\n            continue\n        matched_property = True\n        actual_kind.extend(output.kind)\n    if not matched_property:\n        property_name = get_property_with_invalid_selector(\n            manifest=source_step_manifest,\n            step_property=step_property,\n        )\n        raise ExecutionGraphStructureError(\n            public_message=f\"Found reference to non-existing property `{step_property}` of step `{step_manifest.name}`.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=source_step_manifest.name,\n                    block_type=source_step_manifest.type,\n                    property_name=property_name,\n                    property_details=f\"'{step_manifest.name}.{step_property}' is an invalid reference\",\n                )\n            ],\n        )\n    return actual_kind\n\n\ndef add_edges_for_step_inputs(\n    execution_graph: DiGraph,\n    input_selectors: Set[str],\n    step_selector: str,\n) -> DiGraph:\n    for input_selector in input_selectors:\n        if is_step_output_selector(selector_or_value=input_selector):\n            input_selector = get_step_selector_from_its_output(\n                step_output_selector=input_selector\n            )\n        verify_edge_is_created_between_existing_nodes(\n            execution_graph=execution_graph,\n            start=input_selector,\n            end=step_selector,\n        )\n        execution_graph.add_edge(input_selector, step_selector)\n    return execution_graph\n\n\ndef add_edges_for_outputs(\n    workflow_definition: ParsedWorkflowDefinition,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for output in workflow_definition.outputs:\n        node_selector = output.selector\n        if is_step_output_selector(selector_or_value=node_selector):\n            node_selector = get_step_selector_from_its_output(\n                step_output_selector=node_selector\n            )\n        output_selector = construct_output_selector(name=output.name)\n        verify_edge_is_created_between_existing_nodes(\n            execution_graph=execution_graph,\n            start=node_selector,\n            end=output_selector,\n        )\n        output_node_manifest = node_as(\n            execution_graph=execution_graph,\n            node=output_selector,\n            expected_type=OutputNode,\n        )\n        if is_step_output_selector(selector_or_value=output.selector):\n            step_manifest = execution_graph.nodes[node_selector][\n                NODE_COMPILATION_OUTPUT_PROPERTY\n            ].step_manifest\n            step_outputs = step_manifest.get_actual_outputs()\n            denote_output_node_kind_based_on_step_outputs(\n                output_selector=output.selector,\n                step_outputs=step_outputs,\n                output_node_manifest=output_node_manifest,\n            )\n        else:\n            input_manifest = node_as(\n                execution_graph=execution_graph,\n                node=node_selector,\n                expected_type=InputNode,\n            ).input_manifest\n            output_node_manifest.kind = copy(input_manifest.kind)\n        execution_graph.add_edge(node_selector, output_selector)\n    return execution_graph\n\n\ndef verify_edge_is_created_between_existing_nodes(\n    execution_graph: DiGraph,\n    start: str,\n    end: str,\n) -> None:\n    if not execution_graph.has_node(start) or not execution_graph.has_node(end):\n        invalid_block = start if not execution_graph.has_node(start) else end\n        referencing_block = end if invalid_block == start else start\n\n        step_type = None\n        property_name = None\n        if execution_graph.has_node(referencing_block):\n            if is_step_node(execution_graph, referencing_block):\n                step_manifest = node_as(\n                    execution_graph=execution_graph,\n                    node=referencing_block,\n                    expected_type=StepNode,\n                ).step_manifest\n                step_type = step_manifest.type\n                property_name = get_property_with_invalid_selector(\n                    manifest=step_manifest,\n                    step_property=invalid_block,\n                )\n\n        block_id = (\n            \"$outputs\"\n            if referencing_block.startswith(\"$outputs.\")\n            else get_last_chunk_of_selector(selector=referencing_block)\n        )\n        property_name = (\n            get_last_chunk_of_selector(selector=referencing_block)\n            if referencing_block.startswith(\"$outputs.\")\n            else property_name\n        )\n\n        is_input = is_input_selector(selector_or_value=invalid_block)\n        raise InvalidReferenceTargetError(\n            public_message=f\"Workflow references '{invalid_block}' which points to a non-existent {is_input and 'input parameter' or 'block'}.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=block_id,\n                    block_type=step_type,\n                    property_name=property_name,\n                    property_details=f\"Invalid reference to {invalid_block}\",\n                ),\n            ],\n        )\n\n\ndef denote_output_node_kind_based_on_step_outputs(\n    output_selector: str,\n    step_outputs: List[OutputDefinition],\n    output_node_manifest: OutputNode,\n) -> None:\n    selected_output_name = get_last_chunk_of_selector(selector=output_selector)\n    kinds_for_outputs = {output.name: output.kind for output in step_outputs}\n\n    if selected_output_name == \"*\":\n        output_node_manifest.kind = deepcopy(kinds_for_outputs)\n        return None\n    if selected_output_name not in kinds_for_outputs:\n        output_name = output_node_manifest.output_manifest.name\n\n        raise InvalidReferenceTargetError(\n            public_message=f\"Workflow output references '{output_selector}' which points to a non-existent block property.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=\"$outputs\",\n                    property_name=output_name,\n                    property_details=f\"Invalid reference to {output_selector}\",\n                ),\n            ],\n        )\n    output_node_manifest.kind = copy(kinds_for_outputs[selected_output_name])\n    return None\n\n\ndef denote_data_flow_in_workflow(\n    execution_graph: DiGraph,\n    parsed_workflow_definition: ParsedWorkflowDefinition,\n) -> nx.DiGraph:\n    block_manifest_by_step_name = {\n        step.name: step for step in parsed_workflow_definition.steps\n    }\n    super_input_node = \"<super-input>\"\n    execution_graph = add_super_input_node_in_execution_graph(\n        execution_graph=execution_graph,\n        super_input_node=super_input_node,\n    )\n    execution_graph.nodes[super_input_node][NODE_COMPILATION_OUTPUT_PROPERTY] = (\n        InputNode(\n            node_category=NodeCategory.INPUT_NODE,\n            name=super_input_node,\n            selector=f\"$inputs.{super_input_node}\",\n            data_lineage=[],\n            input_manifest=None,  # this is expected never to be reached\n        )\n    )\n    top_level_data_lineage = set()\n    for node in traverse_graph_ensuring_parents_are_reached_first(\n        graph=execution_graph,\n        start_node=super_input_node,\n    ):\n        execution_graph = denote_data_flow_for_node(\n            execution_graph=execution_graph,\n            node=node,\n            block_manifest_by_step_name=block_manifest_by_step_name,\n            on_top_level_lineage_denoted=lambda element: top_level_data_lineage.add(\n                element\n            ),\n        )\n    execution_graph.remove_node(super_input_node)\n    execution_graph.graph[TOP_LEVEL_LINEAGES_KEY] = top_level_data_lineage\n    return execution_graph\n\n\ndef denote_data_flow_for_node(\n    execution_graph: DiGraph,\n    node: str,\n    block_manifest_by_step_name: Dict[str, WorkflowBlockManifest],\n    on_top_level_lineage_denoted: Callable[[str], None],\n) -> DiGraph:\n    if is_input_node(execution_graph=execution_graph, node=node):\n        # everything already set there, in the previous stage of compilation\n        return execution_graph\n    if is_step_node(execution_graph=execution_graph, node=node):\n        step_name = get_last_chunk_of_selector(selector=node)\n        if step_name not in block_manifest_by_step_name:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler expected manifest for the step: {step_name} to be registered \"\n                f\"but this condition is not met. This is most likely the bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | retrieving_predecessors_for_output\",\n            )\n        manifest = block_manifest_by_step_name[step_name]\n        return denote_data_flow_for_step(\n            execution_graph=execution_graph,\n            node=node,\n            manifest=manifest,\n            on_top_level_lineage_denoted=on_top_level_lineage_denoted,\n        )\n    if is_output_node(execution_graph=execution_graph, node=node):\n        # output is allowed to have exactly one predecessor\n        output_predecessors = list(execution_graph.predecessors(node))\n        if len(output_predecessors) != 1:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler expected each output in compiled graph to have one predecessor, \"\n                f\"but this condition is not met for node {node}. This is most likely the bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | retrieving_predecessors_for_output\",\n            )\n        predecessor_node = output_predecessors[0]\n        predecessor_node_data = node_as(\n            execution_graph=execution_graph,\n            node=predecessor_node,\n            expected_type=ExecutionGraphNode,\n        )\n        predecessor_node_lineage = predecessor_node_data.data_lineage\n        output_node_data = node_as(\n            execution_graph=execution_graph,\n            node=node,\n            expected_type=OutputNode,\n        )\n        output_node_data.data_lineage = predecessor_node_lineage\n        return execution_graph\n    raise AssumptionError(\n        f\"Workflow Compiler encountered node: {node} which cannot be classified as known node type. \"\n        f\"This is most likely the bug. Contact Roboflow team through github issues \"\n        f\"(https://github.com/roboflow/inference/issues) providing full \"\n        f\"context of the problem - including workflow definition you use.\",\n        context=\"workflow_compilation | execution_graph_construction | denoting_data_flow_for_step\",\n    )\n\n\ndef denote_data_flow_for_step(\n    execution_graph: DiGraph,\n    node: str,\n    manifest: WorkflowBlockManifest,\n    on_top_level_lineage_denoted: Callable[[str], None],\n) -> DiGraph:\n    all_control_flow_predecessors, all_non_control_flow_predecessors = (\n        separate_control_flow_predecessors_from_data_providers(\n            execution_graph=execution_graph, node=node\n        )\n    )\n    input_data = build_input_data_for_step(\n        manifest=manifest,\n        step_node=node,\n        data_providing_predecessors=all_non_control_flow_predecessors,\n        execution_graph=execution_graph,\n    )\n    step_name = get_last_chunk_of_selector(node)\n    step_node_data = node_as(\n        execution_graph=execution_graph,\n        node=node,\n        expected_type=StepNode,\n    )\n    parsed_step_input_selectors: List[ParsedSelector] = execution_graph.nodes[node][\n        PARSED_NODE_INPUT_SELECTORS_PROPERTY\n    ]\n    batch_compatibility_of_properties = retrieve_batch_compatibility_of_input_selectors(\n        input_selectors=parsed_step_input_selectors\n    )\n    scalar_parameters_to_be_batched = (\n        verify_declared_batch_compatibility_against_actual_inputs(\n            node=node,\n            step_node_data=step_node_data,\n            input_data=input_data,\n            batch_compatibility_of_properties=batch_compatibility_of_properties,\n        )\n    )\n    input_dimensionality_offsets = manifest.get_input_dimensionality_offsets()\n    verify_step_input_dimensionality_offsets(\n        step_name=step_name,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n    )\n    inputs_dimensionalities = get_inputs_dimensionalities(\n        step_name=step_name,\n        step_type=manifest.type,\n        input_data=input_data,\n        scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n    )\n    logger.debug(\n        f\"For step: {node}, detected the following input dimensionalities: {inputs_dimensionalities}\"\n    )\n    parameters_with_batch_inputs = grab_parameters_defining_batch_inputs(\n        inputs_dimensionalities=inputs_dimensionalities,\n    )\n    dimensionality_reference_property = manifest.get_dimensionality_reference_property()\n    output_dimensionality_offset = manifest.get_output_dimensionality_offset()\n    verify_step_input_dimensionality_offsets(\n        step_name=step_name,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n    )\n    verify_output_offset(\n        step_name=step_name,\n        parameters_with_batch_inputs=parameters_with_batch_inputs,\n        dimensionality_reference_property=dimensionality_reference_property,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n        output_dimensionality_offset=output_dimensionality_offset,\n    )\n    verify_input_data_dimensionality(\n        step_name=step_name,\n        step_type=manifest.type,\n        dimensionality_reference_property=dimensionality_reference_property,\n        inputs_dimensionalities=inputs_dimensionalities,\n        dimensionality_offstes=input_dimensionality_offsets,\n    )\n    all_data_derived_lineages = get_input_data_lineage_excluding_auto_batch_casting(\n        step_name=step_name,\n        input_data=input_data,\n        scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n    )\n    all_control_flow_lineages = get_lineage_derived_from_control_flow(\n        control_flow_steps_selectors=all_control_flow_predecessors,\n        execution_graph=execution_graph,\n    )\n    verify_compatibility_of_input_data_lineage_with_control_flow_lineage(\n        step_name=step_name,\n        inputs_lineage=all_data_derived_lineages,\n        control_flow_steps_selectors=all_control_flow_predecessors,\n        execution_graph=execution_graph,\n    )\n    step_node_data.input_data = input_data\n    step_node_data.dimensionality_reference_property = dimensionality_reference_property\n    step_node_data.control_flow_lineage_dims = [\n        len(_lineage) for _lineage in all_control_flow_lineages if _lineage\n    ]\n    step_node_data.batch_oriented_parameters = parameters_with_batch_inputs\n    if not all_data_derived_lineages and not all_control_flow_lineages:\n        if manifest.get_output_dimensionality_offset() > 0:\n            # brave decision to open a Pandora box\n            data_lineage = [node]\n        else:\n            data_lineage = []\n        control_flow_lineage_support = []\n    else:\n        data_lineage, control_flow_lineage_support = (\n            establish_batch_oriented_step_lineage(\n                step_selector=node,\n                all_data_derived_lineages=all_data_derived_lineages,\n                all_control_flow_lineages=all_control_flow_lineages,\n                input_data=input_data,\n                dimensionality_reference_property=dimensionality_reference_property,\n                output_dimensionality_offset=output_dimensionality_offset,\n            )\n        )\n    step_node_data.step_execution_dimensionality = (\n        establish_step_execution_dimensionality(\n            inputs_dimensionalities=inputs_dimensionalities,\n            control_flow_lineage_support=control_flow_lineage_support,\n            output_dimensionality_offset=output_dimensionality_offset,\n        )\n    )\n    lineage_supports = get_lineage_support_for_auto_batch_casted_parameters(\n        input_dimensionalities=inputs_dimensionalities,\n        all_lineages_of_batch_parameters=all_data_derived_lineages,\n        scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n    )\n    step_node_data.auto_batch_casting_lineage_supports = lineage_supports\n    step_node_data.control_flow_lineage_support = control_flow_lineage_support\n    if data_lineage:\n        on_top_level_lineage_denoted(data_lineage[0])\n    step_node_data.data_lineage = data_lineage\n    return execution_graph\n\n\ndef _collect_unique_control_flow_lineages_with_step_mapping(\n    control_flow_steps_selectors: List[str],\n    execution_graph: nx.DiGraph,\n) -> Tuple[List[List[str]], Dict[int, List[str]]]:\n    \"\"\"\n    Collect data lineages from control flow steps and deduplicate by lineage id.\n\n    For each given control flow step selector, reads its data_lineage from the\n    execution graph. Returns unique non-empty lineages (by identify_lineage id)\n    and a mapping from lineage id to every step selector that produced that\n    lineage (used e.g. for error reporting when lineage is incompatible).\n\n    Args:\n        control_flow_steps_selectors: Step selectors (node ids) of control\n            flow steps whose data_lineage is to be collected.\n        execution_graph: The workflow execution graph containing step nodes\n            and their data_lineage.\n\n    Returns:\n        A tuple of (unique_lineages, lineage_id_to_step_selectors):\n        - unique_lineages: list of distinct non-empty data lineages.\n        - lineage_id_to_step_selectors: map from lineage id to list of step\n          selectors whose data_lineage has that id (includes empty lineages).\n    \"\"\"\n    unique_lineages: List[List[str]] = []\n    seen_lineage_ids: Set[int] = set()\n    lineage_id_to_step_selectors: Dict[int, List[str]] = defaultdict(list)\n\n    for step_selector in control_flow_steps_selectors:\n        step_data = node_as(\n            execution_graph=execution_graph,\n            node=step_selector,\n            expected_type=StepNode,\n        )\n        lineage = step_data.data_lineage\n        lineage_id = identify_lineage(lineage)\n        lineage_id_to_step_selectors[lineage_id].append(step_selector)\n        if lineage and lineage_id not in seen_lineage_ids:\n            seen_lineage_ids.add(lineage_id)\n            unique_lineages.append(lineage)\n\n    return unique_lineages, dict(lineage_id_to_step_selectors)\n\n\ndef get_lineage_derived_from_control_flow(\n    control_flow_steps_selectors: List[str],\n    execution_graph: nx.DiGraph,\n) -> List[List[str]]:\n    \"\"\"\n    Return unique non-empty data lineages from the given control flow steps.\n\n    Each lineage is taken from the step's data_lineage in the execution graph.\n    Lineages are deduplicated by lineage id (see identify_lineage); empty\n    lineages are omitted. Used when establishing batch-oriented step lineage.\n\n    Args:\n        control_flow_steps_selectors: Step selectors (node ids) of control\n            flow steps whose data_lineage is to be collected.\n        execution_graph: The workflow execution graph containing step nodes\n            and their data_lineage.\n\n    Returns:\n        List of distinct non-empty data lineages, one per unique lineage id.\n    \"\"\"\n    unique_lineages, _ = _collect_unique_control_flow_lineages_with_step_mapping(\n        control_flow_steps_selectors=control_flow_steps_selectors,\n        execution_graph=execution_graph,\n    )\n    return unique_lineages\n\n\ndef separate_control_flow_predecessors_from_data_providers(\n    execution_graph: DiGraph,\n    node: str,\n) -> Tuple[List[str], List[str]]:\n    all_predecessors = list(execution_graph.predecessors(node))\n    all_control_flow_predecessors = [\n        predecessor\n        for predecessor in all_predecessors\n        if is_control_flow_step(execution_graph=execution_graph, node=predecessor)\n    ]\n    all_non_control_flow_predecessors = [\n        predecessor\n        for predecessor in all_predecessors\n        if not is_control_flow_step(execution_graph=execution_graph, node=predecessor)\n    ]\n    return all_control_flow_predecessors, all_non_control_flow_predecessors\n\n\ndef build_input_data_for_step(\n    manifest: WorkflowBlockManifest,\n    step_node: str,\n    data_providing_predecessors: List[str],\n    execution_graph: DiGraph,\n) -> StepInputData:\n    predecessors_by_property_name = get_predecessors_for_step_manifest_properties(\n        execution_graph=execution_graph,\n        step_node=step_node,\n        data_providing_predecessors=data_providing_predecessors,\n    )\n    manifest_fields_values = get_manifest_fields_values(step_manifest=manifest)\n    result = {}\n    for name, value in manifest_fields_values.items():\n        result[name] = build_input_property(\n            step_node=step_node,\n            manifest_property_name=name,\n            manifest_property_value=value,\n            predecessors_by_property_name=predecessors_by_property_name,\n            execution_graph=execution_graph,\n        )\n    return result\n\n\ndef get_predecessors_for_step_manifest_properties(\n    execution_graph: DiGraph, step_node: str, data_providing_predecessors: List[str]\n) -> Dict[str, List[PropertyPredecessorDefinition]]:\n    predecessors_by_property_name = defaultdict(list)\n    for predecessor in data_providing_predecessors:\n        edge_data = execution_graph.edges[(predecessor, step_node)]\n        # STEP_INPUT_SELECTORS_PROPERTY is optional, as special <super-input> node may be directly\n        # connected to step\n        selectors_associated_to_edge: List[ParsedSelector] = edge_data.get(\n            STEP_INPUT_SELECTORS_PROPERTY, []\n        )\n        for selector_associated_to_edge in selectors_associated_to_edge:\n            definition = PropertyPredecessorDefinition(\n                predecessor_selector=predecessor,\n                parsed_selector=selector_associated_to_edge,\n            )\n            predecessors_by_property_name[\n                selector_associated_to_edge.definition.property_name\n            ].append(definition)\n    return predecessors_by_property_name\n\n\ndef build_input_property(\n    step_node: str,\n    manifest_property_name: str,\n    manifest_property_value: Any,\n    predecessors_by_property_name: Dict[str, List[PropertyPredecessorDefinition]],\n    execution_graph: DiGraph,\n) -> Union[StepInputDefinition, CompoundStepInputDefinition]:\n    if manifest_property_name not in predecessors_by_property_name:\n        return StaticStepInputDefinition(\n            parameter_specification=ParameterSpecification(\n                parameter_name=manifest_property_name,\n            ),\n            category=NodeInputCategory.STATIC_VALUE,\n            value=manifest_property_value,\n        )\n    if isinstance(manifest_property_value, dict):\n        return build_nested_dictionary_for_input_property(\n            step_node=step_node,\n            manifest_property_name=manifest_property_name,\n            manifest_property_value=manifest_property_value,\n            predecessors_definitions=predecessors_by_property_name[\n                manifest_property_name\n            ],\n            execution_graph=execution_graph,\n        )\n    if isinstance(manifest_property_value, list):\n        return build_nested_list_for_input_property(\n            step_node=step_node,\n            manifest_property_name=manifest_property_name,\n            manifest_property_value=manifest_property_value,\n            predecessors_definitions=predecessors_by_property_name[\n                manifest_property_name\n            ],\n            execution_graph=execution_graph,\n        )\n    matching_predecessors_data = predecessors_by_property_name[manifest_property_name]\n    if len(matching_predecessors_data) != 1:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler deduced that property `{manifest_property_name}` of step `{step_node}` \"\n            f\"should be fed with data coming from exactly one execution graph node, but found \"\n            f\"{len(matching_predecessors_data)} data sources. This is most likely the bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n        )\n    predecessor_selector, predecessor_parsed_selector = (\n        matching_predecessors_data[0].predecessor_selector,\n        matching_predecessors_data[0].parsed_selector,\n    )\n    if is_input_node(execution_graph=execution_graph, node=predecessor_selector):\n        predecessor_node_data = node_as(\n            execution_graph=execution_graph,\n            node=matching_predecessors_data[0].predecessor_selector,\n            expected_type=InputNode,\n        )\n        category = (\n            NodeInputCategory.BATCH_INPUT_PARAMETER\n            if predecessor_node_data.is_batch_oriented()\n            else NodeInputCategory.NON_BATCH_INPUT_PARAMETER\n        )\n        return DynamicStepInputDefinition(\n            parameter_specification=ParameterSpecification(\n                parameter_name=manifest_property_name,\n            ),\n            category=category,\n            data_lineage=predecessor_node_data.data_lineage,\n            selector=predecessor_node_data.selector,\n        )\n    if is_step_node(execution_graph=execution_graph, node=predecessor_selector):\n        predecessor_node_data = node_as(\n            execution_graph=execution_graph,\n            node=matching_predecessors_data[0].predecessor_selector,\n            expected_type=StepNode,\n        )\n        category = (\n            NodeInputCategory.BATCH_STEP_OUTPUT\n            if predecessor_node_data.output_dimensionality > 0\n            else NodeInputCategory.NON_BATCH_STEP_OUTPUT\n        )\n        return DynamicStepInputDefinition(\n            parameter_specification=ParameterSpecification(\n                parameter_name=manifest_property_name,\n            ),\n            category=category,\n            data_lineage=predecessor_node_data.data_lineage,\n            selector=predecessor_parsed_selector.value,\n        )\n    raise AssumptionError(\n        public_message=f\"Workflow Compiler for property `{manifest_property_name}` of step `{step_node}` \"\n        f\"found data providing predecessor `{predecessor_selector}` which has unsupported step type.\"\n        f\"This is most likely the bug. \"\n        f\"Contact Roboflow team through github issues \"\n        f\"(https://github.com/roboflow/inference/issues) providing full \"\n        f\"context of the problem - including workflow definition you use.\",\n        context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n    )\n\n\ndef build_nested_dictionary_for_input_property(\n    step_node: str,\n    manifest_property_name: str,\n    manifest_property_value: dict,\n    predecessors_definitions: List[PropertyPredecessorDefinition],\n    execution_graph: DiGraph,\n) -> DictOfStepInputDefinitions:\n    nested_property_name2data: Dict[Optional[str], PropertyPredecessorDefinition] = {\n        predecessor_definition.parsed_selector.key: predecessor_definition\n        for predecessor_definition in predecessors_definitions\n    }\n    result = {}\n    for nested_dict_key, nested_dict_value in manifest_property_value.items():\n        if nested_dict_key not in nested_property_name2data:\n            result[nested_dict_key] = StaticStepInputDefinition(\n                parameter_specification=ParameterSpecification(\n                    parameter_name=manifest_property_name,\n                    nested_element_key=nested_dict_key,\n                ),\n                category=NodeInputCategory.STATIC_VALUE,\n                value=nested_dict_value,\n            )\n            continue\n        referred_node_selector = nested_property_name2data[\n            nested_dict_key\n        ].predecessor_selector\n        referred_node_parsed_selector = nested_property_name2data[\n            nested_dict_key\n        ].parsed_selector\n        if is_input_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=InputNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_INPUT_PARAMETER\n                if predecessor_node_data.is_batch_oriented()\n                else NodeInputCategory.NON_BATCH_INPUT_PARAMETER\n            )\n            result[nested_dict_key] = DynamicStepInputDefinition(\n                parameter_specification=ParameterSpecification(\n                    parameter_name=manifest_property_name,\n                    nested_element_key=nested_dict_key,\n                ),\n                category=category,\n                data_lineage=predecessor_node_data.data_lineage,\n                selector=predecessor_node_data.selector,\n            )\n            continue\n        if is_step_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=StepNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_STEP_OUTPUT\n                if predecessor_node_data.output_dimensionality > 0\n                else NodeInputCategory.NON_BATCH_STEP_OUTPUT\n            )\n            result[nested_dict_key] = DynamicStepInputDefinition(\n                parameter_specification=ParameterSpecification(\n                    parameter_name=manifest_property_name,\n                    nested_element_key=nested_dict_key,\n                ),\n                category=category,\n                data_lineage=predecessor_node_data.data_lineage,\n                selector=referred_node_parsed_selector.value,\n            )\n            continue\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for property `{manifest_property_name}` of step `{step_node}` \"\n            f\"found data providing predecessor `{referred_node_selector}` which has \"\n            f\"unsupported step type (key: {nested_dict_key} of nested data dictionary). \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n        )\n    return DictOfStepInputDefinitions(\n        name=manifest_property_name,\n        nested_definitions=result,\n    )\n\n\ndef get_manifest_fields_values(step_manifest: WorkflowBlockManifest) -> Dict[str, Any]:\n    result = {}\n    for field in step_manifest.model_fields:\n        if field in EXCLUDED_FIELDS:\n            continue\n        result[field] = getattr(step_manifest, field)\n    return result\n\n\ndef build_nested_list_for_input_property(\n    step_node: str,\n    manifest_property_name: str,\n    manifest_property_value: list,\n    predecessors_definitions: List[PropertyPredecessorDefinition],\n    execution_graph: DiGraph,\n) -> ListOfStepInputDefinitions:\n    nested_index2data: Dict[Optional[int], PropertyPredecessorDefinition] = {\n        e.parsed_selector.index: e for e in predecessors_definitions\n    }\n    result = []\n    for index, element in enumerate(manifest_property_value):\n        if index not in nested_index2data:\n            result.append(\n                StaticStepInputDefinition(\n                    parameter_specification=ParameterSpecification(\n                        parameter_name=manifest_property_name,\n                        nested_element_index=index,\n                    ),\n                    category=NodeInputCategory.STATIC_VALUE,\n                    value=element,\n                )\n            )\n            continue\n        referred_node_selector = nested_index2data[index].predecessor_selector\n        referred_node_parsed_selector = nested_index2data[index].parsed_selector\n        if is_input_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=InputNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_INPUT_PARAMETER\n                if predecessor_node_data.is_batch_oriented()\n                else NodeInputCategory.NON_BATCH_INPUT_PARAMETER\n            )\n            result.append(\n                DynamicStepInputDefinition(\n                    parameter_specification=ParameterSpecification(\n                        parameter_name=manifest_property_name,\n                        nested_element_index=index,\n                    ),\n                    category=category,\n                    data_lineage=predecessor_node_data.data_lineage,\n                    selector=predecessor_node_data.selector,\n                )\n            )\n            continue\n        if is_step_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=StepNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_STEP_OUTPUT\n                if predecessor_node_data.output_dimensionality > 0\n                else NodeInputCategory.NON_BATCH_STEP_OUTPUT\n            )\n            result.append(\n                DynamicStepInputDefinition(\n                    parameter_specification=ParameterSpecification(\n                        parameter_name=manifest_property_name,\n                        nested_element_index=index,\n                    ),\n                    category=category,\n                    data_lineage=predecessor_node_data.data_lineage,\n                    selector=referred_node_parsed_selector.value,\n                )\n            )\n            continue\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for property `{manifest_property_name}` of step `{step_node}` \"\n            f\"found data providing predecessor `{referred_node_selector}` which has \"\n            f\"unsupported step type (index: {index} of nested data list). \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n        )\n    return ListOfStepInputDefinitions(\n        name=manifest_property_name,\n        nested_definitions=result,\n    )\n\n\ndef verify_step_input_dimensionality_offsets(\n    step_name: str,\n    input_dimensionality_offsets: Dict[str, int],\n) -> None:\n    min_offset, max_offset = None, None\n    for offset in input_dimensionality_offsets.values():\n        if min_offset is None or offset < min_offset:\n            min_offset = offset\n        if max_offset is None or offset > max_offset:\n            max_offset = offset\n    if min_offset is None or max_offset is None:\n        return None\n    if min_offset < 0 or max_offset < 0:\n        raise BlockInterfaceError(\n            public_message=f\"Offsets could not be negative, but block defining step: {step_name} defines that values.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_input_offset_definitions\",\n        )\n    if abs(max_offset - min_offset) > 1:\n        raise BlockInterfaceError(\n            public_message=\"Offsets of input parameters could not differ more than 1, but block defining step {step_name} \"\n            f\"violates that rule.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_input_offset_definitions\",\n        )\n\n\ndef verify_output_offset(\n    step_name: str,\n    parameters_with_batch_inputs: Set[str],\n    input_dimensionality_offsets: Dict[str, int],\n    dimensionality_reference_property: Optional[str],\n    output_dimensionality_offset: int,\n) -> None:\n    if not parameters_with_batch_inputs and output_dimensionality_offset < 0:\n        raise StepInputDimensionalityError(\n            public_message=f\"Block defining step {step_name} defines negative dimensionality offset while only \"\n            f\"scalar inputs being provided - the block cannot run as there is no dimension to collapse.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if (\n        dimensionality_reference_property is not None\n        and dimensionality_reference_property not in parameters_with_batch_inputs\n    ):\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} defines dimensionality reference property \"\n            f\"which is not in scope of parameters bring batch-oriented input, which makes it impossible \"\n            f\"to use as reference for output dimensionality.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if output_dimensionality_offset not in {-1, 0, 1}:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} defines output dimensionality offset \"\n            f\"being {output_dimensionality_offset}, whereas it is only possible for that offset being \"\n            f\"in set [-1, 0, 1].\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    different_offsets = {o for o in input_dimensionality_offsets.values()}\n    if len(parameters_with_batch_inputs) != len(input_dimensionality_offsets):\n        # assumption of default offset being zero - and this one does not need to be manifested\n        # by block\n        different_offsets.add(0)\n    if 0 not in different_offsets and parameters_with_batch_inputs:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} explicitly defines input dimensionalities offsets\"\n            f\"with {input_dimensionality_offsets}, but the definition lack 0-level input, which is \"\n            f\"not allowed, as in this scenario offsets could be adjusted to include 0\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if len(different_offsets) > 1 and dimensionality_reference_property is None:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} explicitly defines input dimensionality \"\n            f\"offsets {input_dimensionality_offsets}. In this scenario it is required to provide dimensionality \"\n            f\"reference property.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if len(different_offsets) > 1 and output_dimensionality_offset != 0:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} explicitly defines input dimensionality \"\n            f\"offsets {input_dimensionality_offsets} and output dimensionality offset {output_dimensionality_offset} \"\n            f\"where the latter is not 0, but for inputs differing with dimensionality it is only possible to keep \"\n            f\"output dimensionality the same and point reference parameter.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n\n\ndef verify_input_data_dimensionality(\n    step_name: str,\n    step_type: str,\n    dimensionality_reference_property: Optional[str],\n    inputs_dimensionalities: Dict[str, Set[int]],\n    dimensionality_offstes: Dict[str, int],\n) -> None:\n    parameter_name2dimensionality_specification = (\n        grab_input_data_dimensionality_specifications(\n            step_name=step_name,\n            inputs_dimensionalities=inputs_dimensionalities,\n            dimensionality_offstes=dimensionality_offstes,\n        )\n    )\n    if not parameter_name2dimensionality_specification:\n        # nothing to check if no batch-oriented inputs\n        return None\n    different_dimensionalities_of_parameters = {\n        specification.actual_dimensionality\n        for specification in parameter_name2dimensionality_specification.values()\n    }\n    if dimensionality_reference_property is None:\n        if len(different_dimensionalities_of_parameters) > 1:\n            parameter2dimensionality = {\n                k: e.actual_dimensionality\n                for k, e in parameter_name2dimensionality_specification.items()\n            }\n            raise StepInputDimensionalityError(\n                public_message=f\"Block defining step {step_name} does not define dimensionality reference property, \"\n                f\"which means that all batch-oriented parameters must be at the same dimensionality level, \"\n                f\"but detected the following dimensionalities for parameters {parameter2dimensionality}\",\n                context=\"workflow_compilation | execution_graph_construction | denoting_step_inputs_dimensionality\",\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=step_name,\n                        block_type=step_type,\n                        block_details=f\"Dimensionality of input parameters doesn't match: {parameter2dimensionality}\",\n                    )\n                ],\n            )\n        return None\n    reference_specification = parameter_name2dimensionality_specification[\n        dimensionality_reference_property\n    ]\n    expected_dimensionalities = {\n        property_name: (e.expected_offset - reference_specification.expected_offset)\n        + reference_specification.actual_dimensionality\n        for property_name, e in parameter_name2dimensionality_specification.items()\n    }\n    if any(dim <= 0 for dim in expected_dimensionalities.values()):\n        raise StepInputDimensionalityError(\n            public_message=f\"Given the definition of block defining step {step_name} and data provided, \"\n            f\"the block would expect batch input dimensionality to be 0 or below, which is invalid.\",\n            context=\"workflow_compilation | execution_graph_construction | denoting_step_inputs_dimensionality\",\n        )\n    for property_name, expected_dimensionality in expected_dimensionalities.items():\n        actual_dimensionality = parameter_name2dimensionality_specification[\n            property_name\n        ].actual_dimensionality\n        if actual_dimensionality != expected_dimensionality:\n            raise StepInputDimensionalityError(\n                public_message=f\"Data fed into step `{step_name}` property `{property_name}` has \"\n                f\"actual dimensionality {actual_dimensionality}, \"\n                f\"when expected was {expected_dimensionality}\",\n                context=\"workflow_compilation | execution_graph_construction | denoting_step_inputs_dimensionality\",\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=step_name,\n                        block_type=step_type,\n                        property_name=property_name,\n                        property_details=f\"Expected dimensionality {expected_dimensionality}, but received dimensionality {actual_dimensionality}\",\n                    )\n                ],\n            )\n    return None\n\n\ndef grab_input_data_dimensionality_specifications(\n    step_name: str,\n    inputs_dimensionalities: Dict[str, Set[int]],\n    dimensionality_offstes: Dict[str, int],\n) -> Dict[str, InputDimensionalitySpecification]:\n    result = {}\n    for parameter_name, dimensionality in inputs_dimensionalities.items():\n        parameter_offset = dimensionality_offstes.get(parameter_name, 0)\n        non_zero_dimensionalities_for_parameter = {d for d in dimensionality if d > 0}\n        if len(non_zero_dimensionalities_for_parameter) > 1:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler for step: `{step_name}` and parameter: {parameter_name}\"\n                f\"found multiple different values of actual input dimensionalities: \"\n                f\"`{non_zero_dimensionalities_for_parameter}` which should be detected and addresses \"\n                f\"at earlier stages of compilation.\"\n                f\"This is most likely the bug. Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n            )\n        if non_zero_dimensionalities_for_parameter:\n            actual_dimensionality = next(iter(non_zero_dimensionalities_for_parameter))\n            result[parameter_name] = InputDimensionalitySpecification(\n                actual_dimensionality=actual_dimensionality,\n                expected_offset=parameter_offset,\n            )\n    return result\n\n\ndef verify_compatibility_of_input_data_lineage_with_control_flow_lineage(\n    step_name: str,\n    inputs_lineage: List[List[str]],\n    control_flow_steps_selectors: List[str],\n    execution_graph: DiGraph,\n) -> None:\n    \"\"\"\n    Ensure control flow steps' data lineage is compatible with the step's inputs.\n\n    Control flow steps that affect this step must operate on data that is\n    compatible with the data fed to the step; otherwise the step could never\n    execute. Compares unique control flow lineages against input lineage\n    prefixes and raises ControlFlowDefinitionError if any control flow lineage\n    is not covered by the inputs.\n\n    If inputs_lineage is empty, there is no sense to verify compatibility. The lineage of the\n    step should be established based on the control flow lineages.\n\n    Args:\n        step_name: Name of the step being verified (used in error messages).\n        inputs_lineage: Data lineages derived from the step's input data.\n        control_flow_steps_selectors: Step selectors of control flow steps\n            that affect this step's execution.\n        execution_graph: The workflow execution graph.\n\n    Raises:\n        ControlFlowDefinitionError: When a control flow step's lineage is not\n            compatible with the step's input lineage (step would never execute).\n    \"\"\"\n    (\n        batch_oriented_control_flow_lineages,\n        lineage_id2control_flow_steps,\n    ) = _collect_unique_control_flow_lineages_with_step_mapping(\n        control_flow_steps_selectors=control_flow_steps_selectors,\n        execution_graph=execution_graph,\n    )\n    if not inputs_lineage:\n        return\n\n    all_input_lineage_prefixes = get_all_batch_lineage_prefixes(lineages=inputs_lineage)\n    all_input_lineage_prefixes_hashes = {\n        identify_lineage(lineage=lineage) for lineage in all_input_lineage_prefixes\n    }\n    for control_flow_lineage in batch_oriented_control_flow_lineages:\n        control_flow_lineage_id = identify_lineage(lineage=control_flow_lineage)\n        if control_flow_lineage_id not in all_input_lineage_prefixes_hashes:\n            problematic_flow_control_steps = lineage_id2control_flow_steps[\n                control_flow_lineage_id\n            ]\n            raise ControlFlowDefinitionError(\n                public_message=f\"Step {step_name} execution is impacted by control flow outcome of the following \"\n                f\"steps {problematic_flow_control_steps} which make decision based on data that is \"\n                f\"not compatible with data fed to the step {step_name} - which would cause the step \"\n                f\"to never execute. This behaviour is invalid and prevented upfront by Workflows compiler.\",\n                context=\"workflow_compilation | execution_graph_construction | verification_of_control_flow_lineage\",\n            )\n\n\ndef get_all_batch_lineage_prefixes(lineages: List[List[str]]) -> List[List[str]]:\n    result = []\n    already_spotted = set()\n    for lineage in lineages:\n        lineage_prefixes = get_batch_lineage_prefixes(lineage=lineage)\n        for lineage_prefix in lineage_prefixes:\n            lineage_prefix_id = identify_lineage(lineage=lineage_prefix)\n            if lineage_prefix_id not in already_spotted:\n                already_spotted.add(lineage_prefix_id)\n                result.append(lineage_prefix)\n    return result\n\n\ndef get_batch_lineage_prefixes(lineage: List[str]) -> List[List[str]]:\n    if not lineage:\n        return []\n    result = []\n    prefix = []\n    for i in range(len(lineage)):\n        prefix.append(lineage[i])\n        result.append(copy(prefix))\n    return result\n\n\ndef get_inputs_dimensionalities(\n    step_name: str,\n    step_type: str,\n    input_data: StepInputData,\n    scalar_parameters_to_be_batched: Set[str],\n    input_dimensionality_offsets: Dict[str, int],\n) -> Dict[str, Set[int]]:\n    result = defaultdict(set)\n    dimensionalities_spotted = set()\n    offset_parameters = {\n        parameter: value\n        for parameter, value in input_dimensionality_offsets.items()\n        if value > 0\n    }\n    non_offset_parameters_dimensionality_values = set()\n    for property_name, input_definition in input_data.items():\n        if property_name in offset_parameters:\n            continue\n        if input_definition.is_compound_input():\n            for value in input_definition.iterate_through_definitions():\n                if value.is_batch_oriented():\n                    non_offset_parameters_dimensionality_values.add(\n                        value.get_dimensionality()\n                    )\n        elif input_definition.is_batch_oriented():\n            non_offset_parameters_dimensionality_values.add(\n                input_definition.get_dimensionality()\n            )\n    if len(non_offset_parameters_dimensionality_values) > 1:\n        raise StepInputDimensionalityError(\n            public_message=f\"For step {step_name} attempted to plug input data that are in different dimensions, \"\n            f\"whereas block defines the inputs to be equal in that terms.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_input_data\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=step_name,\n                    block_type=step_type,\n                    block_details=f\"Dimensionality of input parameters differs by more than 1. Detected dimensions: {dict(result)}\",\n                )\n            ],\n        )\n    non_offset_parameters_dimensionality_value = (\n        non_offset_parameters_dimensionality_values.pop()\n        if len(non_offset_parameters_dimensionality_values) > 0\n        else 1\n    )\n    for property_name, input_definition in input_data.items():\n        if input_definition.is_compound_input():\n            result[property_name] = get_compound_input_dimensionality(\n                step_name=step_name,\n                step_type=step_type,\n                property_name=property_name,\n                input_definition=input_definition,\n                scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n                non_offset_parameters_dimensionality_value=non_offset_parameters_dimensionality_value,\n                offset_parameters=offset_parameters,\n            )\n        else:\n            if property_name in scalar_parameters_to_be_batched:\n                if property_name not in offset_parameters:\n                    result[property_name] = {non_offset_parameters_dimensionality_value}\n                else:\n                    result[property_name] = (\n                        non_offset_parameters_dimensionality_value\n                        + offset_parameters[property_name]\n                    )\n            else:\n                result[property_name] = {input_definition.get_dimensionality()}\n        dimensionalities_spotted.update(result[property_name])\n    non_zero_dimensionalities_spotted = {d for d in dimensionalities_spotted if d != 0}\n    if len(non_zero_dimensionalities_spotted) > 0:\n        min_dim, max_dim = min(non_zero_dimensionalities_spotted), max(\n            non_zero_dimensionalities_spotted\n        )\n        if abs(max_dim - min_dim) > 1:\n            raise StepInputDimensionalityError(\n                public_message=f\"For step {step_name} attempted to plug input data differing in dimensionality more than 1\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_input_data\",\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=step_name,\n                        block_type=step_type,\n                        block_details=f\"Dimensionality of input parameters differs by more than 1. Detected dimensions: {dict(result)}\",\n                    )\n                ],\n            )\n    return result\n\n\ndef get_compound_input_dimensionality(\n    step_name: str,\n    property_name: str,\n    step_type: str,\n    input_definition: CompoundStepInputDefinition,\n    scalar_parameters_to_be_batched: Set[str],\n    offset_parameters: Dict[str, int],\n    non_offset_parameters_dimensionality_value: int,\n) -> Set[int]:\n    dimensionalities_spotted = set()\n    for definition in input_definition.iterate_through_definitions():\n        if (\n            property_name not in scalar_parameters_to_be_batched\n            or definition.is_batch_oriented()\n        ):\n            dimensionalities_spotted.add(definition.get_dimensionality())\n        elif property_name not in offset_parameters:\n            dimensionalities_spotted.add(non_offset_parameters_dimensionality_value)\n        else:\n            dimensionalities_spotted.add(\n                non_offset_parameters_dimensionality_value\n                + offset_parameters[property_name]\n            )\n    non_zero_dimensionalities = {e for e in dimensionalities_spotted if e != 0}\n    if len(non_zero_dimensionalities) > 1:\n        raise StepInputDimensionalityError(\n            public_message=f\"While evaluating compound property {property_name} of step {step_name}, \"\n            f\"detected multiple inputs of differing batch dimensionalities: {non_zero_dimensionalities}\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_input_data\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=step_name,\n                    block_type=step_type,\n                    property_name=property_name,\n                    property_details=f\"Detected multiple inputs of differing batch dimensionalities: {non_zero_dimensionalities}\",\n                )\n            ],\n        )\n    return dimensionalities_spotted\n\n\ndef grab_parameters_defining_batch_inputs(\n    inputs_dimensionalities: Dict[str, Set[int]],\n) -> Set[str]:\n    result = set()\n    for paremeter, dimensionalities in inputs_dimensionalities.items():\n        batch_dimensionalities = {d for d in dimensionalities if d > 0}\n        if len(batch_dimensionalities):\n            result.add(paremeter)\n    return result\n\n\ndef retrieve_batch_compatibility_of_input_selectors(\n    input_selectors: List[ParsedSelector],\n) -> Dict[str, Set[bool]]:\n    batch_compatibility_of_properties = defaultdict(set)\n    for parsed_selector in input_selectors:\n        for reference in parsed_selector.definition.allowed_references:\n            batch_compatibility_of_properties[\n                parsed_selector.definition.property_name\n            ].update(reference.points_to_batch)\n    return batch_compatibility_of_properties\n\n\ndef verify_declared_batch_compatibility_against_actual_inputs(\n    node: str,\n    step_node_data: StepNode,\n    input_data: StepInputData,\n    batch_compatibility_of_properties: Dict[str, Set[bool]],\n) -> Set[str]:\n    scalar_parameters_to_be_batched = set()\n    parameters_accepting_batches_and_scalars = set(\n        step_node_data.step_manifest.get_parameters_accepting_batches_and_scalars()\n    )\n    hardcoded_inputs_to_be_batch_compatible = set(\n        step_node_data.step_manifest.get_parameters_enforcing_auto_batch_casting()\n        + step_node_data.step_manifest.get_parameters_accepting_batches()\n    )\n    for property_name, input_definition in input_data.items():\n        if property_name not in batch_compatibility_of_properties:\n            actual_input_is_batch = {False}\n            if property_name in parameters_accepting_batches_and_scalars:\n                batch_compatibility = {True, False}\n            elif property_name in hardcoded_inputs_to_be_batch_compatible:\n                batch_compatibility = {True}\n            else:\n                continue\n        elif input_definition.is_compound_input():\n            actual_input_is_batch = {\n                element.is_batch_oriented()\n                for element in input_definition.iterate_through_definitions()\n            }\n            batch_compatibility = batch_compatibility_of_properties[property_name]\n        else:\n            actual_input_is_batch = {input_definition.is_batch_oriented()}\n            batch_compatibility = batch_compatibility_of_properties[property_name]\n        step_accepts_batch_input = step_node_data.step_manifest.accepts_batch_input()\n        if (\n            step_accepts_batch_input\n            and batch_compatibility == {False}\n            and True in actual_input_is_batch\n        ):\n            raise ExecutionGraphStructureError(\n                public_message=f\"Detected invalid reference plugged \"\n                f\"into property `{property_name}` of step `{node}` - the step \"\n                f\"property do not accept batch-oriented inputs, yet the input selector \"\n                f\"holds one - this indicates the problem with \"\n                f\"construction of your Workflow - usually the problem occurs when non-batch oriented \"\n                f\"step inputs are filled with outputs of batch-oriented steps or batch-oriented inputs.\",\n                context=\"workflow_compilation | execution_graph_construction\",\n            )\n        if batch_compatibility == {True} and False in actual_input_is_batch:\n            scalar_parameters_to_be_batched.add(property_name)\n    return scalar_parameters_to_be_batched\n\n\ndef get_input_data_lineage_excluding_auto_batch_casting(\n    step_name: str,\n    input_data: StepInputData,\n    scalar_parameters_to_be_batched: Set[str],\n) -> List[List[str]]:\n    lineage_deduplication_set = set()\n    lineages = []\n    for property_name, input_definition in input_data.items():\n        new_lineages_detected_within_property_data = get_lineage_for_input_property(\n            step_name=step_name,\n            property_name=property_name,\n            input_definition=input_definition,\n            lineage_deduplication_set=lineage_deduplication_set,\n        )\n        if (\n            property_name in scalar_parameters_to_be_batched\n            and len(new_lineages_detected_within_property_data) == 0\n        ):\n            continue\n        lineages.extend(new_lineages_detected_within_property_data)\n    if not lineages:\n        return lineages\n    verify_lineages(step_name=step_name, detected_lineages=lineages)\n    return lineages\n\n\ndef get_lineage_support_for_auto_batch_casted_parameters(\n    input_dimensionalities: Dict[str, Set[int]],\n    scalar_parameters_to_be_batched: Set[str],\n    all_lineages_of_batch_parameters: List[List[str]],\n) -> Dict[str, AutoBatchCastingConfig]:\n    longest_lineage_support = find_longest_lineage_support(\n        all_lineages_of_batch_parameters=all_lineages_of_batch_parameters,\n    )\n    result = {}\n    for parameter_name in scalar_parameters_to_be_batched:\n        parameter_dimensionality = max(input_dimensionalities[parameter_name])\n        if longest_lineage_support is None:\n            lineage_support = None\n        else:\n            lineage_support = longest_lineage_support[:parameter_dimensionality]\n        result[parameter_name] = AutoBatchCastingConfig(\n            casted_dimensionality=parameter_dimensionality,\n            lineage_support=lineage_support,\n        )\n    return result\n\n\ndef find_longest_lineage_support(\n    all_lineages_of_batch_parameters: List[List[str]],\n) -> Optional[List[str]]:\n    longest_longest_lineage_support = []\n    for lineage in all_lineages_of_batch_parameters:\n        if len(lineage) > len(longest_longest_lineage_support):\n            longest_longest_lineage_support = lineage\n    if len(longest_longest_lineage_support) == 0:\n        return None\n    return longest_longest_lineage_support\n\n\ndef get_lineage_for_input_property(\n    step_name: str,\n    property_name: str,\n    input_definition: Union[StepInputDefinition, CompoundStepInputDefinition],\n    lineage_deduplication_set: Set[int],\n) -> List[List[str]]:\n    if input_definition.is_compound_input():\n        return get_lineage_from_compound_input(\n            step_name=step_name,\n            property_name=property_name,\n            input_definition=input_definition,\n            lineage_deduplication_set=lineage_deduplication_set,\n        )\n    lineages = []\n    if input_definition.is_batch_oriented():\n        lineage = input_definition.data_lineage\n        lineage_id = identify_lineage(lineage=lineage)\n        if lineage_id not in lineage_deduplication_set:\n            lineage_deduplication_set.add(lineage_id)\n            lineages.append(lineage)\n    return lineages\n\n\ndef get_lineage_from_compound_input(\n    step_name: str,\n    property_name: str,\n    input_definition: Union[StepInputDefinition, CompoundStepInputDefinition],\n    lineage_deduplication_set: Set[int],\n) -> List[List[str]]:\n    lineages = []\n    for nested_element in input_definition.iterate_through_definitions():\n        if nested_element.is_batch_oriented():\n            lineage = nested_element.data_lineage\n            lineage_id = identify_lineage(lineage=lineage)\n            if lineage_id not in lineage_deduplication_set:\n                lineage_deduplication_set.add(lineage_id)\n                lineages.append(lineage)\n    if len(lineages) > 1:\n        raise StepInputLineageError(\n            public_message=f\"Input data provided for step: `{step_name}` comes with multiple different lineages \"\n            f\"{lineages} for property `{property_name}` accepting \"\n            f\"multiple selectors, which is not allowed.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    return lineages\n\n\ndef verify_lineages(step_name: str, detected_lineages: List[List[str]]) -> None:\n    lineages_by_length = defaultdict(list)\n    for lineage in detected_lineages:\n        lineages_by_length[len(lineage)].append(lineage)\n    if len(lineages_by_length) > 2:\n        raise StepInputLineageError(\n            public_message=f\"Input data provided for step: `{step_name}` comes with lineages at more than two \"\n            f\"dimensionality levels, which should not be possible.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    lineage_lengths = sorted(lineages_by_length.keys())\n    for lineage_length in lineage_lengths:\n        if len(lineages_by_length[lineage_length]) > 1:\n            raise StepInputLineageError(\n                public_message=f\"Among step `{step_name}` inputs found different lineages at the same  \"\n                f\"dimensionality levels dimensionality.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if len(lineages_by_length[lineage_lengths[-1]]) > 1 and len(lineage_lengths) < 2:\n        raise StepInputLineageError(\n            public_message=f\"If lineage differ at the last level, then Execution Engine requires at least one \"\n            f\"higher-dimension  input that will come with common lineage, but this is not the \"\n            f\"case for step {step_name}.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    if len(lineage_lengths) == 2:\n        reference_lineage = lineages_by_length[lineage_lengths[0]][0]\n        if reference_lineage != lineages_by_length[lineage_lengths[1]][0][:-1]:\n            raise StepInputLineageError(\n                public_message=f\"Step `{step_name}` inputs does not share common lineage. Differing element: \"\n                f\"{lineages_by_length[lineage_lengths[1]][0]}, \"\n                f\"reference lineage prefix: {reference_lineage}\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n\n\ndef establish_step_execution_dimensionality(\n    inputs_dimensionalities: Dict[str, Set[int]],\n    control_flow_lineage_support: List[str],\n    output_dimensionality_offset: int,\n) -> int:\n    \"\"\"\n    Determine how many batch dimensions (execution slices) a step runs with.\n\n    Used during workflow compilation in denote_data_flow_for_step. The result\n    is stored on StepNode.step_execution_dimensionality and consumed at\n    execution time to:\n    - Drive how many times the step is executed (which batch indices/slices).\n    - Align and expand inputs (e.g. auto-batch casting) to match this size.\n    - Validate that parameter dimensionalities are compatible (runtime checks\n      in step_input_assembler and manager).\n\n    Logic:\n    - If no input has non-zero dimensionality but the step is gated by\n      control flow (control_flow_lineage_support non-empty), the\n      dimensionality is the number of control-flow branches.\n    - Otherwise, the minimum non-zero input dimensionality is used; if\n      output_dimensionality_offset < 0 (step reduces batch dimension),\n      one is subtracted.\n\n    Args:\n        inputs_dimensionalities: Per-input sets of dimensionalities (from\n            get_inputs_dimensionalities).\n        control_flow_lineage_support: Lineage identifiers for control-flow\n            branches that gate this step (from establish_batch_oriented_step_lineage).\n        output_dimensionality_offset: Block's output dimensionality offset\n            (positive = expand, negative = reduce batch dimension).\n\n    Returns:\n        The number of batch dimensions (execution slices) for this step.\n    \"\"\"\n    step_execution_dimensionality = 0\n    non_zero_dimensionalities = {\n        dimensionality\n        for dimensionalities in inputs_dimensionalities.values()\n        for dimensionality in dimensionalities\n        if dimensionality > 0\n    }\n    if len(non_zero_dimensionalities) == 0 and len(control_flow_lineage_support) > 0:\n        return len(control_flow_lineage_support)\n    if len(non_zero_dimensionalities) > 0:\n        step_execution_dimensionality = min(non_zero_dimensionalities)\n        if output_dimensionality_offset < 0:\n            step_execution_dimensionality -= 1\n    return step_execution_dimensionality\n\n\ndef establish_batch_oriented_step_lineage(\n    step_selector: str,\n    all_data_derived_lineages: List[List[str]],\n    all_control_flow_lineages: List[List[str]],\n    input_data: StepInputData,\n    dimensionality_reference_property: Optional[str],\n    output_dimensionality_offset: int,\n) -> Tuple[List[str], List[str]]:\n    reference_lineage, control_flow_lineage_support = get_reference_lineage(\n        step_selector=step_selector,\n        all_data_derived_lineages=all_data_derived_lineages,\n        all_control_flow_lineages=all_control_flow_lineages,\n        input_data=input_data,\n        dimensionality_reference_property=dimensionality_reference_property,\n    )\n    if output_dimensionality_offset < 0:\n        result_dimensionality = reference_lineage[:output_dimensionality_offset]\n        return result_dimensionality, []\n    if output_dimensionality_offset == 0:\n        return reference_lineage, control_flow_lineage_support\n    reference_lineage.append(step_selector)\n    return reference_lineage, []\n\n\ndef get_reference_lineage(\n    step_selector: str,\n    all_data_derived_lineages: List[List[str]],\n    all_control_flow_lineages: List[List[str]],\n    input_data: StepInputData,\n    dimensionality_reference_property: Optional[str],\n) -> Tuple[List[str], List[str]]:\n    if not all_data_derived_lineages:\n        if len(all_control_flow_lineages) == 1:\n            return copy(all_control_flow_lineages[0]), copy(\n                all_control_flow_lineages[0]\n            )\n        # Multiple control-flow lineages and no data-derived lineage: pick the deepest.\n        max_lineage_len = max(len(lineage) for lineage in all_control_flow_lineages)\n        lineages_matching_max_len = [\n            _lineage\n            for _lineage in all_control_flow_lineages\n            if len(_lineage) == max_lineage_len\n        ]\n        if len(lineages_matching_max_len) == 1:\n            return copy(lineages_matching_max_len[0]), copy(\n                lineages_matching_max_len[0]\n            )\n        else:\n            raise AssumptionError(\n                public_message=f\"Multiple control-flow lineages at the same level for step `{step_selector}` \"\n                f\"and no data-derived lineage; unique lineage level required. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if len(all_data_derived_lineages) == 1:\n        return copy(all_data_derived_lineages[0]), []\n    if dimensionality_reference_property not in input_data:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` expected dimensionality_reference_property \"\n            f\"presence to be verified at earlier stages, which did not happen as expected. \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    property_data = input_data[dimensionality_reference_property]\n    if property_data.is_compound_input():\n        lineage = None\n        for nested_element in property_data.iterate_through_definitions():\n            if nested_element.is_batch_oriented():\n                lineage = copy(nested_element.data_lineage)\n                return lineage, []\n        if lineage is None:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n                f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if not property_data.is_batch_oriented():\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n            f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    return copy(property_data.data_lineage), []\n\n\ndef get_property_with_invalid_selector(\n    manifest: WorkflowBlockManifest, step_property: str\n) -> Optional[str]:\n    property_name = None\n    for key, value in manifest.__dict__.items():\n        if isinstance(value, str) and step_property in value:\n            property_name = key\n            break\n    return property_name\n\n\ndef add_super_input_node_in_execution_graph(\n    execution_graph: DiGraph,\n    super_input_node: str,\n) -> DiGraph:\n    nodes_to_attach_super_input_into = get_nodes_of_specific_category(\n        execution_graph=execution_graph,\n        category=NodeCategory.INPUT_NODE,\n    )\n    step_nodes_without_predecessors = [\n        node\n        for node in execution_graph.nodes\n        if not list(execution_graph.predecessors(node))\n    ]\n    nodes_to_attach_super_input_into.update(step_nodes_without_predecessors)\n    execution_graph.add_node(super_input_node)\n    for node in nodes_to_attach_super_input_into:\n        execution_graph.add_edge(super_input_node, node)\n    return execution_graph\n",
    "patch": null
  },
  {
    "trace_id": "c21c77ee-d784-456b-8b2d-b6d6a31c6a2f",
    "function_name": "separate_control_flow_predecessors_from_data_providers",
    "file_path": "inference/core/workflows/execution_engine/v1/compiler/graph_constructor.py",
    "speedup_x": 0.8722674638863921,
    "review_quality": "high",
    "pre_optimization_commit": "90243bdc6278ef7d17b6db09dc1eb5b0d155b4be",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def separate_control_flow_predecessors_from_data_providers(\n    execution_graph: DiGraph,\n    node: str,\n) -> Tuple[List[str], List[str]]:\n    all_predecessors = list(execution_graph.predecessors(node))\n    all_control_flow_predecessors = [\n        predecessor\n        for predecessor in all_predecessors\n        if is_control_flow_step(execution_graph=execution_graph, node=predecessor)\n    ]\n    all_non_control_flow_predecessors = [\n        predecessor\n        for predecessor in all_predecessors\n        if not is_control_flow_step(execution_graph=execution_graph, node=predecessor)\n    ]\n    return all_control_flow_predecessors, all_non_control_flow_predecessors\n",
    "optimized_function_code": "from typing import List, Tuple\n\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import \\\n    is_control_flow_step\nfrom networkx import DiGraph\n\n\ndef separate_control_flow_predecessors_from_data_providers(\n    execution_graph: DiGraph,\n    node: str,\n) -> Tuple[List[str], List[str]]:\n    all_control_flow_predecessors: List[str] = []\n    all_non_control_flow_predecessors: List[str] = []\n    append_cf = all_control_flow_predecessors.append\n    append_non = all_non_control_flow_predecessors.append\n\n    for predecessor in execution_graph.predecessors(node):\n        if is_control_flow_step(execution_graph=execution_graph, node=predecessor):\n            append_cf(predecessor)\n        else:\n            append_non(predecessor)\n\n    return all_control_flow_predecessors, all_non_control_flow_predecessors",
    "optimized_raw_markdown": "```python:inference/core/workflows/execution_engine/v1/compiler/utils.py\nfrom inference.core.workflows.execution_engine.constants import \\\n    NODE_COMPILATION_OUTPUT_PROPERTY\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import \\\n    NodeCategory\nfrom networkx import DiGraph\n\n\ndef is_control_flow_step(execution_graph: DiGraph, node: str) -> bool:\n    if not is_step_node(execution_graph=execution_graph, node=node):\n        return False\n    return execution_graph.nodes[node][NODE_COMPILATION_OUTPUT_PROPERTY].controls_flow()\n```\n```python:inference/core/workflows/execution_engine/v1/compiler/graph_constructor.py\nfrom typing import List, Tuple\n\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import \\\n    is_control_flow_step\nfrom networkx import DiGraph\n\n\ndef separate_control_flow_predecessors_from_data_providers(\n    execution_graph: DiGraph,\n    node: str,\n) -> Tuple[List[str], List[str]]:\n    all_control_flow_predecessors: List[str] = []\n    all_non_control_flow_predecessors: List[str] = []\n    append_cf = all_control_flow_predecessors.append\n    append_non = all_non_control_flow_predecessors.append\n\n    for predecessor in execution_graph.predecessors(node):\n        if is_control_flow_step(execution_graph=execution_graph, node=predecessor):\n            append_cf(predecessor)\n        else:\n            append_non(predecessor)\n\n    return all_control_flow_predecessors, all_non_control_flow_predecessors\n```",
    "optimized_function_only": "def separate_control_flow_predecessors_from_data_providers(\n    execution_graph: DiGraph,\n    node: str,\n) -> Tuple[List[str], List[str]]:\n    all_control_flow_predecessors: List[str] = []\n    all_non_control_flow_predecessors: List[str] = []\n    append_cf = all_control_flow_predecessors.append\n    append_non = all_non_control_flow_predecessors.append\n\n    for predecessor in execution_graph.predecessors(node):\n        if is_control_flow_step(execution_graph=execution_graph, node=predecessor):\n            append_cf(predecessor)\n        else:\n            append_non(predecessor)\n\n    return all_control_flow_predecessors, all_non_control_flow_predecessors",
    "original_file_content": "import itertools\nfrom collections import defaultdict\nfrom copy import copy, deepcopy\nfrom typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union\nfrom uuid import uuid4\n\nimport networkx as nx\nfrom networkx import DiGraph\n\nfrom inference.core import logger\nfrom inference.core.workflows.errors import (\n    AssumptionError,\n    BlockInterfaceError,\n    ControlFlowDefinitionError,\n    ExecutionGraphStructureError,\n    InvalidReferenceTargetError,\n    StepInputDimensionalityError,\n    StepInputLineageError,\n    WorkflowBlockError,\n)\nfrom inference.core.workflows.execution_engine.constants import (\n    NODE_COMPILATION_OUTPUT_PROPERTY,\n    PARSED_NODE_INPUT_SELECTORS_PROPERTY,\n    TOP_LEVEL_LINEAGES_KEY,\n    WORKFLOW_INPUT_BATCH_LINEAGE_ID,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    InputType,\n    JsonField,\n    OutputDefinition,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    STEP_AS_SELECTED_ELEMENT,\n    Kind,\n)\nfrom inference.core.workflows.execution_engine.introspection.entities import (\n    ParsedSelector,\n)\nfrom inference.core.workflows.execution_engine.introspection.selectors_parser import (\n    get_step_selectors,\n)\nfrom inference.core.workflows.execution_engine.profiling.core import (\n    WorkflowsProfiler,\n    execution_phase,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import (\n    AutoBatchCastingConfig,\n    CompoundStepInputDefinition,\n    DictOfStepInputDefinitions,\n    DynamicStepInputDefinition,\n    ExecutionGraphNode,\n    InputDimensionalitySpecification,\n    InputNode,\n    ListOfStepInputDefinitions,\n    NodeCategory,\n    NodeInputCategory,\n    OutputNode,\n    ParameterSpecification,\n    ParsedWorkflowDefinition,\n    PropertyPredecessorDefinition,\n    StaticStepInputDefinition,\n    StepInputData,\n    StepInputDefinition,\n    StepNode,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.graph_traversal import (\n    traverse_graph_ensuring_parents_are_reached_first,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.reference_type_checker import (\n    validate_reference_kinds,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import (\n    construct_input_selector,\n    construct_output_selector,\n    construct_step_selector,\n    get_last_chunk_of_selector,\n    get_nodes_of_specific_category,\n    get_step_selector_from_its_output,\n    identify_lineage,\n    is_control_flow_step,\n    is_input_node,\n    is_input_selector,\n    is_output_node,\n    is_step_node,\n    is_step_output_selector,\n    is_step_selector,\n    node_as,\n)\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nNODE_DEFINITION_KEY = \"definition\"\nSTEP_INPUT_SELECTORS_PROPERTY = \"step_input_selectors\"\nEXCLUDED_FIELDS = {\"type\", \"name\"}\n\n\n@execution_phase(\n    name=\"execution_graph_creation\",\n    categories=[\"execution_engine_operation\"],\n)\ndef prepare_execution_graph(\n    workflow_definition: ParsedWorkflowDefinition,\n    profiler: Optional[WorkflowsProfiler] = None,\n) -> DiGraph:\n    execution_graph = construct_graph(\n        workflow_definition=workflow_definition,\n    )\n    if not nx.is_directed_acyclic_graph(execution_graph):\n        raise ExecutionGraphStructureError(\n            public_message=f\"Detected cycle in execution graph. This means that there is output from one \"\n            f\"step that is connected to input of other step creating loop in the graph that would \"\n            f\"never end if executed.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    return denote_data_flow_in_workflow(\n        execution_graph=execution_graph,\n        parsed_workflow_definition=workflow_definition,\n    )\n\n\ndef construct_graph(\n    workflow_definition: ParsedWorkflowDefinition,\n) -> DiGraph:\n    execution_graph = nx.DiGraph()\n    execution_graph = add_input_nodes_for_graph(\n        inputs=workflow_definition.inputs,\n        execution_graph=execution_graph,\n    )\n    execution_graph = add_steps_nodes_for_graph(\n        steps=workflow_definition.steps,\n        execution_graph=execution_graph,\n    )\n    execution_graph = add_output_nodes_for_graph(\n        outputs=workflow_definition.outputs,\n        execution_graph=execution_graph,\n    )\n    execution_graph = add_steps_edges(\n        workflow_definition=workflow_definition,\n        execution_graph=execution_graph,\n    )\n    return add_edges_for_outputs(\n        workflow_definition=workflow_definition,\n        execution_graph=execution_graph,\n    )\n\n\ndef add_input_nodes_for_graph(\n    inputs: List[InputType],\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for input_spec in inputs:\n        input_selector = construct_input_selector(input_name=input_spec.name)\n        if input_spec.is_batch_oriented():\n            if input_spec.dimensionality < 1:\n                raise ExecutionGraphStructureError(\n                    public_message=f\"Detected batch oriented input `{input_spec.name}` with \"\n                    f\"declared dimensionality `{input_spec.dimensionality}` which is below \"\n                    f\"one (one is minimum dimensionality of the batch). Fix input definition in\"\n                    f\"your Workflow.\",\n                    context=\"workflow_compilation | execution_graph_construction\",\n                )\n            data_lineage = [WORKFLOW_INPUT_BATCH_LINEAGE_ID]\n            for _ in range(input_spec.dimensionality - 1):\n                # TODO: this may end up being a bug - with ability for multi-step debugging, if we will\n                #  ever have a situation that there will be multiple step outputs with nested\n                #  dimensionality with the same lineage, this re-construction method will\n                #  assign a different lineage identifier, causing the inputs being non-composable in\n                #  a single execution branch\n                data_lineage.append(f\"{uuid4()}\")\n        else:\n            data_lineage = []\n        compilation_output = InputNode(\n            node_category=NodeCategory.INPUT_NODE,\n            name=input_spec.name,\n            selector=input_selector,\n            data_lineage=data_lineage,\n            input_manifest=input_spec,\n        )\n        execution_graph.add_node(\n            input_selector,\n            **{\n                NODE_COMPILATION_OUTPUT_PROPERTY: compilation_output,\n            },\n        )\n    return execution_graph\n\n\ndef add_steps_nodes_for_graph(\n    steps: List[WorkflowBlockManifest],\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for step in steps:\n        step_selector = construct_step_selector(step_name=step.name)\n        compilation_output = StepNode(\n            node_category=NodeCategory.STEP_NODE,\n            name=step.name,\n            selector=step_selector,\n            data_lineage=[],\n            step_manifest=step,\n        )\n        execution_graph.add_node(\n            step_selector,\n            **{\n                NODE_COMPILATION_OUTPUT_PROPERTY: compilation_output,\n            },\n        )\n    return execution_graph\n\n\ndef add_output_nodes_for_graph(\n    outputs: List[JsonField],\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for output_spec in outputs:\n        output_selector = construct_output_selector(name=output_spec.name)\n        compilation_output = OutputNode(\n            node_category=NodeCategory.OUTPUT_NODE,\n            name=output_spec.name,\n            selector=output_selector,\n            data_lineage=[],\n            output_manifest=output_spec,\n        )\n        execution_graph.add_node(\n            output_selector,\n            **{\n                NODE_COMPILATION_OUTPUT_PROPERTY: compilation_output,\n            },\n        )\n    return execution_graph\n\n\ndef add_steps_edges(\n    workflow_definition: ParsedWorkflowDefinition,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for step in workflow_definition.steps:\n        source_step_selector = construct_step_selector(step_name=step.name)\n        step_selectors = get_step_selectors(step_manifest=step)\n        execution_graph.nodes[source_step_selector][\n            PARSED_NODE_INPUT_SELECTORS_PROPERTY\n        ] = step_selectors\n        execution_graph = add_edges_for_step(\n            execution_graph=execution_graph,\n            source_step_selector=source_step_selector,\n            target_step_parsed_selectors=step_selectors,\n        )\n    return execution_graph\n\n\ndef add_edges_for_step(\n    execution_graph: DiGraph,\n    source_step_selector: str,\n    target_step_parsed_selectors: List[ParsedSelector],\n) -> DiGraph:\n    for target_step_parsed_selector in target_step_parsed_selectors:\n        execution_graph = add_edge_for_step(\n            execution_graph=execution_graph,\n            source_step_selector=source_step_selector,\n            target_step_parsed_selector=target_step_parsed_selector,\n        )\n    return execution_graph\n\n\ndef add_edge_for_step(\n    execution_graph: DiGraph,\n    source_step_selector: str,\n    target_step_parsed_selector: ParsedSelector,\n) -> DiGraph:\n    target_step_selector = get_step_selector_from_its_output(\n        step_output_selector=target_step_parsed_selector.value\n    )\n    verify_edge_is_created_between_existing_nodes(\n        execution_graph=execution_graph,\n        start=source_step_selector,\n        end=target_step_selector,\n    )\n    if is_step_selector(target_step_parsed_selector.value):\n        return establish_control_flow_edge(\n            source_step_selector=source_step_selector,\n            target_step_parsed_selector=target_step_parsed_selector,\n            execution_graph=execution_graph,\n        )\n    if is_input_selector(target_step_parsed_selector.value):\n        input_node_compilation_data = node_as(\n            execution_graph=execution_graph,\n            node=target_step_parsed_selector.value,\n            expected_type=InputNode,\n        )\n        actual_input_kind = input_node_compilation_data.input_manifest.kind\n    else:\n        other_step_compilation_data = node_as(\n            execution_graph=execution_graph,\n            node=target_step_selector,\n            expected_type=StepNode,\n        )\n        source_step_compilation_data = node_as(\n            execution_graph=execution_graph,\n            node=source_step_selector,\n            expected_type=StepNode,\n        )\n        actual_input_kind = get_kind_of_value_provided_in_step_output(\n            step_manifest=other_step_compilation_data.step_manifest,\n            step_property=get_last_chunk_of_selector(\n                selector=target_step_parsed_selector.value\n            ),\n            source_step_manifest=source_step_compilation_data.step_manifest,\n        )\n    expected_input_kind = list(\n        itertools.chain.from_iterable(\n            ref.kind\n            for ref in target_step_parsed_selector.definition.allowed_references\n        )\n    )\n    error_message = (\n        f\"Failed to validate reference provided for step: {source_step_selector} regarding property: \"\n        f\"{target_step_parsed_selector.definition.property_name} with value: {target_step_parsed_selector.value}. \"\n        f\"Allowed kinds of references for this property: {list(set(e.name for e in expected_input_kind))}. \"\n        f\"Types of output for referred property: \"\n        f\"{list(set(a.name if isinstance(a, Kind) else a for a in actual_input_kind))}\"\n    )\n    validate_reference_kinds(\n        expected=expected_input_kind,\n        actual=actual_input_kind,\n        error_message=error_message,\n    )\n    if execution_graph.has_edge(target_step_selector, source_step_selector):\n        edge_data = execution_graph.edges[(target_step_selector, source_step_selector)]\n        if STEP_INPUT_SELECTORS_PROPERTY not in edge_data:\n            edge_data[STEP_INPUT_SELECTORS_PROPERTY] = []\n        edge_data[STEP_INPUT_SELECTORS_PROPERTY].append(\n            target_step_parsed_selector,\n        )\n    else:\n        execution_graph.add_edge(\n            target_step_selector,\n            source_step_selector,\n            **{STEP_INPUT_SELECTORS_PROPERTY: [target_step_parsed_selector]},\n        )\n    return execution_graph\n\n\ndef establish_control_flow_edge(\n    source_step_selector: str,\n    target_step_parsed_selector: ParsedSelector,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    if not step_definition_allows_control_flow_references(\n        parsed_selector=target_step_parsed_selector\n    ):\n        raise ExecutionGraphStructureError(\n            public_message=f\"Detected reference to other step in manifest of step {source_step_selector}. \"\n            f\"This is not allowed, as step manifest does not define any properties of type `StepSelector` \"\n            f\"allowing for defining connections between steps that represent flow control in `workflows`.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    target_step_selector = get_step_selector_from_its_output(\n        step_output_selector=target_step_parsed_selector.value\n    )\n    source_compilation_data = node_as(\n        execution_graph=execution_graph,\n        node=source_step_selector,\n        expected_type=StepNode,\n    )\n    target_compilation_data = node_as(\n        execution_graph=execution_graph,\n        node=target_step_selector,\n        expected_type=StepNode,\n    )\n    nodes_categories = {\n        source_compilation_data.node_category,\n        target_compilation_data.node_category,\n    }\n    if nodes_categories != {NodeCategory.STEP_NODE}:\n        raise ExecutionGraphStructureError(\n            public_message=f\"Attempted to create flow-control connection between workflow nodes: \"\n            f\"{source_step_selector} and {target_step_selector}, one of which is not denoted\"\n            f\"as step node.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    execution_graph.add_edge(\n        source_step_selector,\n        target_step_selector,\n    )\n    if target_step_selector in source_compilation_data.child_execution_branches:\n        raise ExecutionGraphStructureError(\n            public_message=f\"While establishing flow-control connection between source `{source_step_selector}` \"\n            f\"and target `{target_step_selector}` it was discovered that source step defines\"\n            f\"control flow transition into target one more than once, which is not allowed as \"\n            f\"that situation creates ambiguity in selecting execution branch.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    execution_branch_name = f\"Branch[{source_step_selector} -> {target_step_parsed_selector.definition.property_name}]\"\n    source_compilation_data.child_execution_branches[target_step_selector] = (\n        execution_branch_name\n    )\n    target_compilation_data.execution_branches_impacting_inputs.add(\n        execution_branch_name\n    )\n    return execution_graph\n\n\ndef step_definition_allows_control_flow_references(\n    parsed_selector: ParsedSelector,\n) -> bool:\n    return any(\n        definition.selected_element == STEP_AS_SELECTED_ELEMENT\n        for definition in parsed_selector.definition.allowed_references\n    )\n\n\ndef get_kind_of_value_provided_in_step_output(\n    step_manifest: WorkflowBlockManifest,\n    step_property: str,\n    source_step_manifest: WorkflowBlockManifest,\n) -> List[Kind]:\n    referred_node_outputs = step_manifest.get_actual_outputs()\n    actual_kind = []\n    matched_property = False\n    for output in referred_node_outputs:\n        if output.name != step_property:\n            continue\n        matched_property = True\n        actual_kind.extend(output.kind)\n    if not matched_property:\n        property_name = get_property_with_invalid_selector(\n            manifest=source_step_manifest,\n            step_property=step_property,\n        )\n        raise ExecutionGraphStructureError(\n            public_message=f\"Found reference to non-existing property `{step_property}` of step `{step_manifest.name}`.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=source_step_manifest.name,\n                    block_type=source_step_manifest.type,\n                    property_name=property_name,\n                    property_details=f\"'{step_manifest.name}.{step_property}' is an invalid reference\",\n                )\n            ],\n        )\n    return actual_kind\n\n\ndef add_edges_for_step_inputs(\n    execution_graph: DiGraph,\n    input_selectors: Set[str],\n    step_selector: str,\n) -> DiGraph:\n    for input_selector in input_selectors:\n        if is_step_output_selector(selector_or_value=input_selector):\n            input_selector = get_step_selector_from_its_output(\n                step_output_selector=input_selector\n            )\n        verify_edge_is_created_between_existing_nodes(\n            execution_graph=execution_graph,\n            start=input_selector,\n            end=step_selector,\n        )\n        execution_graph.add_edge(input_selector, step_selector)\n    return execution_graph\n\n\ndef add_edges_for_outputs(\n    workflow_definition: ParsedWorkflowDefinition,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for output in workflow_definition.outputs:\n        node_selector = output.selector\n        if is_step_output_selector(selector_or_value=node_selector):\n            node_selector = get_step_selector_from_its_output(\n                step_output_selector=node_selector\n            )\n        output_selector = construct_output_selector(name=output.name)\n        verify_edge_is_created_between_existing_nodes(\n            execution_graph=execution_graph,\n            start=node_selector,\n            end=output_selector,\n        )\n        output_node_manifest = node_as(\n            execution_graph=execution_graph,\n            node=output_selector,\n            expected_type=OutputNode,\n        )\n        if is_step_output_selector(selector_or_value=output.selector):\n            step_manifest = execution_graph.nodes[node_selector][\n                NODE_COMPILATION_OUTPUT_PROPERTY\n            ].step_manifest\n            step_outputs = step_manifest.get_actual_outputs()\n            denote_output_node_kind_based_on_step_outputs(\n                output_selector=output.selector,\n                step_outputs=step_outputs,\n                output_node_manifest=output_node_manifest,\n            )\n        else:\n            input_manifest = node_as(\n                execution_graph=execution_graph,\n                node=node_selector,\n                expected_type=InputNode,\n            ).input_manifest\n            output_node_manifest.kind = copy(input_manifest.kind)\n        execution_graph.add_edge(node_selector, output_selector)\n    return execution_graph\n\n\ndef verify_edge_is_created_between_existing_nodes(\n    execution_graph: DiGraph,\n    start: str,\n    end: str,\n) -> None:\n    if not execution_graph.has_node(start) or not execution_graph.has_node(end):\n        invalid_block = start if not execution_graph.has_node(start) else end\n        referencing_block = end if invalid_block == start else start\n\n        step_type = None\n        property_name = None\n        if execution_graph.has_node(referencing_block):\n            if is_step_node(execution_graph, referencing_block):\n                step_manifest = node_as(\n                    execution_graph=execution_graph,\n                    node=referencing_block,\n                    expected_type=StepNode,\n                ).step_manifest\n                step_type = step_manifest.type\n                property_name = get_property_with_invalid_selector(\n                    manifest=step_manifest,\n                    step_property=invalid_block,\n                )\n\n        block_id = (\n            \"$outputs\"\n            if referencing_block.startswith(\"$outputs.\")\n            else get_last_chunk_of_selector(selector=referencing_block)\n        )\n        property_name = (\n            get_last_chunk_of_selector(selector=referencing_block)\n            if referencing_block.startswith(\"$outputs.\")\n            else property_name\n        )\n\n        is_input = is_input_selector(selector_or_value=invalid_block)\n        raise InvalidReferenceTargetError(\n            public_message=f\"Workflow references '{invalid_block}' which points to a non-existent {is_input and 'input parameter' or 'block'}.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=block_id,\n                    block_type=step_type,\n                    property_name=property_name,\n                    property_details=f\"Invalid reference to {invalid_block}\",\n                ),\n            ],\n        )\n\n\ndef denote_output_node_kind_based_on_step_outputs(\n    output_selector: str,\n    step_outputs: List[OutputDefinition],\n    output_node_manifest: OutputNode,\n) -> None:\n    selected_output_name = get_last_chunk_of_selector(selector=output_selector)\n    kinds_for_outputs = {output.name: output.kind for output in step_outputs}\n\n    if selected_output_name == \"*\":\n        output_node_manifest.kind = deepcopy(kinds_for_outputs)\n        return None\n    if selected_output_name not in kinds_for_outputs:\n        output_name = output_node_manifest.output_manifest.name\n\n        raise InvalidReferenceTargetError(\n            public_message=f\"Workflow output references '{output_selector}' which points to a non-existent block property.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=\"$outputs\",\n                    property_name=output_name,\n                    property_details=f\"Invalid reference to {output_selector}\",\n                ),\n            ],\n        )\n    output_node_manifest.kind = copy(kinds_for_outputs[selected_output_name])\n    return None\n\n\ndef denote_data_flow_in_workflow(\n    execution_graph: DiGraph,\n    parsed_workflow_definition: ParsedWorkflowDefinition,\n) -> nx.DiGraph:\n    block_manifest_by_step_name = {\n        step.name: step for step in parsed_workflow_definition.steps\n    }\n    super_input_node = \"<super-input>\"\n    execution_graph = add_super_input_node_in_execution_graph(\n        execution_graph=execution_graph,\n        super_input_node=super_input_node,\n    )\n    execution_graph.nodes[super_input_node][NODE_COMPILATION_OUTPUT_PROPERTY] = (\n        InputNode(\n            node_category=NodeCategory.INPUT_NODE,\n            name=super_input_node,\n            selector=f\"$inputs.{super_input_node}\",\n            data_lineage=[],\n            input_manifest=None,  # this is expected never to be reached\n        )\n    )\n    top_level_data_lineage = set()\n    for node in traverse_graph_ensuring_parents_are_reached_first(\n        graph=execution_graph,\n        start_node=super_input_node,\n    ):\n        execution_graph = denote_data_flow_for_node(\n            execution_graph=execution_graph,\n            node=node,\n            block_manifest_by_step_name=block_manifest_by_step_name,\n            on_top_level_lineage_denoted=lambda element: top_level_data_lineage.add(\n                element\n            ),\n        )\n    execution_graph.remove_node(super_input_node)\n    execution_graph.graph[TOP_LEVEL_LINEAGES_KEY] = top_level_data_lineage\n    return execution_graph\n\n\ndef denote_data_flow_for_node(\n    execution_graph: DiGraph,\n    node: str,\n    block_manifest_by_step_name: Dict[str, WorkflowBlockManifest],\n    on_top_level_lineage_denoted: Callable[[str], None],\n) -> DiGraph:\n    if is_input_node(execution_graph=execution_graph, node=node):\n        # everything already set there, in the previous stage of compilation\n        return execution_graph\n    if is_step_node(execution_graph=execution_graph, node=node):\n        step_name = get_last_chunk_of_selector(selector=node)\n        if step_name not in block_manifest_by_step_name:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler expected manifest for the step: {step_name} to be registered \"\n                f\"but this condition is not met. This is most likely the bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | retrieving_predecessors_for_output\",\n            )\n        manifest = block_manifest_by_step_name[step_name]\n        return denote_data_flow_for_step(\n            execution_graph=execution_graph,\n            node=node,\n            manifest=manifest,\n            on_top_level_lineage_denoted=on_top_level_lineage_denoted,\n        )\n    if is_output_node(execution_graph=execution_graph, node=node):\n        # output is allowed to have exactly one predecessor\n        output_predecessors = list(execution_graph.predecessors(node))\n        if len(output_predecessors) != 1:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler expected each output in compiled graph to have one predecessor, \"\n                f\"but this condition is not met for node {node}. This is most likely the bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | retrieving_predecessors_for_output\",\n            )\n        predecessor_node = output_predecessors[0]\n        predecessor_node_data = node_as(\n            execution_graph=execution_graph,\n            node=predecessor_node,\n            expected_type=ExecutionGraphNode,\n        )\n        predecessor_node_lineage = predecessor_node_data.data_lineage\n        output_node_data = node_as(\n            execution_graph=execution_graph,\n            node=node,\n            expected_type=OutputNode,\n        )\n        output_node_data.data_lineage = predecessor_node_lineage\n        return execution_graph\n    raise AssumptionError(\n        f\"Workflow Compiler encountered node: {node} which cannot be classified as known node type. \"\n        f\"This is most likely the bug. Contact Roboflow team through github issues \"\n        f\"(https://github.com/roboflow/inference/issues) providing full \"\n        f\"context of the problem - including workflow definition you use.\",\n        context=\"workflow_compilation | execution_graph_construction | denoting_data_flow_for_step\",\n    )\n\n\ndef denote_data_flow_for_step(\n    execution_graph: DiGraph,\n    node: str,\n    manifest: WorkflowBlockManifest,\n    on_top_level_lineage_denoted: Callable[[str], None],\n) -> DiGraph:\n    all_control_flow_predecessors, all_non_control_flow_predecessors = (\n        separate_control_flow_predecessors_from_data_providers(\n            execution_graph=execution_graph, node=node\n        )\n    )\n    input_data = build_input_data_for_step(\n        manifest=manifest,\n        step_node=node,\n        data_providing_predecessors=all_non_control_flow_predecessors,\n        execution_graph=execution_graph,\n    )\n    step_name = get_last_chunk_of_selector(node)\n    step_node_data = node_as(\n        execution_graph=execution_graph,\n        node=node,\n        expected_type=StepNode,\n    )\n    parsed_step_input_selectors: List[ParsedSelector] = execution_graph.nodes[node][\n        PARSED_NODE_INPUT_SELECTORS_PROPERTY\n    ]\n    batch_compatibility_of_properties = retrieve_batch_compatibility_of_input_selectors(\n        input_selectors=parsed_step_input_selectors\n    )\n    scalar_parameters_to_be_batched = (\n        verify_declared_batch_compatibility_against_actual_inputs(\n            node=node,\n            step_node_data=step_node_data,\n            input_data=input_data,\n            batch_compatibility_of_properties=batch_compatibility_of_properties,\n        )\n    )\n    input_dimensionality_offsets = manifest.get_input_dimensionality_offsets()\n    verify_step_input_dimensionality_offsets(\n        step_name=step_name,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n    )\n    inputs_dimensionalities = get_inputs_dimensionalities(\n        step_name=step_name,\n        step_type=manifest.type,\n        input_data=input_data,\n        scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n    )\n    logger.debug(\n        f\"For step: {node}, detected the following input dimensionalities: {inputs_dimensionalities}\"\n    )\n    parameters_with_batch_inputs = grab_parameters_defining_batch_inputs(\n        inputs_dimensionalities=inputs_dimensionalities,\n    )\n    dimensionality_reference_property = manifest.get_dimensionality_reference_property()\n    output_dimensionality_offset = manifest.get_output_dimensionality_offset()\n    verify_step_input_dimensionality_offsets(\n        step_name=step_name,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n    )\n    verify_output_offset(\n        step_name=step_name,\n        parameters_with_batch_inputs=parameters_with_batch_inputs,\n        dimensionality_reference_property=dimensionality_reference_property,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n        output_dimensionality_offset=output_dimensionality_offset,\n    )\n    verify_input_data_dimensionality(\n        step_name=step_name,\n        step_type=manifest.type,\n        dimensionality_reference_property=dimensionality_reference_property,\n        inputs_dimensionalities=inputs_dimensionalities,\n        dimensionality_offstes=input_dimensionality_offsets,\n    )\n    all_data_derived_lineages = get_input_data_lineage_excluding_auto_batch_casting(\n        step_name=step_name,\n        input_data=input_data,\n        scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n    )\n    all_control_flow_lineages = get_lineage_derived_from_control_flow(\n        control_flow_steps_selectors=all_control_flow_predecessors,\n        execution_graph=execution_graph,\n    )\n    verify_compatibility_of_input_data_lineage_with_control_flow_lineage(\n        step_name=step_name,\n        inputs_lineage=all_data_derived_lineages,\n        control_flow_steps_selectors=all_control_flow_predecessors,\n        execution_graph=execution_graph,\n    )\n    step_node_data.input_data = input_data\n    step_node_data.dimensionality_reference_property = dimensionality_reference_property\n    step_node_data.control_flow_lineage_dims = [\n        len(_lineage) for _lineage in all_control_flow_lineages if _lineage\n    ]\n    step_node_data.batch_oriented_parameters = parameters_with_batch_inputs\n    if not all_data_derived_lineages and not all_control_flow_lineages:\n        if manifest.get_output_dimensionality_offset() > 0:\n            # brave decision to open a Pandora box\n            data_lineage = [node]\n        else:\n            data_lineage = []\n        control_flow_lineage_support = []\n    else:\n        data_lineage, control_flow_lineage_support = (\n            establish_batch_oriented_step_lineage(\n                step_selector=node,\n                all_data_derived_lineages=all_data_derived_lineages,\n                all_control_flow_lineages=all_control_flow_lineages,\n                input_data=input_data,\n                dimensionality_reference_property=dimensionality_reference_property,\n                output_dimensionality_offset=output_dimensionality_offset,\n            )\n        )\n    step_node_data.step_execution_dimensionality = (\n        establish_step_execution_dimensionality(\n            inputs_dimensionalities=inputs_dimensionalities,\n            control_flow_lineage_support=control_flow_lineage_support,\n            output_dimensionality_offset=output_dimensionality_offset,\n        )\n    )\n    lineage_supports = get_lineage_support_for_auto_batch_casted_parameters(\n        input_dimensionalities=inputs_dimensionalities,\n        all_lineages_of_batch_parameters=all_data_derived_lineages,\n        scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n    )\n    step_node_data.auto_batch_casting_lineage_supports = lineage_supports\n    step_node_data.control_flow_lineage_support = control_flow_lineage_support\n    if data_lineage:\n        on_top_level_lineage_denoted(data_lineage[0])\n    step_node_data.data_lineage = data_lineage\n    return execution_graph\n\n\ndef _collect_unique_control_flow_lineages_with_step_mapping(\n    control_flow_steps_selectors: List[str],\n    execution_graph: nx.DiGraph,\n) -> Tuple[List[List[str]], Dict[int, List[str]]]:\n    \"\"\"\n    Collect data lineages from control flow steps and deduplicate by lineage id.\n\n    For each given control flow step selector, reads its data_lineage from the\n    execution graph. Returns unique non-empty lineages (by identify_lineage id)\n    and a mapping from lineage id to every step selector that produced that\n    lineage (used e.g. for error reporting when lineage is incompatible).\n\n    Args:\n        control_flow_steps_selectors: Step selectors (node ids) of control\n            flow steps whose data_lineage is to be collected.\n        execution_graph: The workflow execution graph containing step nodes\n            and their data_lineage.\n\n    Returns:\n        A tuple of (unique_lineages, lineage_id_to_step_selectors):\n        - unique_lineages: list of distinct non-empty data lineages.\n        - lineage_id_to_step_selectors: map from lineage id to list of step\n          selectors whose data_lineage has that id (includes empty lineages).\n    \"\"\"\n    unique_lineages: List[List[str]] = []\n    seen_lineage_ids: Set[int] = set()\n    lineage_id_to_step_selectors: Dict[int, List[str]] = defaultdict(list)\n\n    for step_selector in control_flow_steps_selectors:\n        step_data = node_as(\n            execution_graph=execution_graph,\n            node=step_selector,\n            expected_type=StepNode,\n        )\n        lineage = step_data.data_lineage\n        lineage_id = identify_lineage(lineage)\n        lineage_id_to_step_selectors[lineage_id].append(step_selector)\n        if lineage and lineage_id not in seen_lineage_ids:\n            seen_lineage_ids.add(lineage_id)\n            unique_lineages.append(lineage)\n\n    return unique_lineages, dict(lineage_id_to_step_selectors)\n\n\ndef get_lineage_derived_from_control_flow(\n    control_flow_steps_selectors: List[str],\n    execution_graph: nx.DiGraph,\n) -> List[List[str]]:\n    \"\"\"\n    Return unique non-empty data lineages from the given control flow steps.\n\n    Each lineage is taken from the step's data_lineage in the execution graph.\n    Lineages are deduplicated by lineage id (see identify_lineage); empty\n    lineages are omitted. Used when establishing batch-oriented step lineage.\n\n    Args:\n        control_flow_steps_selectors: Step selectors (node ids) of control\n            flow steps whose data_lineage is to be collected.\n        execution_graph: The workflow execution graph containing step nodes\n            and their data_lineage.\n\n    Returns:\n        List of distinct non-empty data lineages, one per unique lineage id.\n    \"\"\"\n    unique_lineages, _ = _collect_unique_control_flow_lineages_with_step_mapping(\n        control_flow_steps_selectors=control_flow_steps_selectors,\n        execution_graph=execution_graph,\n    )\n    return unique_lineages\n\n\ndef separate_control_flow_predecessors_from_data_providers(\n    execution_graph: DiGraph,\n    node: str,\n) -> Tuple[List[str], List[str]]:\n    all_predecessors = list(execution_graph.predecessors(node))\n    all_control_flow_predecessors = [\n        predecessor\n        for predecessor in all_predecessors\n        if is_control_flow_step(execution_graph=execution_graph, node=predecessor)\n    ]\n    all_non_control_flow_predecessors = [\n        predecessor\n        for predecessor in all_predecessors\n        if not is_control_flow_step(execution_graph=execution_graph, node=predecessor)\n    ]\n    return all_control_flow_predecessors, all_non_control_flow_predecessors\n\n\ndef build_input_data_for_step(\n    manifest: WorkflowBlockManifest,\n    step_node: str,\n    data_providing_predecessors: List[str],\n    execution_graph: DiGraph,\n) -> StepInputData:\n    predecessors_by_property_name = get_predecessors_for_step_manifest_properties(\n        execution_graph=execution_graph,\n        step_node=step_node,\n        data_providing_predecessors=data_providing_predecessors,\n    )\n    manifest_fields_values = get_manifest_fields_values(step_manifest=manifest)\n    result = {}\n    for name, value in manifest_fields_values.items():\n        result[name] = build_input_property(\n            step_node=step_node,\n            manifest_property_name=name,\n            manifest_property_value=value,\n            predecessors_by_property_name=predecessors_by_property_name,\n            execution_graph=execution_graph,\n        )\n    return result\n\n\ndef get_predecessors_for_step_manifest_properties(\n    execution_graph: DiGraph, step_node: str, data_providing_predecessors: List[str]\n) -> Dict[str, List[PropertyPredecessorDefinition]]:\n    predecessors_by_property_name = defaultdict(list)\n    for predecessor in data_providing_predecessors:\n        edge_data = execution_graph.edges[(predecessor, step_node)]\n        # STEP_INPUT_SELECTORS_PROPERTY is optional, as special <super-input> node may be directly\n        # connected to step\n        selectors_associated_to_edge: List[ParsedSelector] = edge_data.get(\n            STEP_INPUT_SELECTORS_PROPERTY, []\n        )\n        for selector_associated_to_edge in selectors_associated_to_edge:\n            definition = PropertyPredecessorDefinition(\n                predecessor_selector=predecessor,\n                parsed_selector=selector_associated_to_edge,\n            )\n            predecessors_by_property_name[\n                selector_associated_to_edge.definition.property_name\n            ].append(definition)\n    return predecessors_by_property_name\n\n\ndef build_input_property(\n    step_node: str,\n    manifest_property_name: str,\n    manifest_property_value: Any,\n    predecessors_by_property_name: Dict[str, List[PropertyPredecessorDefinition]],\n    execution_graph: DiGraph,\n) -> Union[StepInputDefinition, CompoundStepInputDefinition]:\n    if manifest_property_name not in predecessors_by_property_name:\n        return StaticStepInputDefinition(\n            parameter_specification=ParameterSpecification(\n                parameter_name=manifest_property_name,\n            ),\n            category=NodeInputCategory.STATIC_VALUE,\n            value=manifest_property_value,\n        )\n    if isinstance(manifest_property_value, dict):\n        return build_nested_dictionary_for_input_property(\n            step_node=step_node,\n            manifest_property_name=manifest_property_name,\n            manifest_property_value=manifest_property_value,\n            predecessors_definitions=predecessors_by_property_name[\n                manifest_property_name\n            ],\n            execution_graph=execution_graph,\n        )\n    if isinstance(manifest_property_value, list):\n        return build_nested_list_for_input_property(\n            step_node=step_node,\n            manifest_property_name=manifest_property_name,\n            manifest_property_value=manifest_property_value,\n            predecessors_definitions=predecessors_by_property_name[\n                manifest_property_name\n            ],\n            execution_graph=execution_graph,\n        )\n    matching_predecessors_data = predecessors_by_property_name[manifest_property_name]\n    if len(matching_predecessors_data) != 1:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler deduced that property `{manifest_property_name}` of step `{step_node}` \"\n            f\"should be fed with data coming from exactly one execution graph node, but found \"\n            f\"{len(matching_predecessors_data)} data sources. This is most likely the bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n        )\n    predecessor_selector, predecessor_parsed_selector = (\n        matching_predecessors_data[0].predecessor_selector,\n        matching_predecessors_data[0].parsed_selector,\n    )\n    if is_input_node(execution_graph=execution_graph, node=predecessor_selector):\n        predecessor_node_data = node_as(\n            execution_graph=execution_graph,\n            node=matching_predecessors_data[0].predecessor_selector,\n            expected_type=InputNode,\n        )\n        category = (\n            NodeInputCategory.BATCH_INPUT_PARAMETER\n            if predecessor_node_data.is_batch_oriented()\n            else NodeInputCategory.NON_BATCH_INPUT_PARAMETER\n        )\n        return DynamicStepInputDefinition(\n            parameter_specification=ParameterSpecification(\n                parameter_name=manifest_property_name,\n            ),\n            category=category,\n            data_lineage=predecessor_node_data.data_lineage,\n            selector=predecessor_node_data.selector,\n        )\n    if is_step_node(execution_graph=execution_graph, node=predecessor_selector):\n        predecessor_node_data = node_as(\n            execution_graph=execution_graph,\n            node=matching_predecessors_data[0].predecessor_selector,\n            expected_type=StepNode,\n        )\n        category = (\n            NodeInputCategory.BATCH_STEP_OUTPUT\n            if predecessor_node_data.output_dimensionality > 0\n            else NodeInputCategory.NON_BATCH_STEP_OUTPUT\n        )\n        return DynamicStepInputDefinition(\n            parameter_specification=ParameterSpecification(\n                parameter_name=manifest_property_name,\n            ),\n            category=category,\n            data_lineage=predecessor_node_data.data_lineage,\n            selector=predecessor_parsed_selector.value,\n        )\n    raise AssumptionError(\n        public_message=f\"Workflow Compiler for property `{manifest_property_name}` of step `{step_node}` \"\n        f\"found data providing predecessor `{predecessor_selector}` which has unsupported step type.\"\n        f\"This is most likely the bug. \"\n        f\"Contact Roboflow team through github issues \"\n        f\"(https://github.com/roboflow/inference/issues) providing full \"\n        f\"context of the problem - including workflow definition you use.\",\n        context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n    )\n\n\ndef build_nested_dictionary_for_input_property(\n    step_node: str,\n    manifest_property_name: str,\n    manifest_property_value: dict,\n    predecessors_definitions: List[PropertyPredecessorDefinition],\n    execution_graph: DiGraph,\n) -> DictOfStepInputDefinitions:\n    nested_property_name2data: Dict[Optional[str], PropertyPredecessorDefinition] = {\n        predecessor_definition.parsed_selector.key: predecessor_definition\n        for predecessor_definition in predecessors_definitions\n    }\n    result = {}\n    for nested_dict_key, nested_dict_value in manifest_property_value.items():\n        if nested_dict_key not in nested_property_name2data:\n            result[nested_dict_key] = StaticStepInputDefinition(\n                parameter_specification=ParameterSpecification(\n                    parameter_name=manifest_property_name,\n                    nested_element_key=nested_dict_key,\n                ),\n                category=NodeInputCategory.STATIC_VALUE,\n                value=nested_dict_value,\n            )\n            continue\n        referred_node_selector = nested_property_name2data[\n            nested_dict_key\n        ].predecessor_selector\n        referred_node_parsed_selector = nested_property_name2data[\n            nested_dict_key\n        ].parsed_selector\n        if is_input_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=InputNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_INPUT_PARAMETER\n                if predecessor_node_data.is_batch_oriented()\n                else NodeInputCategory.NON_BATCH_INPUT_PARAMETER\n            )\n            result[nested_dict_key] = DynamicStepInputDefinition(\n                parameter_specification=ParameterSpecification(\n                    parameter_name=manifest_property_name,\n                    nested_element_key=nested_dict_key,\n                ),\n                category=category,\n                data_lineage=predecessor_node_data.data_lineage,\n                selector=predecessor_node_data.selector,\n            )\n            continue\n        if is_step_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=StepNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_STEP_OUTPUT\n                if predecessor_node_data.output_dimensionality > 0\n                else NodeInputCategory.NON_BATCH_STEP_OUTPUT\n            )\n            result[nested_dict_key] = DynamicStepInputDefinition(\n                parameter_specification=ParameterSpecification(\n                    parameter_name=manifest_property_name,\n                    nested_element_key=nested_dict_key,\n                ),\n                category=category,\n                data_lineage=predecessor_node_data.data_lineage,\n                selector=referred_node_parsed_selector.value,\n            )\n            continue\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for property `{manifest_property_name}` of step `{step_node}` \"\n            f\"found data providing predecessor `{referred_node_selector}` which has \"\n            f\"unsupported step type (key: {nested_dict_key} of nested data dictionary). \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n        )\n    return DictOfStepInputDefinitions(\n        name=manifest_property_name,\n        nested_definitions=result,\n    )\n\n\ndef get_manifest_fields_values(step_manifest: WorkflowBlockManifest) -> Dict[str, Any]:\n    result = {}\n    for field in step_manifest.model_fields:\n        if field in EXCLUDED_FIELDS:\n            continue\n        result[field] = getattr(step_manifest, field)\n    return result\n\n\ndef build_nested_list_for_input_property(\n    step_node: str,\n    manifest_property_name: str,\n    manifest_property_value: list,\n    predecessors_definitions: List[PropertyPredecessorDefinition],\n    execution_graph: DiGraph,\n) -> ListOfStepInputDefinitions:\n    nested_index2data: Dict[Optional[int], PropertyPredecessorDefinition] = {\n        e.parsed_selector.index: e for e in predecessors_definitions\n    }\n    result = []\n    for index, element in enumerate(manifest_property_value):\n        if index not in nested_index2data:\n            result.append(\n                StaticStepInputDefinition(\n                    parameter_specification=ParameterSpecification(\n                        parameter_name=manifest_property_name,\n                        nested_element_index=index,\n                    ),\n                    category=NodeInputCategory.STATIC_VALUE,\n                    value=element,\n                )\n            )\n            continue\n        referred_node_selector = nested_index2data[index].predecessor_selector\n        referred_node_parsed_selector = nested_index2data[index].parsed_selector\n        if is_input_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=InputNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_INPUT_PARAMETER\n                if predecessor_node_data.is_batch_oriented()\n                else NodeInputCategory.NON_BATCH_INPUT_PARAMETER\n            )\n            result.append(\n                DynamicStepInputDefinition(\n                    parameter_specification=ParameterSpecification(\n                        parameter_name=manifest_property_name,\n                        nested_element_index=index,\n                    ),\n                    category=category,\n                    data_lineage=predecessor_node_data.data_lineage,\n                    selector=predecessor_node_data.selector,\n                )\n            )\n            continue\n        if is_step_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=StepNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_STEP_OUTPUT\n                if predecessor_node_data.output_dimensionality > 0\n                else NodeInputCategory.NON_BATCH_STEP_OUTPUT\n            )\n            result.append(\n                DynamicStepInputDefinition(\n                    parameter_specification=ParameterSpecification(\n                        parameter_name=manifest_property_name,\n                        nested_element_index=index,\n                    ),\n                    category=category,\n                    data_lineage=predecessor_node_data.data_lineage,\n                    selector=referred_node_parsed_selector.value,\n                )\n            )\n            continue\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for property `{manifest_property_name}` of step `{step_node}` \"\n            f\"found data providing predecessor `{referred_node_selector}` which has \"\n            f\"unsupported step type (index: {index} of nested data list). \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n        )\n    return ListOfStepInputDefinitions(\n        name=manifest_property_name,\n        nested_definitions=result,\n    )\n\n\ndef verify_step_input_dimensionality_offsets(\n    step_name: str,\n    input_dimensionality_offsets: Dict[str, int],\n) -> None:\n    min_offset, max_offset = None, None\n    for offset in input_dimensionality_offsets.values():\n        if min_offset is None or offset < min_offset:\n            min_offset = offset\n        if max_offset is None or offset > max_offset:\n            max_offset = offset\n    if min_offset is None or max_offset is None:\n        return None\n    if min_offset < 0 or max_offset < 0:\n        raise BlockInterfaceError(\n            public_message=f\"Offsets could not be negative, but block defining step: {step_name} defines that values.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_input_offset_definitions\",\n        )\n    if abs(max_offset - min_offset) > 1:\n        raise BlockInterfaceError(\n            public_message=\"Offsets of input parameters could not differ more than 1, but block defining step {step_name} \"\n            f\"violates that rule.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_input_offset_definitions\",\n        )\n\n\ndef verify_output_offset(\n    step_name: str,\n    parameters_with_batch_inputs: Set[str],\n    input_dimensionality_offsets: Dict[str, int],\n    dimensionality_reference_property: Optional[str],\n    output_dimensionality_offset: int,\n) -> None:\n    if not parameters_with_batch_inputs and output_dimensionality_offset < 0:\n        raise StepInputDimensionalityError(\n            public_message=f\"Block defining step {step_name} defines negative dimensionality offset while only \"\n            f\"scalar inputs being provided - the block cannot run as there is no dimension to collapse.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if (\n        dimensionality_reference_property is not None\n        and dimensionality_reference_property not in parameters_with_batch_inputs\n    ):\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} defines dimensionality reference property \"\n            f\"which is not in scope of parameters bring batch-oriented input, which makes it impossible \"\n            f\"to use as reference for output dimensionality.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if output_dimensionality_offset not in {-1, 0, 1}:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} defines output dimensionality offset \"\n            f\"being {output_dimensionality_offset}, whereas it is only possible for that offset being \"\n            f\"in set [-1, 0, 1].\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    different_offsets = {o for o in input_dimensionality_offsets.values()}\n    if len(parameters_with_batch_inputs) != len(input_dimensionality_offsets):\n        # assumption of default offset being zero - and this one does not need to be manifested\n        # by block\n        different_offsets.add(0)\n    if 0 not in different_offsets and parameters_with_batch_inputs:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} explicitly defines input dimensionalities offsets\"\n            f\"with {input_dimensionality_offsets}, but the definition lack 0-level input, which is \"\n            f\"not allowed, as in this scenario offsets could be adjusted to include 0\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if len(different_offsets) > 1 and dimensionality_reference_property is None:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} explicitly defines input dimensionality \"\n            f\"offsets {input_dimensionality_offsets}. In this scenario it is required to provide dimensionality \"\n            f\"reference property.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if len(different_offsets) > 1 and output_dimensionality_offset != 0:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} explicitly defines input dimensionality \"\n            f\"offsets {input_dimensionality_offsets} and output dimensionality offset {output_dimensionality_offset} \"\n            f\"where the latter is not 0, but for inputs differing with dimensionality it is only possible to keep \"\n            f\"output dimensionality the same and point reference parameter.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n\n\ndef verify_input_data_dimensionality(\n    step_name: str,\n    step_type: str,\n    dimensionality_reference_property: Optional[str],\n    inputs_dimensionalities: Dict[str, Set[int]],\n    dimensionality_offstes: Dict[str, int],\n) -> None:\n    parameter_name2dimensionality_specification = (\n        grab_input_data_dimensionality_specifications(\n            step_name=step_name,\n            inputs_dimensionalities=inputs_dimensionalities,\n            dimensionality_offstes=dimensionality_offstes,\n        )\n    )\n    if not parameter_name2dimensionality_specification:\n        # nothing to check if no batch-oriented inputs\n        return None\n    different_dimensionalities_of_parameters = {\n        specification.actual_dimensionality\n        for specification in parameter_name2dimensionality_specification.values()\n    }\n    if dimensionality_reference_property is None:\n        if len(different_dimensionalities_of_parameters) > 1:\n            parameter2dimensionality = {\n                k: e.actual_dimensionality\n                for k, e in parameter_name2dimensionality_specification.items()\n            }\n            raise StepInputDimensionalityError(\n                public_message=f\"Block defining step {step_name} does not define dimensionality reference property, \"\n                f\"which means that all batch-oriented parameters must be at the same dimensionality level, \"\n                f\"but detected the following dimensionalities for parameters {parameter2dimensionality}\",\n                context=\"workflow_compilation | execution_graph_construction | denoting_step_inputs_dimensionality\",\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=step_name,\n                        block_type=step_type,\n                        block_details=f\"Dimensionality of input parameters doesn't match: {parameter2dimensionality}\",\n                    )\n                ],\n            )\n        return None\n    reference_specification = parameter_name2dimensionality_specification[\n        dimensionality_reference_property\n    ]\n    expected_dimensionalities = {\n        property_name: (e.expected_offset - reference_specification.expected_offset)\n        + reference_specification.actual_dimensionality\n        for property_name, e in parameter_name2dimensionality_specification.items()\n    }\n    if any(dim <= 0 for dim in expected_dimensionalities.values()):\n        raise StepInputDimensionalityError(\n            public_message=f\"Given the definition of block defining step {step_name} and data provided, \"\n            f\"the block would expect batch input dimensionality to be 0 or below, which is invalid.\",\n            context=\"workflow_compilation | execution_graph_construction | denoting_step_inputs_dimensionality\",\n        )\n    for property_name, expected_dimensionality in expected_dimensionalities.items():\n        actual_dimensionality = parameter_name2dimensionality_specification[\n            property_name\n        ].actual_dimensionality\n        if actual_dimensionality != expected_dimensionality:\n            raise StepInputDimensionalityError(\n                public_message=f\"Data fed into step `{step_name}` property `{property_name}` has \"\n                f\"actual dimensionality {actual_dimensionality}, \"\n                f\"when expected was {expected_dimensionality}\",\n                context=\"workflow_compilation | execution_graph_construction | denoting_step_inputs_dimensionality\",\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=step_name,\n                        block_type=step_type,\n                        property_name=property_name,\n                        property_details=f\"Expected dimensionality {expected_dimensionality}, but received dimensionality {actual_dimensionality}\",\n                    )\n                ],\n            )\n    return None\n\n\ndef grab_input_data_dimensionality_specifications(\n    step_name: str,\n    inputs_dimensionalities: Dict[str, Set[int]],\n    dimensionality_offstes: Dict[str, int],\n) -> Dict[str, InputDimensionalitySpecification]:\n    result = {}\n    for parameter_name, dimensionality in inputs_dimensionalities.items():\n        parameter_offset = dimensionality_offstes.get(parameter_name, 0)\n        non_zero_dimensionalities_for_parameter = {d for d in dimensionality if d > 0}\n        if len(non_zero_dimensionalities_for_parameter) > 1:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler for step: `{step_name}` and parameter: {parameter_name}\"\n                f\"found multiple different values of actual input dimensionalities: \"\n                f\"`{non_zero_dimensionalities_for_parameter}` which should be detected and addresses \"\n                f\"at earlier stages of compilation.\"\n                f\"This is most likely the bug. Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n            )\n        if non_zero_dimensionalities_for_parameter:\n            actual_dimensionality = next(iter(non_zero_dimensionalities_for_parameter))\n            result[parameter_name] = InputDimensionalitySpecification(\n                actual_dimensionality=actual_dimensionality,\n                expected_offset=parameter_offset,\n            )\n    return result\n\n\ndef verify_compatibility_of_input_data_lineage_with_control_flow_lineage(\n    step_name: str,\n    inputs_lineage: List[List[str]],\n    control_flow_steps_selectors: List[str],\n    execution_graph: DiGraph,\n) -> None:\n    \"\"\"\n    Ensure control flow steps' data lineage is compatible with the step's inputs.\n\n    Control flow steps that affect this step must operate on data that is\n    compatible with the data fed to the step; otherwise the step could never\n    execute. Compares unique control flow lineages against input lineage\n    prefixes and raises ControlFlowDefinitionError if any control flow lineage\n    is not covered by the inputs.\n\n    If inputs_lineage is empty, there is no sense to verify compatibility. The lineage of the\n    step should be established based on the control flow lineages.\n\n    Args:\n        step_name: Name of the step being verified (used in error messages).\n        inputs_lineage: Data lineages derived from the step's input data.\n        control_flow_steps_selectors: Step selectors of control flow steps\n            that affect this step's execution.\n        execution_graph: The workflow execution graph.\n\n    Raises:\n        ControlFlowDefinitionError: When a control flow step's lineage is not\n            compatible with the step's input lineage (step would never execute).\n    \"\"\"\n    (\n        batch_oriented_control_flow_lineages,\n        lineage_id2control_flow_steps,\n    ) = _collect_unique_control_flow_lineages_with_step_mapping(\n        control_flow_steps_selectors=control_flow_steps_selectors,\n        execution_graph=execution_graph,\n    )\n    if not inputs_lineage:\n        return\n\n    all_input_lineage_prefixes = get_all_batch_lineage_prefixes(lineages=inputs_lineage)\n    all_input_lineage_prefixes_hashes = {\n        identify_lineage(lineage=lineage) for lineage in all_input_lineage_prefixes\n    }\n    for control_flow_lineage in batch_oriented_control_flow_lineages:\n        control_flow_lineage_id = identify_lineage(lineage=control_flow_lineage)\n        if control_flow_lineage_id not in all_input_lineage_prefixes_hashes:\n            problematic_flow_control_steps = lineage_id2control_flow_steps[\n                control_flow_lineage_id\n            ]\n            raise ControlFlowDefinitionError(\n                public_message=f\"Step {step_name} execution is impacted by control flow outcome of the following \"\n                f\"steps {problematic_flow_control_steps} which make decision based on data that is \"\n                f\"not compatible with data fed to the step {step_name} - which would cause the step \"\n                f\"to never execute. This behaviour is invalid and prevented upfront by Workflows compiler.\",\n                context=\"workflow_compilation | execution_graph_construction | verification_of_control_flow_lineage\",\n            )\n\n\ndef get_all_batch_lineage_prefixes(lineages: List[List[str]]) -> List[List[str]]:\n    result = []\n    already_spotted = set()\n    for lineage in lineages:\n        lineage_prefixes = get_batch_lineage_prefixes(lineage=lineage)\n        for lineage_prefix in lineage_prefixes:\n            lineage_prefix_id = identify_lineage(lineage=lineage_prefix)\n            if lineage_prefix_id not in already_spotted:\n                already_spotted.add(lineage_prefix_id)\n                result.append(lineage_prefix)\n    return result\n\n\ndef get_batch_lineage_prefixes(lineage: List[str]) -> List[List[str]]:\n    if not lineage:\n        return []\n    result = []\n    prefix = []\n    for i in range(len(lineage)):\n        prefix.append(lineage[i])\n        result.append(copy(prefix))\n    return result\n\n\ndef get_inputs_dimensionalities(\n    step_name: str,\n    step_type: str,\n    input_data: StepInputData,\n    scalar_parameters_to_be_batched: Set[str],\n    input_dimensionality_offsets: Dict[str, int],\n) -> Dict[str, Set[int]]:\n    result = defaultdict(set)\n    dimensionalities_spotted = set()\n    offset_parameters = {\n        parameter: value\n        for parameter, value in input_dimensionality_offsets.items()\n        if value > 0\n    }\n    non_offset_parameters_dimensionality_values = set()\n    for property_name, input_definition in input_data.items():\n        if property_name in offset_parameters:\n            continue\n        if input_definition.is_compound_input():\n            for value in input_definition.iterate_through_definitions():\n                if value.is_batch_oriented():\n                    non_offset_parameters_dimensionality_values.add(\n                        value.get_dimensionality()\n                    )\n        elif input_definition.is_batch_oriented():\n            non_offset_parameters_dimensionality_values.add(\n                input_definition.get_dimensionality()\n            )\n    if len(non_offset_parameters_dimensionality_values) > 1:\n        raise StepInputDimensionalityError(\n            public_message=f\"For step {step_name} attempted to plug input data that are in different dimensions, \"\n            f\"whereas block defines the inputs to be equal in that terms.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_input_data\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=step_name,\n                    block_type=step_type,\n                    block_details=f\"Dimensionality of input parameters differs by more than 1. Detected dimensions: {dict(result)}\",\n                )\n            ],\n        )\n    non_offset_parameters_dimensionality_value = (\n        non_offset_parameters_dimensionality_values.pop()\n        if len(non_offset_parameters_dimensionality_values) > 0\n        else 1\n    )\n    for property_name, input_definition in input_data.items():\n        if input_definition.is_compound_input():\n            result[property_name] = get_compound_input_dimensionality(\n                step_name=step_name,\n                step_type=step_type,\n                property_name=property_name,\n                input_definition=input_definition,\n                scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n                non_offset_parameters_dimensionality_value=non_offset_parameters_dimensionality_value,\n                offset_parameters=offset_parameters,\n            )\n        else:\n            if property_name in scalar_parameters_to_be_batched:\n                if property_name not in offset_parameters:\n                    result[property_name] = {non_offset_parameters_dimensionality_value}\n                else:\n                    result[property_name] = (\n                        non_offset_parameters_dimensionality_value\n                        + offset_parameters[property_name]\n                    )\n            else:\n                result[property_name] = {input_definition.get_dimensionality()}\n        dimensionalities_spotted.update(result[property_name])\n    non_zero_dimensionalities_spotted = {d for d in dimensionalities_spotted if d != 0}\n    if len(non_zero_dimensionalities_spotted) > 0:\n        min_dim, max_dim = min(non_zero_dimensionalities_spotted), max(\n            non_zero_dimensionalities_spotted\n        )\n        if abs(max_dim - min_dim) > 1:\n            raise StepInputDimensionalityError(\n                public_message=f\"For step {step_name} attempted to plug input data differing in dimensionality more than 1\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_input_data\",\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=step_name,\n                        block_type=step_type,\n                        block_details=f\"Dimensionality of input parameters differs by more than 1. Detected dimensions: {dict(result)}\",\n                    )\n                ],\n            )\n    return result\n\n\ndef get_compound_input_dimensionality(\n    step_name: str,\n    property_name: str,\n    step_type: str,\n    input_definition: CompoundStepInputDefinition,\n    scalar_parameters_to_be_batched: Set[str],\n    offset_parameters: Dict[str, int],\n    non_offset_parameters_dimensionality_value: int,\n) -> Set[int]:\n    dimensionalities_spotted = set()\n    for definition in input_definition.iterate_through_definitions():\n        if (\n            property_name not in scalar_parameters_to_be_batched\n            or definition.is_batch_oriented()\n        ):\n            dimensionalities_spotted.add(definition.get_dimensionality())\n        elif property_name not in offset_parameters:\n            dimensionalities_spotted.add(non_offset_parameters_dimensionality_value)\n        else:\n            dimensionalities_spotted.add(\n                non_offset_parameters_dimensionality_value\n                + offset_parameters[property_name]\n            )\n    non_zero_dimensionalities = {e for e in dimensionalities_spotted if e != 0}\n    if len(non_zero_dimensionalities) > 1:\n        raise StepInputDimensionalityError(\n            public_message=f\"While evaluating compound property {property_name} of step {step_name}, \"\n            f\"detected multiple inputs of differing batch dimensionalities: {non_zero_dimensionalities}\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_input_data\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=step_name,\n                    block_type=step_type,\n                    property_name=property_name,\n                    property_details=f\"Detected multiple inputs of differing batch dimensionalities: {non_zero_dimensionalities}\",\n                )\n            ],\n        )\n    return dimensionalities_spotted\n\n\ndef grab_parameters_defining_batch_inputs(\n    inputs_dimensionalities: Dict[str, Set[int]],\n) -> Set[str]:\n    result = set()\n    for paremeter, dimensionalities in inputs_dimensionalities.items():\n        batch_dimensionalities = {d for d in dimensionalities if d > 0}\n        if len(batch_dimensionalities):\n            result.add(paremeter)\n    return result\n\n\ndef retrieve_batch_compatibility_of_input_selectors(\n    input_selectors: List[ParsedSelector],\n) -> Dict[str, Set[bool]]:\n    batch_compatibility_of_properties = defaultdict(set)\n    for parsed_selector in input_selectors:\n        for reference in parsed_selector.definition.allowed_references:\n            batch_compatibility_of_properties[\n                parsed_selector.definition.property_name\n            ].update(reference.points_to_batch)\n    return batch_compatibility_of_properties\n\n\ndef verify_declared_batch_compatibility_against_actual_inputs(\n    node: str,\n    step_node_data: StepNode,\n    input_data: StepInputData,\n    batch_compatibility_of_properties: Dict[str, Set[bool]],\n) -> Set[str]:\n    scalar_parameters_to_be_batched = set()\n    parameters_accepting_batches_and_scalars = set(\n        step_node_data.step_manifest.get_parameters_accepting_batches_and_scalars()\n    )\n    hardcoded_inputs_to_be_batch_compatible = set(\n        step_node_data.step_manifest.get_parameters_enforcing_auto_batch_casting()\n        + step_node_data.step_manifest.get_parameters_accepting_batches()\n    )\n    for property_name, input_definition in input_data.items():\n        if property_name not in batch_compatibility_of_properties:\n            actual_input_is_batch = {False}\n            if property_name in parameters_accepting_batches_and_scalars:\n                batch_compatibility = {True, False}\n            elif property_name in hardcoded_inputs_to_be_batch_compatible:\n                batch_compatibility = {True}\n            else:\n                continue\n        elif input_definition.is_compound_input():\n            actual_input_is_batch = {\n                element.is_batch_oriented()\n                for element in input_definition.iterate_through_definitions()\n            }\n            batch_compatibility = batch_compatibility_of_properties[property_name]\n        else:\n            actual_input_is_batch = {input_definition.is_batch_oriented()}\n            batch_compatibility = batch_compatibility_of_properties[property_name]\n        step_accepts_batch_input = step_node_data.step_manifest.accepts_batch_input()\n        if (\n            step_accepts_batch_input\n            and batch_compatibility == {False}\n            and True in actual_input_is_batch\n        ):\n            raise ExecutionGraphStructureError(\n                public_message=f\"Detected invalid reference plugged \"\n                f\"into property `{property_name}` of step `{node}` - the step \"\n                f\"property do not accept batch-oriented inputs, yet the input selector \"\n                f\"holds one - this indicates the problem with \"\n                f\"construction of your Workflow - usually the problem occurs when non-batch oriented \"\n                f\"step inputs are filled with outputs of batch-oriented steps or batch-oriented inputs.\",\n                context=\"workflow_compilation | execution_graph_construction\",\n            )\n        if batch_compatibility == {True} and False in actual_input_is_batch:\n            scalar_parameters_to_be_batched.add(property_name)\n    return scalar_parameters_to_be_batched\n\n\ndef get_input_data_lineage_excluding_auto_batch_casting(\n    step_name: str,\n    input_data: StepInputData,\n    scalar_parameters_to_be_batched: Set[str],\n) -> List[List[str]]:\n    lineage_deduplication_set = set()\n    lineages = []\n    for property_name, input_definition in input_data.items():\n        new_lineages_detected_within_property_data = get_lineage_for_input_property(\n            step_name=step_name,\n            property_name=property_name,\n            input_definition=input_definition,\n            lineage_deduplication_set=lineage_deduplication_set,\n        )\n        if (\n            property_name in scalar_parameters_to_be_batched\n            and len(new_lineages_detected_within_property_data) == 0\n        ):\n            continue\n        lineages.extend(new_lineages_detected_within_property_data)\n    if not lineages:\n        return lineages\n    verify_lineages(step_name=step_name, detected_lineages=lineages)\n    return lineages\n\n\ndef get_lineage_support_for_auto_batch_casted_parameters(\n    input_dimensionalities: Dict[str, Set[int]],\n    scalar_parameters_to_be_batched: Set[str],\n    all_lineages_of_batch_parameters: List[List[str]],\n) -> Dict[str, AutoBatchCastingConfig]:\n    longest_lineage_support = find_longest_lineage_support(\n        all_lineages_of_batch_parameters=all_lineages_of_batch_parameters,\n    )\n    result = {}\n    for parameter_name in scalar_parameters_to_be_batched:\n        parameter_dimensionality = max(input_dimensionalities[parameter_name])\n        if longest_lineage_support is None:\n            lineage_support = None\n        else:\n            lineage_support = longest_lineage_support[:parameter_dimensionality]\n        result[parameter_name] = AutoBatchCastingConfig(\n            casted_dimensionality=parameter_dimensionality,\n            lineage_support=lineage_support,\n        )\n    return result\n\n\ndef find_longest_lineage_support(\n    all_lineages_of_batch_parameters: List[List[str]],\n) -> Optional[List[str]]:\n    longest_longest_lineage_support = []\n    for lineage in all_lineages_of_batch_parameters:\n        if len(lineage) > len(longest_longest_lineage_support):\n            longest_longest_lineage_support = lineage\n    if len(longest_longest_lineage_support) == 0:\n        return None\n    return longest_longest_lineage_support\n\n\ndef get_lineage_for_input_property(\n    step_name: str,\n    property_name: str,\n    input_definition: Union[StepInputDefinition, CompoundStepInputDefinition],\n    lineage_deduplication_set: Set[int],\n) -> List[List[str]]:\n    if input_definition.is_compound_input():\n        return get_lineage_from_compound_input(\n            step_name=step_name,\n            property_name=property_name,\n            input_definition=input_definition,\n            lineage_deduplication_set=lineage_deduplication_set,\n        )\n    lineages = []\n    if input_definition.is_batch_oriented():\n        lineage = input_definition.data_lineage\n        lineage_id = identify_lineage(lineage=lineage)\n        if lineage_id not in lineage_deduplication_set:\n            lineage_deduplication_set.add(lineage_id)\n            lineages.append(lineage)\n    return lineages\n\n\ndef get_lineage_from_compound_input(\n    step_name: str,\n    property_name: str,\n    input_definition: Union[StepInputDefinition, CompoundStepInputDefinition],\n    lineage_deduplication_set: Set[int],\n) -> List[List[str]]:\n    lineages = []\n    for nested_element in input_definition.iterate_through_definitions():\n        if nested_element.is_batch_oriented():\n            lineage = nested_element.data_lineage\n            lineage_id = identify_lineage(lineage=lineage)\n            if lineage_id not in lineage_deduplication_set:\n                lineage_deduplication_set.add(lineage_id)\n                lineages.append(lineage)\n    if len(lineages) > 1:\n        raise StepInputLineageError(\n            public_message=f\"Input data provided for step: `{step_name}` comes with multiple different lineages \"\n            f\"{lineages} for property `{property_name}` accepting \"\n            f\"multiple selectors, which is not allowed.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    return lineages\n\n\ndef verify_lineages(step_name: str, detected_lineages: List[List[str]]) -> None:\n    lineages_by_length = defaultdict(list)\n    for lineage in detected_lineages:\n        lineages_by_length[len(lineage)].append(lineage)\n    if len(lineages_by_length) > 2:\n        raise StepInputLineageError(\n            public_message=f\"Input data provided for step: `{step_name}` comes with lineages at more than two \"\n            f\"dimensionality levels, which should not be possible.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    lineage_lengths = sorted(lineages_by_length.keys())\n    for lineage_length in lineage_lengths:\n        if len(lineages_by_length[lineage_length]) > 1:\n            raise StepInputLineageError(\n                public_message=f\"Among step `{step_name}` inputs found different lineages at the same  \"\n                f\"dimensionality levels dimensionality.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if len(lineages_by_length[lineage_lengths[-1]]) > 1 and len(lineage_lengths) < 2:\n        raise StepInputLineageError(\n            public_message=f\"If lineage differ at the last level, then Execution Engine requires at least one \"\n            f\"higher-dimension  input that will come with common lineage, but this is not the \"\n            f\"case for step {step_name}.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    if len(lineage_lengths) == 2:\n        reference_lineage = lineages_by_length[lineage_lengths[0]][0]\n        if reference_lineage != lineages_by_length[lineage_lengths[1]][0][:-1]:\n            raise StepInputLineageError(\n                public_message=f\"Step `{step_name}` inputs does not share common lineage. Differing element: \"\n                f\"{lineages_by_length[lineage_lengths[1]][0]}, \"\n                f\"reference lineage prefix: {reference_lineage}\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n\n\ndef establish_step_execution_dimensionality(\n    inputs_dimensionalities: Dict[str, Set[int]],\n    control_flow_lineage_support: List[str],\n    output_dimensionality_offset: int,\n) -> int:\n    \"\"\"\n    Determine how many batch dimensions (execution slices) a step runs with.\n\n    Used during workflow compilation in denote_data_flow_for_step. The result\n    is stored on StepNode.step_execution_dimensionality and consumed at\n    execution time to:\n    - Drive how many times the step is executed (which batch indices/slices).\n    - Align and expand inputs (e.g. auto-batch casting) to match this size.\n    - Validate that parameter dimensionalities are compatible (runtime checks\n      in step_input_assembler and manager).\n\n    Logic:\n    - If no input has non-zero dimensionality but the step is gated by\n      control flow (control_flow_lineage_support non-empty), the\n      dimensionality is the number of control-flow branches.\n    - Otherwise, the minimum non-zero input dimensionality is used; if\n      output_dimensionality_offset < 0 (step reduces batch dimension),\n      one is subtracted.\n\n    Args:\n        inputs_dimensionalities: Per-input sets of dimensionalities (from\n            get_inputs_dimensionalities).\n        control_flow_lineage_support: Lineage identifiers for control-flow\n            branches that gate this step (from establish_batch_oriented_step_lineage).\n        output_dimensionality_offset: Block's output dimensionality offset\n            (positive = expand, negative = reduce batch dimension).\n\n    Returns:\n        The number of batch dimensions (execution slices) for this step.\n    \"\"\"\n    step_execution_dimensionality = 0\n    non_zero_dimensionalities = {\n        dimensionality\n        for dimensionalities in inputs_dimensionalities.values()\n        for dimensionality in dimensionalities\n        if dimensionality > 0\n    }\n    if len(non_zero_dimensionalities) == 0 and len(control_flow_lineage_support) > 0:\n        return len(control_flow_lineage_support)\n    if len(non_zero_dimensionalities) > 0:\n        step_execution_dimensionality = min(non_zero_dimensionalities)\n        if output_dimensionality_offset < 0:\n            step_execution_dimensionality -= 1\n    return step_execution_dimensionality\n\n\ndef establish_batch_oriented_step_lineage(\n    step_selector: str,\n    all_data_derived_lineages: List[List[str]],\n    all_control_flow_lineages: List[List[str]],\n    input_data: StepInputData,\n    dimensionality_reference_property: Optional[str],\n    output_dimensionality_offset: int,\n) -> Tuple[List[str], List[str]]:\n    reference_lineage, control_flow_lineage_support = get_reference_lineage(\n        step_selector=step_selector,\n        all_data_derived_lineages=all_data_derived_lineages,\n        all_control_flow_lineages=all_control_flow_lineages,\n        input_data=input_data,\n        dimensionality_reference_property=dimensionality_reference_property,\n    )\n    if output_dimensionality_offset < 0:\n        result_dimensionality = reference_lineage[:output_dimensionality_offset]\n        return result_dimensionality, []\n    if output_dimensionality_offset == 0:\n        return reference_lineage, control_flow_lineage_support\n    reference_lineage.append(step_selector)\n    return reference_lineage, []\n\n\ndef get_reference_lineage(\n    step_selector: str,\n    all_data_derived_lineages: List[List[str]],\n    all_control_flow_lineages: List[List[str]],\n    input_data: StepInputData,\n    dimensionality_reference_property: Optional[str],\n) -> Tuple[List[str], List[str]]:\n    if not all_data_derived_lineages:\n        if len(all_control_flow_lineages) == 1:\n            return copy(all_control_flow_lineages[0]), copy(\n                all_control_flow_lineages[0]\n            )\n        # Multiple control-flow lineages and no data-derived lineage: pick the deepest.\n        max_lineage_len = max(len(lineage) for lineage in all_control_flow_lineages)\n        lineages_matching_max_len = [\n            _lineage\n            for _lineage in all_control_flow_lineages\n            if len(_lineage) == max_lineage_len\n        ]\n        if len(lineages_matching_max_len) == 1:\n            return copy(lineages_matching_max_len[0]), copy(\n                lineages_matching_max_len[0]\n            )\n        else:\n            raise AssumptionError(\n                public_message=f\"Multiple control-flow lineages at the same level for step `{step_selector}` \"\n                f\"and no data-derived lineage; unique lineage level required. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if len(all_data_derived_lineages) == 1:\n        return copy(all_data_derived_lineages[0]), []\n    if dimensionality_reference_property not in input_data:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` expected dimensionality_reference_property \"\n            f\"presence to be verified at earlier stages, which did not happen as expected. \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    property_data = input_data[dimensionality_reference_property]\n    if property_data.is_compound_input():\n        lineage = None\n        for nested_element in property_data.iterate_through_definitions():\n            if nested_element.is_batch_oriented():\n                lineage = copy(nested_element.data_lineage)\n                return lineage, []\n        if lineage is None:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n                f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if not property_data.is_batch_oriented():\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n            f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    return copy(property_data.data_lineage), []\n\n\ndef get_property_with_invalid_selector(\n    manifest: WorkflowBlockManifest, step_property: str\n) -> Optional[str]:\n    property_name = None\n    for key, value in manifest.__dict__.items():\n        if isinstance(value, str) and step_property in value:\n            property_name = key\n            break\n    return property_name\n\n\ndef add_super_input_node_in_execution_graph(\n    execution_graph: DiGraph,\n    super_input_node: str,\n) -> DiGraph:\n    nodes_to_attach_super_input_into = get_nodes_of_specific_category(\n        execution_graph=execution_graph,\n        category=NodeCategory.INPUT_NODE,\n    )\n    step_nodes_without_predecessors = [\n        node\n        for node in execution_graph.nodes\n        if not list(execution_graph.predecessors(node))\n    ]\n    nodes_to_attach_super_input_into.update(step_nodes_without_predecessors)\n    execution_graph.add_node(super_input_node)\n    for node in nodes_to_attach_super_input_into:\n        execution_graph.add_edge(super_input_node, node)\n    return execution_graph\n",
    "patch": null
  },
  {
    "trace_id": "0002ba50-9095-411e-88c3-5ebdfb7d7988",
    "function_name": "_collect_unique_control_flow_lineages_with_step_mapping",
    "file_path": "inference/core/workflows/execution_engine/v1/compiler/graph_constructor.py",
    "speedup_x": 0.951922176641884,
    "review_quality": "medium",
    "pre_optimization_commit": "90243bdc6278ef7d17b6db09dc1eb5b0d155b4be",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def _collect_unique_control_flow_lineages_with_step_mapping(\n    control_flow_steps_selectors: List[str],\n    execution_graph: nx.DiGraph,\n) -> Tuple[List[List[str]], Dict[int, List[str]]]:\n    \"\"\"\n    Collect data lineages from control flow steps and deduplicate by lineage id.\n\n    For each given control flow step selector, reads its data_lineage from the\n    execution graph. Returns unique non-empty lineages (by identify_lineage id)\n    and a mapping from lineage id to every step selector that produced that\n    lineage (used e.g. for error reporting when lineage is incompatible).\n\n    Args:\n        control_flow_steps_selectors: Step selectors (node ids) of control\n            flow steps whose data_lineage is to be collected.\n        execution_graph: The workflow execution graph containing step nodes\n            and their data_lineage.\n\n    Returns:\n        A tuple of (unique_lineages, lineage_id_to_step_selectors):\n        - unique_lineages: list of distinct non-empty data lineages.\n        - lineage_id_to_step_selectors: map from lineage id to list of step\n          selectors whose data_lineage has that id (includes empty lineages).\n    \"\"\"\n    unique_lineages: List[List[str]] = []\n    seen_lineage_ids: Set[int] = set()\n    lineage_id_to_step_selectors: Dict[int, List[str]] = defaultdict(list)\n\n    for step_selector in control_flow_steps_selectors:\n        step_data = node_as(\n            execution_graph=execution_graph,\n            node=step_selector,\n            expected_type=StepNode,\n        )\n        lineage = step_data.data_lineage\n        lineage_id = identify_lineage(lineage)\n        lineage_id_to_step_selectors[lineage_id].append(step_selector)\n        if lineage and lineage_id not in seen_lineage_ids:\n            seen_lineage_ids.add(lineage_id)\n            unique_lineages.append(lineage)\n\n    return unique_lineages, dict(lineage_id_to_step_selectors)\n",
    "optimized_function_code": "from collections import defaultdict\nfrom typing import Dict, List, Set, Tuple\n\nimport networkx as nx\nfrom inference.core.workflows.errors import AssumptionError\nfrom inference.core.workflows.execution_engine.constants import \\\n    NODE_COMPILATION_OUTPUT_PROPERTY\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import \\\n    StepNode\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import \\\n    identify_lineage\n\n\ndef _collect_unique_control_flow_lineages_with_step_mapping(\n    control_flow_steps_selectors: List[str],\n    execution_graph: nx.DiGraph,\n) -> Tuple[List[List[str]], Dict[int, List[str]]]:\n    \"\"\"\n    Collect data lineages from control flow steps and deduplicate by lineage id.\n\n    For each given control flow step selector, reads its data_lineage from the\n    execution graph. Returns unique non-empty lineages (by identify_lineage id)\n    and a mapping from lineage id to every step selector that produced that\n    lineage (used e.g. for error reporting when lineage is incompatible).\n\n    Args:\n        control_flow_steps_selectors: Step selectors (node ids) of control\n            flow steps whose data_lineage is to be collected.\n        execution_graph: The workflow execution graph containing step nodes\n            and their data_lineage.\n\n    Returns:\n        A tuple of (unique_lineages, lineage_id_to_step_selectors):\n        - unique_lineages: list of distinct non-empty data lineages.\n        - lineage_id_to_step_selectors: map from lineage id to list of step\n          selectors whose data_lineage has that id (includes empty lineages).\n    \"\"\"\n    unique_lineages: List[List[str]] = []\n    seen_lineage_ids: Set[int] = set()\n    lineage_id_to_step_selectors: Dict[int, List[str]] = defaultdict(list)\n\n    for step_selector in control_flow_steps_selectors:\n        # Inline node retrieval to avoid function-call overhead for each step\n        try:\n            node_attrs = execution_graph.nodes[step_selector]\n        except Exception:\n            # networkx may raise KeyError or other exceptions on missing node; preserve message\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler expected node: {step_selector} to be present in execution graph, \"\n                f\"but condition failed to be met. This is most likely the bug. Contact Roboflow team \"\n                f\"through github issues (https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | retrieving_compiled_node\",\n            )\n\n        if NODE_COMPILATION_OUTPUT_PROPERTY not in node_attrs:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler expected key: {NODE_COMPILATION_OUTPUT_PROPERTY} to be present \"\n                f\"for node {step_selector} in execution graph, \"\n                f\"but condition failed to be met. This is most likely the bug. Contact Roboflow team \"\n                f\"through github issues (https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | retrieving_compiled_node\",\n            )\n\n        step_data = node_attrs[NODE_COMPILATION_OUTPUT_PROPERTY]\n        if not isinstance(step_data, StepNode):\n            node_data_type = type(step_data)\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler expected compilation output for node {step_selector}\"\n                f\"to be {StepNode}, but found: {node_data_type}. \"\n                f\"This is most likely the bug. Contact Roboflow team \"\n                f\"through github issues (https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | retrieving_compiled_node\",\n            )\n\n        lineage = step_data.data_lineage\n        # Avoid hashing when lineage is empty (identify_lineage would sum over empty iterable -> 0)\n        if not lineage:\n            lineage_id = 0\n        else:\n            lineage_id = identify_lineage(lineage)\n\n        lineage_id_to_step_selectors[lineage_id].append(step_selector)\n        if lineage and lineage_id not in seen_lineage_ids:\n            seen_lineage_ids.add(lineage_id)\n            unique_lineages.append(lineage)\n\n    return unique_lineages, dict(lineage_id_to_step_selectors)",
    "optimized_raw_markdown": "```python:inference/core/workflows/execution_engine/v1/compiler/utils.py\nfrom __future__ import annotations\n\nfrom typing import List, Type, TypeVar\n\nfrom inference.core.workflows.errors import AssumptionError\nfrom inference.core.workflows.execution_engine.constants import \\\n    NODE_COMPILATION_OUTPUT_PROPERTY\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import \\\n    ExecutionGraphNode\nfrom networkx import DiGraph\n\nNodeTypeVar = TypeVar(\"NodeTypeVar\", bound=ExecutionGraphNode)\n\n\ndef identify_lineage(lineage: List[str]) -> int:\n    # Avoid generator overhead by using a simple local loop and local binding of hash\n    h = hash\n    total = 0\n    for e in lineage:\n        total += h(e)\n    return total\n\n\n\n\ndef node_as(\n    execution_graph: DiGraph, node: str, expected_type: Type[NodeTypeVar]\n) -> NodeTypeVar:\n    if node not in execution_graph.nodes:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler expected node: {node} to be present in execution graph, \"\n            f\"but condition failed to be met. This is most likely the bug. Contact Roboflow team \"\n            f\"through github issues (https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | retrieving_compiled_node\",\n        )\n    if NODE_COMPILATION_OUTPUT_PROPERTY not in execution_graph.nodes[node]:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler expected key: {NODE_COMPILATION_OUTPUT_PROPERTY} to be present \"\n            f\"for node {node} in execution graph, \"\n            f\"but condition failed to be met. This is most likely the bug. Contact Roboflow team \"\n            f\"through github issues (https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | retrieving_compiled_node\",\n        )\n    node_data: ExecutionGraphNode = execution_graph.nodes[node][\n        NODE_COMPILATION_OUTPUT_PROPERTY\n    ]\n    if not isinstance(node_data, expected_type):\n        node_data_type = type(node_data)\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler expected compilation output for node {node}\"\n            f\"to be {expected_type}, but found: {node_data_type}. \"\n            f\"This is most likely the bug. Contact Roboflow team \"\n            f\"through github issues (https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | retrieving_compiled_node\",\n        )\n    return node_data\n```\n```python:inference/core/workflows/execution_engine/v1/compiler/graph_constructor.py\nfrom collections import defaultdict\nfrom typing import Dict, List, Set, Tuple\n\nimport networkx as nx\nfrom inference.core.workflows.errors import AssumptionError\nfrom inference.core.workflows.execution_engine.constants import \\\n    NODE_COMPILATION_OUTPUT_PROPERTY\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import \\\n    StepNode\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import \\\n    identify_lineage\n\n\ndef _collect_unique_control_flow_lineages_with_step_mapping(\n    control_flow_steps_selectors: List[str],\n    execution_graph: nx.DiGraph,\n) -> Tuple[List[List[str]], Dict[int, List[str]]]:\n    \"\"\"\n    Collect data lineages from control flow steps and deduplicate by lineage id.\n\n    For each given control flow step selector, reads its data_lineage from the\n    execution graph. Returns unique non-empty lineages (by identify_lineage id)\n    and a mapping from lineage id to every step selector that produced that\n    lineage (used e.g. for error reporting when lineage is incompatible).\n\n    Args:\n        control_flow_steps_selectors: Step selectors (node ids) of control\n            flow steps whose data_lineage is to be collected.\n        execution_graph: The workflow execution graph containing step nodes\n            and their data_lineage.\n\n    Returns:\n        A tuple of (unique_lineages, lineage_id_to_step_selectors):\n        - unique_lineages: list of distinct non-empty data lineages.\n        - lineage_id_to_step_selectors: map from lineage id to list of step\n          selectors whose data_lineage has that id (includes empty lineages).\n    \"\"\"\n    unique_lineages: List[List[str]] = []\n    seen_lineage_ids: Set[int] = set()\n    lineage_id_to_step_selectors: Dict[int, List[str]] = defaultdict(list)\n\n    for step_selector in control_flow_steps_selectors:\n        # Inline node retrieval to avoid function-call overhead for each step\n        try:\n            node_attrs = execution_graph.nodes[step_selector]\n        except Exception:\n            # networkx may raise KeyError or other exceptions on missing node; preserve message\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler expected node: {step_selector} to be present in execution graph, \"\n                f\"but condition failed to be met. This is most likely the bug. Contact Roboflow team \"\n                f\"through github issues (https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | retrieving_compiled_node\",\n            )\n\n        if NODE_COMPILATION_OUTPUT_PROPERTY not in node_attrs:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler expected key: {NODE_COMPILATION_OUTPUT_PROPERTY} to be present \"\n                f\"for node {step_selector} in execution graph, \"\n                f\"but condition failed to be met. This is most likely the bug. Contact Roboflow team \"\n                f\"through github issues (https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | retrieving_compiled_node\",\n            )\n\n        step_data = node_attrs[NODE_COMPILATION_OUTPUT_PROPERTY]\n        if not isinstance(step_data, StepNode):\n            node_data_type = type(step_data)\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler expected compilation output for node {step_selector}\"\n                f\"to be {StepNode}, but found: {node_data_type}. \"\n                f\"This is most likely the bug. Contact Roboflow team \"\n                f\"through github issues (https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | retrieving_compiled_node\",\n            )\n\n        lineage = step_data.data_lineage\n        # Avoid hashing when lineage is empty (identify_lineage would sum over empty iterable -> 0)\n        if not lineage:\n            lineage_id = 0\n        else:\n            lineage_id = identify_lineage(lineage)\n\n        lineage_id_to_step_selectors[lineage_id].append(step_selector)\n        if lineage and lineage_id not in seen_lineage_ids:\n            seen_lineage_ids.add(lineage_id)\n            unique_lineages.append(lineage)\n\n    return unique_lineages, dict(lineage_id_to_step_selectors)\n```",
    "optimized_function_only": "def _collect_unique_control_flow_lineages_with_step_mapping(\n    control_flow_steps_selectors: List[str],\n    execution_graph: nx.DiGraph,\n) -> Tuple[List[List[str]], Dict[int, List[str]]]:\n    \"\"\"\n    Collect data lineages from control flow steps and deduplicate by lineage id.\n\n    For each given control flow step selector, reads its data_lineage from the\n    execution graph. Returns unique non-empty lineages (by identify_lineage id)\n    and a mapping from lineage id to every step selector that produced that\n    lineage (used e.g. for error reporting when lineage is incompatible).\n\n    Args:\n        control_flow_steps_selectors: Step selectors (node ids) of control\n            flow steps whose data_lineage is to be collected.\n        execution_graph: The workflow execution graph containing step nodes\n            and their data_lineage.\n\n    Returns:\n        A tuple of (unique_lineages, lineage_id_to_step_selectors):\n        - unique_lineages: list of distinct non-empty data lineages.\n        - lineage_id_to_step_selectors: map from lineage id to list of step\n          selectors whose data_lineage has that id (includes empty lineages).\n    \"\"\"\n    unique_lineages: List[List[str]] = []\n    seen_lineage_ids: Set[int] = set()\n    lineage_id_to_step_selectors: Dict[int, List[str]] = defaultdict(list)\n\n    for step_selector in control_flow_steps_selectors:\n        # Inline node retrieval to avoid function-call overhead for each step\n        try:\n            node_attrs = execution_graph.nodes[step_selector]\n        except Exception:\n            # networkx may raise KeyError or other exceptions on missing node; preserve message\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler expected node: {step_selector} to be present in execution graph, \"\n                f\"but condition failed to be met. This is most likely the bug. Contact Roboflow team \"\n                f\"through github issues (https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | retrieving_compiled_node\",\n            )\n\n        if NODE_COMPILATION_OUTPUT_PROPERTY not in node_attrs:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler expected key: {NODE_COMPILATION_OUTPUT_PROPERTY} to be present \"\n                f\"for node {step_selector} in execution graph, \"\n                f\"but condition failed to be met. This is most likely the bug. Contact Roboflow team \"\n                f\"through github issues (https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | retrieving_compiled_node\",\n            )\n\n        step_data = node_attrs[NODE_COMPILATION_OUTPUT_PROPERTY]\n        if not isinstance(step_data, StepNode):\n            node_data_type = type(step_data)\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler expected compilation output for node {step_selector}\"\n                f\"to be {StepNode}, but found: {node_data_type}. \"\n                f\"This is most likely the bug. Contact Roboflow team \"\n                f\"through github issues (https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | retrieving_compiled_node\",\n            )\n\n        lineage = step_data.data_lineage\n        # Avoid hashing when lineage is empty (identify_lineage would sum over empty iterable -> 0)\n        if not lineage:\n            lineage_id = 0\n        else:\n            lineage_id = identify_lineage(lineage)\n\n        lineage_id_to_step_selectors[lineage_id].append(step_selector)\n        if lineage and lineage_id not in seen_lineage_ids:\n            seen_lineage_ids.add(lineage_id)\n            unique_lineages.append(lineage)\n\n    return unique_lineages, dict(lineage_id_to_step_selectors)",
    "original_file_content": "import itertools\nfrom collections import defaultdict\nfrom copy import copy, deepcopy\nfrom typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union\nfrom uuid import uuid4\n\nimport networkx as nx\nfrom networkx import DiGraph\n\nfrom inference.core import logger\nfrom inference.core.workflows.errors import (\n    AssumptionError,\n    BlockInterfaceError,\n    ControlFlowDefinitionError,\n    ExecutionGraphStructureError,\n    InvalidReferenceTargetError,\n    StepInputDimensionalityError,\n    StepInputLineageError,\n    WorkflowBlockError,\n)\nfrom inference.core.workflows.execution_engine.constants import (\n    NODE_COMPILATION_OUTPUT_PROPERTY,\n    PARSED_NODE_INPUT_SELECTORS_PROPERTY,\n    TOP_LEVEL_LINEAGES_KEY,\n    WORKFLOW_INPUT_BATCH_LINEAGE_ID,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    InputType,\n    JsonField,\n    OutputDefinition,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    STEP_AS_SELECTED_ELEMENT,\n    Kind,\n)\nfrom inference.core.workflows.execution_engine.introspection.entities import (\n    ParsedSelector,\n)\nfrom inference.core.workflows.execution_engine.introspection.selectors_parser import (\n    get_step_selectors,\n)\nfrom inference.core.workflows.execution_engine.profiling.core import (\n    WorkflowsProfiler,\n    execution_phase,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import (\n    AutoBatchCastingConfig,\n    CompoundStepInputDefinition,\n    DictOfStepInputDefinitions,\n    DynamicStepInputDefinition,\n    ExecutionGraphNode,\n    InputDimensionalitySpecification,\n    InputNode,\n    ListOfStepInputDefinitions,\n    NodeCategory,\n    NodeInputCategory,\n    OutputNode,\n    ParameterSpecification,\n    ParsedWorkflowDefinition,\n    PropertyPredecessorDefinition,\n    StaticStepInputDefinition,\n    StepInputData,\n    StepInputDefinition,\n    StepNode,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.graph_traversal import (\n    traverse_graph_ensuring_parents_are_reached_first,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.reference_type_checker import (\n    validate_reference_kinds,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import (\n    construct_input_selector,\n    construct_output_selector,\n    construct_step_selector,\n    get_last_chunk_of_selector,\n    get_nodes_of_specific_category,\n    get_step_selector_from_its_output,\n    identify_lineage,\n    is_control_flow_step,\n    is_input_node,\n    is_input_selector,\n    is_output_node,\n    is_step_node,\n    is_step_output_selector,\n    is_step_selector,\n    node_as,\n)\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nNODE_DEFINITION_KEY = \"definition\"\nSTEP_INPUT_SELECTORS_PROPERTY = \"step_input_selectors\"\nEXCLUDED_FIELDS = {\"type\", \"name\"}\n\n\n@execution_phase(\n    name=\"execution_graph_creation\",\n    categories=[\"execution_engine_operation\"],\n)\ndef prepare_execution_graph(\n    workflow_definition: ParsedWorkflowDefinition,\n    profiler: Optional[WorkflowsProfiler] = None,\n) -> DiGraph:\n    execution_graph = construct_graph(\n        workflow_definition=workflow_definition,\n    )\n    if not nx.is_directed_acyclic_graph(execution_graph):\n        raise ExecutionGraphStructureError(\n            public_message=f\"Detected cycle in execution graph. This means that there is output from one \"\n            f\"step that is connected to input of other step creating loop in the graph that would \"\n            f\"never end if executed.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    return denote_data_flow_in_workflow(\n        execution_graph=execution_graph,\n        parsed_workflow_definition=workflow_definition,\n    )\n\n\ndef construct_graph(\n    workflow_definition: ParsedWorkflowDefinition,\n) -> DiGraph:\n    execution_graph = nx.DiGraph()\n    execution_graph = add_input_nodes_for_graph(\n        inputs=workflow_definition.inputs,\n        execution_graph=execution_graph,\n    )\n    execution_graph = add_steps_nodes_for_graph(\n        steps=workflow_definition.steps,\n        execution_graph=execution_graph,\n    )\n    execution_graph = add_output_nodes_for_graph(\n        outputs=workflow_definition.outputs,\n        execution_graph=execution_graph,\n    )\n    execution_graph = add_steps_edges(\n        workflow_definition=workflow_definition,\n        execution_graph=execution_graph,\n    )\n    return add_edges_for_outputs(\n        workflow_definition=workflow_definition,\n        execution_graph=execution_graph,\n    )\n\n\ndef add_input_nodes_for_graph(\n    inputs: List[InputType],\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for input_spec in inputs:\n        input_selector = construct_input_selector(input_name=input_spec.name)\n        if input_spec.is_batch_oriented():\n            if input_spec.dimensionality < 1:\n                raise ExecutionGraphStructureError(\n                    public_message=f\"Detected batch oriented input `{input_spec.name}` with \"\n                    f\"declared dimensionality `{input_spec.dimensionality}` which is below \"\n                    f\"one (one is minimum dimensionality of the batch). Fix input definition in\"\n                    f\"your Workflow.\",\n                    context=\"workflow_compilation | execution_graph_construction\",\n                )\n            data_lineage = [WORKFLOW_INPUT_BATCH_LINEAGE_ID]\n            for _ in range(input_spec.dimensionality - 1):\n                # TODO: this may end up being a bug - with ability for multi-step debugging, if we will\n                #  ever have a situation that there will be multiple step outputs with nested\n                #  dimensionality with the same lineage, this re-construction method will\n                #  assign a different lineage identifier, causing the inputs being non-composable in\n                #  a single execution branch\n                data_lineage.append(f\"{uuid4()}\")\n        else:\n            data_lineage = []\n        compilation_output = InputNode(\n            node_category=NodeCategory.INPUT_NODE,\n            name=input_spec.name,\n            selector=input_selector,\n            data_lineage=data_lineage,\n            input_manifest=input_spec,\n        )\n        execution_graph.add_node(\n            input_selector,\n            **{\n                NODE_COMPILATION_OUTPUT_PROPERTY: compilation_output,\n            },\n        )\n    return execution_graph\n\n\ndef add_steps_nodes_for_graph(\n    steps: List[WorkflowBlockManifest],\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for step in steps:\n        step_selector = construct_step_selector(step_name=step.name)\n        compilation_output = StepNode(\n            node_category=NodeCategory.STEP_NODE,\n            name=step.name,\n            selector=step_selector,\n            data_lineage=[],\n            step_manifest=step,\n        )\n        execution_graph.add_node(\n            step_selector,\n            **{\n                NODE_COMPILATION_OUTPUT_PROPERTY: compilation_output,\n            },\n        )\n    return execution_graph\n\n\ndef add_output_nodes_for_graph(\n    outputs: List[JsonField],\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for output_spec in outputs:\n        output_selector = construct_output_selector(name=output_spec.name)\n        compilation_output = OutputNode(\n            node_category=NodeCategory.OUTPUT_NODE,\n            name=output_spec.name,\n            selector=output_selector,\n            data_lineage=[],\n            output_manifest=output_spec,\n        )\n        execution_graph.add_node(\n            output_selector,\n            **{\n                NODE_COMPILATION_OUTPUT_PROPERTY: compilation_output,\n            },\n        )\n    return execution_graph\n\n\ndef add_steps_edges(\n    workflow_definition: ParsedWorkflowDefinition,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for step in workflow_definition.steps:\n        source_step_selector = construct_step_selector(step_name=step.name)\n        step_selectors = get_step_selectors(step_manifest=step)\n        execution_graph.nodes[source_step_selector][\n            PARSED_NODE_INPUT_SELECTORS_PROPERTY\n        ] = step_selectors\n        execution_graph = add_edges_for_step(\n            execution_graph=execution_graph,\n            source_step_selector=source_step_selector,\n            target_step_parsed_selectors=step_selectors,\n        )\n    return execution_graph\n\n\ndef add_edges_for_step(\n    execution_graph: DiGraph,\n    source_step_selector: str,\n    target_step_parsed_selectors: List[ParsedSelector],\n) -> DiGraph:\n    for target_step_parsed_selector in target_step_parsed_selectors:\n        execution_graph = add_edge_for_step(\n            execution_graph=execution_graph,\n            source_step_selector=source_step_selector,\n            target_step_parsed_selector=target_step_parsed_selector,\n        )\n    return execution_graph\n\n\ndef add_edge_for_step(\n    execution_graph: DiGraph,\n    source_step_selector: str,\n    target_step_parsed_selector: ParsedSelector,\n) -> DiGraph:\n    target_step_selector = get_step_selector_from_its_output(\n        step_output_selector=target_step_parsed_selector.value\n    )\n    verify_edge_is_created_between_existing_nodes(\n        execution_graph=execution_graph,\n        start=source_step_selector,\n        end=target_step_selector,\n    )\n    if is_step_selector(target_step_parsed_selector.value):\n        return establish_control_flow_edge(\n            source_step_selector=source_step_selector,\n            target_step_parsed_selector=target_step_parsed_selector,\n            execution_graph=execution_graph,\n        )\n    if is_input_selector(target_step_parsed_selector.value):\n        input_node_compilation_data = node_as(\n            execution_graph=execution_graph,\n            node=target_step_parsed_selector.value,\n            expected_type=InputNode,\n        )\n        actual_input_kind = input_node_compilation_data.input_manifest.kind\n    else:\n        other_step_compilation_data = node_as(\n            execution_graph=execution_graph,\n            node=target_step_selector,\n            expected_type=StepNode,\n        )\n        source_step_compilation_data = node_as(\n            execution_graph=execution_graph,\n            node=source_step_selector,\n            expected_type=StepNode,\n        )\n        actual_input_kind = get_kind_of_value_provided_in_step_output(\n            step_manifest=other_step_compilation_data.step_manifest,\n            step_property=get_last_chunk_of_selector(\n                selector=target_step_parsed_selector.value\n            ),\n            source_step_manifest=source_step_compilation_data.step_manifest,\n        )\n    expected_input_kind = list(\n        itertools.chain.from_iterable(\n            ref.kind\n            for ref in target_step_parsed_selector.definition.allowed_references\n        )\n    )\n    error_message = (\n        f\"Failed to validate reference provided for step: {source_step_selector} regarding property: \"\n        f\"{target_step_parsed_selector.definition.property_name} with value: {target_step_parsed_selector.value}. \"\n        f\"Allowed kinds of references for this property: {list(set(e.name for e in expected_input_kind))}. \"\n        f\"Types of output for referred property: \"\n        f\"{list(set(a.name if isinstance(a, Kind) else a for a in actual_input_kind))}\"\n    )\n    validate_reference_kinds(\n        expected=expected_input_kind,\n        actual=actual_input_kind,\n        error_message=error_message,\n    )\n    if execution_graph.has_edge(target_step_selector, source_step_selector):\n        edge_data = execution_graph.edges[(target_step_selector, source_step_selector)]\n        if STEP_INPUT_SELECTORS_PROPERTY not in edge_data:\n            edge_data[STEP_INPUT_SELECTORS_PROPERTY] = []\n        edge_data[STEP_INPUT_SELECTORS_PROPERTY].append(\n            target_step_parsed_selector,\n        )\n    else:\n        execution_graph.add_edge(\n            target_step_selector,\n            source_step_selector,\n            **{STEP_INPUT_SELECTORS_PROPERTY: [target_step_parsed_selector]},\n        )\n    return execution_graph\n\n\ndef establish_control_flow_edge(\n    source_step_selector: str,\n    target_step_parsed_selector: ParsedSelector,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    if not step_definition_allows_control_flow_references(\n        parsed_selector=target_step_parsed_selector\n    ):\n        raise ExecutionGraphStructureError(\n            public_message=f\"Detected reference to other step in manifest of step {source_step_selector}. \"\n            f\"This is not allowed, as step manifest does not define any properties of type `StepSelector` \"\n            f\"allowing for defining connections between steps that represent flow control in `workflows`.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    target_step_selector = get_step_selector_from_its_output(\n        step_output_selector=target_step_parsed_selector.value\n    )\n    source_compilation_data = node_as(\n        execution_graph=execution_graph,\n        node=source_step_selector,\n        expected_type=StepNode,\n    )\n    target_compilation_data = node_as(\n        execution_graph=execution_graph,\n        node=target_step_selector,\n        expected_type=StepNode,\n    )\n    nodes_categories = {\n        source_compilation_data.node_category,\n        target_compilation_data.node_category,\n    }\n    if nodes_categories != {NodeCategory.STEP_NODE}:\n        raise ExecutionGraphStructureError(\n            public_message=f\"Attempted to create flow-control connection between workflow nodes: \"\n            f\"{source_step_selector} and {target_step_selector}, one of which is not denoted\"\n            f\"as step node.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    execution_graph.add_edge(\n        source_step_selector,\n        target_step_selector,\n    )\n    if target_step_selector in source_compilation_data.child_execution_branches:\n        raise ExecutionGraphStructureError(\n            public_message=f\"While establishing flow-control connection between source `{source_step_selector}` \"\n            f\"and target `{target_step_selector}` it was discovered that source step defines\"\n            f\"control flow transition into target one more than once, which is not allowed as \"\n            f\"that situation creates ambiguity in selecting execution branch.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    execution_branch_name = f\"Branch[{source_step_selector} -> {target_step_parsed_selector.definition.property_name}]\"\n    source_compilation_data.child_execution_branches[target_step_selector] = (\n        execution_branch_name\n    )\n    target_compilation_data.execution_branches_impacting_inputs.add(\n        execution_branch_name\n    )\n    return execution_graph\n\n\ndef step_definition_allows_control_flow_references(\n    parsed_selector: ParsedSelector,\n) -> bool:\n    return any(\n        definition.selected_element == STEP_AS_SELECTED_ELEMENT\n        for definition in parsed_selector.definition.allowed_references\n    )\n\n\ndef get_kind_of_value_provided_in_step_output(\n    step_manifest: WorkflowBlockManifest,\n    step_property: str,\n    source_step_manifest: WorkflowBlockManifest,\n) -> List[Kind]:\n    referred_node_outputs = step_manifest.get_actual_outputs()\n    actual_kind = []\n    matched_property = False\n    for output in referred_node_outputs:\n        if output.name != step_property:\n            continue\n        matched_property = True\n        actual_kind.extend(output.kind)\n    if not matched_property:\n        property_name = get_property_with_invalid_selector(\n            manifest=source_step_manifest,\n            step_property=step_property,\n        )\n        raise ExecutionGraphStructureError(\n            public_message=f\"Found reference to non-existing property `{step_property}` of step `{step_manifest.name}`.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=source_step_manifest.name,\n                    block_type=source_step_manifest.type,\n                    property_name=property_name,\n                    property_details=f\"'{step_manifest.name}.{step_property}' is an invalid reference\",\n                )\n            ],\n        )\n    return actual_kind\n\n\ndef add_edges_for_step_inputs(\n    execution_graph: DiGraph,\n    input_selectors: Set[str],\n    step_selector: str,\n) -> DiGraph:\n    for input_selector in input_selectors:\n        if is_step_output_selector(selector_or_value=input_selector):\n            input_selector = get_step_selector_from_its_output(\n                step_output_selector=input_selector\n            )\n        verify_edge_is_created_between_existing_nodes(\n            execution_graph=execution_graph,\n            start=input_selector,\n            end=step_selector,\n        )\n        execution_graph.add_edge(input_selector, step_selector)\n    return execution_graph\n\n\ndef add_edges_for_outputs(\n    workflow_definition: ParsedWorkflowDefinition,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for output in workflow_definition.outputs:\n        node_selector = output.selector\n        if is_step_output_selector(selector_or_value=node_selector):\n            node_selector = get_step_selector_from_its_output(\n                step_output_selector=node_selector\n            )\n        output_selector = construct_output_selector(name=output.name)\n        verify_edge_is_created_between_existing_nodes(\n            execution_graph=execution_graph,\n            start=node_selector,\n            end=output_selector,\n        )\n        output_node_manifest = node_as(\n            execution_graph=execution_graph,\n            node=output_selector,\n            expected_type=OutputNode,\n        )\n        if is_step_output_selector(selector_or_value=output.selector):\n            step_manifest = execution_graph.nodes[node_selector][\n                NODE_COMPILATION_OUTPUT_PROPERTY\n            ].step_manifest\n            step_outputs = step_manifest.get_actual_outputs()\n            denote_output_node_kind_based_on_step_outputs(\n                output_selector=output.selector,\n                step_outputs=step_outputs,\n                output_node_manifest=output_node_manifest,\n            )\n        else:\n            input_manifest = node_as(\n                execution_graph=execution_graph,\n                node=node_selector,\n                expected_type=InputNode,\n            ).input_manifest\n            output_node_manifest.kind = copy(input_manifest.kind)\n        execution_graph.add_edge(node_selector, output_selector)\n    return execution_graph\n\n\ndef verify_edge_is_created_between_existing_nodes(\n    execution_graph: DiGraph,\n    start: str,\n    end: str,\n) -> None:\n    if not execution_graph.has_node(start) or not execution_graph.has_node(end):\n        invalid_block = start if not execution_graph.has_node(start) else end\n        referencing_block = end if invalid_block == start else start\n\n        step_type = None\n        property_name = None\n        if execution_graph.has_node(referencing_block):\n            if is_step_node(execution_graph, referencing_block):\n                step_manifest = node_as(\n                    execution_graph=execution_graph,\n                    node=referencing_block,\n                    expected_type=StepNode,\n                ).step_manifest\n                step_type = step_manifest.type\n                property_name = get_property_with_invalid_selector(\n                    manifest=step_manifest,\n                    step_property=invalid_block,\n                )\n\n        block_id = (\n            \"$outputs\"\n            if referencing_block.startswith(\"$outputs.\")\n            else get_last_chunk_of_selector(selector=referencing_block)\n        )\n        property_name = (\n            get_last_chunk_of_selector(selector=referencing_block)\n            if referencing_block.startswith(\"$outputs.\")\n            else property_name\n        )\n\n        is_input = is_input_selector(selector_or_value=invalid_block)\n        raise InvalidReferenceTargetError(\n            public_message=f\"Workflow references '{invalid_block}' which points to a non-existent {is_input and 'input parameter' or 'block'}.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=block_id,\n                    block_type=step_type,\n                    property_name=property_name,\n                    property_details=f\"Invalid reference to {invalid_block}\",\n                ),\n            ],\n        )\n\n\ndef denote_output_node_kind_based_on_step_outputs(\n    output_selector: str,\n    step_outputs: List[OutputDefinition],\n    output_node_manifest: OutputNode,\n) -> None:\n    selected_output_name = get_last_chunk_of_selector(selector=output_selector)\n    kinds_for_outputs = {output.name: output.kind for output in step_outputs}\n\n    if selected_output_name == \"*\":\n        output_node_manifest.kind = deepcopy(kinds_for_outputs)\n        return None\n    if selected_output_name not in kinds_for_outputs:\n        output_name = output_node_manifest.output_manifest.name\n\n        raise InvalidReferenceTargetError(\n            public_message=f\"Workflow output references '{output_selector}' which points to a non-existent block property.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=\"$outputs\",\n                    property_name=output_name,\n                    property_details=f\"Invalid reference to {output_selector}\",\n                ),\n            ],\n        )\n    output_node_manifest.kind = copy(kinds_for_outputs[selected_output_name])\n    return None\n\n\ndef denote_data_flow_in_workflow(\n    execution_graph: DiGraph,\n    parsed_workflow_definition: ParsedWorkflowDefinition,\n) -> nx.DiGraph:\n    block_manifest_by_step_name = {\n        step.name: step for step in parsed_workflow_definition.steps\n    }\n    super_input_node = \"<super-input>\"\n    execution_graph = add_super_input_node_in_execution_graph(\n        execution_graph=execution_graph,\n        super_input_node=super_input_node,\n    )\n    execution_graph.nodes[super_input_node][NODE_COMPILATION_OUTPUT_PROPERTY] = (\n        InputNode(\n            node_category=NodeCategory.INPUT_NODE,\n            name=super_input_node,\n            selector=f\"$inputs.{super_input_node}\",\n            data_lineage=[],\n            input_manifest=None,  # this is expected never to be reached\n        )\n    )\n    top_level_data_lineage = set()\n    for node in traverse_graph_ensuring_parents_are_reached_first(\n        graph=execution_graph,\n        start_node=super_input_node,\n    ):\n        execution_graph = denote_data_flow_for_node(\n            execution_graph=execution_graph,\n            node=node,\n            block_manifest_by_step_name=block_manifest_by_step_name,\n            on_top_level_lineage_denoted=lambda element: top_level_data_lineage.add(\n                element\n            ),\n        )\n    execution_graph.remove_node(super_input_node)\n    execution_graph.graph[TOP_LEVEL_LINEAGES_KEY] = top_level_data_lineage\n    return execution_graph\n\n\ndef denote_data_flow_for_node(\n    execution_graph: DiGraph,\n    node: str,\n    block_manifest_by_step_name: Dict[str, WorkflowBlockManifest],\n    on_top_level_lineage_denoted: Callable[[str], None],\n) -> DiGraph:\n    if is_input_node(execution_graph=execution_graph, node=node):\n        # everything already set there, in the previous stage of compilation\n        return execution_graph\n    if is_step_node(execution_graph=execution_graph, node=node):\n        step_name = get_last_chunk_of_selector(selector=node)\n        if step_name not in block_manifest_by_step_name:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler expected manifest for the step: {step_name} to be registered \"\n                f\"but this condition is not met. This is most likely the bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | retrieving_predecessors_for_output\",\n            )\n        manifest = block_manifest_by_step_name[step_name]\n        return denote_data_flow_for_step(\n            execution_graph=execution_graph,\n            node=node,\n            manifest=manifest,\n            on_top_level_lineage_denoted=on_top_level_lineage_denoted,\n        )\n    if is_output_node(execution_graph=execution_graph, node=node):\n        # output is allowed to have exactly one predecessor\n        output_predecessors = list(execution_graph.predecessors(node))\n        if len(output_predecessors) != 1:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler expected each output in compiled graph to have one predecessor, \"\n                f\"but this condition is not met for node {node}. This is most likely the bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | retrieving_predecessors_for_output\",\n            )\n        predecessor_node = output_predecessors[0]\n        predecessor_node_data = node_as(\n            execution_graph=execution_graph,\n            node=predecessor_node,\n            expected_type=ExecutionGraphNode,\n        )\n        predecessor_node_lineage = predecessor_node_data.data_lineage\n        output_node_data = node_as(\n            execution_graph=execution_graph,\n            node=node,\n            expected_type=OutputNode,\n        )\n        output_node_data.data_lineage = predecessor_node_lineage\n        return execution_graph\n    raise AssumptionError(\n        f\"Workflow Compiler encountered node: {node} which cannot be classified as known node type. \"\n        f\"This is most likely the bug. Contact Roboflow team through github issues \"\n        f\"(https://github.com/roboflow/inference/issues) providing full \"\n        f\"context of the problem - including workflow definition you use.\",\n        context=\"workflow_compilation | execution_graph_construction | denoting_data_flow_for_step\",\n    )\n\n\ndef denote_data_flow_for_step(\n    execution_graph: DiGraph,\n    node: str,\n    manifest: WorkflowBlockManifest,\n    on_top_level_lineage_denoted: Callable[[str], None],\n) -> DiGraph:\n    all_control_flow_predecessors, all_non_control_flow_predecessors = (\n        separate_control_flow_predecessors_from_data_providers(\n            execution_graph=execution_graph, node=node\n        )\n    )\n    input_data = build_input_data_for_step(\n        manifest=manifest,\n        step_node=node,\n        data_providing_predecessors=all_non_control_flow_predecessors,\n        execution_graph=execution_graph,\n    )\n    step_name = get_last_chunk_of_selector(node)\n    step_node_data = node_as(\n        execution_graph=execution_graph,\n        node=node,\n        expected_type=StepNode,\n    )\n    parsed_step_input_selectors: List[ParsedSelector] = execution_graph.nodes[node][\n        PARSED_NODE_INPUT_SELECTORS_PROPERTY\n    ]\n    batch_compatibility_of_properties = retrieve_batch_compatibility_of_input_selectors(\n        input_selectors=parsed_step_input_selectors\n    )\n    scalar_parameters_to_be_batched = (\n        verify_declared_batch_compatibility_against_actual_inputs(\n            node=node,\n            step_node_data=step_node_data,\n            input_data=input_data,\n            batch_compatibility_of_properties=batch_compatibility_of_properties,\n        )\n    )\n    input_dimensionality_offsets = manifest.get_input_dimensionality_offsets()\n    verify_step_input_dimensionality_offsets(\n        step_name=step_name,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n    )\n    inputs_dimensionalities = get_inputs_dimensionalities(\n        step_name=step_name,\n        step_type=manifest.type,\n        input_data=input_data,\n        scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n    )\n    logger.debug(\n        f\"For step: {node}, detected the following input dimensionalities: {inputs_dimensionalities}\"\n    )\n    parameters_with_batch_inputs = grab_parameters_defining_batch_inputs(\n        inputs_dimensionalities=inputs_dimensionalities,\n    )\n    dimensionality_reference_property = manifest.get_dimensionality_reference_property()\n    output_dimensionality_offset = manifest.get_output_dimensionality_offset()\n    verify_step_input_dimensionality_offsets(\n        step_name=step_name,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n    )\n    verify_output_offset(\n        step_name=step_name,\n        parameters_with_batch_inputs=parameters_with_batch_inputs,\n        dimensionality_reference_property=dimensionality_reference_property,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n        output_dimensionality_offset=output_dimensionality_offset,\n    )\n    verify_input_data_dimensionality(\n        step_name=step_name,\n        step_type=manifest.type,\n        dimensionality_reference_property=dimensionality_reference_property,\n        inputs_dimensionalities=inputs_dimensionalities,\n        dimensionality_offstes=input_dimensionality_offsets,\n    )\n    all_data_derived_lineages = get_input_data_lineage_excluding_auto_batch_casting(\n        step_name=step_name,\n        input_data=input_data,\n        scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n    )\n    all_control_flow_lineages = get_lineage_derived_from_control_flow(\n        control_flow_steps_selectors=all_control_flow_predecessors,\n        execution_graph=execution_graph,\n    )\n    verify_compatibility_of_input_data_lineage_with_control_flow_lineage(\n        step_name=step_name,\n        inputs_lineage=all_data_derived_lineages,\n        control_flow_steps_selectors=all_control_flow_predecessors,\n        execution_graph=execution_graph,\n    )\n    step_node_data.input_data = input_data\n    step_node_data.dimensionality_reference_property = dimensionality_reference_property\n    step_node_data.control_flow_lineage_dims = [\n        len(_lineage) for _lineage in all_control_flow_lineages if _lineage\n    ]\n    step_node_data.batch_oriented_parameters = parameters_with_batch_inputs\n    if not all_data_derived_lineages and not all_control_flow_lineages:\n        if manifest.get_output_dimensionality_offset() > 0:\n            # brave decision to open a Pandora box\n            data_lineage = [node]\n        else:\n            data_lineage = []\n        control_flow_lineage_support = []\n    else:\n        data_lineage, control_flow_lineage_support = (\n            establish_batch_oriented_step_lineage(\n                step_selector=node,\n                all_data_derived_lineages=all_data_derived_lineages,\n                all_control_flow_lineages=all_control_flow_lineages,\n                input_data=input_data,\n                dimensionality_reference_property=dimensionality_reference_property,\n                output_dimensionality_offset=output_dimensionality_offset,\n            )\n        )\n    step_node_data.step_execution_dimensionality = (\n        establish_step_execution_dimensionality(\n            inputs_dimensionalities=inputs_dimensionalities,\n            control_flow_lineage_support=control_flow_lineage_support,\n            output_dimensionality_offset=output_dimensionality_offset,\n        )\n    )\n    lineage_supports = get_lineage_support_for_auto_batch_casted_parameters(\n        input_dimensionalities=inputs_dimensionalities,\n        all_lineages_of_batch_parameters=all_data_derived_lineages,\n        scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n    )\n    step_node_data.auto_batch_casting_lineage_supports = lineage_supports\n    step_node_data.control_flow_lineage_support = control_flow_lineage_support\n    if data_lineage:\n        on_top_level_lineage_denoted(data_lineage[0])\n    step_node_data.data_lineage = data_lineage\n    return execution_graph\n\n\ndef _collect_unique_control_flow_lineages_with_step_mapping(\n    control_flow_steps_selectors: List[str],\n    execution_graph: nx.DiGraph,\n) -> Tuple[List[List[str]], Dict[int, List[str]]]:\n    \"\"\"\n    Collect data lineages from control flow steps and deduplicate by lineage id.\n\n    For each given control flow step selector, reads its data_lineage from the\n    execution graph. Returns unique non-empty lineages (by identify_lineage id)\n    and a mapping from lineage id to every step selector that produced that\n    lineage (used e.g. for error reporting when lineage is incompatible).\n\n    Args:\n        control_flow_steps_selectors: Step selectors (node ids) of control\n            flow steps whose data_lineage is to be collected.\n        execution_graph: The workflow execution graph containing step nodes\n            and their data_lineage.\n\n    Returns:\n        A tuple of (unique_lineages, lineage_id_to_step_selectors):\n        - unique_lineages: list of distinct non-empty data lineages.\n        - lineage_id_to_step_selectors: map from lineage id to list of step\n          selectors whose data_lineage has that id (includes empty lineages).\n    \"\"\"\n    unique_lineages: List[List[str]] = []\n    seen_lineage_ids: Set[int] = set()\n    lineage_id_to_step_selectors: Dict[int, List[str]] = defaultdict(list)\n\n    for step_selector in control_flow_steps_selectors:\n        step_data = node_as(\n            execution_graph=execution_graph,\n            node=step_selector,\n            expected_type=StepNode,\n        )\n        lineage = step_data.data_lineage\n        lineage_id = identify_lineage(lineage)\n        lineage_id_to_step_selectors[lineage_id].append(step_selector)\n        if lineage and lineage_id not in seen_lineage_ids:\n            seen_lineage_ids.add(lineage_id)\n            unique_lineages.append(lineage)\n\n    return unique_lineages, dict(lineage_id_to_step_selectors)\n\n\ndef get_lineage_derived_from_control_flow(\n    control_flow_steps_selectors: List[str],\n    execution_graph: nx.DiGraph,\n) -> List[List[str]]:\n    \"\"\"\n    Return unique non-empty data lineages from the given control flow steps.\n\n    Each lineage is taken from the step's data_lineage in the execution graph.\n    Lineages are deduplicated by lineage id (see identify_lineage); empty\n    lineages are omitted. Used when establishing batch-oriented step lineage.\n\n    Args:\n        control_flow_steps_selectors: Step selectors (node ids) of control\n            flow steps whose data_lineage is to be collected.\n        execution_graph: The workflow execution graph containing step nodes\n            and their data_lineage.\n\n    Returns:\n        List of distinct non-empty data lineages, one per unique lineage id.\n    \"\"\"\n    unique_lineages, _ = _collect_unique_control_flow_lineages_with_step_mapping(\n        control_flow_steps_selectors=control_flow_steps_selectors,\n        execution_graph=execution_graph,\n    )\n    return unique_lineages\n\n\ndef separate_control_flow_predecessors_from_data_providers(\n    execution_graph: DiGraph,\n    node: str,\n) -> Tuple[List[str], List[str]]:\n    all_predecessors = list(execution_graph.predecessors(node))\n    all_control_flow_predecessors = [\n        predecessor\n        for predecessor in all_predecessors\n        if is_control_flow_step(execution_graph=execution_graph, node=predecessor)\n    ]\n    all_non_control_flow_predecessors = [\n        predecessor\n        for predecessor in all_predecessors\n        if not is_control_flow_step(execution_graph=execution_graph, node=predecessor)\n    ]\n    return all_control_flow_predecessors, all_non_control_flow_predecessors\n\n\ndef build_input_data_for_step(\n    manifest: WorkflowBlockManifest,\n    step_node: str,\n    data_providing_predecessors: List[str],\n    execution_graph: DiGraph,\n) -> StepInputData:\n    predecessors_by_property_name = get_predecessors_for_step_manifest_properties(\n        execution_graph=execution_graph,\n        step_node=step_node,\n        data_providing_predecessors=data_providing_predecessors,\n    )\n    manifest_fields_values = get_manifest_fields_values(step_manifest=manifest)\n    result = {}\n    for name, value in manifest_fields_values.items():\n        result[name] = build_input_property(\n            step_node=step_node,\n            manifest_property_name=name,\n            manifest_property_value=value,\n            predecessors_by_property_name=predecessors_by_property_name,\n            execution_graph=execution_graph,\n        )\n    return result\n\n\ndef get_predecessors_for_step_manifest_properties(\n    execution_graph: DiGraph, step_node: str, data_providing_predecessors: List[str]\n) -> Dict[str, List[PropertyPredecessorDefinition]]:\n    predecessors_by_property_name = defaultdict(list)\n    for predecessor in data_providing_predecessors:\n        edge_data = execution_graph.edges[(predecessor, step_node)]\n        # STEP_INPUT_SELECTORS_PROPERTY is optional, as special <super-input> node may be directly\n        # connected to step\n        selectors_associated_to_edge: List[ParsedSelector] = edge_data.get(\n            STEP_INPUT_SELECTORS_PROPERTY, []\n        )\n        for selector_associated_to_edge in selectors_associated_to_edge:\n            definition = PropertyPredecessorDefinition(\n                predecessor_selector=predecessor,\n                parsed_selector=selector_associated_to_edge,\n            )\n            predecessors_by_property_name[\n                selector_associated_to_edge.definition.property_name\n            ].append(definition)\n    return predecessors_by_property_name\n\n\ndef build_input_property(\n    step_node: str,\n    manifest_property_name: str,\n    manifest_property_value: Any,\n    predecessors_by_property_name: Dict[str, List[PropertyPredecessorDefinition]],\n    execution_graph: DiGraph,\n) -> Union[StepInputDefinition, CompoundStepInputDefinition]:\n    if manifest_property_name not in predecessors_by_property_name:\n        return StaticStepInputDefinition(\n            parameter_specification=ParameterSpecification(\n                parameter_name=manifest_property_name,\n            ),\n            category=NodeInputCategory.STATIC_VALUE,\n            value=manifest_property_value,\n        )\n    if isinstance(manifest_property_value, dict):\n        return build_nested_dictionary_for_input_property(\n            step_node=step_node,\n            manifest_property_name=manifest_property_name,\n            manifest_property_value=manifest_property_value,\n            predecessors_definitions=predecessors_by_property_name[\n                manifest_property_name\n            ],\n            execution_graph=execution_graph,\n        )\n    if isinstance(manifest_property_value, list):\n        return build_nested_list_for_input_property(\n            step_node=step_node,\n            manifest_property_name=manifest_property_name,\n            manifest_property_value=manifest_property_value,\n            predecessors_definitions=predecessors_by_property_name[\n                manifest_property_name\n            ],\n            execution_graph=execution_graph,\n        )\n    matching_predecessors_data = predecessors_by_property_name[manifest_property_name]\n    if len(matching_predecessors_data) != 1:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler deduced that property `{manifest_property_name}` of step `{step_node}` \"\n            f\"should be fed with data coming from exactly one execution graph node, but found \"\n            f\"{len(matching_predecessors_data)} data sources. This is most likely the bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n        )\n    predecessor_selector, predecessor_parsed_selector = (\n        matching_predecessors_data[0].predecessor_selector,\n        matching_predecessors_data[0].parsed_selector,\n    )\n    if is_input_node(execution_graph=execution_graph, node=predecessor_selector):\n        predecessor_node_data = node_as(\n            execution_graph=execution_graph,\n            node=matching_predecessors_data[0].predecessor_selector,\n            expected_type=InputNode,\n        )\n        category = (\n            NodeInputCategory.BATCH_INPUT_PARAMETER\n            if predecessor_node_data.is_batch_oriented()\n            else NodeInputCategory.NON_BATCH_INPUT_PARAMETER\n        )\n        return DynamicStepInputDefinition(\n            parameter_specification=ParameterSpecification(\n                parameter_name=manifest_property_name,\n            ),\n            category=category,\n            data_lineage=predecessor_node_data.data_lineage,\n            selector=predecessor_node_data.selector,\n        )\n    if is_step_node(execution_graph=execution_graph, node=predecessor_selector):\n        predecessor_node_data = node_as(\n            execution_graph=execution_graph,\n            node=matching_predecessors_data[0].predecessor_selector,\n            expected_type=StepNode,\n        )\n        category = (\n            NodeInputCategory.BATCH_STEP_OUTPUT\n            if predecessor_node_data.output_dimensionality > 0\n            else NodeInputCategory.NON_BATCH_STEP_OUTPUT\n        )\n        return DynamicStepInputDefinition(\n            parameter_specification=ParameterSpecification(\n                parameter_name=manifest_property_name,\n            ),\n            category=category,\n            data_lineage=predecessor_node_data.data_lineage,\n            selector=predecessor_parsed_selector.value,\n        )\n    raise AssumptionError(\n        public_message=f\"Workflow Compiler for property `{manifest_property_name}` of step `{step_node}` \"\n        f\"found data providing predecessor `{predecessor_selector}` which has unsupported step type.\"\n        f\"This is most likely the bug. \"\n        f\"Contact Roboflow team through github issues \"\n        f\"(https://github.com/roboflow/inference/issues) providing full \"\n        f\"context of the problem - including workflow definition you use.\",\n        context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n    )\n\n\ndef build_nested_dictionary_for_input_property(\n    step_node: str,\n    manifest_property_name: str,\n    manifest_property_value: dict,\n    predecessors_definitions: List[PropertyPredecessorDefinition],\n    execution_graph: DiGraph,\n) -> DictOfStepInputDefinitions:\n    nested_property_name2data: Dict[Optional[str], PropertyPredecessorDefinition] = {\n        predecessor_definition.parsed_selector.key: predecessor_definition\n        for predecessor_definition in predecessors_definitions\n    }\n    result = {}\n    for nested_dict_key, nested_dict_value in manifest_property_value.items():\n        if nested_dict_key not in nested_property_name2data:\n            result[nested_dict_key] = StaticStepInputDefinition(\n                parameter_specification=ParameterSpecification(\n                    parameter_name=manifest_property_name,\n                    nested_element_key=nested_dict_key,\n                ),\n                category=NodeInputCategory.STATIC_VALUE,\n                value=nested_dict_value,\n            )\n            continue\n        referred_node_selector = nested_property_name2data[\n            nested_dict_key\n        ].predecessor_selector\n        referred_node_parsed_selector = nested_property_name2data[\n            nested_dict_key\n        ].parsed_selector\n        if is_input_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=InputNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_INPUT_PARAMETER\n                if predecessor_node_data.is_batch_oriented()\n                else NodeInputCategory.NON_BATCH_INPUT_PARAMETER\n            )\n            result[nested_dict_key] = DynamicStepInputDefinition(\n                parameter_specification=ParameterSpecification(\n                    parameter_name=manifest_property_name,\n                    nested_element_key=nested_dict_key,\n                ),\n                category=category,\n                data_lineage=predecessor_node_data.data_lineage,\n                selector=predecessor_node_data.selector,\n            )\n            continue\n        if is_step_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=StepNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_STEP_OUTPUT\n                if predecessor_node_data.output_dimensionality > 0\n                else NodeInputCategory.NON_BATCH_STEP_OUTPUT\n            )\n            result[nested_dict_key] = DynamicStepInputDefinition(\n                parameter_specification=ParameterSpecification(\n                    parameter_name=manifest_property_name,\n                    nested_element_key=nested_dict_key,\n                ),\n                category=category,\n                data_lineage=predecessor_node_data.data_lineage,\n                selector=referred_node_parsed_selector.value,\n            )\n            continue\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for property `{manifest_property_name}` of step `{step_node}` \"\n            f\"found data providing predecessor `{referred_node_selector}` which has \"\n            f\"unsupported step type (key: {nested_dict_key} of nested data dictionary). \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n        )\n    return DictOfStepInputDefinitions(\n        name=manifest_property_name,\n        nested_definitions=result,\n    )\n\n\ndef get_manifest_fields_values(step_manifest: WorkflowBlockManifest) -> Dict[str, Any]:\n    result = {}\n    for field in step_manifest.model_fields:\n        if field in EXCLUDED_FIELDS:\n            continue\n        result[field] = getattr(step_manifest, field)\n    return result\n\n\ndef build_nested_list_for_input_property(\n    step_node: str,\n    manifest_property_name: str,\n    manifest_property_value: list,\n    predecessors_definitions: List[PropertyPredecessorDefinition],\n    execution_graph: DiGraph,\n) -> ListOfStepInputDefinitions:\n    nested_index2data: Dict[Optional[int], PropertyPredecessorDefinition] = {\n        e.parsed_selector.index: e for e in predecessors_definitions\n    }\n    result = []\n    for index, element in enumerate(manifest_property_value):\n        if index not in nested_index2data:\n            result.append(\n                StaticStepInputDefinition(\n                    parameter_specification=ParameterSpecification(\n                        parameter_name=manifest_property_name,\n                        nested_element_index=index,\n                    ),\n                    category=NodeInputCategory.STATIC_VALUE,\n                    value=element,\n                )\n            )\n            continue\n        referred_node_selector = nested_index2data[index].predecessor_selector\n        referred_node_parsed_selector = nested_index2data[index].parsed_selector\n        if is_input_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=InputNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_INPUT_PARAMETER\n                if predecessor_node_data.is_batch_oriented()\n                else NodeInputCategory.NON_BATCH_INPUT_PARAMETER\n            )\n            result.append(\n                DynamicStepInputDefinition(\n                    parameter_specification=ParameterSpecification(\n                        parameter_name=manifest_property_name,\n                        nested_element_index=index,\n                    ),\n                    category=category,\n                    data_lineage=predecessor_node_data.data_lineage,\n                    selector=predecessor_node_data.selector,\n                )\n            )\n            continue\n        if is_step_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=StepNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_STEP_OUTPUT\n                if predecessor_node_data.output_dimensionality > 0\n                else NodeInputCategory.NON_BATCH_STEP_OUTPUT\n            )\n            result.append(\n                DynamicStepInputDefinition(\n                    parameter_specification=ParameterSpecification(\n                        parameter_name=manifest_property_name,\n                        nested_element_index=index,\n                    ),\n                    category=category,\n                    data_lineage=predecessor_node_data.data_lineage,\n                    selector=referred_node_parsed_selector.value,\n                )\n            )\n            continue\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for property `{manifest_property_name}` of step `{step_node}` \"\n            f\"found data providing predecessor `{referred_node_selector}` which has \"\n            f\"unsupported step type (index: {index} of nested data list). \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n        )\n    return ListOfStepInputDefinitions(\n        name=manifest_property_name,\n        nested_definitions=result,\n    )\n\n\ndef verify_step_input_dimensionality_offsets(\n    step_name: str,\n    input_dimensionality_offsets: Dict[str, int],\n) -> None:\n    min_offset, max_offset = None, None\n    for offset in input_dimensionality_offsets.values():\n        if min_offset is None or offset < min_offset:\n            min_offset = offset\n        if max_offset is None or offset > max_offset:\n            max_offset = offset\n    if min_offset is None or max_offset is None:\n        return None\n    if min_offset < 0 or max_offset < 0:\n        raise BlockInterfaceError(\n            public_message=f\"Offsets could not be negative, but block defining step: {step_name} defines that values.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_input_offset_definitions\",\n        )\n    if abs(max_offset - min_offset) > 1:\n        raise BlockInterfaceError(\n            public_message=\"Offsets of input parameters could not differ more than 1, but block defining step {step_name} \"\n            f\"violates that rule.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_input_offset_definitions\",\n        )\n\n\ndef verify_output_offset(\n    step_name: str,\n    parameters_with_batch_inputs: Set[str],\n    input_dimensionality_offsets: Dict[str, int],\n    dimensionality_reference_property: Optional[str],\n    output_dimensionality_offset: int,\n) -> None:\n    if not parameters_with_batch_inputs and output_dimensionality_offset < 0:\n        raise StepInputDimensionalityError(\n            public_message=f\"Block defining step {step_name} defines negative dimensionality offset while only \"\n            f\"scalar inputs being provided - the block cannot run as there is no dimension to collapse.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if (\n        dimensionality_reference_property is not None\n        and dimensionality_reference_property not in parameters_with_batch_inputs\n    ):\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} defines dimensionality reference property \"\n            f\"which is not in scope of parameters bring batch-oriented input, which makes it impossible \"\n            f\"to use as reference for output dimensionality.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if output_dimensionality_offset not in {-1, 0, 1}:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} defines output dimensionality offset \"\n            f\"being {output_dimensionality_offset}, whereas it is only possible for that offset being \"\n            f\"in set [-1, 0, 1].\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    different_offsets = {o for o in input_dimensionality_offsets.values()}\n    if len(parameters_with_batch_inputs) != len(input_dimensionality_offsets):\n        # assumption of default offset being zero - and this one does not need to be manifested\n        # by block\n        different_offsets.add(0)\n    if 0 not in different_offsets and parameters_with_batch_inputs:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} explicitly defines input dimensionalities offsets\"\n            f\"with {input_dimensionality_offsets}, but the definition lack 0-level input, which is \"\n            f\"not allowed, as in this scenario offsets could be adjusted to include 0\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if len(different_offsets) > 1 and dimensionality_reference_property is None:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} explicitly defines input dimensionality \"\n            f\"offsets {input_dimensionality_offsets}. In this scenario it is required to provide dimensionality \"\n            f\"reference property.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if len(different_offsets) > 1 and output_dimensionality_offset != 0:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} explicitly defines input dimensionality \"\n            f\"offsets {input_dimensionality_offsets} and output dimensionality offset {output_dimensionality_offset} \"\n            f\"where the latter is not 0, but for inputs differing with dimensionality it is only possible to keep \"\n            f\"output dimensionality the same and point reference parameter.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n\n\ndef verify_input_data_dimensionality(\n    step_name: str,\n    step_type: str,\n    dimensionality_reference_property: Optional[str],\n    inputs_dimensionalities: Dict[str, Set[int]],\n    dimensionality_offstes: Dict[str, int],\n) -> None:\n    parameter_name2dimensionality_specification = (\n        grab_input_data_dimensionality_specifications(\n            step_name=step_name,\n            inputs_dimensionalities=inputs_dimensionalities,\n            dimensionality_offstes=dimensionality_offstes,\n        )\n    )\n    if not parameter_name2dimensionality_specification:\n        # nothing to check if no batch-oriented inputs\n        return None\n    different_dimensionalities_of_parameters = {\n        specification.actual_dimensionality\n        for specification in parameter_name2dimensionality_specification.values()\n    }\n    if dimensionality_reference_property is None:\n        if len(different_dimensionalities_of_parameters) > 1:\n            parameter2dimensionality = {\n                k: e.actual_dimensionality\n                for k, e in parameter_name2dimensionality_specification.items()\n            }\n            raise StepInputDimensionalityError(\n                public_message=f\"Block defining step {step_name} does not define dimensionality reference property, \"\n                f\"which means that all batch-oriented parameters must be at the same dimensionality level, \"\n                f\"but detected the following dimensionalities for parameters {parameter2dimensionality}\",\n                context=\"workflow_compilation | execution_graph_construction | denoting_step_inputs_dimensionality\",\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=step_name,\n                        block_type=step_type,\n                        block_details=f\"Dimensionality of input parameters doesn't match: {parameter2dimensionality}\",\n                    )\n                ],\n            )\n        return None\n    reference_specification = parameter_name2dimensionality_specification[\n        dimensionality_reference_property\n    ]\n    expected_dimensionalities = {\n        property_name: (e.expected_offset - reference_specification.expected_offset)\n        + reference_specification.actual_dimensionality\n        for property_name, e in parameter_name2dimensionality_specification.items()\n    }\n    if any(dim <= 0 for dim in expected_dimensionalities.values()):\n        raise StepInputDimensionalityError(\n            public_message=f\"Given the definition of block defining step {step_name} and data provided, \"\n            f\"the block would expect batch input dimensionality to be 0 or below, which is invalid.\",\n            context=\"workflow_compilation | execution_graph_construction | denoting_step_inputs_dimensionality\",\n        )\n    for property_name, expected_dimensionality in expected_dimensionalities.items():\n        actual_dimensionality = parameter_name2dimensionality_specification[\n            property_name\n        ].actual_dimensionality\n        if actual_dimensionality != expected_dimensionality:\n            raise StepInputDimensionalityError(\n                public_message=f\"Data fed into step `{step_name}` property `{property_name}` has \"\n                f\"actual dimensionality {actual_dimensionality}, \"\n                f\"when expected was {expected_dimensionality}\",\n                context=\"workflow_compilation | execution_graph_construction | denoting_step_inputs_dimensionality\",\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=step_name,\n                        block_type=step_type,\n                        property_name=property_name,\n                        property_details=f\"Expected dimensionality {expected_dimensionality}, but received dimensionality {actual_dimensionality}\",\n                    )\n                ],\n            )\n    return None\n\n\ndef grab_input_data_dimensionality_specifications(\n    step_name: str,\n    inputs_dimensionalities: Dict[str, Set[int]],\n    dimensionality_offstes: Dict[str, int],\n) -> Dict[str, InputDimensionalitySpecification]:\n    result = {}\n    for parameter_name, dimensionality in inputs_dimensionalities.items():\n        parameter_offset = dimensionality_offstes.get(parameter_name, 0)\n        non_zero_dimensionalities_for_parameter = {d for d in dimensionality if d > 0}\n        if len(non_zero_dimensionalities_for_parameter) > 1:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler for step: `{step_name}` and parameter: {parameter_name}\"\n                f\"found multiple different values of actual input dimensionalities: \"\n                f\"`{non_zero_dimensionalities_for_parameter}` which should be detected and addresses \"\n                f\"at earlier stages of compilation.\"\n                f\"This is most likely the bug. Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n            )\n        if non_zero_dimensionalities_for_parameter:\n            actual_dimensionality = next(iter(non_zero_dimensionalities_for_parameter))\n            result[parameter_name] = InputDimensionalitySpecification(\n                actual_dimensionality=actual_dimensionality,\n                expected_offset=parameter_offset,\n            )\n    return result\n\n\ndef verify_compatibility_of_input_data_lineage_with_control_flow_lineage(\n    step_name: str,\n    inputs_lineage: List[List[str]],\n    control_flow_steps_selectors: List[str],\n    execution_graph: DiGraph,\n) -> None:\n    \"\"\"\n    Ensure control flow steps' data lineage is compatible with the step's inputs.\n\n    Control flow steps that affect this step must operate on data that is\n    compatible with the data fed to the step; otherwise the step could never\n    execute. Compares unique control flow lineages against input lineage\n    prefixes and raises ControlFlowDefinitionError if any control flow lineage\n    is not covered by the inputs.\n\n    If inputs_lineage is empty, there is no sense to verify compatibility. The lineage of the\n    step should be established based on the control flow lineages.\n\n    Args:\n        step_name: Name of the step being verified (used in error messages).\n        inputs_lineage: Data lineages derived from the step's input data.\n        control_flow_steps_selectors: Step selectors of control flow steps\n            that affect this step's execution.\n        execution_graph: The workflow execution graph.\n\n    Raises:\n        ControlFlowDefinitionError: When a control flow step's lineage is not\n            compatible with the step's input lineage (step would never execute).\n    \"\"\"\n    (\n        batch_oriented_control_flow_lineages,\n        lineage_id2control_flow_steps,\n    ) = _collect_unique_control_flow_lineages_with_step_mapping(\n        control_flow_steps_selectors=control_flow_steps_selectors,\n        execution_graph=execution_graph,\n    )\n    if not inputs_lineage:\n        return\n\n    all_input_lineage_prefixes = get_all_batch_lineage_prefixes(lineages=inputs_lineage)\n    all_input_lineage_prefixes_hashes = {\n        identify_lineage(lineage=lineage) for lineage in all_input_lineage_prefixes\n    }\n    for control_flow_lineage in batch_oriented_control_flow_lineages:\n        control_flow_lineage_id = identify_lineage(lineage=control_flow_lineage)\n        if control_flow_lineage_id not in all_input_lineage_prefixes_hashes:\n            problematic_flow_control_steps = lineage_id2control_flow_steps[\n                control_flow_lineage_id\n            ]\n            raise ControlFlowDefinitionError(\n                public_message=f\"Step {step_name} execution is impacted by control flow outcome of the following \"\n                f\"steps {problematic_flow_control_steps} which make decision based on data that is \"\n                f\"not compatible with data fed to the step {step_name} - which would cause the step \"\n                f\"to never execute. This behaviour is invalid and prevented upfront by Workflows compiler.\",\n                context=\"workflow_compilation | execution_graph_construction | verification_of_control_flow_lineage\",\n            )\n\n\ndef get_all_batch_lineage_prefixes(lineages: List[List[str]]) -> List[List[str]]:\n    result = []\n    already_spotted = set()\n    for lineage in lineages:\n        lineage_prefixes = get_batch_lineage_prefixes(lineage=lineage)\n        for lineage_prefix in lineage_prefixes:\n            lineage_prefix_id = identify_lineage(lineage=lineage_prefix)\n            if lineage_prefix_id not in already_spotted:\n                already_spotted.add(lineage_prefix_id)\n                result.append(lineage_prefix)\n    return result\n\n\ndef get_batch_lineage_prefixes(lineage: List[str]) -> List[List[str]]:\n    if not lineage:\n        return []\n    result = []\n    prefix = []\n    for i in range(len(lineage)):\n        prefix.append(lineage[i])\n        result.append(copy(prefix))\n    return result\n\n\ndef get_inputs_dimensionalities(\n    step_name: str,\n    step_type: str,\n    input_data: StepInputData,\n    scalar_parameters_to_be_batched: Set[str],\n    input_dimensionality_offsets: Dict[str, int],\n) -> Dict[str, Set[int]]:\n    result = defaultdict(set)\n    dimensionalities_spotted = set()\n    offset_parameters = {\n        parameter: value\n        for parameter, value in input_dimensionality_offsets.items()\n        if value > 0\n    }\n    non_offset_parameters_dimensionality_values = set()\n    for property_name, input_definition in input_data.items():\n        if property_name in offset_parameters:\n            continue\n        if input_definition.is_compound_input():\n            for value in input_definition.iterate_through_definitions():\n                if value.is_batch_oriented():\n                    non_offset_parameters_dimensionality_values.add(\n                        value.get_dimensionality()\n                    )\n        elif input_definition.is_batch_oriented():\n            non_offset_parameters_dimensionality_values.add(\n                input_definition.get_dimensionality()\n            )\n    if len(non_offset_parameters_dimensionality_values) > 1:\n        raise StepInputDimensionalityError(\n            public_message=f\"For step {step_name} attempted to plug input data that are in different dimensions, \"\n            f\"whereas block defines the inputs to be equal in that terms.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_input_data\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=step_name,\n                    block_type=step_type,\n                    block_details=f\"Dimensionality of input parameters differs by more than 1. Detected dimensions: {dict(result)}\",\n                )\n            ],\n        )\n    non_offset_parameters_dimensionality_value = (\n        non_offset_parameters_dimensionality_values.pop()\n        if len(non_offset_parameters_dimensionality_values) > 0\n        else 1\n    )\n    for property_name, input_definition in input_data.items():\n        if input_definition.is_compound_input():\n            result[property_name] = get_compound_input_dimensionality(\n                step_name=step_name,\n                step_type=step_type,\n                property_name=property_name,\n                input_definition=input_definition,\n                scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n                non_offset_parameters_dimensionality_value=non_offset_parameters_dimensionality_value,\n                offset_parameters=offset_parameters,\n            )\n        else:\n            if property_name in scalar_parameters_to_be_batched:\n                if property_name not in offset_parameters:\n                    result[property_name] = {non_offset_parameters_dimensionality_value}\n                else:\n                    result[property_name] = (\n                        non_offset_parameters_dimensionality_value\n                        + offset_parameters[property_name]\n                    )\n            else:\n                result[property_name] = {input_definition.get_dimensionality()}\n        dimensionalities_spotted.update(result[property_name])\n    non_zero_dimensionalities_spotted = {d for d in dimensionalities_spotted if d != 0}\n    if len(non_zero_dimensionalities_spotted) > 0:\n        min_dim, max_dim = min(non_zero_dimensionalities_spotted), max(\n            non_zero_dimensionalities_spotted\n        )\n        if abs(max_dim - min_dim) > 1:\n            raise StepInputDimensionalityError(\n                public_message=f\"For step {step_name} attempted to plug input data differing in dimensionality more than 1\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_input_data\",\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=step_name,\n                        block_type=step_type,\n                        block_details=f\"Dimensionality of input parameters differs by more than 1. Detected dimensions: {dict(result)}\",\n                    )\n                ],\n            )\n    return result\n\n\ndef get_compound_input_dimensionality(\n    step_name: str,\n    property_name: str,\n    step_type: str,\n    input_definition: CompoundStepInputDefinition,\n    scalar_parameters_to_be_batched: Set[str],\n    offset_parameters: Dict[str, int],\n    non_offset_parameters_dimensionality_value: int,\n) -> Set[int]:\n    dimensionalities_spotted = set()\n    for definition in input_definition.iterate_through_definitions():\n        if (\n            property_name not in scalar_parameters_to_be_batched\n            or definition.is_batch_oriented()\n        ):\n            dimensionalities_spotted.add(definition.get_dimensionality())\n        elif property_name not in offset_parameters:\n            dimensionalities_spotted.add(non_offset_parameters_dimensionality_value)\n        else:\n            dimensionalities_spotted.add(\n                non_offset_parameters_dimensionality_value\n                + offset_parameters[property_name]\n            )\n    non_zero_dimensionalities = {e for e in dimensionalities_spotted if e != 0}\n    if len(non_zero_dimensionalities) > 1:\n        raise StepInputDimensionalityError(\n            public_message=f\"While evaluating compound property {property_name} of step {step_name}, \"\n            f\"detected multiple inputs of differing batch dimensionalities: {non_zero_dimensionalities}\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_input_data\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=step_name,\n                    block_type=step_type,\n                    property_name=property_name,\n                    property_details=f\"Detected multiple inputs of differing batch dimensionalities: {non_zero_dimensionalities}\",\n                )\n            ],\n        )\n    return dimensionalities_spotted\n\n\ndef grab_parameters_defining_batch_inputs(\n    inputs_dimensionalities: Dict[str, Set[int]],\n) -> Set[str]:\n    result = set()\n    for paremeter, dimensionalities in inputs_dimensionalities.items():\n        batch_dimensionalities = {d for d in dimensionalities if d > 0}\n        if len(batch_dimensionalities):\n            result.add(paremeter)\n    return result\n\n\ndef retrieve_batch_compatibility_of_input_selectors(\n    input_selectors: List[ParsedSelector],\n) -> Dict[str, Set[bool]]:\n    batch_compatibility_of_properties = defaultdict(set)\n    for parsed_selector in input_selectors:\n        for reference in parsed_selector.definition.allowed_references:\n            batch_compatibility_of_properties[\n                parsed_selector.definition.property_name\n            ].update(reference.points_to_batch)\n    return batch_compatibility_of_properties\n\n\ndef verify_declared_batch_compatibility_against_actual_inputs(\n    node: str,\n    step_node_data: StepNode,\n    input_data: StepInputData,\n    batch_compatibility_of_properties: Dict[str, Set[bool]],\n) -> Set[str]:\n    scalar_parameters_to_be_batched = set()\n    parameters_accepting_batches_and_scalars = set(\n        step_node_data.step_manifest.get_parameters_accepting_batches_and_scalars()\n    )\n    hardcoded_inputs_to_be_batch_compatible = set(\n        step_node_data.step_manifest.get_parameters_enforcing_auto_batch_casting()\n        + step_node_data.step_manifest.get_parameters_accepting_batches()\n    )\n    for property_name, input_definition in input_data.items():\n        if property_name not in batch_compatibility_of_properties:\n            actual_input_is_batch = {False}\n            if property_name in parameters_accepting_batches_and_scalars:\n                batch_compatibility = {True, False}\n            elif property_name in hardcoded_inputs_to_be_batch_compatible:\n                batch_compatibility = {True}\n            else:\n                continue\n        elif input_definition.is_compound_input():\n            actual_input_is_batch = {\n                element.is_batch_oriented()\n                for element in input_definition.iterate_through_definitions()\n            }\n            batch_compatibility = batch_compatibility_of_properties[property_name]\n        else:\n            actual_input_is_batch = {input_definition.is_batch_oriented()}\n            batch_compatibility = batch_compatibility_of_properties[property_name]\n        step_accepts_batch_input = step_node_data.step_manifest.accepts_batch_input()\n        if (\n            step_accepts_batch_input\n            and batch_compatibility == {False}\n            and True in actual_input_is_batch\n        ):\n            raise ExecutionGraphStructureError(\n                public_message=f\"Detected invalid reference plugged \"\n                f\"into property `{property_name}` of step `{node}` - the step \"\n                f\"property do not accept batch-oriented inputs, yet the input selector \"\n                f\"holds one - this indicates the problem with \"\n                f\"construction of your Workflow - usually the problem occurs when non-batch oriented \"\n                f\"step inputs are filled with outputs of batch-oriented steps or batch-oriented inputs.\",\n                context=\"workflow_compilation | execution_graph_construction\",\n            )\n        if batch_compatibility == {True} and False in actual_input_is_batch:\n            scalar_parameters_to_be_batched.add(property_name)\n    return scalar_parameters_to_be_batched\n\n\ndef get_input_data_lineage_excluding_auto_batch_casting(\n    step_name: str,\n    input_data: StepInputData,\n    scalar_parameters_to_be_batched: Set[str],\n) -> List[List[str]]:\n    lineage_deduplication_set = set()\n    lineages = []\n    for property_name, input_definition in input_data.items():\n        new_lineages_detected_within_property_data = get_lineage_for_input_property(\n            step_name=step_name,\n            property_name=property_name,\n            input_definition=input_definition,\n            lineage_deduplication_set=lineage_deduplication_set,\n        )\n        if (\n            property_name in scalar_parameters_to_be_batched\n            and len(new_lineages_detected_within_property_data) == 0\n        ):\n            continue\n        lineages.extend(new_lineages_detected_within_property_data)\n    if not lineages:\n        return lineages\n    verify_lineages(step_name=step_name, detected_lineages=lineages)\n    return lineages\n\n\ndef get_lineage_support_for_auto_batch_casted_parameters(\n    input_dimensionalities: Dict[str, Set[int]],\n    scalar_parameters_to_be_batched: Set[str],\n    all_lineages_of_batch_parameters: List[List[str]],\n) -> Dict[str, AutoBatchCastingConfig]:\n    longest_lineage_support = find_longest_lineage_support(\n        all_lineages_of_batch_parameters=all_lineages_of_batch_parameters,\n    )\n    result = {}\n    for parameter_name in scalar_parameters_to_be_batched:\n        parameter_dimensionality = max(input_dimensionalities[parameter_name])\n        if longest_lineage_support is None:\n            lineage_support = None\n        else:\n            lineage_support = longest_lineage_support[:parameter_dimensionality]\n        result[parameter_name] = AutoBatchCastingConfig(\n            casted_dimensionality=parameter_dimensionality,\n            lineage_support=lineage_support,\n        )\n    return result\n\n\ndef find_longest_lineage_support(\n    all_lineages_of_batch_parameters: List[List[str]],\n) -> Optional[List[str]]:\n    longest_longest_lineage_support = []\n    for lineage in all_lineages_of_batch_parameters:\n        if len(lineage) > len(longest_longest_lineage_support):\n            longest_longest_lineage_support = lineage\n    if len(longest_longest_lineage_support) == 0:\n        return None\n    return longest_longest_lineage_support\n\n\ndef get_lineage_for_input_property(\n    step_name: str,\n    property_name: str,\n    input_definition: Union[StepInputDefinition, CompoundStepInputDefinition],\n    lineage_deduplication_set: Set[int],\n) -> List[List[str]]:\n    if input_definition.is_compound_input():\n        return get_lineage_from_compound_input(\n            step_name=step_name,\n            property_name=property_name,\n            input_definition=input_definition,\n            lineage_deduplication_set=lineage_deduplication_set,\n        )\n    lineages = []\n    if input_definition.is_batch_oriented():\n        lineage = input_definition.data_lineage\n        lineage_id = identify_lineage(lineage=lineage)\n        if lineage_id not in lineage_deduplication_set:\n            lineage_deduplication_set.add(lineage_id)\n            lineages.append(lineage)\n    return lineages\n\n\ndef get_lineage_from_compound_input(\n    step_name: str,\n    property_name: str,\n    input_definition: Union[StepInputDefinition, CompoundStepInputDefinition],\n    lineage_deduplication_set: Set[int],\n) -> List[List[str]]:\n    lineages = []\n    for nested_element in input_definition.iterate_through_definitions():\n        if nested_element.is_batch_oriented():\n            lineage = nested_element.data_lineage\n            lineage_id = identify_lineage(lineage=lineage)\n            if lineage_id not in lineage_deduplication_set:\n                lineage_deduplication_set.add(lineage_id)\n                lineages.append(lineage)\n    if len(lineages) > 1:\n        raise StepInputLineageError(\n            public_message=f\"Input data provided for step: `{step_name}` comes with multiple different lineages \"\n            f\"{lineages} for property `{property_name}` accepting \"\n            f\"multiple selectors, which is not allowed.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    return lineages\n\n\ndef verify_lineages(step_name: str, detected_lineages: List[List[str]]) -> None:\n    lineages_by_length = defaultdict(list)\n    for lineage in detected_lineages:\n        lineages_by_length[len(lineage)].append(lineage)\n    if len(lineages_by_length) > 2:\n        raise StepInputLineageError(\n            public_message=f\"Input data provided for step: `{step_name}` comes with lineages at more than two \"\n            f\"dimensionality levels, which should not be possible.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    lineage_lengths = sorted(lineages_by_length.keys())\n    for lineage_length in lineage_lengths:\n        if len(lineages_by_length[lineage_length]) > 1:\n            raise StepInputLineageError(\n                public_message=f\"Among step `{step_name}` inputs found different lineages at the same  \"\n                f\"dimensionality levels dimensionality.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if len(lineages_by_length[lineage_lengths[-1]]) > 1 and len(lineage_lengths) < 2:\n        raise StepInputLineageError(\n            public_message=f\"If lineage differ at the last level, then Execution Engine requires at least one \"\n            f\"higher-dimension  input that will come with common lineage, but this is not the \"\n            f\"case for step {step_name}.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    if len(lineage_lengths) == 2:\n        reference_lineage = lineages_by_length[lineage_lengths[0]][0]\n        if reference_lineage != lineages_by_length[lineage_lengths[1]][0][:-1]:\n            raise StepInputLineageError(\n                public_message=f\"Step `{step_name}` inputs does not share common lineage. Differing element: \"\n                f\"{lineages_by_length[lineage_lengths[1]][0]}, \"\n                f\"reference lineage prefix: {reference_lineage}\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n\n\ndef establish_step_execution_dimensionality(\n    inputs_dimensionalities: Dict[str, Set[int]],\n    control_flow_lineage_support: List[str],\n    output_dimensionality_offset: int,\n) -> int:\n    \"\"\"\n    Determine how many batch dimensions (execution slices) a step runs with.\n\n    Used during workflow compilation in denote_data_flow_for_step. The result\n    is stored on StepNode.step_execution_dimensionality and consumed at\n    execution time to:\n    - Drive how many times the step is executed (which batch indices/slices).\n    - Align and expand inputs (e.g. auto-batch casting) to match this size.\n    - Validate that parameter dimensionalities are compatible (runtime checks\n      in step_input_assembler and manager).\n\n    Logic:\n    - If no input has non-zero dimensionality but the step is gated by\n      control flow (control_flow_lineage_support non-empty), the\n      dimensionality is the number of control-flow branches.\n    - Otherwise, the minimum non-zero input dimensionality is used; if\n      output_dimensionality_offset < 0 (step reduces batch dimension),\n      one is subtracted.\n\n    Args:\n        inputs_dimensionalities: Per-input sets of dimensionalities (from\n            get_inputs_dimensionalities).\n        control_flow_lineage_support: Lineage identifiers for control-flow\n            branches that gate this step (from establish_batch_oriented_step_lineage).\n        output_dimensionality_offset: Block's output dimensionality offset\n            (positive = expand, negative = reduce batch dimension).\n\n    Returns:\n        The number of batch dimensions (execution slices) for this step.\n    \"\"\"\n    step_execution_dimensionality = 0\n    non_zero_dimensionalities = {\n        dimensionality\n        for dimensionalities in inputs_dimensionalities.values()\n        for dimensionality in dimensionalities\n        if dimensionality > 0\n    }\n    if len(non_zero_dimensionalities) == 0 and len(control_flow_lineage_support) > 0:\n        return len(control_flow_lineage_support)\n    if len(non_zero_dimensionalities) > 0:\n        step_execution_dimensionality = min(non_zero_dimensionalities)\n        if output_dimensionality_offset < 0:\n            step_execution_dimensionality -= 1\n    return step_execution_dimensionality\n\n\ndef establish_batch_oriented_step_lineage(\n    step_selector: str,\n    all_data_derived_lineages: List[List[str]],\n    all_control_flow_lineages: List[List[str]],\n    input_data: StepInputData,\n    dimensionality_reference_property: Optional[str],\n    output_dimensionality_offset: int,\n) -> Tuple[List[str], List[str]]:\n    reference_lineage, control_flow_lineage_support = get_reference_lineage(\n        step_selector=step_selector,\n        all_data_derived_lineages=all_data_derived_lineages,\n        all_control_flow_lineages=all_control_flow_lineages,\n        input_data=input_data,\n        dimensionality_reference_property=dimensionality_reference_property,\n    )\n    if output_dimensionality_offset < 0:\n        result_dimensionality = reference_lineage[:output_dimensionality_offset]\n        return result_dimensionality, []\n    if output_dimensionality_offset == 0:\n        return reference_lineage, control_flow_lineage_support\n    reference_lineage.append(step_selector)\n    return reference_lineage, []\n\n\ndef get_reference_lineage(\n    step_selector: str,\n    all_data_derived_lineages: List[List[str]],\n    all_control_flow_lineages: List[List[str]],\n    input_data: StepInputData,\n    dimensionality_reference_property: Optional[str],\n) -> Tuple[List[str], List[str]]:\n    if not all_data_derived_lineages:\n        if len(all_control_flow_lineages) == 1:\n            return copy(all_control_flow_lineages[0]), copy(\n                all_control_flow_lineages[0]\n            )\n        # Multiple control-flow lineages and no data-derived lineage: pick the deepest.\n        max_lineage_len = max(len(lineage) for lineage in all_control_flow_lineages)\n        lineages_matching_max_len = [\n            _lineage\n            for _lineage in all_control_flow_lineages\n            if len(_lineage) == max_lineage_len\n        ]\n        if len(lineages_matching_max_len) == 1:\n            return copy(lineages_matching_max_len[0]), copy(\n                lineages_matching_max_len[0]\n            )\n        else:\n            raise AssumptionError(\n                public_message=f\"Multiple control-flow lineages at the same level for step `{step_selector}` \"\n                f\"and no data-derived lineage; unique lineage level required. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if len(all_data_derived_lineages) == 1:\n        return copy(all_data_derived_lineages[0]), []\n    if dimensionality_reference_property not in input_data:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` expected dimensionality_reference_property \"\n            f\"presence to be verified at earlier stages, which did not happen as expected. \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    property_data = input_data[dimensionality_reference_property]\n    if property_data.is_compound_input():\n        lineage = None\n        for nested_element in property_data.iterate_through_definitions():\n            if nested_element.is_batch_oriented():\n                lineage = copy(nested_element.data_lineage)\n                return lineage, []\n        if lineage is None:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n                f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if not property_data.is_batch_oriented():\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n            f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    return copy(property_data.data_lineage), []\n\n\ndef get_property_with_invalid_selector(\n    manifest: WorkflowBlockManifest, step_property: str\n) -> Optional[str]:\n    property_name = None\n    for key, value in manifest.__dict__.items():\n        if isinstance(value, str) and step_property in value:\n            property_name = key\n            break\n    return property_name\n\n\ndef add_super_input_node_in_execution_graph(\n    execution_graph: DiGraph,\n    super_input_node: str,\n) -> DiGraph:\n    nodes_to_attach_super_input_into = get_nodes_of_specific_category(\n        execution_graph=execution_graph,\n        category=NodeCategory.INPUT_NODE,\n    )\n    step_nodes_without_predecessors = [\n        node\n        for node in execution_graph.nodes\n        if not list(execution_graph.predecessors(node))\n    ]\n    nodes_to_attach_super_input_into.update(step_nodes_without_predecessors)\n    execution_graph.add_node(super_input_node)\n    for node in nodes_to_attach_super_input_into:\n        execution_graph.add_edge(super_input_node, node)\n    return execution_graph\n",
    "patch": null
  },
  {
    "trace_id": "1fde2419-152a-4203-9bd3-b8e5650b0594",
    "function_name": "step_definition_allows_control_flow_references",
    "file_path": "inference/core/workflows/execution_engine/v1/compiler/graph_constructor.py",
    "speedup_x": 0.8627488853477554,
    "review_quality": "high",
    "pre_optimization_commit": "90243bdc6278ef7d17b6db09dc1eb5b0d155b4be",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def step_definition_allows_control_flow_references(\n    parsed_selector: ParsedSelector,\n) -> bool:\n    return any(\n        definition.selected_element == STEP_AS_SELECTED_ELEMENT\n        for definition in parsed_selector.definition.allowed_references\n    )\n",
    "optimized_function_code": "from inference.core.workflows.execution_engine.entities.types import \\\n    STEP_AS_SELECTED_ELEMENT\nfrom inference.core.workflows.execution_engine.introspection.entities import \\\n    ParsedSelector\n\n\ndef step_definition_allows_control_flow_references(\n    parsed_selector: ParsedSelector,\n) -> bool:\n    target = STEP_AS_SELECTED_ELEMENT\n    for definition in parsed_selector.definition.allowed_references:\n        if definition.selected_element == target:\n            return True\n    return False",
    "optimized_raw_markdown": "```python:inference/core/workflows/execution_engine/v1/compiler/graph_constructor.py\nfrom inference.core.workflows.execution_engine.entities.types import \\\n    STEP_AS_SELECTED_ELEMENT\nfrom inference.core.workflows.execution_engine.introspection.entities import \\\n    ParsedSelector\n\n\ndef step_definition_allows_control_flow_references(\n    parsed_selector: ParsedSelector,\n) -> bool:\n    target = STEP_AS_SELECTED_ELEMENT\n    for definition in parsed_selector.definition.allowed_references:\n        if definition.selected_element == target:\n            return True\n    return False\n```",
    "optimized_function_only": "def step_definition_allows_control_flow_references(\n    parsed_selector: ParsedSelector,\n) -> bool:\n    target = STEP_AS_SELECTED_ELEMENT\n    for definition in parsed_selector.definition.allowed_references:\n        if definition.selected_element == target:\n            return True\n    return False",
    "original_file_content": "import itertools\nfrom collections import defaultdict\nfrom copy import copy, deepcopy\nfrom typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union\nfrom uuid import uuid4\n\nimport networkx as nx\nfrom networkx import DiGraph\n\nfrom inference.core import logger\nfrom inference.core.workflows.errors import (\n    AssumptionError,\n    BlockInterfaceError,\n    ControlFlowDefinitionError,\n    ExecutionGraphStructureError,\n    InvalidReferenceTargetError,\n    StepInputDimensionalityError,\n    StepInputLineageError,\n    WorkflowBlockError,\n)\nfrom inference.core.workflows.execution_engine.constants import (\n    NODE_COMPILATION_OUTPUT_PROPERTY,\n    PARSED_NODE_INPUT_SELECTORS_PROPERTY,\n    TOP_LEVEL_LINEAGES_KEY,\n    WORKFLOW_INPUT_BATCH_LINEAGE_ID,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    InputType,\n    JsonField,\n    OutputDefinition,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    STEP_AS_SELECTED_ELEMENT,\n    Kind,\n)\nfrom inference.core.workflows.execution_engine.introspection.entities import (\n    ParsedSelector,\n)\nfrom inference.core.workflows.execution_engine.introspection.selectors_parser import (\n    get_step_selectors,\n)\nfrom inference.core.workflows.execution_engine.profiling.core import (\n    WorkflowsProfiler,\n    execution_phase,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import (\n    AutoBatchCastingConfig,\n    CompoundStepInputDefinition,\n    DictOfStepInputDefinitions,\n    DynamicStepInputDefinition,\n    ExecutionGraphNode,\n    InputDimensionalitySpecification,\n    InputNode,\n    ListOfStepInputDefinitions,\n    NodeCategory,\n    NodeInputCategory,\n    OutputNode,\n    ParameterSpecification,\n    ParsedWorkflowDefinition,\n    PropertyPredecessorDefinition,\n    StaticStepInputDefinition,\n    StepInputData,\n    StepInputDefinition,\n    StepNode,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.graph_traversal import (\n    traverse_graph_ensuring_parents_are_reached_first,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.reference_type_checker import (\n    validate_reference_kinds,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import (\n    construct_input_selector,\n    construct_output_selector,\n    construct_step_selector,\n    get_last_chunk_of_selector,\n    get_nodes_of_specific_category,\n    get_step_selector_from_its_output,\n    identify_lineage,\n    is_control_flow_step,\n    is_input_node,\n    is_input_selector,\n    is_output_node,\n    is_step_node,\n    is_step_output_selector,\n    is_step_selector,\n    node_as,\n)\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nNODE_DEFINITION_KEY = \"definition\"\nSTEP_INPUT_SELECTORS_PROPERTY = \"step_input_selectors\"\nEXCLUDED_FIELDS = {\"type\", \"name\"}\n\n\n@execution_phase(\n    name=\"execution_graph_creation\",\n    categories=[\"execution_engine_operation\"],\n)\ndef prepare_execution_graph(\n    workflow_definition: ParsedWorkflowDefinition,\n    profiler: Optional[WorkflowsProfiler] = None,\n) -> DiGraph:\n    execution_graph = construct_graph(\n        workflow_definition=workflow_definition,\n    )\n    if not nx.is_directed_acyclic_graph(execution_graph):\n        raise ExecutionGraphStructureError(\n            public_message=f\"Detected cycle in execution graph. This means that there is output from one \"\n            f\"step that is connected to input of other step creating loop in the graph that would \"\n            f\"never end if executed.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    return denote_data_flow_in_workflow(\n        execution_graph=execution_graph,\n        parsed_workflow_definition=workflow_definition,\n    )\n\n\ndef construct_graph(\n    workflow_definition: ParsedWorkflowDefinition,\n) -> DiGraph:\n    execution_graph = nx.DiGraph()\n    execution_graph = add_input_nodes_for_graph(\n        inputs=workflow_definition.inputs,\n        execution_graph=execution_graph,\n    )\n    execution_graph = add_steps_nodes_for_graph(\n        steps=workflow_definition.steps,\n        execution_graph=execution_graph,\n    )\n    execution_graph = add_output_nodes_for_graph(\n        outputs=workflow_definition.outputs,\n        execution_graph=execution_graph,\n    )\n    execution_graph = add_steps_edges(\n        workflow_definition=workflow_definition,\n        execution_graph=execution_graph,\n    )\n    return add_edges_for_outputs(\n        workflow_definition=workflow_definition,\n        execution_graph=execution_graph,\n    )\n\n\ndef add_input_nodes_for_graph(\n    inputs: List[InputType],\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for input_spec in inputs:\n        input_selector = construct_input_selector(input_name=input_spec.name)\n        if input_spec.is_batch_oriented():\n            if input_spec.dimensionality < 1:\n                raise ExecutionGraphStructureError(\n                    public_message=f\"Detected batch oriented input `{input_spec.name}` with \"\n                    f\"declared dimensionality `{input_spec.dimensionality}` which is below \"\n                    f\"one (one is minimum dimensionality of the batch). Fix input definition in\"\n                    f\"your Workflow.\",\n                    context=\"workflow_compilation | execution_graph_construction\",\n                )\n            data_lineage = [WORKFLOW_INPUT_BATCH_LINEAGE_ID]\n            for _ in range(input_spec.dimensionality - 1):\n                # TODO: this may end up being a bug - with ability for multi-step debugging, if we will\n                #  ever have a situation that there will be multiple step outputs with nested\n                #  dimensionality with the same lineage, this re-construction method will\n                #  assign a different lineage identifier, causing the inputs being non-composable in\n                #  a single execution branch\n                data_lineage.append(f\"{uuid4()}\")\n        else:\n            data_lineage = []\n        compilation_output = InputNode(\n            node_category=NodeCategory.INPUT_NODE,\n            name=input_spec.name,\n            selector=input_selector,\n            data_lineage=data_lineage,\n            input_manifest=input_spec,\n        )\n        execution_graph.add_node(\n            input_selector,\n            **{\n                NODE_COMPILATION_OUTPUT_PROPERTY: compilation_output,\n            },\n        )\n    return execution_graph\n\n\ndef add_steps_nodes_for_graph(\n    steps: List[WorkflowBlockManifest],\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for step in steps:\n        step_selector = construct_step_selector(step_name=step.name)\n        compilation_output = StepNode(\n            node_category=NodeCategory.STEP_NODE,\n            name=step.name,\n            selector=step_selector,\n            data_lineage=[],\n            step_manifest=step,\n        )\n        execution_graph.add_node(\n            step_selector,\n            **{\n                NODE_COMPILATION_OUTPUT_PROPERTY: compilation_output,\n            },\n        )\n    return execution_graph\n\n\ndef add_output_nodes_for_graph(\n    outputs: List[JsonField],\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for output_spec in outputs:\n        output_selector = construct_output_selector(name=output_spec.name)\n        compilation_output = OutputNode(\n            node_category=NodeCategory.OUTPUT_NODE,\n            name=output_spec.name,\n            selector=output_selector,\n            data_lineage=[],\n            output_manifest=output_spec,\n        )\n        execution_graph.add_node(\n            output_selector,\n            **{\n                NODE_COMPILATION_OUTPUT_PROPERTY: compilation_output,\n            },\n        )\n    return execution_graph\n\n\ndef add_steps_edges(\n    workflow_definition: ParsedWorkflowDefinition,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for step in workflow_definition.steps:\n        source_step_selector = construct_step_selector(step_name=step.name)\n        step_selectors = get_step_selectors(step_manifest=step)\n        execution_graph.nodes[source_step_selector][\n            PARSED_NODE_INPUT_SELECTORS_PROPERTY\n        ] = step_selectors\n        execution_graph = add_edges_for_step(\n            execution_graph=execution_graph,\n            source_step_selector=source_step_selector,\n            target_step_parsed_selectors=step_selectors,\n        )\n    return execution_graph\n\n\ndef add_edges_for_step(\n    execution_graph: DiGraph,\n    source_step_selector: str,\n    target_step_parsed_selectors: List[ParsedSelector],\n) -> DiGraph:\n    for target_step_parsed_selector in target_step_parsed_selectors:\n        execution_graph = add_edge_for_step(\n            execution_graph=execution_graph,\n            source_step_selector=source_step_selector,\n            target_step_parsed_selector=target_step_parsed_selector,\n        )\n    return execution_graph\n\n\ndef add_edge_for_step(\n    execution_graph: DiGraph,\n    source_step_selector: str,\n    target_step_parsed_selector: ParsedSelector,\n) -> DiGraph:\n    target_step_selector = get_step_selector_from_its_output(\n        step_output_selector=target_step_parsed_selector.value\n    )\n    verify_edge_is_created_between_existing_nodes(\n        execution_graph=execution_graph,\n        start=source_step_selector,\n        end=target_step_selector,\n    )\n    if is_step_selector(target_step_parsed_selector.value):\n        return establish_control_flow_edge(\n            source_step_selector=source_step_selector,\n            target_step_parsed_selector=target_step_parsed_selector,\n            execution_graph=execution_graph,\n        )\n    if is_input_selector(target_step_parsed_selector.value):\n        input_node_compilation_data = node_as(\n            execution_graph=execution_graph,\n            node=target_step_parsed_selector.value,\n            expected_type=InputNode,\n        )\n        actual_input_kind = input_node_compilation_data.input_manifest.kind\n    else:\n        other_step_compilation_data = node_as(\n            execution_graph=execution_graph,\n            node=target_step_selector,\n            expected_type=StepNode,\n        )\n        source_step_compilation_data = node_as(\n            execution_graph=execution_graph,\n            node=source_step_selector,\n            expected_type=StepNode,\n        )\n        actual_input_kind = get_kind_of_value_provided_in_step_output(\n            step_manifest=other_step_compilation_data.step_manifest,\n            step_property=get_last_chunk_of_selector(\n                selector=target_step_parsed_selector.value\n            ),\n            source_step_manifest=source_step_compilation_data.step_manifest,\n        )\n    expected_input_kind = list(\n        itertools.chain.from_iterable(\n            ref.kind\n            for ref in target_step_parsed_selector.definition.allowed_references\n        )\n    )\n    error_message = (\n        f\"Failed to validate reference provided for step: {source_step_selector} regarding property: \"\n        f\"{target_step_parsed_selector.definition.property_name} with value: {target_step_parsed_selector.value}. \"\n        f\"Allowed kinds of references for this property: {list(set(e.name for e in expected_input_kind))}. \"\n        f\"Types of output for referred property: \"\n        f\"{list(set(a.name if isinstance(a, Kind) else a for a in actual_input_kind))}\"\n    )\n    validate_reference_kinds(\n        expected=expected_input_kind,\n        actual=actual_input_kind,\n        error_message=error_message,\n    )\n    if execution_graph.has_edge(target_step_selector, source_step_selector):\n        edge_data = execution_graph.edges[(target_step_selector, source_step_selector)]\n        if STEP_INPUT_SELECTORS_PROPERTY not in edge_data:\n            edge_data[STEP_INPUT_SELECTORS_PROPERTY] = []\n        edge_data[STEP_INPUT_SELECTORS_PROPERTY].append(\n            target_step_parsed_selector,\n        )\n    else:\n        execution_graph.add_edge(\n            target_step_selector,\n            source_step_selector,\n            **{STEP_INPUT_SELECTORS_PROPERTY: [target_step_parsed_selector]},\n        )\n    return execution_graph\n\n\ndef establish_control_flow_edge(\n    source_step_selector: str,\n    target_step_parsed_selector: ParsedSelector,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    if not step_definition_allows_control_flow_references(\n        parsed_selector=target_step_parsed_selector\n    ):\n        raise ExecutionGraphStructureError(\n            public_message=f\"Detected reference to other step in manifest of step {source_step_selector}. \"\n            f\"This is not allowed, as step manifest does not define any properties of type `StepSelector` \"\n            f\"allowing for defining connections between steps that represent flow control in `workflows`.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    target_step_selector = get_step_selector_from_its_output(\n        step_output_selector=target_step_parsed_selector.value\n    )\n    source_compilation_data = node_as(\n        execution_graph=execution_graph,\n        node=source_step_selector,\n        expected_type=StepNode,\n    )\n    target_compilation_data = node_as(\n        execution_graph=execution_graph,\n        node=target_step_selector,\n        expected_type=StepNode,\n    )\n    nodes_categories = {\n        source_compilation_data.node_category,\n        target_compilation_data.node_category,\n    }\n    if nodes_categories != {NodeCategory.STEP_NODE}:\n        raise ExecutionGraphStructureError(\n            public_message=f\"Attempted to create flow-control connection between workflow nodes: \"\n            f\"{source_step_selector} and {target_step_selector}, one of which is not denoted\"\n            f\"as step node.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    execution_graph.add_edge(\n        source_step_selector,\n        target_step_selector,\n    )\n    if target_step_selector in source_compilation_data.child_execution_branches:\n        raise ExecutionGraphStructureError(\n            public_message=f\"While establishing flow-control connection between source `{source_step_selector}` \"\n            f\"and target `{target_step_selector}` it was discovered that source step defines\"\n            f\"control flow transition into target one more than once, which is not allowed as \"\n            f\"that situation creates ambiguity in selecting execution branch.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    execution_branch_name = f\"Branch[{source_step_selector} -> {target_step_parsed_selector.definition.property_name}]\"\n    source_compilation_data.child_execution_branches[target_step_selector] = (\n        execution_branch_name\n    )\n    target_compilation_data.execution_branches_impacting_inputs.add(\n        execution_branch_name\n    )\n    return execution_graph\n\n\ndef step_definition_allows_control_flow_references(\n    parsed_selector: ParsedSelector,\n) -> bool:\n    return any(\n        definition.selected_element == STEP_AS_SELECTED_ELEMENT\n        for definition in parsed_selector.definition.allowed_references\n    )\n\n\ndef get_kind_of_value_provided_in_step_output(\n    step_manifest: WorkflowBlockManifest,\n    step_property: str,\n    source_step_manifest: WorkflowBlockManifest,\n) -> List[Kind]:\n    referred_node_outputs = step_manifest.get_actual_outputs()\n    actual_kind = []\n    matched_property = False\n    for output in referred_node_outputs:\n        if output.name != step_property:\n            continue\n        matched_property = True\n        actual_kind.extend(output.kind)\n    if not matched_property:\n        property_name = get_property_with_invalid_selector(\n            manifest=source_step_manifest,\n            step_property=step_property,\n        )\n        raise ExecutionGraphStructureError(\n            public_message=f\"Found reference to non-existing property `{step_property}` of step `{step_manifest.name}`.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=source_step_manifest.name,\n                    block_type=source_step_manifest.type,\n                    property_name=property_name,\n                    property_details=f\"'{step_manifest.name}.{step_property}' is an invalid reference\",\n                )\n            ],\n        )\n    return actual_kind\n\n\ndef add_edges_for_step_inputs(\n    execution_graph: DiGraph,\n    input_selectors: Set[str],\n    step_selector: str,\n) -> DiGraph:\n    for input_selector in input_selectors:\n        if is_step_output_selector(selector_or_value=input_selector):\n            input_selector = get_step_selector_from_its_output(\n                step_output_selector=input_selector\n            )\n        verify_edge_is_created_between_existing_nodes(\n            execution_graph=execution_graph,\n            start=input_selector,\n            end=step_selector,\n        )\n        execution_graph.add_edge(input_selector, step_selector)\n    return execution_graph\n\n\ndef add_edges_for_outputs(\n    workflow_definition: ParsedWorkflowDefinition,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for output in workflow_definition.outputs:\n        node_selector = output.selector\n        if is_step_output_selector(selector_or_value=node_selector):\n            node_selector = get_step_selector_from_its_output(\n                step_output_selector=node_selector\n            )\n        output_selector = construct_output_selector(name=output.name)\n        verify_edge_is_created_between_existing_nodes(\n            execution_graph=execution_graph,\n            start=node_selector,\n            end=output_selector,\n        )\n        output_node_manifest = node_as(\n            execution_graph=execution_graph,\n            node=output_selector,\n            expected_type=OutputNode,\n        )\n        if is_step_output_selector(selector_or_value=output.selector):\n            step_manifest = execution_graph.nodes[node_selector][\n                NODE_COMPILATION_OUTPUT_PROPERTY\n            ].step_manifest\n            step_outputs = step_manifest.get_actual_outputs()\n            denote_output_node_kind_based_on_step_outputs(\n                output_selector=output.selector,\n                step_outputs=step_outputs,\n                output_node_manifest=output_node_manifest,\n            )\n        else:\n            input_manifest = node_as(\n                execution_graph=execution_graph,\n                node=node_selector,\n                expected_type=InputNode,\n            ).input_manifest\n            output_node_manifest.kind = copy(input_manifest.kind)\n        execution_graph.add_edge(node_selector, output_selector)\n    return execution_graph\n\n\ndef verify_edge_is_created_between_existing_nodes(\n    execution_graph: DiGraph,\n    start: str,\n    end: str,\n) -> None:\n    if not execution_graph.has_node(start) or not execution_graph.has_node(end):\n        invalid_block = start if not execution_graph.has_node(start) else end\n        referencing_block = end if invalid_block == start else start\n\n        step_type = None\n        property_name = None\n        if execution_graph.has_node(referencing_block):\n            if is_step_node(execution_graph, referencing_block):\n                step_manifest = node_as(\n                    execution_graph=execution_graph,\n                    node=referencing_block,\n                    expected_type=StepNode,\n                ).step_manifest\n                step_type = step_manifest.type\n                property_name = get_property_with_invalid_selector(\n                    manifest=step_manifest,\n                    step_property=invalid_block,\n                )\n\n        block_id = (\n            \"$outputs\"\n            if referencing_block.startswith(\"$outputs.\")\n            else get_last_chunk_of_selector(selector=referencing_block)\n        )\n        property_name = (\n            get_last_chunk_of_selector(selector=referencing_block)\n            if referencing_block.startswith(\"$outputs.\")\n            else property_name\n        )\n\n        is_input = is_input_selector(selector_or_value=invalid_block)\n        raise InvalidReferenceTargetError(\n            public_message=f\"Workflow references '{invalid_block}' which points to a non-existent {is_input and 'input parameter' or 'block'}.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=block_id,\n                    block_type=step_type,\n                    property_name=property_name,\n                    property_details=f\"Invalid reference to {invalid_block}\",\n                ),\n            ],\n        )\n\n\ndef denote_output_node_kind_based_on_step_outputs(\n    output_selector: str,\n    step_outputs: List[OutputDefinition],\n    output_node_manifest: OutputNode,\n) -> None:\n    selected_output_name = get_last_chunk_of_selector(selector=output_selector)\n    kinds_for_outputs = {output.name: output.kind for output in step_outputs}\n\n    if selected_output_name == \"*\":\n        output_node_manifest.kind = deepcopy(kinds_for_outputs)\n        return None\n    if selected_output_name not in kinds_for_outputs:\n        output_name = output_node_manifest.output_manifest.name\n\n        raise InvalidReferenceTargetError(\n            public_message=f\"Workflow output references '{output_selector}' which points to a non-existent block property.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=\"$outputs\",\n                    property_name=output_name,\n                    property_details=f\"Invalid reference to {output_selector}\",\n                ),\n            ],\n        )\n    output_node_manifest.kind = copy(kinds_for_outputs[selected_output_name])\n    return None\n\n\ndef denote_data_flow_in_workflow(\n    execution_graph: DiGraph,\n    parsed_workflow_definition: ParsedWorkflowDefinition,\n) -> nx.DiGraph:\n    block_manifest_by_step_name = {\n        step.name: step for step in parsed_workflow_definition.steps\n    }\n    super_input_node = \"<super-input>\"\n    execution_graph = add_super_input_node_in_execution_graph(\n        execution_graph=execution_graph,\n        super_input_node=super_input_node,\n    )\n    execution_graph.nodes[super_input_node][NODE_COMPILATION_OUTPUT_PROPERTY] = (\n        InputNode(\n            node_category=NodeCategory.INPUT_NODE,\n            name=super_input_node,\n            selector=f\"$inputs.{super_input_node}\",\n            data_lineage=[],\n            input_manifest=None,  # this is expected never to be reached\n        )\n    )\n    top_level_data_lineage = set()\n    for node in traverse_graph_ensuring_parents_are_reached_first(\n        graph=execution_graph,\n        start_node=super_input_node,\n    ):\n        execution_graph = denote_data_flow_for_node(\n            execution_graph=execution_graph,\n            node=node,\n            block_manifest_by_step_name=block_manifest_by_step_name,\n            on_top_level_lineage_denoted=lambda element: top_level_data_lineage.add(\n                element\n            ),\n        )\n    execution_graph.remove_node(super_input_node)\n    execution_graph.graph[TOP_LEVEL_LINEAGES_KEY] = top_level_data_lineage\n    return execution_graph\n\n\ndef denote_data_flow_for_node(\n    execution_graph: DiGraph,\n    node: str,\n    block_manifest_by_step_name: Dict[str, WorkflowBlockManifest],\n    on_top_level_lineage_denoted: Callable[[str], None],\n) -> DiGraph:\n    if is_input_node(execution_graph=execution_graph, node=node):\n        # everything already set there, in the previous stage of compilation\n        return execution_graph\n    if is_step_node(execution_graph=execution_graph, node=node):\n        step_name = get_last_chunk_of_selector(selector=node)\n        if step_name not in block_manifest_by_step_name:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler expected manifest for the step: {step_name} to be registered \"\n                f\"but this condition is not met. This is most likely the bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | retrieving_predecessors_for_output\",\n            )\n        manifest = block_manifest_by_step_name[step_name]\n        return denote_data_flow_for_step(\n            execution_graph=execution_graph,\n            node=node,\n            manifest=manifest,\n            on_top_level_lineage_denoted=on_top_level_lineage_denoted,\n        )\n    if is_output_node(execution_graph=execution_graph, node=node):\n        # output is allowed to have exactly one predecessor\n        output_predecessors = list(execution_graph.predecessors(node))\n        if len(output_predecessors) != 1:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler expected each output in compiled graph to have one predecessor, \"\n                f\"but this condition is not met for node {node}. This is most likely the bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | retrieving_predecessors_for_output\",\n            )\n        predecessor_node = output_predecessors[0]\n        predecessor_node_data = node_as(\n            execution_graph=execution_graph,\n            node=predecessor_node,\n            expected_type=ExecutionGraphNode,\n        )\n        predecessor_node_lineage = predecessor_node_data.data_lineage\n        output_node_data = node_as(\n            execution_graph=execution_graph,\n            node=node,\n            expected_type=OutputNode,\n        )\n        output_node_data.data_lineage = predecessor_node_lineage\n        return execution_graph\n    raise AssumptionError(\n        f\"Workflow Compiler encountered node: {node} which cannot be classified as known node type. \"\n        f\"This is most likely the bug. Contact Roboflow team through github issues \"\n        f\"(https://github.com/roboflow/inference/issues) providing full \"\n        f\"context of the problem - including workflow definition you use.\",\n        context=\"workflow_compilation | execution_graph_construction | denoting_data_flow_for_step\",\n    )\n\n\ndef denote_data_flow_for_step(\n    execution_graph: DiGraph,\n    node: str,\n    manifest: WorkflowBlockManifest,\n    on_top_level_lineage_denoted: Callable[[str], None],\n) -> DiGraph:\n    all_control_flow_predecessors, all_non_control_flow_predecessors = (\n        separate_control_flow_predecessors_from_data_providers(\n            execution_graph=execution_graph, node=node\n        )\n    )\n    input_data = build_input_data_for_step(\n        manifest=manifest,\n        step_node=node,\n        data_providing_predecessors=all_non_control_flow_predecessors,\n        execution_graph=execution_graph,\n    )\n    step_name = get_last_chunk_of_selector(node)\n    step_node_data = node_as(\n        execution_graph=execution_graph,\n        node=node,\n        expected_type=StepNode,\n    )\n    parsed_step_input_selectors: List[ParsedSelector] = execution_graph.nodes[node][\n        PARSED_NODE_INPUT_SELECTORS_PROPERTY\n    ]\n    batch_compatibility_of_properties = retrieve_batch_compatibility_of_input_selectors(\n        input_selectors=parsed_step_input_selectors\n    )\n    scalar_parameters_to_be_batched = (\n        verify_declared_batch_compatibility_against_actual_inputs(\n            node=node,\n            step_node_data=step_node_data,\n            input_data=input_data,\n            batch_compatibility_of_properties=batch_compatibility_of_properties,\n        )\n    )\n    input_dimensionality_offsets = manifest.get_input_dimensionality_offsets()\n    verify_step_input_dimensionality_offsets(\n        step_name=step_name,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n    )\n    inputs_dimensionalities = get_inputs_dimensionalities(\n        step_name=step_name,\n        step_type=manifest.type,\n        input_data=input_data,\n        scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n    )\n    logger.debug(\n        f\"For step: {node}, detected the following input dimensionalities: {inputs_dimensionalities}\"\n    )\n    parameters_with_batch_inputs = grab_parameters_defining_batch_inputs(\n        inputs_dimensionalities=inputs_dimensionalities,\n    )\n    dimensionality_reference_property = manifest.get_dimensionality_reference_property()\n    output_dimensionality_offset = manifest.get_output_dimensionality_offset()\n    verify_step_input_dimensionality_offsets(\n        step_name=step_name,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n    )\n    verify_output_offset(\n        step_name=step_name,\n        parameters_with_batch_inputs=parameters_with_batch_inputs,\n        dimensionality_reference_property=dimensionality_reference_property,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n        output_dimensionality_offset=output_dimensionality_offset,\n    )\n    verify_input_data_dimensionality(\n        step_name=step_name,\n        step_type=manifest.type,\n        dimensionality_reference_property=dimensionality_reference_property,\n        inputs_dimensionalities=inputs_dimensionalities,\n        dimensionality_offstes=input_dimensionality_offsets,\n    )\n    all_data_derived_lineages = get_input_data_lineage_excluding_auto_batch_casting(\n        step_name=step_name,\n        input_data=input_data,\n        scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n    )\n    all_control_flow_lineages = get_lineage_derived_from_control_flow(\n        control_flow_steps_selectors=all_control_flow_predecessors,\n        execution_graph=execution_graph,\n    )\n    verify_compatibility_of_input_data_lineage_with_control_flow_lineage(\n        step_name=step_name,\n        inputs_lineage=all_data_derived_lineages,\n        control_flow_steps_selectors=all_control_flow_predecessors,\n        execution_graph=execution_graph,\n    )\n    step_node_data.input_data = input_data\n    step_node_data.dimensionality_reference_property = dimensionality_reference_property\n    step_node_data.control_flow_lineage_dims = [\n        len(_lineage) for _lineage in all_control_flow_lineages if _lineage\n    ]\n    step_node_data.batch_oriented_parameters = parameters_with_batch_inputs\n    if not all_data_derived_lineages and not all_control_flow_lineages:\n        if manifest.get_output_dimensionality_offset() > 0:\n            # brave decision to open a Pandora box\n            data_lineage = [node]\n        else:\n            data_lineage = []\n        control_flow_lineage_support = []\n    else:\n        data_lineage, control_flow_lineage_support = (\n            establish_batch_oriented_step_lineage(\n                step_selector=node,\n                all_data_derived_lineages=all_data_derived_lineages,\n                all_control_flow_lineages=all_control_flow_lineages,\n                input_data=input_data,\n                dimensionality_reference_property=dimensionality_reference_property,\n                output_dimensionality_offset=output_dimensionality_offset,\n            )\n        )\n    step_node_data.step_execution_dimensionality = (\n        establish_step_execution_dimensionality(\n            inputs_dimensionalities=inputs_dimensionalities,\n            control_flow_lineage_support=control_flow_lineage_support,\n            output_dimensionality_offset=output_dimensionality_offset,\n        )\n    )\n    lineage_supports = get_lineage_support_for_auto_batch_casted_parameters(\n        input_dimensionalities=inputs_dimensionalities,\n        all_lineages_of_batch_parameters=all_data_derived_lineages,\n        scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n    )\n    step_node_data.auto_batch_casting_lineage_supports = lineage_supports\n    step_node_data.control_flow_lineage_support = control_flow_lineage_support\n    if data_lineage:\n        on_top_level_lineage_denoted(data_lineage[0])\n    step_node_data.data_lineage = data_lineage\n    return execution_graph\n\n\ndef _collect_unique_control_flow_lineages_with_step_mapping(\n    control_flow_steps_selectors: List[str],\n    execution_graph: nx.DiGraph,\n) -> Tuple[List[List[str]], Dict[int, List[str]]]:\n    \"\"\"\n    Collect data lineages from control flow steps and deduplicate by lineage id.\n\n    For each given control flow step selector, reads its data_lineage from the\n    execution graph. Returns unique non-empty lineages (by identify_lineage id)\n    and a mapping from lineage id to every step selector that produced that\n    lineage (used e.g. for error reporting when lineage is incompatible).\n\n    Args:\n        control_flow_steps_selectors: Step selectors (node ids) of control\n            flow steps whose data_lineage is to be collected.\n        execution_graph: The workflow execution graph containing step nodes\n            and their data_lineage.\n\n    Returns:\n        A tuple of (unique_lineages, lineage_id_to_step_selectors):\n        - unique_lineages: list of distinct non-empty data lineages.\n        - lineage_id_to_step_selectors: map from lineage id to list of step\n          selectors whose data_lineage has that id (includes empty lineages).\n    \"\"\"\n    unique_lineages: List[List[str]] = []\n    seen_lineage_ids: Set[int] = set()\n    lineage_id_to_step_selectors: Dict[int, List[str]] = defaultdict(list)\n\n    for step_selector in control_flow_steps_selectors:\n        step_data = node_as(\n            execution_graph=execution_graph,\n            node=step_selector,\n            expected_type=StepNode,\n        )\n        lineage = step_data.data_lineage\n        lineage_id = identify_lineage(lineage)\n        lineage_id_to_step_selectors[lineage_id].append(step_selector)\n        if lineage and lineage_id not in seen_lineage_ids:\n            seen_lineage_ids.add(lineage_id)\n            unique_lineages.append(lineage)\n\n    return unique_lineages, dict(lineage_id_to_step_selectors)\n\n\ndef get_lineage_derived_from_control_flow(\n    control_flow_steps_selectors: List[str],\n    execution_graph: nx.DiGraph,\n) -> List[List[str]]:\n    \"\"\"\n    Return unique non-empty data lineages from the given control flow steps.\n\n    Each lineage is taken from the step's data_lineage in the execution graph.\n    Lineages are deduplicated by lineage id (see identify_lineage); empty\n    lineages are omitted. Used when establishing batch-oriented step lineage.\n\n    Args:\n        control_flow_steps_selectors: Step selectors (node ids) of control\n            flow steps whose data_lineage is to be collected.\n        execution_graph: The workflow execution graph containing step nodes\n            and their data_lineage.\n\n    Returns:\n        List of distinct non-empty data lineages, one per unique lineage id.\n    \"\"\"\n    unique_lineages, _ = _collect_unique_control_flow_lineages_with_step_mapping(\n        control_flow_steps_selectors=control_flow_steps_selectors,\n        execution_graph=execution_graph,\n    )\n    return unique_lineages\n\n\ndef separate_control_flow_predecessors_from_data_providers(\n    execution_graph: DiGraph,\n    node: str,\n) -> Tuple[List[str], List[str]]:\n    all_predecessors = list(execution_graph.predecessors(node))\n    all_control_flow_predecessors = [\n        predecessor\n        for predecessor in all_predecessors\n        if is_control_flow_step(execution_graph=execution_graph, node=predecessor)\n    ]\n    all_non_control_flow_predecessors = [\n        predecessor\n        for predecessor in all_predecessors\n        if not is_control_flow_step(execution_graph=execution_graph, node=predecessor)\n    ]\n    return all_control_flow_predecessors, all_non_control_flow_predecessors\n\n\ndef build_input_data_for_step(\n    manifest: WorkflowBlockManifest,\n    step_node: str,\n    data_providing_predecessors: List[str],\n    execution_graph: DiGraph,\n) -> StepInputData:\n    predecessors_by_property_name = get_predecessors_for_step_manifest_properties(\n        execution_graph=execution_graph,\n        step_node=step_node,\n        data_providing_predecessors=data_providing_predecessors,\n    )\n    manifest_fields_values = get_manifest_fields_values(step_manifest=manifest)\n    result = {}\n    for name, value in manifest_fields_values.items():\n        result[name] = build_input_property(\n            step_node=step_node,\n            manifest_property_name=name,\n            manifest_property_value=value,\n            predecessors_by_property_name=predecessors_by_property_name,\n            execution_graph=execution_graph,\n        )\n    return result\n\n\ndef get_predecessors_for_step_manifest_properties(\n    execution_graph: DiGraph, step_node: str, data_providing_predecessors: List[str]\n) -> Dict[str, List[PropertyPredecessorDefinition]]:\n    predecessors_by_property_name = defaultdict(list)\n    for predecessor in data_providing_predecessors:\n        edge_data = execution_graph.edges[(predecessor, step_node)]\n        # STEP_INPUT_SELECTORS_PROPERTY is optional, as special <super-input> node may be directly\n        # connected to step\n        selectors_associated_to_edge: List[ParsedSelector] = edge_data.get(\n            STEP_INPUT_SELECTORS_PROPERTY, []\n        )\n        for selector_associated_to_edge in selectors_associated_to_edge:\n            definition = PropertyPredecessorDefinition(\n                predecessor_selector=predecessor,\n                parsed_selector=selector_associated_to_edge,\n            )\n            predecessors_by_property_name[\n                selector_associated_to_edge.definition.property_name\n            ].append(definition)\n    return predecessors_by_property_name\n\n\ndef build_input_property(\n    step_node: str,\n    manifest_property_name: str,\n    manifest_property_value: Any,\n    predecessors_by_property_name: Dict[str, List[PropertyPredecessorDefinition]],\n    execution_graph: DiGraph,\n) -> Union[StepInputDefinition, CompoundStepInputDefinition]:\n    if manifest_property_name not in predecessors_by_property_name:\n        return StaticStepInputDefinition(\n            parameter_specification=ParameterSpecification(\n                parameter_name=manifest_property_name,\n            ),\n            category=NodeInputCategory.STATIC_VALUE,\n            value=manifest_property_value,\n        )\n    if isinstance(manifest_property_value, dict):\n        return build_nested_dictionary_for_input_property(\n            step_node=step_node,\n            manifest_property_name=manifest_property_name,\n            manifest_property_value=manifest_property_value,\n            predecessors_definitions=predecessors_by_property_name[\n                manifest_property_name\n            ],\n            execution_graph=execution_graph,\n        )\n    if isinstance(manifest_property_value, list):\n        return build_nested_list_for_input_property(\n            step_node=step_node,\n            manifest_property_name=manifest_property_name,\n            manifest_property_value=manifest_property_value,\n            predecessors_definitions=predecessors_by_property_name[\n                manifest_property_name\n            ],\n            execution_graph=execution_graph,\n        )\n    matching_predecessors_data = predecessors_by_property_name[manifest_property_name]\n    if len(matching_predecessors_data) != 1:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler deduced that property `{manifest_property_name}` of step `{step_node}` \"\n            f\"should be fed with data coming from exactly one execution graph node, but found \"\n            f\"{len(matching_predecessors_data)} data sources. This is most likely the bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n        )\n    predecessor_selector, predecessor_parsed_selector = (\n        matching_predecessors_data[0].predecessor_selector,\n        matching_predecessors_data[0].parsed_selector,\n    )\n    if is_input_node(execution_graph=execution_graph, node=predecessor_selector):\n        predecessor_node_data = node_as(\n            execution_graph=execution_graph,\n            node=matching_predecessors_data[0].predecessor_selector,\n            expected_type=InputNode,\n        )\n        category = (\n            NodeInputCategory.BATCH_INPUT_PARAMETER\n            if predecessor_node_data.is_batch_oriented()\n            else NodeInputCategory.NON_BATCH_INPUT_PARAMETER\n        )\n        return DynamicStepInputDefinition(\n            parameter_specification=ParameterSpecification(\n                parameter_name=manifest_property_name,\n            ),\n            category=category,\n            data_lineage=predecessor_node_data.data_lineage,\n            selector=predecessor_node_data.selector,\n        )\n    if is_step_node(execution_graph=execution_graph, node=predecessor_selector):\n        predecessor_node_data = node_as(\n            execution_graph=execution_graph,\n            node=matching_predecessors_data[0].predecessor_selector,\n            expected_type=StepNode,\n        )\n        category = (\n            NodeInputCategory.BATCH_STEP_OUTPUT\n            if predecessor_node_data.output_dimensionality > 0\n            else NodeInputCategory.NON_BATCH_STEP_OUTPUT\n        )\n        return DynamicStepInputDefinition(\n            parameter_specification=ParameterSpecification(\n                parameter_name=manifest_property_name,\n            ),\n            category=category,\n            data_lineage=predecessor_node_data.data_lineage,\n            selector=predecessor_parsed_selector.value,\n        )\n    raise AssumptionError(\n        public_message=f\"Workflow Compiler for property `{manifest_property_name}` of step `{step_node}` \"\n        f\"found data providing predecessor `{predecessor_selector}` which has unsupported step type.\"\n        f\"This is most likely the bug. \"\n        f\"Contact Roboflow team through github issues \"\n        f\"(https://github.com/roboflow/inference/issues) providing full \"\n        f\"context of the problem - including workflow definition you use.\",\n        context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n    )\n\n\ndef build_nested_dictionary_for_input_property(\n    step_node: str,\n    manifest_property_name: str,\n    manifest_property_value: dict,\n    predecessors_definitions: List[PropertyPredecessorDefinition],\n    execution_graph: DiGraph,\n) -> DictOfStepInputDefinitions:\n    nested_property_name2data: Dict[Optional[str], PropertyPredecessorDefinition] = {\n        predecessor_definition.parsed_selector.key: predecessor_definition\n        for predecessor_definition in predecessors_definitions\n    }\n    result = {}\n    for nested_dict_key, nested_dict_value in manifest_property_value.items():\n        if nested_dict_key not in nested_property_name2data:\n            result[nested_dict_key] = StaticStepInputDefinition(\n                parameter_specification=ParameterSpecification(\n                    parameter_name=manifest_property_name,\n                    nested_element_key=nested_dict_key,\n                ),\n                category=NodeInputCategory.STATIC_VALUE,\n                value=nested_dict_value,\n            )\n            continue\n        referred_node_selector = nested_property_name2data[\n            nested_dict_key\n        ].predecessor_selector\n        referred_node_parsed_selector = nested_property_name2data[\n            nested_dict_key\n        ].parsed_selector\n        if is_input_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=InputNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_INPUT_PARAMETER\n                if predecessor_node_data.is_batch_oriented()\n                else NodeInputCategory.NON_BATCH_INPUT_PARAMETER\n            )\n            result[nested_dict_key] = DynamicStepInputDefinition(\n                parameter_specification=ParameterSpecification(\n                    parameter_name=manifest_property_name,\n                    nested_element_key=nested_dict_key,\n                ),\n                category=category,\n                data_lineage=predecessor_node_data.data_lineage,\n                selector=predecessor_node_data.selector,\n            )\n            continue\n        if is_step_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=StepNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_STEP_OUTPUT\n                if predecessor_node_data.output_dimensionality > 0\n                else NodeInputCategory.NON_BATCH_STEP_OUTPUT\n            )\n            result[nested_dict_key] = DynamicStepInputDefinition(\n                parameter_specification=ParameterSpecification(\n                    parameter_name=manifest_property_name,\n                    nested_element_key=nested_dict_key,\n                ),\n                category=category,\n                data_lineage=predecessor_node_data.data_lineage,\n                selector=referred_node_parsed_selector.value,\n            )\n            continue\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for property `{manifest_property_name}` of step `{step_node}` \"\n            f\"found data providing predecessor `{referred_node_selector}` which has \"\n            f\"unsupported step type (key: {nested_dict_key} of nested data dictionary). \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n        )\n    return DictOfStepInputDefinitions(\n        name=manifest_property_name,\n        nested_definitions=result,\n    )\n\n\ndef get_manifest_fields_values(step_manifest: WorkflowBlockManifest) -> Dict[str, Any]:\n    result = {}\n    for field in step_manifest.model_fields:\n        if field in EXCLUDED_FIELDS:\n            continue\n        result[field] = getattr(step_manifest, field)\n    return result\n\n\ndef build_nested_list_for_input_property(\n    step_node: str,\n    manifest_property_name: str,\n    manifest_property_value: list,\n    predecessors_definitions: List[PropertyPredecessorDefinition],\n    execution_graph: DiGraph,\n) -> ListOfStepInputDefinitions:\n    nested_index2data: Dict[Optional[int], PropertyPredecessorDefinition] = {\n        e.parsed_selector.index: e for e in predecessors_definitions\n    }\n    result = []\n    for index, element in enumerate(manifest_property_value):\n        if index not in nested_index2data:\n            result.append(\n                StaticStepInputDefinition(\n                    parameter_specification=ParameterSpecification(\n                        parameter_name=manifest_property_name,\n                        nested_element_index=index,\n                    ),\n                    category=NodeInputCategory.STATIC_VALUE,\n                    value=element,\n                )\n            )\n            continue\n        referred_node_selector = nested_index2data[index].predecessor_selector\n        referred_node_parsed_selector = nested_index2data[index].parsed_selector\n        if is_input_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=InputNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_INPUT_PARAMETER\n                if predecessor_node_data.is_batch_oriented()\n                else NodeInputCategory.NON_BATCH_INPUT_PARAMETER\n            )\n            result.append(\n                DynamicStepInputDefinition(\n                    parameter_specification=ParameterSpecification(\n                        parameter_name=manifest_property_name,\n                        nested_element_index=index,\n                    ),\n                    category=category,\n                    data_lineage=predecessor_node_data.data_lineage,\n                    selector=predecessor_node_data.selector,\n                )\n            )\n            continue\n        if is_step_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=StepNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_STEP_OUTPUT\n                if predecessor_node_data.output_dimensionality > 0\n                else NodeInputCategory.NON_BATCH_STEP_OUTPUT\n            )\n            result.append(\n                DynamicStepInputDefinition(\n                    parameter_specification=ParameterSpecification(\n                        parameter_name=manifest_property_name,\n                        nested_element_index=index,\n                    ),\n                    category=category,\n                    data_lineage=predecessor_node_data.data_lineage,\n                    selector=referred_node_parsed_selector.value,\n                )\n            )\n            continue\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for property `{manifest_property_name}` of step `{step_node}` \"\n            f\"found data providing predecessor `{referred_node_selector}` which has \"\n            f\"unsupported step type (index: {index} of nested data list). \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n        )\n    return ListOfStepInputDefinitions(\n        name=manifest_property_name,\n        nested_definitions=result,\n    )\n\n\ndef verify_step_input_dimensionality_offsets(\n    step_name: str,\n    input_dimensionality_offsets: Dict[str, int],\n) -> None:\n    min_offset, max_offset = None, None\n    for offset in input_dimensionality_offsets.values():\n        if min_offset is None or offset < min_offset:\n            min_offset = offset\n        if max_offset is None or offset > max_offset:\n            max_offset = offset\n    if min_offset is None or max_offset is None:\n        return None\n    if min_offset < 0 or max_offset < 0:\n        raise BlockInterfaceError(\n            public_message=f\"Offsets could not be negative, but block defining step: {step_name} defines that values.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_input_offset_definitions\",\n        )\n    if abs(max_offset - min_offset) > 1:\n        raise BlockInterfaceError(\n            public_message=\"Offsets of input parameters could not differ more than 1, but block defining step {step_name} \"\n            f\"violates that rule.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_input_offset_definitions\",\n        )\n\n\ndef verify_output_offset(\n    step_name: str,\n    parameters_with_batch_inputs: Set[str],\n    input_dimensionality_offsets: Dict[str, int],\n    dimensionality_reference_property: Optional[str],\n    output_dimensionality_offset: int,\n) -> None:\n    if not parameters_with_batch_inputs and output_dimensionality_offset < 0:\n        raise StepInputDimensionalityError(\n            public_message=f\"Block defining step {step_name} defines negative dimensionality offset while only \"\n            f\"scalar inputs being provided - the block cannot run as there is no dimension to collapse.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if (\n        dimensionality_reference_property is not None\n        and dimensionality_reference_property not in parameters_with_batch_inputs\n    ):\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} defines dimensionality reference property \"\n            f\"which is not in scope of parameters bring batch-oriented input, which makes it impossible \"\n            f\"to use as reference for output dimensionality.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if output_dimensionality_offset not in {-1, 0, 1}:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} defines output dimensionality offset \"\n            f\"being {output_dimensionality_offset}, whereas it is only possible for that offset being \"\n            f\"in set [-1, 0, 1].\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    different_offsets = {o for o in input_dimensionality_offsets.values()}\n    if len(parameters_with_batch_inputs) != len(input_dimensionality_offsets):\n        # assumption of default offset being zero - and this one does not need to be manifested\n        # by block\n        different_offsets.add(0)\n    if 0 not in different_offsets and parameters_with_batch_inputs:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} explicitly defines input dimensionalities offsets\"\n            f\"with {input_dimensionality_offsets}, but the definition lack 0-level input, which is \"\n            f\"not allowed, as in this scenario offsets could be adjusted to include 0\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if len(different_offsets) > 1 and dimensionality_reference_property is None:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} explicitly defines input dimensionality \"\n            f\"offsets {input_dimensionality_offsets}. In this scenario it is required to provide dimensionality \"\n            f\"reference property.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if len(different_offsets) > 1 and output_dimensionality_offset != 0:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} explicitly defines input dimensionality \"\n            f\"offsets {input_dimensionality_offsets} and output dimensionality offset {output_dimensionality_offset} \"\n            f\"where the latter is not 0, but for inputs differing with dimensionality it is only possible to keep \"\n            f\"output dimensionality the same and point reference parameter.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n\n\ndef verify_input_data_dimensionality(\n    step_name: str,\n    step_type: str,\n    dimensionality_reference_property: Optional[str],\n    inputs_dimensionalities: Dict[str, Set[int]],\n    dimensionality_offstes: Dict[str, int],\n) -> None:\n    parameter_name2dimensionality_specification = (\n        grab_input_data_dimensionality_specifications(\n            step_name=step_name,\n            inputs_dimensionalities=inputs_dimensionalities,\n            dimensionality_offstes=dimensionality_offstes,\n        )\n    )\n    if not parameter_name2dimensionality_specification:\n        # nothing to check if no batch-oriented inputs\n        return None\n    different_dimensionalities_of_parameters = {\n        specification.actual_dimensionality\n        for specification in parameter_name2dimensionality_specification.values()\n    }\n    if dimensionality_reference_property is None:\n        if len(different_dimensionalities_of_parameters) > 1:\n            parameter2dimensionality = {\n                k: e.actual_dimensionality\n                for k, e in parameter_name2dimensionality_specification.items()\n            }\n            raise StepInputDimensionalityError(\n                public_message=f\"Block defining step {step_name} does not define dimensionality reference property, \"\n                f\"which means that all batch-oriented parameters must be at the same dimensionality level, \"\n                f\"but detected the following dimensionalities for parameters {parameter2dimensionality}\",\n                context=\"workflow_compilation | execution_graph_construction | denoting_step_inputs_dimensionality\",\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=step_name,\n                        block_type=step_type,\n                        block_details=f\"Dimensionality of input parameters doesn't match: {parameter2dimensionality}\",\n                    )\n                ],\n            )\n        return None\n    reference_specification = parameter_name2dimensionality_specification[\n        dimensionality_reference_property\n    ]\n    expected_dimensionalities = {\n        property_name: (e.expected_offset - reference_specification.expected_offset)\n        + reference_specification.actual_dimensionality\n        for property_name, e in parameter_name2dimensionality_specification.items()\n    }\n    if any(dim <= 0 for dim in expected_dimensionalities.values()):\n        raise StepInputDimensionalityError(\n            public_message=f\"Given the definition of block defining step {step_name} and data provided, \"\n            f\"the block would expect batch input dimensionality to be 0 or below, which is invalid.\",\n            context=\"workflow_compilation | execution_graph_construction | denoting_step_inputs_dimensionality\",\n        )\n    for property_name, expected_dimensionality in expected_dimensionalities.items():\n        actual_dimensionality = parameter_name2dimensionality_specification[\n            property_name\n        ].actual_dimensionality\n        if actual_dimensionality != expected_dimensionality:\n            raise StepInputDimensionalityError(\n                public_message=f\"Data fed into step `{step_name}` property `{property_name}` has \"\n                f\"actual dimensionality {actual_dimensionality}, \"\n                f\"when expected was {expected_dimensionality}\",\n                context=\"workflow_compilation | execution_graph_construction | denoting_step_inputs_dimensionality\",\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=step_name,\n                        block_type=step_type,\n                        property_name=property_name,\n                        property_details=f\"Expected dimensionality {expected_dimensionality}, but received dimensionality {actual_dimensionality}\",\n                    )\n                ],\n            )\n    return None\n\n\ndef grab_input_data_dimensionality_specifications(\n    step_name: str,\n    inputs_dimensionalities: Dict[str, Set[int]],\n    dimensionality_offstes: Dict[str, int],\n) -> Dict[str, InputDimensionalitySpecification]:\n    result = {}\n    for parameter_name, dimensionality in inputs_dimensionalities.items():\n        parameter_offset = dimensionality_offstes.get(parameter_name, 0)\n        non_zero_dimensionalities_for_parameter = {d for d in dimensionality if d > 0}\n        if len(non_zero_dimensionalities_for_parameter) > 1:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler for step: `{step_name}` and parameter: {parameter_name}\"\n                f\"found multiple different values of actual input dimensionalities: \"\n                f\"`{non_zero_dimensionalities_for_parameter}` which should be detected and addresses \"\n                f\"at earlier stages of compilation.\"\n                f\"This is most likely the bug. Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n            )\n        if non_zero_dimensionalities_for_parameter:\n            actual_dimensionality = next(iter(non_zero_dimensionalities_for_parameter))\n            result[parameter_name] = InputDimensionalitySpecification(\n                actual_dimensionality=actual_dimensionality,\n                expected_offset=parameter_offset,\n            )\n    return result\n\n\ndef verify_compatibility_of_input_data_lineage_with_control_flow_lineage(\n    step_name: str,\n    inputs_lineage: List[List[str]],\n    control_flow_steps_selectors: List[str],\n    execution_graph: DiGraph,\n) -> None:\n    \"\"\"\n    Ensure control flow steps' data lineage is compatible with the step's inputs.\n\n    Control flow steps that affect this step must operate on data that is\n    compatible with the data fed to the step; otherwise the step could never\n    execute. Compares unique control flow lineages against input lineage\n    prefixes and raises ControlFlowDefinitionError if any control flow lineage\n    is not covered by the inputs.\n\n    If inputs_lineage is empty, there is no sense to verify compatibility. The lineage of the\n    step should be established based on the control flow lineages.\n\n    Args:\n        step_name: Name of the step being verified (used in error messages).\n        inputs_lineage: Data lineages derived from the step's input data.\n        control_flow_steps_selectors: Step selectors of control flow steps\n            that affect this step's execution.\n        execution_graph: The workflow execution graph.\n\n    Raises:\n        ControlFlowDefinitionError: When a control flow step's lineage is not\n            compatible with the step's input lineage (step would never execute).\n    \"\"\"\n    (\n        batch_oriented_control_flow_lineages,\n        lineage_id2control_flow_steps,\n    ) = _collect_unique_control_flow_lineages_with_step_mapping(\n        control_flow_steps_selectors=control_flow_steps_selectors,\n        execution_graph=execution_graph,\n    )\n    if not inputs_lineage:\n        return\n\n    all_input_lineage_prefixes = get_all_batch_lineage_prefixes(lineages=inputs_lineage)\n    all_input_lineage_prefixes_hashes = {\n        identify_lineage(lineage=lineage) for lineage in all_input_lineage_prefixes\n    }\n    for control_flow_lineage in batch_oriented_control_flow_lineages:\n        control_flow_lineage_id = identify_lineage(lineage=control_flow_lineage)\n        if control_flow_lineage_id not in all_input_lineage_prefixes_hashes:\n            problematic_flow_control_steps = lineage_id2control_flow_steps[\n                control_flow_lineage_id\n            ]\n            raise ControlFlowDefinitionError(\n                public_message=f\"Step {step_name} execution is impacted by control flow outcome of the following \"\n                f\"steps {problematic_flow_control_steps} which make decision based on data that is \"\n                f\"not compatible with data fed to the step {step_name} - which would cause the step \"\n                f\"to never execute. This behaviour is invalid and prevented upfront by Workflows compiler.\",\n                context=\"workflow_compilation | execution_graph_construction | verification_of_control_flow_lineage\",\n            )\n\n\ndef get_all_batch_lineage_prefixes(lineages: List[List[str]]) -> List[List[str]]:\n    result = []\n    already_spotted = set()\n    for lineage in lineages:\n        lineage_prefixes = get_batch_lineage_prefixes(lineage=lineage)\n        for lineage_prefix in lineage_prefixes:\n            lineage_prefix_id = identify_lineage(lineage=lineage_prefix)\n            if lineage_prefix_id not in already_spotted:\n                already_spotted.add(lineage_prefix_id)\n                result.append(lineage_prefix)\n    return result\n\n\ndef get_batch_lineage_prefixes(lineage: List[str]) -> List[List[str]]:\n    if not lineage:\n        return []\n    result = []\n    prefix = []\n    for i in range(len(lineage)):\n        prefix.append(lineage[i])\n        result.append(copy(prefix))\n    return result\n\n\ndef get_inputs_dimensionalities(\n    step_name: str,\n    step_type: str,\n    input_data: StepInputData,\n    scalar_parameters_to_be_batched: Set[str],\n    input_dimensionality_offsets: Dict[str, int],\n) -> Dict[str, Set[int]]:\n    result = defaultdict(set)\n    dimensionalities_spotted = set()\n    offset_parameters = {\n        parameter: value\n        for parameter, value in input_dimensionality_offsets.items()\n        if value > 0\n    }\n    non_offset_parameters_dimensionality_values = set()\n    for property_name, input_definition in input_data.items():\n        if property_name in offset_parameters:\n            continue\n        if input_definition.is_compound_input():\n            for value in input_definition.iterate_through_definitions():\n                if value.is_batch_oriented():\n                    non_offset_parameters_dimensionality_values.add(\n                        value.get_dimensionality()\n                    )\n        elif input_definition.is_batch_oriented():\n            non_offset_parameters_dimensionality_values.add(\n                input_definition.get_dimensionality()\n            )\n    if len(non_offset_parameters_dimensionality_values) > 1:\n        raise StepInputDimensionalityError(\n            public_message=f\"For step {step_name} attempted to plug input data that are in different dimensions, \"\n            f\"whereas block defines the inputs to be equal in that terms.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_input_data\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=step_name,\n                    block_type=step_type,\n                    block_details=f\"Dimensionality of input parameters differs by more than 1. Detected dimensions: {dict(result)}\",\n                )\n            ],\n        )\n    non_offset_parameters_dimensionality_value = (\n        non_offset_parameters_dimensionality_values.pop()\n        if len(non_offset_parameters_dimensionality_values) > 0\n        else 1\n    )\n    for property_name, input_definition in input_data.items():\n        if input_definition.is_compound_input():\n            result[property_name] = get_compound_input_dimensionality(\n                step_name=step_name,\n                step_type=step_type,\n                property_name=property_name,\n                input_definition=input_definition,\n                scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n                non_offset_parameters_dimensionality_value=non_offset_parameters_dimensionality_value,\n                offset_parameters=offset_parameters,\n            )\n        else:\n            if property_name in scalar_parameters_to_be_batched:\n                if property_name not in offset_parameters:\n                    result[property_name] = {non_offset_parameters_dimensionality_value}\n                else:\n                    result[property_name] = (\n                        non_offset_parameters_dimensionality_value\n                        + offset_parameters[property_name]\n                    )\n            else:\n                result[property_name] = {input_definition.get_dimensionality()}\n        dimensionalities_spotted.update(result[property_name])\n    non_zero_dimensionalities_spotted = {d for d in dimensionalities_spotted if d != 0}\n    if len(non_zero_dimensionalities_spotted) > 0:\n        min_dim, max_dim = min(non_zero_dimensionalities_spotted), max(\n            non_zero_dimensionalities_spotted\n        )\n        if abs(max_dim - min_dim) > 1:\n            raise StepInputDimensionalityError(\n                public_message=f\"For step {step_name} attempted to plug input data differing in dimensionality more than 1\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_input_data\",\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=step_name,\n                        block_type=step_type,\n                        block_details=f\"Dimensionality of input parameters differs by more than 1. Detected dimensions: {dict(result)}\",\n                    )\n                ],\n            )\n    return result\n\n\ndef get_compound_input_dimensionality(\n    step_name: str,\n    property_name: str,\n    step_type: str,\n    input_definition: CompoundStepInputDefinition,\n    scalar_parameters_to_be_batched: Set[str],\n    offset_parameters: Dict[str, int],\n    non_offset_parameters_dimensionality_value: int,\n) -> Set[int]:\n    dimensionalities_spotted = set()\n    for definition in input_definition.iterate_through_definitions():\n        if (\n            property_name not in scalar_parameters_to_be_batched\n            or definition.is_batch_oriented()\n        ):\n            dimensionalities_spotted.add(definition.get_dimensionality())\n        elif property_name not in offset_parameters:\n            dimensionalities_spotted.add(non_offset_parameters_dimensionality_value)\n        else:\n            dimensionalities_spotted.add(\n                non_offset_parameters_dimensionality_value\n                + offset_parameters[property_name]\n            )\n    non_zero_dimensionalities = {e for e in dimensionalities_spotted if e != 0}\n    if len(non_zero_dimensionalities) > 1:\n        raise StepInputDimensionalityError(\n            public_message=f\"While evaluating compound property {property_name} of step {step_name}, \"\n            f\"detected multiple inputs of differing batch dimensionalities: {non_zero_dimensionalities}\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_input_data\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=step_name,\n                    block_type=step_type,\n                    property_name=property_name,\n                    property_details=f\"Detected multiple inputs of differing batch dimensionalities: {non_zero_dimensionalities}\",\n                )\n            ],\n        )\n    return dimensionalities_spotted\n\n\ndef grab_parameters_defining_batch_inputs(\n    inputs_dimensionalities: Dict[str, Set[int]],\n) -> Set[str]:\n    result = set()\n    for paremeter, dimensionalities in inputs_dimensionalities.items():\n        batch_dimensionalities = {d for d in dimensionalities if d > 0}\n        if len(batch_dimensionalities):\n            result.add(paremeter)\n    return result\n\n\ndef retrieve_batch_compatibility_of_input_selectors(\n    input_selectors: List[ParsedSelector],\n) -> Dict[str, Set[bool]]:\n    batch_compatibility_of_properties = defaultdict(set)\n    for parsed_selector in input_selectors:\n        for reference in parsed_selector.definition.allowed_references:\n            batch_compatibility_of_properties[\n                parsed_selector.definition.property_name\n            ].update(reference.points_to_batch)\n    return batch_compatibility_of_properties\n\n\ndef verify_declared_batch_compatibility_against_actual_inputs(\n    node: str,\n    step_node_data: StepNode,\n    input_data: StepInputData,\n    batch_compatibility_of_properties: Dict[str, Set[bool]],\n) -> Set[str]:\n    scalar_parameters_to_be_batched = set()\n    parameters_accepting_batches_and_scalars = set(\n        step_node_data.step_manifest.get_parameters_accepting_batches_and_scalars()\n    )\n    hardcoded_inputs_to_be_batch_compatible = set(\n        step_node_data.step_manifest.get_parameters_enforcing_auto_batch_casting()\n        + step_node_data.step_manifest.get_parameters_accepting_batches()\n    )\n    for property_name, input_definition in input_data.items():\n        if property_name not in batch_compatibility_of_properties:\n            actual_input_is_batch = {False}\n            if property_name in parameters_accepting_batches_and_scalars:\n                batch_compatibility = {True, False}\n            elif property_name in hardcoded_inputs_to_be_batch_compatible:\n                batch_compatibility = {True}\n            else:\n                continue\n        elif input_definition.is_compound_input():\n            actual_input_is_batch = {\n                element.is_batch_oriented()\n                for element in input_definition.iterate_through_definitions()\n            }\n            batch_compatibility = batch_compatibility_of_properties[property_name]\n        else:\n            actual_input_is_batch = {input_definition.is_batch_oriented()}\n            batch_compatibility = batch_compatibility_of_properties[property_name]\n        step_accepts_batch_input = step_node_data.step_manifest.accepts_batch_input()\n        if (\n            step_accepts_batch_input\n            and batch_compatibility == {False}\n            and True in actual_input_is_batch\n        ):\n            raise ExecutionGraphStructureError(\n                public_message=f\"Detected invalid reference plugged \"\n                f\"into property `{property_name}` of step `{node}` - the step \"\n                f\"property do not accept batch-oriented inputs, yet the input selector \"\n                f\"holds one - this indicates the problem with \"\n                f\"construction of your Workflow - usually the problem occurs when non-batch oriented \"\n                f\"step inputs are filled with outputs of batch-oriented steps or batch-oriented inputs.\",\n                context=\"workflow_compilation | execution_graph_construction\",\n            )\n        if batch_compatibility == {True} and False in actual_input_is_batch:\n            scalar_parameters_to_be_batched.add(property_name)\n    return scalar_parameters_to_be_batched\n\n\ndef get_input_data_lineage_excluding_auto_batch_casting(\n    step_name: str,\n    input_data: StepInputData,\n    scalar_parameters_to_be_batched: Set[str],\n) -> List[List[str]]:\n    lineage_deduplication_set = set()\n    lineages = []\n    for property_name, input_definition in input_data.items():\n        new_lineages_detected_within_property_data = get_lineage_for_input_property(\n            step_name=step_name,\n            property_name=property_name,\n            input_definition=input_definition,\n            lineage_deduplication_set=lineage_deduplication_set,\n        )\n        if (\n            property_name in scalar_parameters_to_be_batched\n            and len(new_lineages_detected_within_property_data) == 0\n        ):\n            continue\n        lineages.extend(new_lineages_detected_within_property_data)\n    if not lineages:\n        return lineages\n    verify_lineages(step_name=step_name, detected_lineages=lineages)\n    return lineages\n\n\ndef get_lineage_support_for_auto_batch_casted_parameters(\n    input_dimensionalities: Dict[str, Set[int]],\n    scalar_parameters_to_be_batched: Set[str],\n    all_lineages_of_batch_parameters: List[List[str]],\n) -> Dict[str, AutoBatchCastingConfig]:\n    longest_lineage_support = find_longest_lineage_support(\n        all_lineages_of_batch_parameters=all_lineages_of_batch_parameters,\n    )\n    result = {}\n    for parameter_name in scalar_parameters_to_be_batched:\n        parameter_dimensionality = max(input_dimensionalities[parameter_name])\n        if longest_lineage_support is None:\n            lineage_support = None\n        else:\n            lineage_support = longest_lineage_support[:parameter_dimensionality]\n        result[parameter_name] = AutoBatchCastingConfig(\n            casted_dimensionality=parameter_dimensionality,\n            lineage_support=lineage_support,\n        )\n    return result\n\n\ndef find_longest_lineage_support(\n    all_lineages_of_batch_parameters: List[List[str]],\n) -> Optional[List[str]]:\n    longest_longest_lineage_support = []\n    for lineage in all_lineages_of_batch_parameters:\n        if len(lineage) > len(longest_longest_lineage_support):\n            longest_longest_lineage_support = lineage\n    if len(longest_longest_lineage_support) == 0:\n        return None\n    return longest_longest_lineage_support\n\n\ndef get_lineage_for_input_property(\n    step_name: str,\n    property_name: str,\n    input_definition: Union[StepInputDefinition, CompoundStepInputDefinition],\n    lineage_deduplication_set: Set[int],\n) -> List[List[str]]:\n    if input_definition.is_compound_input():\n        return get_lineage_from_compound_input(\n            step_name=step_name,\n            property_name=property_name,\n            input_definition=input_definition,\n            lineage_deduplication_set=lineage_deduplication_set,\n        )\n    lineages = []\n    if input_definition.is_batch_oriented():\n        lineage = input_definition.data_lineage\n        lineage_id = identify_lineage(lineage=lineage)\n        if lineage_id not in lineage_deduplication_set:\n            lineage_deduplication_set.add(lineage_id)\n            lineages.append(lineage)\n    return lineages\n\n\ndef get_lineage_from_compound_input(\n    step_name: str,\n    property_name: str,\n    input_definition: Union[StepInputDefinition, CompoundStepInputDefinition],\n    lineage_deduplication_set: Set[int],\n) -> List[List[str]]:\n    lineages = []\n    for nested_element in input_definition.iterate_through_definitions():\n        if nested_element.is_batch_oriented():\n            lineage = nested_element.data_lineage\n            lineage_id = identify_lineage(lineage=lineage)\n            if lineage_id not in lineage_deduplication_set:\n                lineage_deduplication_set.add(lineage_id)\n                lineages.append(lineage)\n    if len(lineages) > 1:\n        raise StepInputLineageError(\n            public_message=f\"Input data provided for step: `{step_name}` comes with multiple different lineages \"\n            f\"{lineages} for property `{property_name}` accepting \"\n            f\"multiple selectors, which is not allowed.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    return lineages\n\n\ndef verify_lineages(step_name: str, detected_lineages: List[List[str]]) -> None:\n    lineages_by_length = defaultdict(list)\n    for lineage in detected_lineages:\n        lineages_by_length[len(lineage)].append(lineage)\n    if len(lineages_by_length) > 2:\n        raise StepInputLineageError(\n            public_message=f\"Input data provided for step: `{step_name}` comes with lineages at more than two \"\n            f\"dimensionality levels, which should not be possible.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    lineage_lengths = sorted(lineages_by_length.keys())\n    for lineage_length in lineage_lengths:\n        if len(lineages_by_length[lineage_length]) > 1:\n            raise StepInputLineageError(\n                public_message=f\"Among step `{step_name}` inputs found different lineages at the same  \"\n                f\"dimensionality levels dimensionality.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if len(lineages_by_length[lineage_lengths[-1]]) > 1 and len(lineage_lengths) < 2:\n        raise StepInputLineageError(\n            public_message=f\"If lineage differ at the last level, then Execution Engine requires at least one \"\n            f\"higher-dimension  input that will come with common lineage, but this is not the \"\n            f\"case for step {step_name}.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    if len(lineage_lengths) == 2:\n        reference_lineage = lineages_by_length[lineage_lengths[0]][0]\n        if reference_lineage != lineages_by_length[lineage_lengths[1]][0][:-1]:\n            raise StepInputLineageError(\n                public_message=f\"Step `{step_name}` inputs does not share common lineage. Differing element: \"\n                f\"{lineages_by_length[lineage_lengths[1]][0]}, \"\n                f\"reference lineage prefix: {reference_lineage}\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n\n\ndef establish_step_execution_dimensionality(\n    inputs_dimensionalities: Dict[str, Set[int]],\n    control_flow_lineage_support: List[str],\n    output_dimensionality_offset: int,\n) -> int:\n    \"\"\"\n    Determine how many batch dimensions (execution slices) a step runs with.\n\n    Used during workflow compilation in denote_data_flow_for_step. The result\n    is stored on StepNode.step_execution_dimensionality and consumed at\n    execution time to:\n    - Drive how many times the step is executed (which batch indices/slices).\n    - Align and expand inputs (e.g. auto-batch casting) to match this size.\n    - Validate that parameter dimensionalities are compatible (runtime checks\n      in step_input_assembler and manager).\n\n    Logic:\n    - If no input has non-zero dimensionality but the step is gated by\n      control flow (control_flow_lineage_support non-empty), the\n      dimensionality is the number of control-flow branches.\n    - Otherwise, the minimum non-zero input dimensionality is used; if\n      output_dimensionality_offset < 0 (step reduces batch dimension),\n      one is subtracted.\n\n    Args:\n        inputs_dimensionalities: Per-input sets of dimensionalities (from\n            get_inputs_dimensionalities).\n        control_flow_lineage_support: Lineage identifiers for control-flow\n            branches that gate this step (from establish_batch_oriented_step_lineage).\n        output_dimensionality_offset: Block's output dimensionality offset\n            (positive = expand, negative = reduce batch dimension).\n\n    Returns:\n        The number of batch dimensions (execution slices) for this step.\n    \"\"\"\n    step_execution_dimensionality = 0\n    non_zero_dimensionalities = {\n        dimensionality\n        for dimensionalities in inputs_dimensionalities.values()\n        for dimensionality in dimensionalities\n        if dimensionality > 0\n    }\n    if len(non_zero_dimensionalities) == 0 and len(control_flow_lineage_support) > 0:\n        return len(control_flow_lineage_support)\n    if len(non_zero_dimensionalities) > 0:\n        step_execution_dimensionality = min(non_zero_dimensionalities)\n        if output_dimensionality_offset < 0:\n            step_execution_dimensionality -= 1\n    return step_execution_dimensionality\n\n\ndef establish_batch_oriented_step_lineage(\n    step_selector: str,\n    all_data_derived_lineages: List[List[str]],\n    all_control_flow_lineages: List[List[str]],\n    input_data: StepInputData,\n    dimensionality_reference_property: Optional[str],\n    output_dimensionality_offset: int,\n) -> Tuple[List[str], List[str]]:\n    reference_lineage, control_flow_lineage_support = get_reference_lineage(\n        step_selector=step_selector,\n        all_data_derived_lineages=all_data_derived_lineages,\n        all_control_flow_lineages=all_control_flow_lineages,\n        input_data=input_data,\n        dimensionality_reference_property=dimensionality_reference_property,\n    )\n    if output_dimensionality_offset < 0:\n        result_dimensionality = reference_lineage[:output_dimensionality_offset]\n        return result_dimensionality, []\n    if output_dimensionality_offset == 0:\n        return reference_lineage, control_flow_lineage_support\n    reference_lineage.append(step_selector)\n    return reference_lineage, []\n\n\ndef get_reference_lineage(\n    step_selector: str,\n    all_data_derived_lineages: List[List[str]],\n    all_control_flow_lineages: List[List[str]],\n    input_data: StepInputData,\n    dimensionality_reference_property: Optional[str],\n) -> Tuple[List[str], List[str]]:\n    if not all_data_derived_lineages:\n        if len(all_control_flow_lineages) == 1:\n            return copy(all_control_flow_lineages[0]), copy(\n                all_control_flow_lineages[0]\n            )\n        # Multiple control-flow lineages and no data-derived lineage: pick the deepest.\n        max_lineage_len = max(len(lineage) for lineage in all_control_flow_lineages)\n        lineages_matching_max_len = [\n            _lineage\n            for _lineage in all_control_flow_lineages\n            if len(_lineage) == max_lineage_len\n        ]\n        if len(lineages_matching_max_len) == 1:\n            return copy(lineages_matching_max_len[0]), copy(\n                lineages_matching_max_len[0]\n            )\n        else:\n            raise AssumptionError(\n                public_message=f\"Multiple control-flow lineages at the same level for step `{step_selector}` \"\n                f\"and no data-derived lineage; unique lineage level required. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if len(all_data_derived_lineages) == 1:\n        return copy(all_data_derived_lineages[0]), []\n    if dimensionality_reference_property not in input_data:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` expected dimensionality_reference_property \"\n            f\"presence to be verified at earlier stages, which did not happen as expected. \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    property_data = input_data[dimensionality_reference_property]\n    if property_data.is_compound_input():\n        lineage = None\n        for nested_element in property_data.iterate_through_definitions():\n            if nested_element.is_batch_oriented():\n                lineage = copy(nested_element.data_lineage)\n                return lineage, []\n        if lineage is None:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n                f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if not property_data.is_batch_oriented():\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n            f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    return copy(property_data.data_lineage), []\n\n\ndef get_property_with_invalid_selector(\n    manifest: WorkflowBlockManifest, step_property: str\n) -> Optional[str]:\n    property_name = None\n    for key, value in manifest.__dict__.items():\n        if isinstance(value, str) and step_property in value:\n            property_name = key\n            break\n    return property_name\n\n\ndef add_super_input_node_in_execution_graph(\n    execution_graph: DiGraph,\n    super_input_node: str,\n) -> DiGraph:\n    nodes_to_attach_super_input_into = get_nodes_of_specific_category(\n        execution_graph=execution_graph,\n        category=NodeCategory.INPUT_NODE,\n    )\n    step_nodes_without_predecessors = [\n        node\n        for node in execution_graph.nodes\n        if not list(execution_graph.predecessors(node))\n    ]\n    nodes_to_attach_super_input_into.update(step_nodes_without_predecessors)\n    execution_graph.add_node(super_input_node)\n    for node in nodes_to_attach_super_input_into:\n        execution_graph.add_edge(super_input_node, node)\n    return execution_graph\n",
    "patch": null
  },
  {
    "trace_id": "a56974ff-a3fb-4de3-974d-3a70beee6581",
    "function_name": "sequence_apply",
    "file_path": "inference/core/workflows/core_steps/common/query_language/operations/sequences/base.py",
    "speedup_x": 0.4845884027899415,
    "review_quality": "high",
    "pre_optimization_commit": "90243bdc6278ef7d17b6db09dc1eb5b0d155b4be",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def sequence_apply(\n    value: Any, fun: callable, execution_context: str, **kwargs\n) -> List[Any]:\n    try:\n        return [fun(v, **kwargs) for v in value]\n    except (TypeError, ValueError) as e:\n        raise InvalidInputTypeError(\n            public_message=f\"While executing sequence_apply(...) in context {execution_context}, encountered \"\n            f\"value of type {type(value)} which is not a sequence to be iterated\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n            inner_error=e,\n        )\n",
    "optimized_function_code": "from inference.core.workflows.core_steps.common.query_language.errors import InvalidInputTypeError\nfrom typing import Any, List\n\ndef sequence_apply(\n    value: Any, fun: callable, execution_context: str, **kwargs\n) -> List[Any]:\n    try:\n        if kwargs:\n            return [fun(v, **kwargs) for v in value]\n        else:\n            return [fun(v) for v in value]\n    except (TypeError, ValueError) as e:\n        raise InvalidInputTypeError(\n            public_message=f\"While executing sequence_apply(...) in context {execution_context}, encountered \"\n            f\"value of type {type(value)} which is not a sequence to be iterated\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n            inner_error=e,\n        )",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/common/query_language/operations/sequences/base.py\nfrom inference.core.workflows.core_steps.common.query_language.errors import InvalidInputTypeError\nfrom typing import Any, List\n\ndef sequence_apply(\n    value: Any, fun: callable, execution_context: str, **kwargs\n) -> List[Any]:\n    try:\n        if kwargs:\n            return [fun(v, **kwargs) for v in value]\n        else:\n            return [fun(v) for v in value]\n    except (TypeError, ValueError) as e:\n        raise InvalidInputTypeError(\n            public_message=f\"While executing sequence_apply(...) in context {execution_context}, encountered \"\n            f\"value of type {type(value)} which is not a sequence to be iterated\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n            inner_error=e,\n        )\n```",
    "optimized_function_only": "def sequence_apply(\n    value: Any, fun: callable, execution_context: str, **kwargs\n) -> List[Any]:\n    try:\n        if kwargs:\n            return [fun(v, **kwargs) for v in value]\n        else:\n            return [fun(v) for v in value]\n    except (TypeError, ValueError) as e:\n        raise InvalidInputTypeError(\n            public_message=f\"While executing sequence_apply(...) in context {execution_context}, encountered \"\n            f\"value of type {type(value)} which is not a sequence to be iterated\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n            inner_error=e,\n        )",
    "original_file_content": "from collections import Counter\nfrom typing import Any, Dict, List\n\nfrom inference.core.workflows.core_steps.common.query_language.entities.enums import (\n    SequenceAggregationFunction,\n    SequenceAggregationMode,\n)\nfrom inference.core.workflows.core_steps.common.query_language.errors import (\n    InvalidInputTypeError,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.utils import (\n    safe_stringify,\n)\n\n\ndef sequence_map(\n    value: Any, lookup_table: dict, execution_context: str, **kwargs\n) -> List[Any]:\n    try:\n        return [lookup_table[v] for v in value]\n    except (TypeError, ValueError) as e:\n        raise InvalidInputTypeError(\n            public_message=f\"While executing sequence_map(...) in context {execution_context}, encountered \"\n            f\"value of type {type(value)} which is not a sequence to be iterated\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n            inner_error=e,\n        )\n    except KeyError as e:\n        raise InvalidInputTypeError(\n            public_message=f\"While executing operation sequence_map(...) in context {execution_context}, encountered \"\n            f\"value `{e}` which cannot be found in lookup \"\n            f\"table with keys: {list(lookup_table.keys())}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n            inner_error=e,\n        )\n\n\ndef sequence_apply(\n    value: Any, fun: callable, execution_context: str, **kwargs\n) -> List[Any]:\n    try:\n        return [fun(v, **kwargs) for v in value]\n    except (TypeError, ValueError) as e:\n        raise InvalidInputTypeError(\n            public_message=f\"While executing sequence_apply(...) in context {execution_context}, encountered \"\n            f\"value of type {type(value)} which is not a sequence to be iterated\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n            inner_error=e,\n        )\n\n\nAGGREGATION_FUNCTIONS = {\n    SequenceAggregationFunction.MIN: min,\n    SequenceAggregationFunction.MAX: max,\n    SequenceAggregationFunction.SUM: sum,\n}\n\n\ndef aggregate_numeric_sequence(\n    value: Any,\n    function: SequenceAggregationFunction,\n    neutral_value: Any,\n    execution_context: str,\n    **kwargs,\n) -> Any:\n    try:\n        if len(value) == 0:\n            return neutral_value\n        return AGGREGATION_FUNCTIONS[function](value)\n    except (TypeError, ValueError) as e:\n        raise InvalidInputTypeError(\n            public_message=f\"While executing aggregate_numeric_sequence(...) in context {execution_context}, \"\n            f\"encountered value of type {type(value)} which is not suited to execute operation. \"\n            f\"Details: {e}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n            inner_error=e,\n        )\n    except KeyError as e:\n        raise InvalidInputTypeError(\n            public_message=f\"While executing aggregate_numeric_sequence(...) in context {execution_context}, \"\n            f\"requested aggregation function {function.value} which is not supported.\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n            inner_error=e,\n        )\n\n\ndef aggregate_sequence(\n    value: Any, mode: SequenceAggregationMode, execution_context: str, **kwargs\n) -> Any:\n    try:\n        if len(value) < 1:\n            raise InvalidInputTypeError(\n                public_message=f\"While executing aggregate_sequence(...) in context {execution_context}, encountered \"\n                f\"value empty sequence which cannot be aggregated\",\n                context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n            )\n        if mode in {SequenceAggregationMode.FIRST, SequenceAggregationMode.LAST}:\n            index = 0 if mode is SequenceAggregationMode.FIRST else -1\n            return value[index]\n        ctr_ordered = [e[0] for e in Counter(value).most_common()]\n        index = 0 if mode is SequenceAggregationMode.MOST_COMMON else -1\n        return ctr_ordered[index]\n    except (TypeError, ValueError) as e:\n        raise InvalidInputTypeError(\n            public_message=f\"While executing aggregate_sequence(...) in context {execution_context}, encountered \"\n            f\"value of type {type(value)} which is not suited to execute operation. Details: {e}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n            inner_error=e,\n        )\n\n\ndef get_sequence_length(value: Any, execution_context: str, **kwargs) -> int:\n    try:\n        return len(value)\n    except TypeError as e:\n        raise InvalidInputTypeError(\n            public_message=f\"While executing get_sequence_length(...) in context {execution_context}, encountered \"\n            f\"value of type {type(value)} which is not suited to execute operation. Details: {e}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n            inner_error=e,\n        )\n\n\ndef get_sequence_elements_count(\n    value: Any, execution_context: str, **kwargs\n) -> Dict[Any, int]:\n    try:\n        res = {}\n        for v in value:\n            value_as_str = safe_stringify(value=v)\n            res[value_as_str] = res.setdefault(value_as_str, 0) + 1\n        return res\n    except (TypeError, ValueError) as e:\n        raise InvalidInputTypeError(\n            public_message=f\"While executing get_sequence_elements_count(...) in context {execution_context}, encountered \"\n            f\"value of type {type(value)} which is not suited to execute operation. Details: {e}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n            inner_error=e,\n        )\n",
    "patch": null
  },
  {
    "trace_id": "5847e541-0af9-4809-932b-d16b55a97157",
    "function_name": "build_sequence_apply_operation",
    "file_path": "inference/core/workflows/core_steps/common/query_language/operations/core.py",
    "speedup_x": 0.35129740518962077,
    "review_quality": "high",
    "pre_optimization_commit": "90243bdc6278ef7d17b6db09dc1eb5b0d155b4be",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def build_sequence_apply_operation(\n    definition: SequenceApply, execution_context: str\n) -> Callable[[T], V]:\n    operations_functions = []\n    for operation in definition.operations:\n        operation_function = build_operation(\n            operation_definition=operation, execution_context=execution_context\n        )\n        operations_functions.append(operation_function)\n    chained_function = partial(chain, functions=operations_functions)\n    return partial(\n        sequence_apply, fun=chained_function, execution_context=execution_context\n    )\n",
    "optimized_function_code": "from functools import partial\nfrom typing import Any, Callable, Dict, List\n\nfrom inference.core.workflows.core_steps.common.query_language.entities.operations import (\n    TYPE_PARAMETER_NAME, OperationDefinition, SequenceApply)\nfrom inference.core.workflows.core_steps.common.query_language.entities.types import (\n    T, V)\nfrom inference.core.workflows.core_steps.common.query_language.errors import \\\n    OperationTypeNotRecognisedError\nfrom inference.core.workflows.core_steps.common.query_language.operations.booleans.base import \\\n    to_bool\nfrom inference.core.workflows.core_steps.common.query_language.operations.classification_results.base import \\\n    extract_classification_property\nfrom inference.core.workflows.core_steps.common.query_language.operations.detection.base import \\\n    extract_detection_property\nfrom inference.core.workflows.core_steps.common.query_language.operations.detections.base import (\n    detections_to_dictionary, extract_detections_property, offset_detections,\n    pick_detections_by_parent_class, rename_detections, select_detections,\n    shift_detections, sort_detections)\nfrom inference.core.workflows.core_steps.common.query_language.operations.dictionaries.base import \\\n    dictionary_to_json\nfrom inference.core.workflows.core_steps.common.query_language.operations.frame_metadata.base import \\\n    extract_frame_metadata\nfrom inference.core.workflows.core_steps.common.query_language.operations.generic.base import (\n    apply_lookup, generate_random_number)\nfrom inference.core.workflows.core_steps.common.query_language.operations.images.base import (\n    encode_image_to_base64, encode_image_to_jpeg, extract_image_property)\nfrom inference.core.workflows.core_steps.common.query_language.operations.numbers.base import (\n    divide, multiply, number_round, to_number)\nfrom inference.core.workflows.core_steps.common.query_language.operations.sequences.base import (\n    aggregate_numeric_sequence, aggregate_sequence,\n    get_sequence_elements_count, get_sequence_length, sequence_apply,\n    sequence_map)\nfrom inference.core.workflows.core_steps.common.query_language.operations.strings.base import (\n    string_matches, string_sub_sequence, string_to_lower, string_to_upper,\n    to_string)\nfrom inference.core.workflows.core_steps.common.query_language.operations.timestamps.base import \\\n    timestamp_to_iso_format\n\n\ndef build_simple_operation(\n    operation_definition: OperationDefinition,\n    operation_function: Callable[[T], V],\n    execution_context: str,\n) -> Callable[[T], V]:\n    kwargs = {\n        a: v for a, v in vars(operation_definition).items() if a != TYPE_PARAMETER_NAME\n    }\n    kwargs[\"execution_context\"] = execution_context\n    return partial(operation_function, **kwargs)\n\n\ndef build_operation(\n    operation_definition: OperationDefinition,\n    execution_context: str,\n) -> Callable[[T], V]:\n    operation_type = operation_definition.type\n    \n    # Check simple operations first (most common case)\n    operation_function = REGISTERED_SIMPLE_OPERATIONS.get(operation_type)\n    if operation_function is not None:\n        return build_simple_operation(\n            operation_definition=operation_definition,\n            operation_function=operation_function,\n            execution_context=execution_context,\n        )\n    \n    # Check compound operations\n    builder = REGISTERED_COMPOUND_OPERATIONS_BUILDERS.get(operation_type)\n    if builder is not None:\n        return builder(operation_definition, execution_context)\n    \n    raise OperationTypeNotRecognisedError(\n        public_message=f\"Attempted to build operation with declared type: {operation_type} \"\n        f\"which was not registered in Roboflow Query Language.\",\n        context=\"step_execution | roboflow_query_language_compilation\",\n    )\n\n\ndef build_sequence_apply_operation(\n    definition: SequenceApply, execution_context: str\n) -> Callable[[T], V]:\n    operations_functions = [\n        build_operation(operation_definition=operation, execution_context=execution_context)\n        for operation in definition.operations\n    ]\n    chained_function = partial(chain, functions=operations_functions)\n    return partial(\n        sequence_apply, fun=chained_function, execution_context=execution_context\n    )\n\n\ndef chain(\n    value: T, global_parameters: Dict[str, Any], functions: List[Callable[[T], V]]\n) -> Callable[[T, Dict[str, Any]], V]:\n    for function in functions:\n        value = function(value, global_parameters=global_parameters)\n    return value\n\n\nREGISTERED_SIMPLE_OPERATIONS = {\n    \"StringToLowerCase\": string_to_lower,\n    \"StringToUpperCase\": string_to_upper,\n    \"LookupTable\": apply_lookup,\n    \"ToNumber\": to_number,\n    \"NumberRound\": number_round,\n    \"SequenceMap\": sequence_map,\n    \"NumericSequenceAggregate\": aggregate_numeric_sequence,\n    \"ToString\": to_string,\n    \"ToBoolean\": to_bool,\n    \"StringSubSequence\": string_sub_sequence,\n    \"DetectionsPropertyExtract\": extract_detections_property,\n    \"SequenceAggregate\": aggregate_sequence,\n    \"ExtractDetectionProperty\": extract_detection_property,\n    \"DetectionsOffset\": offset_detections,\n    \"DetectionsShift\": shift_detections,\n    \"RandomNumber\": generate_random_number,\n    \"StringMatches\": string_matches,\n    \"SequenceLength\": get_sequence_length,\n    \"SequenceElementsCount\": get_sequence_elements_count,\n    \"ExtractImageProperty\": extract_image_property,\n    \"ExtractFrameMetadata\": extract_frame_metadata,\n    \"Multiply\": multiply,\n    \"Divide\": divide,\n    \"DetectionsSelection\": select_detections,\n    \"SortDetections\": sort_detections,\n    \"ClassificationPropertyExtract\": extract_classification_property,\n    \"DetectionsRename\": rename_detections,\n    \"ConvertImageToJPEG\": encode_image_to_jpeg,\n    \"ConvertImageToBase64\": encode_image_to_base64,\n    \"DetectionsToDictionary\": detections_to_dictionary,\n    \"ConvertDictionaryToJSON\": dictionary_to_json,\n    \"PickDetectionsByParentClass\": pick_detections_by_parent_class,\n    \"TimestampToISOFormat\": timestamp_to_iso_format,\n}\n\nREGISTERED_COMPOUND_OPERATIONS_BUILDERS = {\n    \"SequenceApply\": build_sequence_apply_operation,\n    \"DetectionsFilter\": build_detections_filter_operation,\n}",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/common/query_language/operations/core.py\nfrom functools import partial\nfrom typing import Any, Callable, Dict, List\n\nfrom inference.core.workflows.core_steps.common.query_language.entities.operations import (\n    TYPE_PARAMETER_NAME, OperationDefinition, SequenceApply)\nfrom inference.core.workflows.core_steps.common.query_language.entities.types import (\n    T, V)\nfrom inference.core.workflows.core_steps.common.query_language.errors import \\\n    OperationTypeNotRecognisedError\nfrom inference.core.workflows.core_steps.common.query_language.operations.booleans.base import \\\n    to_bool\nfrom inference.core.workflows.core_steps.common.query_language.operations.classification_results.base import \\\n    extract_classification_property\nfrom inference.core.workflows.core_steps.common.query_language.operations.detection.base import \\\n    extract_detection_property\nfrom inference.core.workflows.core_steps.common.query_language.operations.detections.base import (\n    detections_to_dictionary, extract_detections_property, offset_detections,\n    pick_detections_by_parent_class, rename_detections, select_detections,\n    shift_detections, sort_detections)\nfrom inference.core.workflows.core_steps.common.query_language.operations.dictionaries.base import \\\n    dictionary_to_json\nfrom inference.core.workflows.core_steps.common.query_language.operations.frame_metadata.base import \\\n    extract_frame_metadata\nfrom inference.core.workflows.core_steps.common.query_language.operations.generic.base import (\n    apply_lookup, generate_random_number)\nfrom inference.core.workflows.core_steps.common.query_language.operations.images.base import (\n    encode_image_to_base64, encode_image_to_jpeg, extract_image_property)\nfrom inference.core.workflows.core_steps.common.query_language.operations.numbers.base import (\n    divide, multiply, number_round, to_number)\nfrom inference.core.workflows.core_steps.common.query_language.operations.sequences.base import (\n    aggregate_numeric_sequence, aggregate_sequence,\n    get_sequence_elements_count, get_sequence_length, sequence_apply,\n    sequence_map)\nfrom inference.core.workflows.core_steps.common.query_language.operations.strings.base import (\n    string_matches, string_sub_sequence, string_to_lower, string_to_upper,\n    to_string)\nfrom inference.core.workflows.core_steps.common.query_language.operations.timestamps.base import \\\n    timestamp_to_iso_format\n\n\ndef build_simple_operation(\n    operation_definition: OperationDefinition,\n    operation_function: Callable[[T], V],\n    execution_context: str,\n) -> Callable[[T], V]:\n    kwargs = {\n        a: v for a, v in vars(operation_definition).items() if a != TYPE_PARAMETER_NAME\n    }\n    kwargs[\"execution_context\"] = execution_context\n    return partial(operation_function, **kwargs)\n\n\ndef build_operation(\n    operation_definition: OperationDefinition,\n    execution_context: str,\n) -> Callable[[T], V]:\n    operation_type = operation_definition.type\n    \n    # Check simple operations first (most common case)\n    operation_function = REGISTERED_SIMPLE_OPERATIONS.get(operation_type)\n    if operation_function is not None:\n        return build_simple_operation(\n            operation_definition=operation_definition,\n            operation_function=operation_function,\n            execution_context=execution_context,\n        )\n    \n    # Check compound operations\n    builder = REGISTERED_COMPOUND_OPERATIONS_BUILDERS.get(operation_type)\n    if builder is not None:\n        return builder(operation_definition, execution_context)\n    \n    raise OperationTypeNotRecognisedError(\n        public_message=f\"Attempted to build operation with declared type: {operation_type} \"\n        f\"which was not registered in Roboflow Query Language.\",\n        context=\"step_execution | roboflow_query_language_compilation\",\n    )\n\n\ndef build_sequence_apply_operation(\n    definition: SequenceApply, execution_context: str\n) -> Callable[[T], V]:\n    operations_functions = [\n        build_operation(operation_definition=operation, execution_context=execution_context)\n        for operation in definition.operations\n    ]\n    chained_function = partial(chain, functions=operations_functions)\n    return partial(\n        sequence_apply, fun=chained_function, execution_context=execution_context\n    )\n\n\ndef chain(\n    value: T, global_parameters: Dict[str, Any], functions: List[Callable[[T], V]]\n) -> Callable[[T, Dict[str, Any]], V]:\n    for function in functions:\n        value = function(value, global_parameters=global_parameters)\n    return value\n\n\nREGISTERED_SIMPLE_OPERATIONS = {\n    \"StringToLowerCase\": string_to_lower,\n    \"StringToUpperCase\": string_to_upper,\n    \"LookupTable\": apply_lookup,\n    \"ToNumber\": to_number,\n    \"NumberRound\": number_round,\n    \"SequenceMap\": sequence_map,\n    \"NumericSequenceAggregate\": aggregate_numeric_sequence,\n    \"ToString\": to_string,\n    \"ToBoolean\": to_bool,\n    \"StringSubSequence\": string_sub_sequence,\n    \"DetectionsPropertyExtract\": extract_detections_property,\n    \"SequenceAggregate\": aggregate_sequence,\n    \"ExtractDetectionProperty\": extract_detection_property,\n    \"DetectionsOffset\": offset_detections,\n    \"DetectionsShift\": shift_detections,\n    \"RandomNumber\": generate_random_number,\n    \"StringMatches\": string_matches,\n    \"SequenceLength\": get_sequence_length,\n    \"SequenceElementsCount\": get_sequence_elements_count,\n    \"ExtractImageProperty\": extract_image_property,\n    \"ExtractFrameMetadata\": extract_frame_metadata,\n    \"Multiply\": multiply,\n    \"Divide\": divide,\n    \"DetectionsSelection\": select_detections,\n    \"SortDetections\": sort_detections,\n    \"ClassificationPropertyExtract\": extract_classification_property,\n    \"DetectionsRename\": rename_detections,\n    \"ConvertImageToJPEG\": encode_image_to_jpeg,\n    \"ConvertImageToBase64\": encode_image_to_base64,\n    \"DetectionsToDictionary\": detections_to_dictionary,\n    \"ConvertDictionaryToJSON\": dictionary_to_json,\n    \"PickDetectionsByParentClass\": pick_detections_by_parent_class,\n    \"TimestampToISOFormat\": timestamp_to_iso_format,\n}\n\nREGISTERED_COMPOUND_OPERATIONS_BUILDERS = {\n    \"SequenceApply\": build_sequence_apply_operation,\n    \"DetectionsFilter\": build_detections_filter_operation,\n}\n```",
    "optimized_function_only": "def build_sequence_apply_operation(\n    definition: SequenceApply, execution_context: str\n) -> Callable[[T], V]:\n    operations_functions = [\n        build_operation(operation_definition=operation, execution_context=execution_context)\n        for operation in definition.operations\n    ]\n    chained_function = partial(chain, functions=operations_functions)\n    return partial(\n        sequence_apply, fun=chained_function, execution_context=execution_context\n    )\n",
    "original_file_content": "from functools import partial\nfrom typing import Any, Callable, Dict, List, Optional\n\nfrom inference.core.workflows.core_steps.common.query_language.entities.operations import (\n    TYPE_PARAMETER_NAME,\n    DetectionsFilter,\n    OperationDefinition,\n    OperationsChain,\n    SequenceApply,\n)\nfrom inference.core.workflows.core_steps.common.query_language.entities.types import (\n    T,\n    V,\n)\nfrom inference.core.workflows.core_steps.common.query_language.errors import (\n    OperationTypeNotRecognisedError,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.booleans.base import (\n    to_bool,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.classification_results.base import (\n    extract_classification_property,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.detection.base import (\n    extract_detection_property,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.detections.base import (\n    detections_to_dictionary,\n    extract_detections_property,\n    filter_detections,\n    offset_detections,\n    pick_detections_by_parent_class,\n    rename_detections,\n    select_detections,\n    shift_detections,\n    sort_detections,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.dictionaries.base import (\n    dictionary_to_json,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.frame_metadata.base import (\n    extract_frame_metadata,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.generic.base import (\n    apply_lookup,\n    generate_random_number,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.images.base import (\n    encode_image_to_base64,\n    encode_image_to_jpeg,\n    extract_image_property,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.numbers.base import (\n    divide,\n    multiply,\n    number_round,\n    to_number,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.sequences.base import (\n    aggregate_numeric_sequence,\n    aggregate_sequence,\n    get_sequence_elements_count,\n    get_sequence_length,\n    sequence_apply,\n    sequence_map,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.strings.base import (\n    string_matches,\n    string_sub_sequence,\n    string_to_lower,\n    string_to_upper,\n    to_string,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.timestamps.base import (\n    timestamp_to_iso_format,\n)\n\n\ndef execute_operations(\n    value: T, operations: List[dict], global_parameters: Optional[Dict[str, Any]] = None\n) -> V:\n    operations_parsed = OperationsChain.model_validate({\"operations\": operations})\n    ops_chain = build_operations_chain(operations_parsed.operations)\n    if global_parameters is None:\n        global_parameters = {}\n    return ops_chain(value, global_parameters=global_parameters)\n\n\ndef identity(value: Any, **kwargs) -> Any:\n    return value\n\n\ndef build_operations_chain(\n    operations: List[OperationDefinition], execution_context: str = \"<root>\"\n) -> Callable[[T, Dict[str, Any]], V]:\n    if not len(operations):\n        return identity  # return identity function\n    operations_functions = []\n    for operation_id, operation_definition in enumerate(operations):\n        operation_context = f\"{execution_context}[{operation_id}]\"\n        operation_function = build_operation(\n            operation_definition=operation_definition,\n            execution_context=operation_context,\n        )\n        operations_functions.append(operation_function)\n    return partial(chain, functions=operations_functions)\n\n\ndef build_operation(\n    operation_definition: OperationDefinition,\n    execution_context: str,\n) -> Callable[[T], V]:\n    if operation_definition.type in REGISTERED_SIMPLE_OPERATIONS:\n        return build_simple_operation(\n            operation_definition=operation_definition,\n            operation_function=REGISTERED_SIMPLE_OPERATIONS[operation_definition.type],\n            execution_context=execution_context,\n        )\n    if operation_definition.type in REGISTERED_COMPOUND_OPERATIONS_BUILDERS:\n        return REGISTERED_COMPOUND_OPERATIONS_BUILDERS[operation_definition.type](\n            operation_definition, execution_context\n        )\n    raise OperationTypeNotRecognisedError(\n        public_message=f\"Attempted to build operation with declared type: {operation_definition.type} \"\n        f\"which was not registered in Roboflow Query Language.\",\n        context=\"step_execution | roboflow_query_language_compilation\",\n    )\n\n\ndef build_simple_operation(\n    operation_definition: OperationDefinition,\n    operation_function: Callable[[T], V],\n    execution_context: str,\n) -> Callable[[T], V]:\n    kwargs = {\n        a: v for a, v in vars(operation_definition).items() if a != TYPE_PARAMETER_NAME\n    }\n    kwargs[\"execution_context\"] = execution_context\n    return partial(operation_function, **kwargs)\n\n\ndef build_sequence_apply_operation(\n    definition: SequenceApply, execution_context: str\n) -> Callable[[T], V]:\n    operations_functions = []\n    for operation in definition.operations:\n        operation_function = build_operation(\n            operation_definition=operation, execution_context=execution_context\n        )\n        operations_functions.append(operation_function)\n    chained_function = partial(chain, functions=operations_functions)\n    return partial(\n        sequence_apply, fun=chained_function, execution_context=execution_context\n    )\n\n\ndef chain(\n    value: T, global_parameters: Dict[str, Any], functions: List[Callable[[T], V]]\n) -> Callable[[T, Dict[str, Any]], V]:\n    for function in functions:\n        value = function(value, global_parameters=global_parameters)\n    return value\n\n\ndef build_detections_filter_operation(\n    definition: DetectionsFilter,\n    execution_context: str,\n) -> Callable[[T], V]:\n    # local import to avoid circular dependency of modules with operations and evaluation\n    from inference.core.workflows.core_steps.common.query_language.evaluation_engine.core import (\n        build_eval_function,\n    )\n\n    filtering_fun = build_eval_function(\n        definition=definition.filter_operation,\n        execution_context=execution_context,\n    )\n    return partial(filter_detections, filtering_fun=filtering_fun)\n\n\nREGISTERED_SIMPLE_OPERATIONS = {\n    \"StringToLowerCase\": string_to_lower,\n    \"StringToUpperCase\": string_to_upper,\n    \"LookupTable\": apply_lookup,\n    \"ToNumber\": to_number,\n    \"NumberRound\": number_round,\n    \"SequenceMap\": sequence_map,\n    \"NumericSequenceAggregate\": aggregate_numeric_sequence,\n    \"ToString\": to_string,\n    \"ToBoolean\": to_bool,\n    \"StringSubSequence\": string_sub_sequence,\n    \"DetectionsPropertyExtract\": extract_detections_property,\n    \"SequenceAggregate\": aggregate_sequence,\n    \"ExtractDetectionProperty\": extract_detection_property,\n    \"DetectionsOffset\": offset_detections,\n    \"DetectionsShift\": shift_detections,\n    \"RandomNumber\": generate_random_number,\n    \"StringMatches\": string_matches,\n    \"SequenceLength\": get_sequence_length,\n    \"SequenceElementsCount\": get_sequence_elements_count,\n    \"ExtractImageProperty\": extract_image_property,\n    \"ExtractFrameMetadata\": extract_frame_metadata,\n    \"Multiply\": multiply,\n    \"Divide\": divide,\n    \"DetectionsSelection\": select_detections,\n    \"SortDetections\": sort_detections,\n    \"ClassificationPropertyExtract\": extract_classification_property,\n    \"DetectionsRename\": rename_detections,\n    \"ConvertImageToJPEG\": encode_image_to_jpeg,\n    \"ConvertImageToBase64\": encode_image_to_base64,\n    \"DetectionsToDictionary\": detections_to_dictionary,\n    \"ConvertDictionaryToJSON\": dictionary_to_json,\n    \"PickDetectionsByParentClass\": pick_detections_by_parent_class,\n    \"TimestampToISOFormat\": timestamp_to_iso_format,\n}\n\nREGISTERED_COMPOUND_OPERATIONS_BUILDERS = {\n    \"SequenceApply\": build_sequence_apply_operation,\n    \"DetectionsFilter\": build_detections_filter_operation,\n}\n",
    "patch": null
  },
  {
    "trace_id": "f777d05c-f3b7-4c73-8b68-220aa677fab5",
    "function_name": "create_dynamic_module",
    "file_path": "inference/core/workflows/execution_engine/v1/dynamic_blocks/block_scaffolding.py",
    "speedup_x": 11.30653022077789,
    "review_quality": "high",
    "pre_optimization_commit": "6a5fec1e3ee3fc67f02b4810039100c99dc65f59",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def create_dynamic_module(\n    block_type_name: str,\n    python_code: PythonCode,\n    module_name: str,\n    api_key: Optional[str] = None,\n    skip_class_eval: Optional[bool] = False,\n) -> types.ModuleType:\n\n    if skip_class_eval:\n        # Create a stub module for local reference\n        dynamic_module = types.ModuleType(module_name)\n        # Add placeholder function\n        setattr(\n            dynamic_module, python_code.run_function_name, lambda *args, **kwargs: None\n        )\n        if python_code.init_function_code:\n            setattr(dynamic_module, python_code.init_function_name, lambda: {})\n        return dynamic_module\n\n    imports = _get_python_code_imports(python_code)\n    code = python_code.run_function_code\n    if python_code.init_function_code:\n        code += \"\\n\\n\" + python_code.init_function_code\n    code = imports + code\n\n    # If using Modal and local execution is disabled, validate code remotely\n    if WORKFLOWS_CUSTOM_PYTHON_EXECUTION_MODE == \"modal\":\n        # Validate code in Modal sandbox for security\n        from inference.core.workflows.execution_engine.v1.dynamic_blocks.modal_executor import (\n            validate_code_in_modal,\n        )\n\n        try:  # Get workspace_id from context if available\n            validation_workspace = get_roboflow_workspace(api_key)\n        except WorkspaceLoadError:\n            validation_workspace = None\n\n        # Fall back to \"anonymous\" for non-authenticated users\n        if not validation_workspace:\n            validation_workspace = MODAL_ANONYMOUS_WORKSPACE_NAME\n\n        # This will raise if validation fails\n        validate_code_in_modal(python_code, validation_workspace)\n\n        # Create a stub module for local reference\n        dynamic_module = types.ModuleType(module_name)\n        # Add placeholder function\n        setattr(\n            dynamic_module, python_code.run_function_name, lambda *args, **kwargs: None\n        )\n        if python_code.init_function_code:\n            setattr(dynamic_module, python_code.init_function_name, lambda: {})\n        return dynamic_module\n    else:\n        # Local validation and module creation\n        try:\n            dynamic_module = types.ModuleType(module_name)\n            # Inject the shared globals dict into the module namespace\n            dynamic_module.__dict__[\"globals\"] = _LOCAL_SHARED_GLOBALS\n            exec(code, dynamic_module.__dict__)\n            return dynamic_module\n        except Exception as error:\n            error_line = getattr(error, \"lineno\", None)\n            code_snippet = None\n            if error_line and python_code.run_function_code:\n                snippet = extract_code_snippet(\n                    python_code.run_function_code, error_line\n                )\n                code_snippet = snippet.lstrip(\"\\n\") if snippet else None\n\n            raise PythonBlockError(\n                message=f\"{error.__class__.__name__}: {error}\",\n                block_type_name=block_type_name,\n                error_line=error_line,\n                code_snippet=code_snippet,\n            ) from error\n",
    "optimized_function_code": "import types\nfrom typing import Optional\n\nfrom inference.core.env import (MODAL_ANONYMOUS_WORKSPACE_NAME,\n                                WORKFLOWS_CUSTOM_PYTHON_EXECUTION_MODE)\nfrom inference.core.exceptions import WorkspaceLoadError\nfrom inference.core.roboflow_api import get_roboflow_workspace\nfrom inference.core.workflows.errors import PythonBlockError\nfrom inference.core.workflows.execution_engine.v1.dynamic_blocks.entities import \\\n    PythonCode\n\nIMPORTS_LINES = [\n    \"from typing import Any, List, Dict, Set, Optional\",\n    \"import supervision as sv\",\n    \"import numpy as np\",\n    \"import math\",\n    \"import time\",\n    \"import json\",\n    \"import os\",\n    \"import requests\",\n    \"import cv2\",\n    \"import shapely\",\n    \"from inference.core.workflows.execution_engine.entities.base import Batch, WorkflowImageData\",\n    \"from inference.core.workflows.prototypes.block import BlockResult\",\n]\n\n# Shared globals dict for all custom python blocks in local mode\n_LOCAL_SHARED_GLOBALS = {}\n\n\n\n# Cached generated imports string keyed by tuple(imports)\n_IMPORTS_CACHE = {}\n\n# Cached compiled code objects keyed by source string\n_COMPILED_CODE_CACHE = {}\n\n\ndef extract_code_snippet(\n    code: Optional[str], error_line: int, context: int = 10\n) -> str:\n    \"\"\"Extract a code snippet around the error line with markers.\"\"\"\n    if not code:\n        return \"\"\n\n    lines = code.splitlines()\n    error_idx = error_line - 1\n    start = max(0, error_idx - context)\n    end = min(len(lines), error_idx + context + 1)\n    snippet_lines = [\n        f\"{'>>>' if i == error_idx else '   '} {i + 1}: {lines[i]}\"\n        for i in range(start, end)\n    ]\n    return \"\\n\" + \"\\n\".join(snippet_lines)\n\n\ndef _get_python_code_imports(python_code: PythonCode) -> str:\n    return \"\\n\".join(IMPORTS_LINES) + \"\\n\" + \"\\n\".join(python_code.imports) + \"\\n\\n\"\n\n\n\n\ndef _build_imports_string_cached(python_code: PythonCode) -> str:\n    # Use tuple(...) as a hashable key; handle None imports gracefully\n    imports_list = tuple(python_code.imports or ())\n    cached = _IMPORTS_CACHE.get(imports_list)\n    if cached is not None:\n        return cached\n    # Build imports string (same format as original helper)\n    # Keep original behavior by delegating to existing function for formatting\n    imports_str = _get_python_code_imports(python_code)\n    _IMPORTS_CACHE[imports_list] = imports_str\n    return imports_str\n\n\ndef _compile_source_cached(source: str):\n    compiled = _COMPILED_CODE_CACHE.get(source)\n    if compiled is not None:\n        return compiled\n    # Use \"<string>\" filename to preserve traceback behavior consistent with exec(source, ...)\n    compiled_code = compile(source, \"<string>\", \"exec\")\n    _COMPILED_CODE_CACHE[source] = compiled_code\n    return compiled_code\n\n\ndef create_dynamic_module(\n    block_type_name: str,\n    python_code: PythonCode,\n    module_name: str,\n    api_key: Optional[str] = None,\n    skip_class_eval: Optional[bool] = False,\n) -> types.ModuleType:\n\n    if skip_class_eval:\n        # Create a stub module for local reference\n        dynamic_module = types.ModuleType(module_name)\n        # Add placeholder function\n        setattr(\n            dynamic_module, python_code.run_function_name, lambda *args, **kwargs: None\n        )\n        if python_code.init_function_code:\n            setattr(dynamic_module, python_code.init_function_name, lambda: {})\n        return dynamic_module\n\n    imports = _build_imports_string_cached(python_code)\n    code = python_code.run_function_code\n    if python_code.init_function_code:\n        code = code + \"\\n\\n\" + python_code.init_function_code\n    # Join imports and code together into source\n    source = imports + code\n\n    # If using Modal and local execution is disabled, validate code remotely\n\n    # If using Modal and local execution is disabled, validate code remotely\n    if WORKFLOWS_CUSTOM_PYTHON_EXECUTION_MODE == \"modal\":\n        # Validate code in Modal sandbox for security\n        from inference.core.workflows.execution_engine.v1.dynamic_blocks.modal_executor import \\\n            validate_code_in_modal\n\n        try:  # Get workspace_id from context if available\n            validation_workspace = get_roboflow_workspace(api_key)\n        except WorkspaceLoadError:\n            validation_workspace = None\n\n        # Fall back to \"anonymous\" for non-authenticated users\n        if not validation_workspace:\n            validation_workspace = MODAL_ANONYMOUS_WORKSPACE_NAME\n\n        # This will raise if validation fails\n        validate_code_in_modal(python_code, validation_workspace)\n\n        # Create a stub module for local reference\n        dynamic_module = types.ModuleType(module_name)\n        # Add placeholder function\n        setattr(\n            dynamic_module, python_code.run_function_name, lambda *args, **kwargs: None\n        )\n        if python_code.init_function_code:\n            setattr(dynamic_module, python_code.init_function_name, lambda: {})\n        return dynamic_module\n    else:\n        # Local validation and module creation\n        try:\n            dynamic_module = types.ModuleType(module_name)\n            # Inject the shared globals dict into the module namespace\n            dynamic_module.__dict__[\"globals\"] = _LOCAL_SHARED_GLOBALS\n            # Compile once and reuse compiled code objects when possible\n            compiled = _compile_source_cached(source)\n            exec(compiled, dynamic_module.__dict__)\n            return dynamic_module\n        except Exception as error:\n            error_line = getattr(error, \"lineno\", None)\n            code_snippet = None\n            if error_line and python_code.run_function_code:\n                snippet = extract_code_snippet(\n                    python_code.run_function_code, error_line\n                )\n                code_snippet = snippet.lstrip(\"\\n\") if snippet else None\n\n            raise PythonBlockError(\n                message=f\"{error.__class__.__name__}: {error}\",\n                block_type_name=block_type_name,\n                error_line=error_line,\n                code_snippet=code_snippet,\n            ) from error",
    "optimized_raw_markdown": "```python:inference/core/workflows/execution_engine/v1/dynamic_blocks/block_scaffolding.py\nimport types\nfrom typing import Optional\n\nfrom inference.core.env import (MODAL_ANONYMOUS_WORKSPACE_NAME,\n                                WORKFLOWS_CUSTOM_PYTHON_EXECUTION_MODE)\nfrom inference.core.exceptions import WorkspaceLoadError\nfrom inference.core.roboflow_api import get_roboflow_workspace\nfrom inference.core.workflows.errors import PythonBlockError\nfrom inference.core.workflows.execution_engine.v1.dynamic_blocks.entities import \\\n    PythonCode\n\nIMPORTS_LINES = [\n    \"from typing import Any, List, Dict, Set, Optional\",\n    \"import supervision as sv\",\n    \"import numpy as np\",\n    \"import math\",\n    \"import time\",\n    \"import json\",\n    \"import os\",\n    \"import requests\",\n    \"import cv2\",\n    \"import shapely\",\n    \"from inference.core.workflows.execution_engine.entities.base import Batch, WorkflowImageData\",\n    \"from inference.core.workflows.prototypes.block import BlockResult\",\n]\n\n# Shared globals dict for all custom python blocks in local mode\n_LOCAL_SHARED_GLOBALS = {}\n\n\n\n# Cached generated imports string keyed by tuple(imports)\n_IMPORTS_CACHE = {}\n\n# Cached compiled code objects keyed by source string\n_COMPILED_CODE_CACHE = {}\n\n\ndef extract_code_snippet(\n    code: Optional[str], error_line: int, context: int = 10\n) -> str:\n    \"\"\"Extract a code snippet around the error line with markers.\"\"\"\n    if not code:\n        return \"\"\n\n    lines = code.splitlines()\n    error_idx = error_line - 1\n    start = max(0, error_idx - context)\n    end = min(len(lines), error_idx + context + 1)\n    snippet_lines = [\n        f\"{'>>>' if i == error_idx else '   '} {i + 1}: {lines[i]}\"\n        for i in range(start, end)\n    ]\n    return \"\\n\" + \"\\n\".join(snippet_lines)\n\n\ndef _get_python_code_imports(python_code: PythonCode) -> str:\n    return \"\\n\".join(IMPORTS_LINES) + \"\\n\" + \"\\n\".join(python_code.imports) + \"\\n\\n\"\n\n\n\n\ndef _build_imports_string_cached(python_code: PythonCode) -> str:\n    # Use tuple(...) as a hashable key; handle None imports gracefully\n    imports_list = tuple(python_code.imports or ())\n    cached = _IMPORTS_CACHE.get(imports_list)\n    if cached is not None:\n        return cached\n    # Build imports string (same format as original helper)\n    # Keep original behavior by delegating to existing function for formatting\n    imports_str = _get_python_code_imports(python_code)\n    _IMPORTS_CACHE[imports_list] = imports_str\n    return imports_str\n\n\ndef _compile_source_cached(source: str):\n    compiled = _COMPILED_CODE_CACHE.get(source)\n    if compiled is not None:\n        return compiled\n    # Use \"<string>\" filename to preserve traceback behavior consistent with exec(source, ...)\n    compiled_code = compile(source, \"<string>\", \"exec\")\n    _COMPILED_CODE_CACHE[source] = compiled_code\n    return compiled_code\n\n\ndef create_dynamic_module(\n    block_type_name: str,\n    python_code: PythonCode,\n    module_name: str,\n    api_key: Optional[str] = None,\n    skip_class_eval: Optional[bool] = False,\n) -> types.ModuleType:\n\n    if skip_class_eval:\n        # Create a stub module for local reference\n        dynamic_module = types.ModuleType(module_name)\n        # Add placeholder function\n        setattr(\n            dynamic_module, python_code.run_function_name, lambda *args, **kwargs: None\n        )\n        if python_code.init_function_code:\n            setattr(dynamic_module, python_code.init_function_name, lambda: {})\n        return dynamic_module\n\n    imports = _build_imports_string_cached(python_code)\n    code = python_code.run_function_code\n    if python_code.init_function_code:\n        code = code + \"\\n\\n\" + python_code.init_function_code\n    # Join imports and code together into source\n    source = imports + code\n\n    # If using Modal and local execution is disabled, validate code remotely\n\n    # If using Modal and local execution is disabled, validate code remotely\n    if WORKFLOWS_CUSTOM_PYTHON_EXECUTION_MODE == \"modal\":\n        # Validate code in Modal sandbox for security\n        from inference.core.workflows.execution_engine.v1.dynamic_blocks.modal_executor import \\\n            validate_code_in_modal\n\n        try:  # Get workspace_id from context if available\n            validation_workspace = get_roboflow_workspace(api_key)\n        except WorkspaceLoadError:\n            validation_workspace = None\n\n        # Fall back to \"anonymous\" for non-authenticated users\n        if not validation_workspace:\n            validation_workspace = MODAL_ANONYMOUS_WORKSPACE_NAME\n\n        # This will raise if validation fails\n        validate_code_in_modal(python_code, validation_workspace)\n\n        # Create a stub module for local reference\n        dynamic_module = types.ModuleType(module_name)\n        # Add placeholder function\n        setattr(\n            dynamic_module, python_code.run_function_name, lambda *args, **kwargs: None\n        )\n        if python_code.init_function_code:\n            setattr(dynamic_module, python_code.init_function_name, lambda: {})\n        return dynamic_module\n    else:\n        # Local validation and module creation\n        try:\n            dynamic_module = types.ModuleType(module_name)\n            # Inject the shared globals dict into the module namespace\n            dynamic_module.__dict__[\"globals\"] = _LOCAL_SHARED_GLOBALS\n            # Compile once and reuse compiled code objects when possible\n            compiled = _compile_source_cached(source)\n            exec(compiled, dynamic_module.__dict__)\n            return dynamic_module\n        except Exception as error:\n            error_line = getattr(error, \"lineno\", None)\n            code_snippet = None\n            if error_line and python_code.run_function_code:\n                snippet = extract_code_snippet(\n                    python_code.run_function_code, error_line\n                )\n                code_snippet = snippet.lstrip(\"\\n\") if snippet else None\n\n            raise PythonBlockError(\n                message=f\"{error.__class__.__name__}: {error}\",\n                block_type_name=block_type_name,\n                error_line=error_line,\n                code_snippet=code_snippet,\n            ) from error\n```",
    "optimized_function_only": "def create_dynamic_module(\n    block_type_name: str,\n    python_code: PythonCode,\n    module_name: str,\n    api_key: Optional[str] = None,\n    skip_class_eval: Optional[bool] = False,\n) -> types.ModuleType:\n\n    if skip_class_eval:\n        # Create a stub module for local reference\n        dynamic_module = types.ModuleType(module_name)\n        # Add placeholder function\n        setattr(\n            dynamic_module, python_code.run_function_name, lambda *args, **kwargs: None\n        )\n        if python_code.init_function_code:\n            setattr(dynamic_module, python_code.init_function_name, lambda: {})\n        return dynamic_module\n\n    imports = _build_imports_string_cached(python_code)\n    code = python_code.run_function_code\n    if python_code.init_function_code:\n        code = code + \"\\n\\n\" + python_code.init_function_code\n    # Join imports and code together into source\n    source = imports + code\n\n    # If using Modal and local execution is disabled, validate code remotely\n\n    # If using Modal and local execution is disabled, validate code remotely\n    if WORKFLOWS_CUSTOM_PYTHON_EXECUTION_MODE == \"modal\":\n        # Validate code in Modal sandbox for security\n        from inference.core.workflows.execution_engine.v1.dynamic_blocks.modal_executor import \\\n            validate_code_in_modal\n\n        try:  # Get workspace_id from context if available\n            validation_workspace = get_roboflow_workspace(api_key)\n        except WorkspaceLoadError:\n            validation_workspace = None\n\n        # Fall back to \"anonymous\" for non-authenticated users\n        if not validation_workspace:\n            validation_workspace = MODAL_ANONYMOUS_WORKSPACE_NAME\n\n        # This will raise if validation fails\n        validate_code_in_modal(python_code, validation_workspace)\n\n        # Create a stub module for local reference\n        dynamic_module = types.ModuleType(module_name)\n        # Add placeholder function\n        setattr(\n            dynamic_module, python_code.run_function_name, lambda *args, **kwargs: None\n        )\n        if python_code.init_function_code:\n            setattr(dynamic_module, python_code.init_function_name, lambda: {})\n        return dynamic_module\n    else:\n        # Local validation and module creation\n        try:\n            dynamic_module = types.ModuleType(module_name)\n            # Inject the shared globals dict into the module namespace\n            dynamic_module.__dict__[\"globals\"] = _LOCAL_SHARED_GLOBALS\n            # Compile once and reuse compiled code objects when possible\n            compiled = _compile_source_cached(source)\n            exec(compiled, dynamic_module.__dict__)\n            return dynamic_module\n        except Exception as error:\n            error_line = getattr(error, \"lineno\", None)\n            code_snippet = None\n            if error_line and python_code.run_function_code:\n                snippet = extract_code_snippet(\n                    python_code.run_function_code, error_line\n                )\n                code_snippet = snippet.lstrip(\"\\n\") if snippet else None\n\n            raise PythonBlockError(\n                message=f\"{error.__class__.__name__}: {error}\",\n                block_type_name=block_type_name,\n                error_line=error_line,\n                code_snippet=code_snippet,\n            ) from error",
    "original_file_content": "import sys\nimport traceback\nimport types\nfrom contextlib import redirect_stderr, redirect_stdout\nfrom io import StringIO\nfrom typing import Any, Dict, List, Optional, Type\n\nfrom inference.core.env import (\n    ALLOW_CUSTOM_PYTHON_EXECUTION_IN_WORKFLOWS,\n    MODAL_ANONYMOUS_WORKSPACE_NAME,\n    WORKFLOWS_CUSTOM_PYTHON_EXECUTION_MODE,\n)\nfrom inference.core.exceptions import WorkspaceLoadError\nfrom inference.core.roboflow_api import get_roboflow_workspace\nfrom inference.core.workflows.errors import (\n    DynamicBlockError,\n    PythonBlockError,\n    WorkflowEnvironmentConfigurationError,\n)\nfrom inference.core.workflows.execution_engine.v1.dynamic_blocks.entities import (\n    PythonCode,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nIMPORTS_LINES = [\n    \"from typing import Any, List, Dict, Set, Optional\",\n    \"import supervision as sv\",\n    \"import numpy as np\",\n    \"import math\",\n    \"import time\",\n    \"import json\",\n    \"import os\",\n    \"import requests\",\n    \"import cv2\",\n    \"import shapely\",\n    \"from inference.core.workflows.execution_engine.entities.base import Batch, WorkflowImageData\",\n    \"from inference.core.workflows.prototypes.block import BlockResult\",\n]\n\n# Shared globals dict for all custom python blocks in local mode\n_LOCAL_SHARED_GLOBALS = {}\n\n\ndef extract_code_snippet(\n    code: Optional[str], error_line: int, context: int = 10\n) -> str:\n    \"\"\"Extract a code snippet around the error line with markers.\"\"\"\n    if not code:\n        return \"\"\n\n    lines = code.splitlines()\n    error_idx = error_line - 1\n    start = max(0, error_idx - context)\n    end = min(len(lines), error_idx + context + 1)\n    snippet_lines = [\n        f\"{'>>>' if i == error_idx else '   '} {i + 1}: {lines[i]}\"\n        for i in range(start, end)\n    ]\n    return \"\\n\" + \"\\n\".join(snippet_lines)\n\n\ndef build_traceback_string(\n    code: Optional[str],\n    line_number: int,\n    function_name: str,\n    error_type: str,\n    error_msg: str,\n) -> str:\n    \"\"\"Build a traceback string from structured error data.\"\"\"\n    code_lines = (code or \"\").splitlines()\n    code_line = (\n        code_lines[line_number - 1].strip()\n        if 0 < line_number <= len(code_lines)\n        else \"\"\n    )\n\n    lines = [\n        \"Traceback (most recent call last):\",\n        f'  File \"Python Block\", line {line_number}, in {function_name}',\n    ]\n    if code_line:\n        lines.append(f\"    {code_line}\")\n    lines.append(f\"{error_type}: {error_msg}\")\n    return \"\\n\".join(lines)\n\n\ndef _create_clean_traceback(\n    error: Exception, python_code: PythonCode, import_lines: int\n) -> str:\n    \"\"\"Create a clean traceback showing only user code with adjusted line numbers.\"\"\"\n    tb = traceback.extract_tb(error.__traceback__)\n    code_lines = (python_code.run_function_code or \"\").splitlines()\n\n    lines = [\"Traceback (most recent call last):\"]\n    for frame in tb:\n        if frame.filename == \"<string>\":\n            adjusted_line = frame.lineno - import_lines\n            code_line = (\n                code_lines[adjusted_line - 1]\n                if 0 < adjusted_line <= len(code_lines)\n                else \"\"\n            )\n            lines.append(\n                f'  File \"Python Block\", line {adjusted_line}, in {frame.name}'\n            )\n            if code_line:\n                lines.append(f\"    {code_line.strip()}\")\n\n    lines.append(f\"{error.__class__.__name__}: {error}\")\n    return \"\\n\".join(lines)\n\n\ndef _create_python_block_error(\n    error: Exception,\n    python_code: PythonCode,\n    stdout: Optional[str] = None,\n    stderr: Optional[str] = None,\n) -> PythonBlockError:\n    \"\"\"Create a PythonBlockError with structured code context.\"\"\"\n    tb = traceback.extract_tb(error.__traceback__)\n    if not tb:\n        return PythonBlockError(\n            f\"{error.__class__.__name__}: {error}\",\n            stdout=stdout,\n            stderr=stderr,\n        )\n\n    import_lines = len(_get_python_code_imports(python_code).splitlines())\n    frame = tb[-1]\n    line_number = frame.lineno - import_lines\n\n    code_snippet = extract_code_snippet(python_code.run_function_code, line_number)\n    message = f\"Error in line {line_number}, in {frame.name}: {error.__class__.__name__}: {error}\"\n    clean_traceback = _create_clean_traceback(error, python_code, import_lines)\n\n    return PythonBlockError(\n        message=message,\n        error_line=line_number,\n        code_snippet=code_snippet.lstrip(\"\\n\") if code_snippet else None,\n        traceback_str=clean_traceback,\n        stdout=stdout,\n        stderr=stderr,\n    )\n\n\ndef assembly_custom_python_block(\n    block_type_name: str,\n    unique_identifier: str,\n    manifest: Type[WorkflowBlockManifest],\n    python_code: PythonCode,\n    api_key: Optional[str] = None,\n    skip_class_eval: Optional[bool] = False,\n) -> Type[WorkflowBlock]:\n\n    code_module = create_dynamic_module(\n        block_type_name=block_type_name,\n        python_code=python_code,\n        module_name=f\"dynamic_module_{unique_identifier}\",\n        api_key=api_key,\n        skip_class_eval=skip_class_eval,\n    )\n\n    if not hasattr(code_module, python_code.run_function_name):\n        raise DynamicBlockError(\n            public_message=f\"Cannot find function: {python_code.run_function_name} in declared code for \"\n            f\"dynamic block: `{block_type_name}`\",\n            context=\"workflow_compilation | dynamic_block_compilation | declared_symbols_fetching\",\n        )\n    run_function = getattr(code_module, python_code.run_function_name)\n\n    def run(self, *args, **kwargs) -> BlockResult:\n        # Check if we're using Modal remote execution\n        if WORKFLOWS_CUSTOM_PYTHON_EXECUTION_MODE == \"modal\":\n            # Remote execution via Modal - allowed even if local execution is disabled\n            from inference.core.workflows.execution_engine.v1.dynamic_blocks.modal_executor import (\n                ModalExecutor,\n            )\n\n            try:  # Get workspace_id from context if available\n                workspace_id = get_roboflow_workspace(self._api_key)\n            except WorkspaceLoadError:\n                workspace_id = None\n\n            # Fall back to \"anonymous\" for non-authenticated users\n            if not workspace_id:\n                workspace_id = MODAL_ANONYMOUS_WORKSPACE_NAME\n\n            executor = ModalExecutor(workspace_id)\n            return executor.execute_remote(\n                block_type_name=block_type_name,\n                python_code=python_code,\n                inputs=kwargs,\n                workspace_id=workspace_id,\n            )\n        else:\n            # Local execution - check if allowed\n            if not ALLOW_CUSTOM_PYTHON_EXECUTION_IN_WORKFLOWS:\n                raise WorkflowEnvironmentConfigurationError(\n                    public_message=\"Cannot use dynamic blocks with custom Python code in this installation of `workflows`. \"\n                    \"This can be changed by setting environmental variable \"\n                    \"`ALLOW_CUSTOM_PYTHON_EXECUTION_IN_WORKFLOWS=True`\",\n                    context=\"workflow_execution | step_execution | dynamic_step\",\n                )\n            stdout_buf, stderr_buf = StringIO(), StringIO()\n            try:\n                with redirect_stdout(stdout_buf), redirect_stderr(stderr_buf):\n                    return run_function(self, *args, **kwargs)\n            except Exception as error:\n                raise _create_python_block_error(\n                    error,\n                    python_code,\n                    stdout=stdout_buf.getvalue() or None,\n                    stderr=stderr_buf.getvalue() or None,\n                ) from error\n\n    if python_code.init_function_code is not None and not hasattr(\n        code_module, python_code.init_function_name\n    ):\n        raise DynamicBlockError(\n            public_message=f\"Cannot find function: {python_code.init_function_name} in declared code for \"\n            f\"dynamic block: `{block_type_name}`\",\n            context=\"workflow_compilation | dynamic_block_compilation | declared_symbols_fetching\",\n        )\n\n    init_function = getattr(code_module, python_code.init_function_name, dict)\n\n    def constructor(self, api_key: Optional[str] = None):\n        self._init_results = init_function()\n        self._api_key = api_key\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"api_key\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return manifest\n\n    return type(\n        f\"DynamicBlock[{unique_identifier}]\",\n        (WorkflowBlock,),\n        {\n            \"__init__\": constructor,\n            \"get_init_parameters\": get_init_parameters,\n            \"get_manifest\": get_manifest,\n            \"run\": run,\n        },\n    )\n\n\ndef _get_python_code_imports(python_code: PythonCode) -> str:\n    return \"\\n\".join(IMPORTS_LINES) + \"\\n\" + \"\\n\".join(python_code.imports) + \"\\n\\n\"\n\n\ndef create_dynamic_module(\n    block_type_name: str,\n    python_code: PythonCode,\n    module_name: str,\n    api_key: Optional[str] = None,\n    skip_class_eval: Optional[bool] = False,\n) -> types.ModuleType:\n\n    if skip_class_eval:\n        # Create a stub module for local reference\n        dynamic_module = types.ModuleType(module_name)\n        # Add placeholder function\n        setattr(\n            dynamic_module, python_code.run_function_name, lambda *args, **kwargs: None\n        )\n        if python_code.init_function_code:\n            setattr(dynamic_module, python_code.init_function_name, lambda: {})\n        return dynamic_module\n\n    imports = _get_python_code_imports(python_code)\n    code = python_code.run_function_code\n    if python_code.init_function_code:\n        code += \"\\n\\n\" + python_code.init_function_code\n    code = imports + code\n\n    # If using Modal and local execution is disabled, validate code remotely\n    if WORKFLOWS_CUSTOM_PYTHON_EXECUTION_MODE == \"modal\":\n        # Validate code in Modal sandbox for security\n        from inference.core.workflows.execution_engine.v1.dynamic_blocks.modal_executor import (\n            validate_code_in_modal,\n        )\n\n        try:  # Get workspace_id from context if available\n            validation_workspace = get_roboflow_workspace(api_key)\n        except WorkspaceLoadError:\n            validation_workspace = None\n\n        # Fall back to \"anonymous\" for non-authenticated users\n        if not validation_workspace:\n            validation_workspace = MODAL_ANONYMOUS_WORKSPACE_NAME\n\n        # This will raise if validation fails\n        validate_code_in_modal(python_code, validation_workspace)\n\n        # Create a stub module for local reference\n        dynamic_module = types.ModuleType(module_name)\n        # Add placeholder function\n        setattr(\n            dynamic_module, python_code.run_function_name, lambda *args, **kwargs: None\n        )\n        if python_code.init_function_code:\n            setattr(dynamic_module, python_code.init_function_name, lambda: {})\n        return dynamic_module\n    else:\n        # Local validation and module creation\n        try:\n            dynamic_module = types.ModuleType(module_name)\n            # Inject the shared globals dict into the module namespace\n            dynamic_module.__dict__[\"globals\"] = _LOCAL_SHARED_GLOBALS\n            exec(code, dynamic_module.__dict__)\n            return dynamic_module\n        except Exception as error:\n            error_line = getattr(error, \"lineno\", None)\n            code_snippet = None\n            if error_line and python_code.run_function_code:\n                snippet = extract_code_snippet(\n                    python_code.run_function_code, error_line\n                )\n                code_snippet = snippet.lstrip(\"\\n\") if snippet else None\n\n            raise PythonBlockError(\n                message=f\"{error.__class__.__name__}: {error}\",\n                block_type_name=block_type_name,\n                error_line=error_line,\n                code_snippet=code_snippet,\n            ) from error\n",
    "patch": null
  },
  {
    "trace_id": "886abc7f-50f2-4f3f-8d9b-7d850993c7bc",
    "function_name": "assembly_custom_python_block",
    "file_path": "inference/core/workflows/execution_engine/v1/dynamic_blocks/block_scaffolding.py",
    "speedup_x": 0.6125445120556794,
    "review_quality": "high",
    "pre_optimization_commit": "6a5fec1e3ee3fc67f02b4810039100c99dc65f59",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def assembly_custom_python_block(\n    block_type_name: str,\n    unique_identifier: str,\n    manifest: Type[WorkflowBlockManifest],\n    python_code: PythonCode,\n    api_key: Optional[str] = None,\n    skip_class_eval: Optional[bool] = False,\n) -> Type[WorkflowBlock]:\n\n    code_module = create_dynamic_module(\n        block_type_name=block_type_name,\n        python_code=python_code,\n        module_name=f\"dynamic_module_{unique_identifier}\",\n        api_key=api_key,\n        skip_class_eval=skip_class_eval,\n    )\n\n    if not hasattr(code_module, python_code.run_function_name):\n        raise DynamicBlockError(\n            public_message=f\"Cannot find function: {python_code.run_function_name} in declared code for \"\n            f\"dynamic block: `{block_type_name}`\",\n            context=\"workflow_compilation | dynamic_block_compilation | declared_symbols_fetching\",\n        )\n    run_function = getattr(code_module, python_code.run_function_name)\n\n    def run(self, *args, **kwargs) -> BlockResult:\n        # Check if we're using Modal remote execution\n        if WORKFLOWS_CUSTOM_PYTHON_EXECUTION_MODE == \"modal\":\n            # Remote execution via Modal - allowed even if local execution is disabled\n            from inference.core.workflows.execution_engine.v1.dynamic_blocks.modal_executor import (\n                ModalExecutor,\n            )\n\n            try:  # Get workspace_id from context if available\n                workspace_id = get_roboflow_workspace(self._api_key)\n            except WorkspaceLoadError:\n                workspace_id = None\n\n            # Fall back to \"anonymous\" for non-authenticated users\n            if not workspace_id:\n                workspace_id = MODAL_ANONYMOUS_WORKSPACE_NAME\n\n            executor = ModalExecutor(workspace_id)\n            return executor.execute_remote(\n                block_type_name=block_type_name,\n                python_code=python_code,\n                inputs=kwargs,\n                workspace_id=workspace_id,\n            )\n        else:\n            # Local execution - check if allowed\n            if not ALLOW_CUSTOM_PYTHON_EXECUTION_IN_WORKFLOWS:\n                raise WorkflowEnvironmentConfigurationError(\n                    public_message=\"Cannot use dynamic blocks with custom Python code in this installation of `workflows`. \"\n                    \"This can be changed by setting environmental variable \"\n                    \"`ALLOW_CUSTOM_PYTHON_EXECUTION_IN_WORKFLOWS=True`\",\n                    context=\"workflow_execution | step_execution | dynamic_step\",\n                )\n            stdout_buf, stderr_buf = StringIO(), StringIO()\n            try:\n                with redirect_stdout(stdout_buf), redirect_stderr(stderr_buf):\n                    return run_function(self, *args, **kwargs)\n            except Exception as error:\n                raise _create_python_block_error(\n                    error,\n                    python_code,\n                    stdout=stdout_buf.getvalue() or None,\n                    stderr=stderr_buf.getvalue() or None,\n                ) from error\n\n    if python_code.init_function_code is not None and not hasattr(\n        code_module, python_code.init_function_name\n    ):\n        raise DynamicBlockError(\n            public_message=f\"Cannot find function: {python_code.init_function_name} in declared code for \"\n            f\"dynamic block: `{block_type_name}`\",\n            context=\"workflow_compilation | dynamic_block_compilation | declared_symbols_fetching\",\n        )\n\n    init_function = getattr(code_module, python_code.init_function_name, dict)\n\n    def constructor(self, api_key: Optional[str] = None):\n        self._init_results = init_function()\n        self._api_key = api_key\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"api_key\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return manifest\n\n    return type(\n        f\"DynamicBlock[{unique_identifier}]\",\n        (WorkflowBlock,),\n        {\n            \"__init__\": constructor,\n            \"get_init_parameters\": get_init_parameters,\n            \"get_manifest\": get_manifest,\n            \"run\": run,\n        },\n    )\n",
    "optimized_function_code": "import types\nfrom contextlib import redirect_stderr, redirect_stdout\nfrom io import StringIO\nfrom typing import List, Optional, Type\n\nfrom inference.core.env import (ALLOW_CUSTOM_PYTHON_EXECUTION_IN_WORKFLOWS,\n                                MODAL_ANONYMOUS_WORKSPACE_NAME,\n                                WORKFLOWS_CUSTOM_PYTHON_EXECUTION_MODE)\nfrom inference.core.exceptions import WorkspaceLoadError\nfrom inference.core.roboflow_api import get_roboflow_workspace\nfrom inference.core.workflows.errors import (\n    DynamicBlockError, PythonBlockError, WorkflowEnvironmentConfigurationError)\nfrom inference.core.workflows.execution_engine.v1.dynamic_blocks.entities import \\\n    PythonCode\nfrom inference.core.workflows.prototypes.block import (BlockResult,\n                                                       WorkflowBlock,\n                                                       WorkflowBlockManifest)\n\nIMPORTS_LINES = [\n    \"from typing import Any, List, Dict, Set, Optional\",\n    \"import supervision as sv\",\n    \"import numpy as np\",\n    \"import math\",\n    \"import time\",\n    \"import json\",\n    \"import os\",\n    \"import requests\",\n    \"import cv2\",\n    \"import shapely\",\n    \"from inference.core.workflows.execution_engine.entities.base import Batch, WorkflowImageData\",\n    \"from inference.core.workflows.prototypes.block import BlockResult\",\n]\n\n# Shared globals dict for all custom python blocks in local mode\n_LOCAL_SHARED_GLOBALS = {}\n\n# Cache for created dynamic modules to avoid re-executing identical code\n_DYNAMIC_MODULE_CACHE: dict = {}\n\n\ndef assembly_custom_python_block(\n    block_type_name: str,\n    unique_identifier: str,\n    manifest: Type[WorkflowBlockManifest],\n    python_code: PythonCode,\n    api_key: Optional[str] = None,\n    skip_class_eval: Optional[bool] = False,\n) -> Type[WorkflowBlock]:\n\n    code_module = create_dynamic_module(\n        block_type_name=block_type_name,\n        python_code=python_code,\n        module_name=f\"dynamic_module_{unique_identifier}\",\n        api_key=api_key,\n        skip_class_eval=skip_class_eval,\n    )\n\n    if not hasattr(code_module, python_code.run_function_name):\n        raise DynamicBlockError(\n            public_message=f\"Cannot find function: {python_code.run_function_name} in declared code for \"\n            f\"dynamic block: `{block_type_name}`\",\n            context=\"workflow_compilation | dynamic_block_compilation | declared_symbols_fetching\",\n        )\n    run_function = getattr(code_module, python_code.run_function_name)\n\n    def run(self, *args, **kwargs) -> BlockResult:\n        # Check if we're using Modal remote execution\n        if WORKFLOWS_CUSTOM_PYTHON_EXECUTION_MODE == \"modal\":\n            # Remote execution via Modal - allowed even if local execution is disabled\n            from inference.core.workflows.execution_engine.v1.dynamic_blocks.modal_executor import \\\n                ModalExecutor\n\n            try:  # Get workspace_id from context if available\n                workspace_id = get_roboflow_workspace(self._api_key)\n            except WorkspaceLoadError:\n                workspace_id = None\n\n            # Fall back to \"anonymous\" for non-authenticated users\n            if not workspace_id:\n                workspace_id = MODAL_ANONYMOUS_WORKSPACE_NAME\n\n            executor = ModalExecutor(workspace_id)\n            return executor.execute_remote(\n                block_type_name=block_type_name,\n                python_code=python_code,\n                inputs=kwargs,\n                workspace_id=workspace_id,\n            )\n        else:\n            # Local execution - check if allowed\n            if not ALLOW_CUSTOM_PYTHON_EXECUTION_IN_WORKFLOWS:\n                raise WorkflowEnvironmentConfigurationError(\n                    public_message=\"Cannot use dynamic blocks with custom Python code in this installation of `workflows`. \"\n                    \"This can be changed by setting environmental variable \"\n                    \"`ALLOW_CUSTOM_PYTHON_EXECUTION_IN_WORKFLOWS=True`\",\n                    context=\"workflow_execution | step_execution | dynamic_step\",\n                )\n            stdout_buf, stderr_buf = StringIO(), StringIO()\n            try:\n                with redirect_stdout(stdout_buf), redirect_stderr(stderr_buf):\n                    return run_function(self, *args, **kwargs)\n            except Exception as error:\n                raise _create_python_block_error(\n                    error,\n                    python_code,\n                    stdout=stdout_buf.getvalue() or None,\n                    stderr=stderr_buf.getvalue() or None,\n                ) from error\n\n    if python_code.init_function_code is not None and not hasattr(\n        code_module, python_code.init_function_name\n    ):\n        raise DynamicBlockError(\n            public_message=f\"Cannot find function: {python_code.init_function_name} in declared code for \"\n            f\"dynamic block: `{block_type_name}`\",\n            context=\"workflow_compilation | dynamic_block_compilation | declared_symbols_fetching\",\n        )\n\n    init_function = getattr(code_module, python_code.init_function_name, dict)\n\n    def constructor(self, api_key: Optional[str] = None):\n        self._init_results = init_function()\n        self._api_key = api_key\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"api_key\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return manifest\n\n    return type(\n        f\"DynamicBlock[{unique_identifier}]\",\n        (WorkflowBlock,),\n        {\n            \"__init__\": constructor,\n            \"get_init_parameters\": get_init_parameters,\n            \"get_manifest\": get_manifest,\n            \"run\": run,\n        },\n    )\n\n\ndef create_dynamic_module(\n    block_type_name: str,\n    python_code: PythonCode,\n    module_name: str,\n    api_key: Optional[str] = None,\n    skip_class_eval: Optional[bool] = False,\n) -> types.ModuleType:\n\n    if skip_class_eval:\n        code_key = None\n    else:\n        imports = _get_python_code_imports(python_code)\n        code = python_code.run_function_code\n        if python_code.init_function_code:\n            code += \"\\n\\n\" + python_code.init_function_code\n        code_key = imports + code\n\n    cache_key = (module_name, code_key, skip_class_eval, WORKFLOWS_CUSTOM_PYTHON_EXECUTION_MODE)\n\n    cached = _DYNAMIC_MODULE_CACHE.get(cache_key)\n    if cached is not None:\n        return cached\n\n    if skip_class_eval:\n        # Create a stub module for local reference\n        dynamic_module = types.ModuleType(module_name)\n        # Add placeholder function\n        setattr(\n            dynamic_module, python_code.run_function_name, lambda *args, **kwargs: None\n        )\n        if python_code.init_function_code:\n            setattr(dynamic_module, python_code.init_function_name, lambda: {})\n        _DYNAMIC_MODULE_CACHE[cache_key] = dynamic_module\n        return dynamic_module\n\n    # If using Modal and local execution is disabled, validate code remotely\n    if WORKFLOWS_CUSTOM_PYTHON_EXECUTION_MODE == \"modal\":\n        # Validate code in Modal sandbox for security\n        from inference.core.workflows.execution_engine.v1.dynamic_blocks.modal_executor import (\n            validate_code_in_modal,\n        )\n\n        try:  # Get workspace_id from context if available\n            validation_workspace = get_roboflow_workspace(api_key)\n        except WorkspaceLoadError:\n            validation_workspace = None\n\n        # Fall back to \"anonymous\" for non-authenticated users\n        if not validation_workspace:\n            validation_workspace = MODAL_ANONYMOUS_WORKSPACE_NAME\n\n        # This will raise if validation fails\n        validate_code_in_modal(python_code, validation_workspace)\n\n        # Create a stub module for local reference\n        dynamic_module = types.ModuleType(module_name)\n        # Add placeholder function\n        setattr(\n            dynamic_module, python_code.run_function_name, lambda *args, **kwargs: None\n        )\n        if python_code.init_function_code:\n            setattr(dynamic_module, python_code.init_function_name, lambda: {})\n        _DYNAMIC_MODULE_CACHE[cache_key] = dynamic_module\n        return dynamic_module\n    else:\n        # Local validation and module creation\n        try:\n            dynamic_module = types.ModuleType(module_name)\n            # Inject the shared globals dict into the module namespace\n            dynamic_module.__dict__[\"globals\"] = _LOCAL_SHARED_GLOBALS\n            exec(code_key, dynamic_module.__dict__)\n            _DYNAMIC_MODULE_CACHE[cache_key] = dynamic_module\n            return dynamic_module\n        except Exception as error:\n            error_line = getattr(error, \"lineno\", None)\n            code_snippet = None\n            if error_line and python_code.run_function_code:\n                snippet = extract_code_snippet(\n                    python_code.run_function_code, error_line\n                )\n                code_snippet = snippet.lstrip(\"\\n\") if snippet else None\n\n            raise PythonBlockError(\n                message=f\"{error.__class__.__name__}: {error}\",\n                block_type_name=block_type_name,\n                error_line=error_line,\n                code_snippet=code_snippet,\n            ) from error",
    "optimized_raw_markdown": "```python:inference/core/workflows/execution_engine/v1/dynamic_blocks/block_scaffolding.py\nimport types\nfrom contextlib import redirect_stderr, redirect_stdout\nfrom io import StringIO\nfrom typing import List, Optional, Type\n\nfrom inference.core.env import (ALLOW_CUSTOM_PYTHON_EXECUTION_IN_WORKFLOWS,\n                                MODAL_ANONYMOUS_WORKSPACE_NAME,\n                                WORKFLOWS_CUSTOM_PYTHON_EXECUTION_MODE)\nfrom inference.core.exceptions import WorkspaceLoadError\nfrom inference.core.roboflow_api import get_roboflow_workspace\nfrom inference.core.workflows.errors import (\n    DynamicBlockError, PythonBlockError, WorkflowEnvironmentConfigurationError)\nfrom inference.core.workflows.execution_engine.v1.dynamic_blocks.entities import \\\n    PythonCode\nfrom inference.core.workflows.prototypes.block import (BlockResult,\n                                                       WorkflowBlock,\n                                                       WorkflowBlockManifest)\n\nIMPORTS_LINES = [\n    \"from typing import Any, List, Dict, Set, Optional\",\n    \"import supervision as sv\",\n    \"import numpy as np\",\n    \"import math\",\n    \"import time\",\n    \"import json\",\n    \"import os\",\n    \"import requests\",\n    \"import cv2\",\n    \"import shapely\",\n    \"from inference.core.workflows.execution_engine.entities.base import Batch, WorkflowImageData\",\n    \"from inference.core.workflows.prototypes.block import BlockResult\",\n]\n\n# Shared globals dict for all custom python blocks in local mode\n_LOCAL_SHARED_GLOBALS = {}\n\n# Cache for created dynamic modules to avoid re-executing identical code\n_DYNAMIC_MODULE_CACHE: dict = {}\n\n\ndef assembly_custom_python_block(\n    block_type_name: str,\n    unique_identifier: str,\n    manifest: Type[WorkflowBlockManifest],\n    python_code: PythonCode,\n    api_key: Optional[str] = None,\n    skip_class_eval: Optional[bool] = False,\n) -> Type[WorkflowBlock]:\n\n    code_module = create_dynamic_module(\n        block_type_name=block_type_name,\n        python_code=python_code,\n        module_name=f\"dynamic_module_{unique_identifier}\",\n        api_key=api_key,\n        skip_class_eval=skip_class_eval,\n    )\n\n    if not hasattr(code_module, python_code.run_function_name):\n        raise DynamicBlockError(\n            public_message=f\"Cannot find function: {python_code.run_function_name} in declared code for \"\n            f\"dynamic block: `{block_type_name}`\",\n            context=\"workflow_compilation | dynamic_block_compilation | declared_symbols_fetching\",\n        )\n    run_function = getattr(code_module, python_code.run_function_name)\n\n    def run(self, *args, **kwargs) -> BlockResult:\n        # Check if we're using Modal remote execution\n        if WORKFLOWS_CUSTOM_PYTHON_EXECUTION_MODE == \"modal\":\n            # Remote execution via Modal - allowed even if local execution is disabled\n            from inference.core.workflows.execution_engine.v1.dynamic_blocks.modal_executor import \\\n                ModalExecutor\n\n            try:  # Get workspace_id from context if available\n                workspace_id = get_roboflow_workspace(self._api_key)\n            except WorkspaceLoadError:\n                workspace_id = None\n\n            # Fall back to \"anonymous\" for non-authenticated users\n            if not workspace_id:\n                workspace_id = MODAL_ANONYMOUS_WORKSPACE_NAME\n\n            executor = ModalExecutor(workspace_id)\n            return executor.execute_remote(\n                block_type_name=block_type_name,\n                python_code=python_code,\n                inputs=kwargs,\n                workspace_id=workspace_id,\n            )\n        else:\n            # Local execution - check if allowed\n            if not ALLOW_CUSTOM_PYTHON_EXECUTION_IN_WORKFLOWS:\n                raise WorkflowEnvironmentConfigurationError(\n                    public_message=\"Cannot use dynamic blocks with custom Python code in this installation of `workflows`. \"\n                    \"This can be changed by setting environmental variable \"\n                    \"`ALLOW_CUSTOM_PYTHON_EXECUTION_IN_WORKFLOWS=True`\",\n                    context=\"workflow_execution | step_execution | dynamic_step\",\n                )\n            stdout_buf, stderr_buf = StringIO(), StringIO()\n            try:\n                with redirect_stdout(stdout_buf), redirect_stderr(stderr_buf):\n                    return run_function(self, *args, **kwargs)\n            except Exception as error:\n                raise _create_python_block_error(\n                    error,\n                    python_code,\n                    stdout=stdout_buf.getvalue() or None,\n                    stderr=stderr_buf.getvalue() or None,\n                ) from error\n\n    if python_code.init_function_code is not None and not hasattr(\n        code_module, python_code.init_function_name\n    ):\n        raise DynamicBlockError(\n            public_message=f\"Cannot find function: {python_code.init_function_name} in declared code for \"\n            f\"dynamic block: `{block_type_name}`\",\n            context=\"workflow_compilation | dynamic_block_compilation | declared_symbols_fetching\",\n        )\n\n    init_function = getattr(code_module, python_code.init_function_name, dict)\n\n    def constructor(self, api_key: Optional[str] = None):\n        self._init_results = init_function()\n        self._api_key = api_key\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"api_key\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return manifest\n\n    return type(\n        f\"DynamicBlock[{unique_identifier}]\",\n        (WorkflowBlock,),\n        {\n            \"__init__\": constructor,\n            \"get_init_parameters\": get_init_parameters,\n            \"get_manifest\": get_manifest,\n            \"run\": run,\n        },\n    )\n\n\ndef create_dynamic_module(\n    block_type_name: str,\n    python_code: PythonCode,\n    module_name: str,\n    api_key: Optional[str] = None,\n    skip_class_eval: Optional[bool] = False,\n) -> types.ModuleType:\n\n    if skip_class_eval:\n        code_key = None\n    else:\n        imports = _get_python_code_imports(python_code)\n        code = python_code.run_function_code\n        if python_code.init_function_code:\n            code += \"\\n\\n\" + python_code.init_function_code\n        code_key = imports + code\n\n    cache_key = (module_name, code_key, skip_class_eval, WORKFLOWS_CUSTOM_PYTHON_EXECUTION_MODE)\n\n    cached = _DYNAMIC_MODULE_CACHE.get(cache_key)\n    if cached is not None:\n        return cached\n\n    if skip_class_eval:\n        # Create a stub module for local reference\n        dynamic_module = types.ModuleType(module_name)\n        # Add placeholder function\n        setattr(\n            dynamic_module, python_code.run_function_name, lambda *args, **kwargs: None\n        )\n        if python_code.init_function_code:\n            setattr(dynamic_module, python_code.init_function_name, lambda: {})\n        _DYNAMIC_MODULE_CACHE[cache_key] = dynamic_module\n        return dynamic_module\n\n    # If using Modal and local execution is disabled, validate code remotely\n    if WORKFLOWS_CUSTOM_PYTHON_EXECUTION_MODE == \"modal\":\n        # Validate code in Modal sandbox for security\n        from inference.core.workflows.execution_engine.v1.dynamic_blocks.modal_executor import (\n            validate_code_in_modal,\n        )\n\n        try:  # Get workspace_id from context if available\n            validation_workspace = get_roboflow_workspace(api_key)\n        except WorkspaceLoadError:\n            validation_workspace = None\n\n        # Fall back to \"anonymous\" for non-authenticated users\n        if not validation_workspace:\n            validation_workspace = MODAL_ANONYMOUS_WORKSPACE_NAME\n\n        # This will raise if validation fails\n        validate_code_in_modal(python_code, validation_workspace)\n\n        # Create a stub module for local reference\n        dynamic_module = types.ModuleType(module_name)\n        # Add placeholder function\n        setattr(\n            dynamic_module, python_code.run_function_name, lambda *args, **kwargs: None\n        )\n        if python_code.init_function_code:\n            setattr(dynamic_module, python_code.init_function_name, lambda: {})\n        _DYNAMIC_MODULE_CACHE[cache_key] = dynamic_module\n        return dynamic_module\n    else:\n        # Local validation and module creation\n        try:\n            dynamic_module = types.ModuleType(module_name)\n            # Inject the shared globals dict into the module namespace\n            dynamic_module.__dict__[\"globals\"] = _LOCAL_SHARED_GLOBALS\n            exec(code_key, dynamic_module.__dict__)\n            _DYNAMIC_MODULE_CACHE[cache_key] = dynamic_module\n            return dynamic_module\n        except Exception as error:\n            error_line = getattr(error, \"lineno\", None)\n            code_snippet = None\n            if error_line and python_code.run_function_code:\n                snippet = extract_code_snippet(\n                    python_code.run_function_code, error_line\n                )\n                code_snippet = snippet.lstrip(\"\\n\") if snippet else None\n\n            raise PythonBlockError(\n                message=f\"{error.__class__.__name__}: {error}\",\n                block_type_name=block_type_name,\n                error_line=error_line,\n                code_snippet=code_snippet,\n            ) from error\n```",
    "optimized_function_only": "def assembly_custom_python_block(\n    block_type_name: str,\n    unique_identifier: str,\n    manifest: Type[WorkflowBlockManifest],\n    python_code: PythonCode,\n    api_key: Optional[str] = None,\n    skip_class_eval: Optional[bool] = False,\n) -> Type[WorkflowBlock]:\n\n    code_module = create_dynamic_module(\n        block_type_name=block_type_name,\n        python_code=python_code,\n        module_name=f\"dynamic_module_{unique_identifier}\",\n        api_key=api_key,\n        skip_class_eval=skip_class_eval,\n    )\n\n    if not hasattr(code_module, python_code.run_function_name):\n        raise DynamicBlockError(\n            public_message=f\"Cannot find function: {python_code.run_function_name} in declared code for \"\n            f\"dynamic block: `{block_type_name}`\",\n            context=\"workflow_compilation | dynamic_block_compilation | declared_symbols_fetching\",\n        )\n    run_function = getattr(code_module, python_code.run_function_name)\n\n    def run(self, *args, **kwargs) -> BlockResult:\n        # Check if we're using Modal remote execution\n        if WORKFLOWS_CUSTOM_PYTHON_EXECUTION_MODE == \"modal\":\n            # Remote execution via Modal - allowed even if local execution is disabled\n            from inference.core.workflows.execution_engine.v1.dynamic_blocks.modal_executor import \\\n                ModalExecutor\n\n            try:  # Get workspace_id from context if available\n                workspace_id = get_roboflow_workspace(self._api_key)\n            except WorkspaceLoadError:\n                workspace_id = None\n\n            # Fall back to \"anonymous\" for non-authenticated users\n            if not workspace_id:\n                workspace_id = MODAL_ANONYMOUS_WORKSPACE_NAME\n\n            executor = ModalExecutor(workspace_id)\n            return executor.execute_remote(\n                block_type_name=block_type_name,\n                python_code=python_code,\n                inputs=kwargs,\n                workspace_id=workspace_id,\n            )\n        else:\n            # Local execution - check if allowed\n            if not ALLOW_CUSTOM_PYTHON_EXECUTION_IN_WORKFLOWS:\n                raise WorkflowEnvironmentConfigurationError(\n                    public_message=\"Cannot use dynamic blocks with custom Python code in this installation of `workflows`. \"\n                    \"This can be changed by setting environmental variable \"\n                    \"`ALLOW_CUSTOM_PYTHON_EXECUTION_IN_WORKFLOWS=True`\",\n                    context=\"workflow_execution | step_execution | dynamic_step\",\n                )\n            stdout_buf, stderr_buf = StringIO(), StringIO()\n            try:\n                with redirect_stdout(stdout_buf), redirect_stderr(stderr_buf):\n                    return run_function(self, *args, **kwargs)\n            except Exception as error:\n                raise _create_python_block_error(\n                    error,\n                    python_code,\n                    stdout=stdout_buf.getvalue() or None,\n                    stderr=stderr_buf.getvalue() or None,\n                ) from error\n\n    if python_code.init_function_code is not None and not hasattr(\n        code_module, python_code.init_function_name\n    ):\n        raise DynamicBlockError(\n            public_message=f\"Cannot find function: {python_code.init_function_name} in declared code for \"\n            f\"dynamic block: `{block_type_name}`\",\n            context=\"workflow_compilation | dynamic_block_compilation | declared_symbols_fetching\",\n        )\n\n    init_function = getattr(code_module, python_code.init_function_name, dict)\n\n    def constructor(self, api_key: Optional[str] = None):\n        self._init_results = init_function()\n        self._api_key = api_key\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"api_key\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return manifest\n\n    return type(\n        f\"DynamicBlock[{unique_identifier}]\",\n        (WorkflowBlock,),\n        {\n            \"__init__\": constructor,\n            \"get_init_parameters\": get_init_parameters,\n            \"get_manifest\": get_manifest,\n            \"run\": run,\n        },\n    )\n",
    "original_file_content": "import sys\nimport traceback\nimport types\nfrom contextlib import redirect_stderr, redirect_stdout\nfrom io import StringIO\nfrom typing import Any, Dict, List, Optional, Type\n\nfrom inference.core.env import (\n    ALLOW_CUSTOM_PYTHON_EXECUTION_IN_WORKFLOWS,\n    MODAL_ANONYMOUS_WORKSPACE_NAME,\n    WORKFLOWS_CUSTOM_PYTHON_EXECUTION_MODE,\n)\nfrom inference.core.exceptions import WorkspaceLoadError\nfrom inference.core.roboflow_api import get_roboflow_workspace\nfrom inference.core.workflows.errors import (\n    DynamicBlockError,\n    PythonBlockError,\n    WorkflowEnvironmentConfigurationError,\n)\nfrom inference.core.workflows.execution_engine.v1.dynamic_blocks.entities import (\n    PythonCode,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nIMPORTS_LINES = [\n    \"from typing import Any, List, Dict, Set, Optional\",\n    \"import supervision as sv\",\n    \"import numpy as np\",\n    \"import math\",\n    \"import time\",\n    \"import json\",\n    \"import os\",\n    \"import requests\",\n    \"import cv2\",\n    \"import shapely\",\n    \"from inference.core.workflows.execution_engine.entities.base import Batch, WorkflowImageData\",\n    \"from inference.core.workflows.prototypes.block import BlockResult\",\n]\n\n# Shared globals dict for all custom python blocks in local mode\n_LOCAL_SHARED_GLOBALS = {}\n\n\ndef extract_code_snippet(\n    code: Optional[str], error_line: int, context: int = 10\n) -> str:\n    \"\"\"Extract a code snippet around the error line with markers.\"\"\"\n    if not code:\n        return \"\"\n\n    lines = code.splitlines()\n    error_idx = error_line - 1\n    start = max(0, error_idx - context)\n    end = min(len(lines), error_idx + context + 1)\n    snippet_lines = [\n        f\"{'>>>' if i == error_idx else '   '} {i + 1}: {lines[i]}\"\n        for i in range(start, end)\n    ]\n    return \"\\n\" + \"\\n\".join(snippet_lines)\n\n\ndef build_traceback_string(\n    code: Optional[str],\n    line_number: int,\n    function_name: str,\n    error_type: str,\n    error_msg: str,\n) -> str:\n    \"\"\"Build a traceback string from structured error data.\"\"\"\n    code_lines = (code or \"\").splitlines()\n    code_line = (\n        code_lines[line_number - 1].strip()\n        if 0 < line_number <= len(code_lines)\n        else \"\"\n    )\n\n    lines = [\n        \"Traceback (most recent call last):\",\n        f'  File \"Python Block\", line {line_number}, in {function_name}',\n    ]\n    if code_line:\n        lines.append(f\"    {code_line}\")\n    lines.append(f\"{error_type}: {error_msg}\")\n    return \"\\n\".join(lines)\n\n\ndef _create_clean_traceback(\n    error: Exception, python_code: PythonCode, import_lines: int\n) -> str:\n    \"\"\"Create a clean traceback showing only user code with adjusted line numbers.\"\"\"\n    tb = traceback.extract_tb(error.__traceback__)\n    code_lines = (python_code.run_function_code or \"\").splitlines()\n\n    lines = [\"Traceback (most recent call last):\"]\n    for frame in tb:\n        if frame.filename == \"<string>\":\n            adjusted_line = frame.lineno - import_lines\n            code_line = (\n                code_lines[adjusted_line - 1]\n                if 0 < adjusted_line <= len(code_lines)\n                else \"\"\n            )\n            lines.append(\n                f'  File \"Python Block\", line {adjusted_line}, in {frame.name}'\n            )\n            if code_line:\n                lines.append(f\"    {code_line.strip()}\")\n\n    lines.append(f\"{error.__class__.__name__}: {error}\")\n    return \"\\n\".join(lines)\n\n\ndef _create_python_block_error(\n    error: Exception,\n    python_code: PythonCode,\n    stdout: Optional[str] = None,\n    stderr: Optional[str] = None,\n) -> PythonBlockError:\n    \"\"\"Create a PythonBlockError with structured code context.\"\"\"\n    tb = traceback.extract_tb(error.__traceback__)\n    if not tb:\n        return PythonBlockError(\n            f\"{error.__class__.__name__}: {error}\",\n            stdout=stdout,\n            stderr=stderr,\n        )\n\n    import_lines = len(_get_python_code_imports(python_code).splitlines())\n    frame = tb[-1]\n    line_number = frame.lineno - import_lines\n\n    code_snippet = extract_code_snippet(python_code.run_function_code, line_number)\n    message = f\"Error in line {line_number}, in {frame.name}: {error.__class__.__name__}: {error}\"\n    clean_traceback = _create_clean_traceback(error, python_code, import_lines)\n\n    return PythonBlockError(\n        message=message,\n        error_line=line_number,\n        code_snippet=code_snippet.lstrip(\"\\n\") if code_snippet else None,\n        traceback_str=clean_traceback,\n        stdout=stdout,\n        stderr=stderr,\n    )\n\n\ndef assembly_custom_python_block(\n    block_type_name: str,\n    unique_identifier: str,\n    manifest: Type[WorkflowBlockManifest],\n    python_code: PythonCode,\n    api_key: Optional[str] = None,\n    skip_class_eval: Optional[bool] = False,\n) -> Type[WorkflowBlock]:\n\n    code_module = create_dynamic_module(\n        block_type_name=block_type_name,\n        python_code=python_code,\n        module_name=f\"dynamic_module_{unique_identifier}\",\n        api_key=api_key,\n        skip_class_eval=skip_class_eval,\n    )\n\n    if not hasattr(code_module, python_code.run_function_name):\n        raise DynamicBlockError(\n            public_message=f\"Cannot find function: {python_code.run_function_name} in declared code for \"\n            f\"dynamic block: `{block_type_name}`\",\n            context=\"workflow_compilation | dynamic_block_compilation | declared_symbols_fetching\",\n        )\n    run_function = getattr(code_module, python_code.run_function_name)\n\n    def run(self, *args, **kwargs) -> BlockResult:\n        # Check if we're using Modal remote execution\n        if WORKFLOWS_CUSTOM_PYTHON_EXECUTION_MODE == \"modal\":\n            # Remote execution via Modal - allowed even if local execution is disabled\n            from inference.core.workflows.execution_engine.v1.dynamic_blocks.modal_executor import (\n                ModalExecutor,\n            )\n\n            try:  # Get workspace_id from context if available\n                workspace_id = get_roboflow_workspace(self._api_key)\n            except WorkspaceLoadError:\n                workspace_id = None\n\n            # Fall back to \"anonymous\" for non-authenticated users\n            if not workspace_id:\n                workspace_id = MODAL_ANONYMOUS_WORKSPACE_NAME\n\n            executor = ModalExecutor(workspace_id)\n            return executor.execute_remote(\n                block_type_name=block_type_name,\n                python_code=python_code,\n                inputs=kwargs,\n                workspace_id=workspace_id,\n            )\n        else:\n            # Local execution - check if allowed\n            if not ALLOW_CUSTOM_PYTHON_EXECUTION_IN_WORKFLOWS:\n                raise WorkflowEnvironmentConfigurationError(\n                    public_message=\"Cannot use dynamic blocks with custom Python code in this installation of `workflows`. \"\n                    \"This can be changed by setting environmental variable \"\n                    \"`ALLOW_CUSTOM_PYTHON_EXECUTION_IN_WORKFLOWS=True`\",\n                    context=\"workflow_execution | step_execution | dynamic_step\",\n                )\n            stdout_buf, stderr_buf = StringIO(), StringIO()\n            try:\n                with redirect_stdout(stdout_buf), redirect_stderr(stderr_buf):\n                    return run_function(self, *args, **kwargs)\n            except Exception as error:\n                raise _create_python_block_error(\n                    error,\n                    python_code,\n                    stdout=stdout_buf.getvalue() or None,\n                    stderr=stderr_buf.getvalue() or None,\n                ) from error\n\n    if python_code.init_function_code is not None and not hasattr(\n        code_module, python_code.init_function_name\n    ):\n        raise DynamicBlockError(\n            public_message=f\"Cannot find function: {python_code.init_function_name} in declared code for \"\n            f\"dynamic block: `{block_type_name}`\",\n            context=\"workflow_compilation | dynamic_block_compilation | declared_symbols_fetching\",\n        )\n\n    init_function = getattr(code_module, python_code.init_function_name, dict)\n\n    def constructor(self, api_key: Optional[str] = None):\n        self._init_results = init_function()\n        self._api_key = api_key\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"api_key\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return manifest\n\n    return type(\n        f\"DynamicBlock[{unique_identifier}]\",\n        (WorkflowBlock,),\n        {\n            \"__init__\": constructor,\n            \"get_init_parameters\": get_init_parameters,\n            \"get_manifest\": get_manifest,\n            \"run\": run,\n        },\n    )\n\n\ndef _get_python_code_imports(python_code: PythonCode) -> str:\n    return \"\\n\".join(IMPORTS_LINES) + \"\\n\" + \"\\n\".join(python_code.imports) + \"\\n\\n\"\n\n\ndef create_dynamic_module(\n    block_type_name: str,\n    python_code: PythonCode,\n    module_name: str,\n    api_key: Optional[str] = None,\n    skip_class_eval: Optional[bool] = False,\n) -> types.ModuleType:\n\n    if skip_class_eval:\n        # Create a stub module for local reference\n        dynamic_module = types.ModuleType(module_name)\n        # Add placeholder function\n        setattr(\n            dynamic_module, python_code.run_function_name, lambda *args, **kwargs: None\n        )\n        if python_code.init_function_code:\n            setattr(dynamic_module, python_code.init_function_name, lambda: {})\n        return dynamic_module\n\n    imports = _get_python_code_imports(python_code)\n    code = python_code.run_function_code\n    if python_code.init_function_code:\n        code += \"\\n\\n\" + python_code.init_function_code\n    code = imports + code\n\n    # If using Modal and local execution is disabled, validate code remotely\n    if WORKFLOWS_CUSTOM_PYTHON_EXECUTION_MODE == \"modal\":\n        # Validate code in Modal sandbox for security\n        from inference.core.workflows.execution_engine.v1.dynamic_blocks.modal_executor import (\n            validate_code_in_modal,\n        )\n\n        try:  # Get workspace_id from context if available\n            validation_workspace = get_roboflow_workspace(api_key)\n        except WorkspaceLoadError:\n            validation_workspace = None\n\n        # Fall back to \"anonymous\" for non-authenticated users\n        if not validation_workspace:\n            validation_workspace = MODAL_ANONYMOUS_WORKSPACE_NAME\n\n        # This will raise if validation fails\n        validate_code_in_modal(python_code, validation_workspace)\n\n        # Create a stub module for local reference\n        dynamic_module = types.ModuleType(module_name)\n        # Add placeholder function\n        setattr(\n            dynamic_module, python_code.run_function_name, lambda *args, **kwargs: None\n        )\n        if python_code.init_function_code:\n            setattr(dynamic_module, python_code.init_function_name, lambda: {})\n        return dynamic_module\n    else:\n        # Local validation and module creation\n        try:\n            dynamic_module = types.ModuleType(module_name)\n            # Inject the shared globals dict into the module namespace\n            dynamic_module.__dict__[\"globals\"] = _LOCAL_SHARED_GLOBALS\n            exec(code, dynamic_module.__dict__)\n            return dynamic_module\n        except Exception as error:\n            error_line = getattr(error, \"lineno\", None)\n            code_snippet = None\n            if error_line and python_code.run_function_code:\n                snippet = extract_code_snippet(\n                    python_code.run_function_code, error_line\n                )\n                code_snippet = snippet.lstrip(\"\\n\") if snippet else None\n\n            raise PythonBlockError(\n                message=f\"{error.__class__.__name__}: {error}\",\n                block_type_name=block_type_name,\n                error_line=error_line,\n                code_snippet=code_snippet,\n            ) from error\n",
    "patch": null
  },
  {
    "trace_id": "3bb32371-8480-4c4b-9a8f-5b3202516327",
    "function_name": "_create_clean_traceback",
    "file_path": "inference/core/workflows/execution_engine/v1/dynamic_blocks/block_scaffolding.py",
    "speedup_x": 2.22346460900176,
    "review_quality": "high",
    "pre_optimization_commit": "f4749c22a8a3beb6045796ed18c98d0e99a6657e",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def _create_clean_traceback(\n    error: Exception, python_code: PythonCode, import_lines: int\n) -> str:\n    \"\"\"Create a clean traceback showing only user code with adjusted line numbers.\"\"\"\n    tb = traceback.extract_tb(error.__traceback__)\n    code_lines = (python_code.run_function_code or \"\").splitlines()\n\n    lines = [\"Traceback (most recent call last):\"]\n    for frame in tb:\n        if frame.filename == \"<string>\":\n            adjusted_line = frame.lineno - import_lines\n            code_line = (\n                code_lines[adjusted_line - 1]\n                if 0 < adjusted_line <= len(code_lines)\n                else \"\"\n            )\n            lines.append(\n                f'  File \"Python Block\", line {adjusted_line}, in {frame.name}'\n            )\n            if code_line:\n                lines.append(f\"    {code_line.strip()}\")\n\n    lines.append(f\"{error.__class__.__name__}: {error}\")\n    return \"\\n\".join(lines)\n",
    "optimized_function_code": "import traceback\nfrom inference.core.workflows.execution_engine.v1.dynamic_blocks.entities import PythonCode\n\n\ndef _create_clean_traceback(\n    error: Exception, python_code: PythonCode, import_lines: int\n) -> str:\n    \"\"\"Create a clean traceback showing only user code with adjusted line numbers.\"\"\"\n    code_lines = (python_code.run_function_code or \"\").splitlines()\n\n    lines = [\"Traceback (most recent call last):\"]\n    \n    tb = error.__traceback__\n    while tb is not None:\n        frame = tb.tb_frame\n        if frame.f_code.co_filename == \"<string>\":\n            adjusted_line = tb.tb_lineno - import_lines\n            code_line = (\n                code_lines[adjusted_line - 1]\n                if 0 < adjusted_line <= len(code_lines)\n                else \"\"\n            )\n            lines.append(\n                f'  File \"Python Block\", line {adjusted_line}, in {frame.f_code.co_name}'\n            )\n            if code_line:\n                lines.append(f\"    {code_line.strip()}\")\n\n        tb = tb.tb_next\n\n    lines.append(f\"{error.__class__.__name__}: {error}\")\n    return \"\\n\".join(lines)",
    "optimized_raw_markdown": "```python:inference/core/workflows/execution_engine/v1/dynamic_blocks/block_scaffolding.py\nimport traceback\nfrom inference.core.workflows.execution_engine.v1.dynamic_blocks.entities import PythonCode\n\n\ndef _create_clean_traceback(\n    error: Exception, python_code: PythonCode, import_lines: int\n) -> str:\n    \"\"\"Create a clean traceback showing only user code with adjusted line numbers.\"\"\"\n    code_lines = (python_code.run_function_code or \"\").splitlines()\n\n    lines = [\"Traceback (most recent call last):\"]\n    \n    tb = error.__traceback__\n    while tb is not None:\n        frame = tb.tb_frame\n        if frame.f_code.co_filename == \"<string>\":\n            adjusted_line = tb.tb_lineno - import_lines\n            code_line = (\n                code_lines[adjusted_line - 1]\n                if 0 < adjusted_line <= len(code_lines)\n                else \"\"\n            )\n            lines.append(\n                f'  File \"Python Block\", line {adjusted_line}, in {frame.f_code.co_name}'\n            )\n            if code_line:\n                lines.append(f\"    {code_line.strip()}\")\n\n        tb = tb.tb_next\n\n    lines.append(f\"{error.__class__.__name__}: {error}\")\n    return \"\\n\".join(lines)\n```",
    "optimized_function_only": "def _create_clean_traceback(\n    error: Exception, python_code: PythonCode, import_lines: int\n) -> str:\n    \"\"\"Create a clean traceback showing only user code with adjusted line numbers.\"\"\"\n    code_lines = (python_code.run_function_code or \"\").splitlines()\n\n    lines = [\"Traceback (most recent call last):\"]\n    \n    tb = error.__traceback__\n    while tb is not None:\n        frame = tb.tb_frame\n        if frame.f_code.co_filename == \"<string>\":\n            adjusted_line = tb.tb_lineno - import_lines\n            code_line = (\n                code_lines[adjusted_line - 1]\n                if 0 < adjusted_line <= len(code_lines)\n                else \"\"\n            )\n            lines.append(\n                f'  File \"Python Block\", line {adjusted_line}, in {frame.f_code.co_name}'\n            )\n            if code_line:\n                lines.append(f\"    {code_line.strip()}\")\n\n        tb = tb.tb_next\n\n    lines.append(f\"{error.__class__.__name__}: {error}\")\n    return \"\\n\".join(lines)",
    "original_file_content": "import traceback\nimport types\nfrom typing import Any, Dict, List, Optional, Type\n\nfrom inference.core.env import (\n    ALLOW_CUSTOM_PYTHON_EXECUTION_IN_WORKFLOWS,\n    MODAL_ANONYMOUS_WORKSPACE_NAME,\n    WORKFLOWS_CUSTOM_PYTHON_EXECUTION_MODE,\n)\nfrom inference.core.exceptions import WorkspaceLoadError\nfrom inference.core.roboflow_api import get_roboflow_workspace\nfrom inference.core.workflows.errors import (\n    DynamicBlockCodeError,\n    DynamicBlockError,\n    WorkflowEnvironmentConfigurationError,\n)\nfrom inference.core.workflows.execution_engine.v1.dynamic_blocks.entities import (\n    PythonCode,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nIMPORTS_LINES = [\n    \"from typing import Any, List, Dict, Set, Optional\",\n    \"import supervision as sv\",\n    \"import numpy as np\",\n    \"import math\",\n    \"import time\",\n    \"import json\",\n    \"import os\",\n    \"import requests\",\n    \"import cv2\",\n    \"import shapely\",\n    \"from inference.core.workflows.execution_engine.entities.base import Batch, WorkflowImageData\",\n    \"from inference.core.workflows.prototypes.block import BlockResult\",\n]\n\n# Shared globals dict for all custom python blocks in local mode\n_LOCAL_SHARED_GLOBALS = {}\n\nfrom inference.core.workflows.execution_engine.v1.dynamic_blocks.error_utils import (\n    capture_output,\n    extract_code_snippet,\n)\n\n\ndef _create_clean_traceback(\n    error: Exception, python_code: PythonCode, import_lines: int\n) -> str:\n    \"\"\"Create a clean traceback showing only user code with adjusted line numbers.\"\"\"\n    tb = traceback.extract_tb(error.__traceback__)\n    code_lines = (python_code.run_function_code or \"\").splitlines()\n\n    lines = [\"Traceback (most recent call last):\"]\n    for frame in tb:\n        if frame.filename == \"<string>\":\n            adjusted_line = frame.lineno - import_lines\n            code_line = (\n                code_lines[adjusted_line - 1]\n                if 0 < adjusted_line <= len(code_lines)\n                else \"\"\n            )\n            lines.append(\n                f'  File \"Python Block\", line {adjusted_line}, in {frame.name}'\n            )\n            if code_line:\n                lines.append(f\"    {code_line.strip()}\")\n\n    lines.append(f\"{error.__class__.__name__}: {error}\")\n    return \"\\n\".join(lines)\n\n\ndef _create_dynamic_block_code_error(\n    error: Exception,\n    python_code: PythonCode,\n    stdout: Optional[str] = None,\n    stderr: Optional[str] = None,\n) -> DynamicBlockCodeError:\n    \"\"\"Create a DynamicBlockCodeError with structured code context.\"\"\"\n    tb = traceback.extract_tb(error.__traceback__)\n    if not tb:\n        return DynamicBlockCodeError(\n            public_message=f\"{error.__class__.__name__}: {error}\",\n            inner_error=error,\n            stdout=stdout,\n            stderr=stderr,\n        )\n\n    import_lines = len(_get_python_code_imports(python_code).splitlines())\n    frame = tb[-1]\n    line_number = frame.lineno - import_lines\n\n    code_snippet = extract_code_snippet(python_code.run_function_code, line_number)\n    message = f\"Error in line {line_number}, in {frame.name}: {error.__class__.__name__}: {error}\"\n    clean_traceback = _create_clean_traceback(error, python_code, import_lines)\n\n    return DynamicBlockCodeError(\n        public_message=message,\n        inner_error=error,\n        error_line=line_number,\n        code_snippet=code_snippet.lstrip(\"\\n\") if code_snippet else None,\n        traceback_str=clean_traceback,\n        stdout=stdout,\n        stderr=stderr,\n    )\n\n\ndef assembly_custom_python_block(\n    block_type_name: str,\n    unique_identifier: str,\n    manifest: Type[WorkflowBlockManifest],\n    python_code: PythonCode,\n    api_key: Optional[str] = None,\n    skip_class_eval: Optional[bool] = False,\n) -> Type[WorkflowBlock]:\n\n    code_module = create_dynamic_module(\n        block_type_name=block_type_name,\n        python_code=python_code,\n        module_name=f\"dynamic_module_{unique_identifier}\",\n        api_key=api_key,\n        skip_class_eval=skip_class_eval,\n    )\n\n    if not hasattr(code_module, python_code.run_function_name):\n        raise DynamicBlockError(\n            public_message=f\"Cannot find function: {python_code.run_function_name} in declared code for \"\n            f\"dynamic block: `{block_type_name}`\",\n            context=\"workflow_compilation | dynamic_block_compilation | declared_symbols_fetching\",\n        )\n    run_function = getattr(code_module, python_code.run_function_name)\n\n    def run(self, *args, **kwargs) -> BlockResult:\n        # Check if we're using Modal remote execution\n        if WORKFLOWS_CUSTOM_PYTHON_EXECUTION_MODE == \"modal\":\n            # Remote execution via Modal - allowed even if local execution is disabled\n            from inference.core.workflows.execution_engine.v1.dynamic_blocks.modal_executor import (\n                ModalExecutor,\n            )\n\n            try:  # Get workspace_id from context if available\n                workspace_id = get_roboflow_workspace(self._api_key)\n            except WorkspaceLoadError:\n                workspace_id = None\n\n            # Fall back to \"anonymous\" for non-authenticated users\n            if not workspace_id:\n                workspace_id = MODAL_ANONYMOUS_WORKSPACE_NAME\n\n            executor = ModalExecutor(workspace_id)\n            return executor.execute_remote(\n                block_type_name=block_type_name,\n                python_code=python_code,\n                inputs=kwargs,\n                workspace_id=workspace_id,\n            )\n            # TODO: also in modal!\n        else:\n            # Local execution - check if allowed\n            if not ALLOW_CUSTOM_PYTHON_EXECUTION_IN_WORKFLOWS:\n                raise WorkflowEnvironmentConfigurationError(\n                    public_message=\"Cannot use dynamic blocks with custom Python code in this installation of `workflows`. \"\n                    \"This can be changed by setting environmental variable \"\n                    \"`ALLOW_CUSTOM_PYTHON_EXECUTION_IN_WORKFLOWS=True`\",\n                    context=\"workflow_execution | step_execution | dynamic_step\",\n                )\n            try:\n                with capture_output() as (stdout_buf, stderr_buf):\n                    return run_function(self, *args, **kwargs)\n            except Exception as error:\n                raise _create_dynamic_block_code_error(\n                    error,\n                    python_code,\n                    stdout=stdout_buf.getvalue() or None,\n                    stderr=stderr_buf.getvalue() or None,\n                ) from error\n\n    if python_code.init_function_code is not None and not hasattr(\n        code_module, python_code.init_function_name\n    ):\n        raise DynamicBlockError(\n            public_message=f\"Cannot find function: {python_code.init_function_name} in declared code for \"\n            f\"dynamic block: `{block_type_name}`\",\n            context=\"workflow_compilation | dynamic_block_compilation | declared_symbols_fetching\",\n        )\n\n    init_function = getattr(code_module, python_code.init_function_name, dict)\n\n    def constructor(self, api_key: Optional[str] = None):\n        self._init_results = init_function()\n        self._api_key = api_key\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"api_key\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return manifest\n\n    return type(\n        f\"DynamicBlock[{unique_identifier}]\",\n        (WorkflowBlock,),\n        {\n            \"__init__\": constructor,\n            \"get_init_parameters\": get_init_parameters,\n            \"get_manifest\": get_manifest,\n            \"run\": run,\n        },\n    )\n\n\ndef _get_python_code_imports(python_code: PythonCode) -> str:\n    return \"\\n\".join(IMPORTS_LINES) + \"\\n\" + \"\\n\".join(python_code.imports) + \"\\n\\n\"\n\n\ndef create_dynamic_module(\n    block_type_name: str,\n    python_code: PythonCode,\n    module_name: str,\n    api_key: Optional[str] = None,\n    skip_class_eval: Optional[bool] = False,\n) -> types.ModuleType:\n\n    if skip_class_eval:\n        # Create a stub module for local reference\n        dynamic_module = types.ModuleType(module_name)\n        # Add placeholder function\n        setattr(\n            dynamic_module, python_code.run_function_name, lambda *args, **kwargs: None\n        )\n        if python_code.init_function_code:\n            setattr(dynamic_module, python_code.init_function_name, lambda: {})\n        return dynamic_module\n\n    imports = _get_python_code_imports(python_code)\n    code = python_code.run_function_code\n    if python_code.init_function_code:\n        code += \"\\n\\n\" + python_code.init_function_code\n    code = imports + code\n\n    # If using Modal and local execution is disabled, validate code remotely\n    if WORKFLOWS_CUSTOM_PYTHON_EXECUTION_MODE == \"modal\":\n        # Validate code in Modal sandbox for security\n        from inference.core.workflows.execution_engine.v1.dynamic_blocks.modal_executor import (\n            validate_code_in_modal,\n        )\n\n        try:  # Get workspace_id from context if available\n            validation_workspace = get_roboflow_workspace(api_key)\n        except WorkspaceLoadError:\n            validation_workspace = None\n\n        # Fall back to \"anonymous\" for non-authenticated users\n        if not validation_workspace:\n            validation_workspace = MODAL_ANONYMOUS_WORKSPACE_NAME\n\n        # This will raise if validation fails\n        validate_code_in_modal(python_code, validation_workspace)\n\n        # Create a stub module for local reference\n        dynamic_module = types.ModuleType(module_name)\n        # Add placeholder function\n        setattr(\n            dynamic_module, python_code.run_function_name, lambda *args, **kwargs: None\n        )\n        if python_code.init_function_code:\n            setattr(dynamic_module, python_code.init_function_name, lambda: {})\n        return dynamic_module\n    else:\n        # Local validation and module creation\n        try:\n            dynamic_module = types.ModuleType(module_name)\n            # Inject the shared globals dict into the module namespace\n            dynamic_module.__dict__[\"globals\"] = _LOCAL_SHARED_GLOBALS\n            exec(code, dynamic_module.__dict__)\n            return dynamic_module\n        except Exception as error:\n            error_line = getattr(error, \"lineno\", None)\n            code_snippet = None\n            if error_line and python_code.run_function_code:\n                import_lines_offset = len(\n                    _get_python_code_imports(python_code).splitlines()\n                )\n                error_line -= import_lines_offset\n                snippet = extract_code_snippet(\n                    python_code.run_function_code, error_line\n                )\n                code_snippet = snippet.lstrip(\"\\n\") if snippet else None\n\n            raise DynamicBlockCodeError(\n                public_message=f\"{error.__class__.__name__}: {error}\",\n                context=\"dynamic_block_code_compilation\",\n                inner_error=error,\n                block_type_name=block_type_name,\n                error_line=error_line,\n                code_snippet=code_snippet,\n            ) from error\n",
    "patch": null
  },
  {
    "trace_id": "9dccafb2-d29d-4786-9a1c-289aad7056b3",
    "function_name": "build_traceback_string",
    "file_path": "inference/core/workflows/execution_engine/v1/dynamic_blocks/block_scaffolding.py",
    "speedup_x": 12.379741533450494,
    "review_quality": "high",
    "pre_optimization_commit": "6a5fec1e3ee3fc67f02b4810039100c99dc65f59",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def build_traceback_string(\n    code: Optional[str],\n    line_number: int,\n    function_name: str,\n    error_type: str,\n    error_msg: str,\n) -> str:\n    \"\"\"Build a traceback string from structured error data.\"\"\"\n    code_lines = (code or \"\").splitlines()\n    code_line = (\n        code_lines[line_number - 1].strip()\n        if 0 < line_number <= len(code_lines)\n        else \"\"\n    )\n\n    lines = [\n        \"Traceback (most recent call last):\",\n        f'  File \"Python Block\", line {line_number}, in {function_name}',\n    ]\n    if code_line:\n        lines.append(f\"    {code_line}\")\n    lines.append(f\"{error_type}: {error_msg}\")\n    return \"\\n\".join(lines)\n",
    "optimized_function_code": "from functools import lru_cache\nfrom typing import Optional\n\n\n@lru_cache(maxsize=128)\ndef _cached_splitlines(code: str) -> list[str]:\n    # Cache splitlines results for recently-seen code strings to avoid\n    # repeated allocation of identical lists across many calls.\n    return code.splitlines()\n\ndef build_traceback_string(\n    code: Optional[str],\n    line_number: int,\n    function_name: str,\n    error_type: str,\n    error_msg: str,\n) -> str:\n    \"\"\"Build a traceback string from structured error data.\"\"\"\n    # Use cached splitlines for performance when same code string recurs.\n    code_lines = _cached_splitlines((code or \"\"))\n    code_line = (\n        code_lines[line_number - 1].strip()\n        if 0 < line_number <= len(code_lines)\n        else \"\"\n    )\n\n    lines = [\n        \"Traceback (most recent call last):\",\n        f'  File \"Python Block\", line {line_number}, in {function_name}',\n    ]\n    if code_line:\n        lines.append(f\"    {code_line}\")\n    lines.append(f\"{error_type}: {error_msg}\")\n    return \"\\n\".join(lines)",
    "optimized_raw_markdown": "```python:inference/core/workflows/execution_engine/v1/dynamic_blocks/block_scaffolding.py\nfrom functools import lru_cache\nfrom typing import Optional\n\n\n@lru_cache(maxsize=128)\ndef _cached_splitlines(code: str) -> list[str]:\n    # Cache splitlines results for recently-seen code strings to avoid\n    # repeated allocation of identical lists across many calls.\n    return code.splitlines()\n\ndef build_traceback_string(\n    code: Optional[str],\n    line_number: int,\n    function_name: str,\n    error_type: str,\n    error_msg: str,\n) -> str:\n    \"\"\"Build a traceback string from structured error data.\"\"\"\n    # Use cached splitlines for performance when same code string recurs.\n    code_lines = _cached_splitlines((code or \"\"))\n    code_line = (\n        code_lines[line_number - 1].strip()\n        if 0 < line_number <= len(code_lines)\n        else \"\"\n    )\n\n    lines = [\n        \"Traceback (most recent call last):\",\n        f'  File \"Python Block\", line {line_number}, in {function_name}',\n    ]\n    if code_line:\n        lines.append(f\"    {code_line}\")\n    lines.append(f\"{error_type}: {error_msg}\")\n    return \"\\n\".join(lines)\n```",
    "optimized_function_only": "def build_traceback_string(\n    code: Optional[str],\n    line_number: int,\n    function_name: str,\n    error_type: str,\n    error_msg: str,\n) -> str:\n    \"\"\"Build a traceback string from structured error data.\"\"\"\n    # Use cached splitlines for performance when same code string recurs.\n    code_lines = _cached_splitlines((code or \"\"))\n    code_line = (\n        code_lines[line_number - 1].strip()\n        if 0 < line_number <= len(code_lines)\n        else \"\"\n    )\n\n    lines = [\n        \"Traceback (most recent call last):\",\n        f'  File \"Python Block\", line {line_number}, in {function_name}',\n    ]\n    if code_line:\n        lines.append(f\"    {code_line}\")\n    lines.append(f\"{error_type}: {error_msg}\")\n    return \"\\n\".join(lines)",
    "original_file_content": "import sys\nimport traceback\nimport types\nfrom contextlib import redirect_stderr, redirect_stdout\nfrom io import StringIO\nfrom typing import Any, Dict, List, Optional, Type\n\nfrom inference.core.env import (\n    ALLOW_CUSTOM_PYTHON_EXECUTION_IN_WORKFLOWS,\n    MODAL_ANONYMOUS_WORKSPACE_NAME,\n    WORKFLOWS_CUSTOM_PYTHON_EXECUTION_MODE,\n)\nfrom inference.core.exceptions import WorkspaceLoadError\nfrom inference.core.roboflow_api import get_roboflow_workspace\nfrom inference.core.workflows.errors import (\n    DynamicBlockError,\n    PythonBlockError,\n    WorkflowEnvironmentConfigurationError,\n)\nfrom inference.core.workflows.execution_engine.v1.dynamic_blocks.entities import (\n    PythonCode,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nIMPORTS_LINES = [\n    \"from typing import Any, List, Dict, Set, Optional\",\n    \"import supervision as sv\",\n    \"import numpy as np\",\n    \"import math\",\n    \"import time\",\n    \"import json\",\n    \"import os\",\n    \"import requests\",\n    \"import cv2\",\n    \"import shapely\",\n    \"from inference.core.workflows.execution_engine.entities.base import Batch, WorkflowImageData\",\n    \"from inference.core.workflows.prototypes.block import BlockResult\",\n]\n\n# Shared globals dict for all custom python blocks in local mode\n_LOCAL_SHARED_GLOBALS = {}\n\n\ndef extract_code_snippet(\n    code: Optional[str], error_line: int, context: int = 10\n) -> str:\n    \"\"\"Extract a code snippet around the error line with markers.\"\"\"\n    if not code:\n        return \"\"\n\n    lines = code.splitlines()\n    error_idx = error_line - 1\n    start = max(0, error_idx - context)\n    end = min(len(lines), error_idx + context + 1)\n    snippet_lines = [\n        f\"{'>>>' if i == error_idx else '   '} {i + 1}: {lines[i]}\"\n        for i in range(start, end)\n    ]\n    return \"\\n\" + \"\\n\".join(snippet_lines)\n\n\ndef build_traceback_string(\n    code: Optional[str],\n    line_number: int,\n    function_name: str,\n    error_type: str,\n    error_msg: str,\n) -> str:\n    \"\"\"Build a traceback string from structured error data.\"\"\"\n    code_lines = (code or \"\").splitlines()\n    code_line = (\n        code_lines[line_number - 1].strip()\n        if 0 < line_number <= len(code_lines)\n        else \"\"\n    )\n\n    lines = [\n        \"Traceback (most recent call last):\",\n        f'  File \"Python Block\", line {line_number}, in {function_name}',\n    ]\n    if code_line:\n        lines.append(f\"    {code_line}\")\n    lines.append(f\"{error_type}: {error_msg}\")\n    return \"\\n\".join(lines)\n\n\ndef _create_clean_traceback(\n    error: Exception, python_code: PythonCode, import_lines: int\n) -> str:\n    \"\"\"Create a clean traceback showing only user code with adjusted line numbers.\"\"\"\n    tb = traceback.extract_tb(error.__traceback__)\n    code_lines = (python_code.run_function_code or \"\").splitlines()\n\n    lines = [\"Traceback (most recent call last):\"]\n    for frame in tb:\n        if frame.filename == \"<string>\":\n            adjusted_line = frame.lineno - import_lines\n            code_line = (\n                code_lines[adjusted_line - 1]\n                if 0 < adjusted_line <= len(code_lines)\n                else \"\"\n            )\n            lines.append(\n                f'  File \"Python Block\", line {adjusted_line}, in {frame.name}'\n            )\n            if code_line:\n                lines.append(f\"    {code_line.strip()}\")\n\n    lines.append(f\"{error.__class__.__name__}: {error}\")\n    return \"\\n\".join(lines)\n\n\ndef _create_python_block_error(\n    error: Exception,\n    python_code: PythonCode,\n    stdout: Optional[str] = None,\n    stderr: Optional[str] = None,\n) -> PythonBlockError:\n    \"\"\"Create a PythonBlockError with structured code context.\"\"\"\n    tb = traceback.extract_tb(error.__traceback__)\n    if not tb:\n        return PythonBlockError(\n            f\"{error.__class__.__name__}: {error}\",\n            stdout=stdout,\n            stderr=stderr,\n        )\n\n    import_lines = len(_get_python_code_imports(python_code).splitlines())\n    frame = tb[-1]\n    line_number = frame.lineno - import_lines\n\n    code_snippet = extract_code_snippet(python_code.run_function_code, line_number)\n    message = f\"Error in line {line_number}, in {frame.name}: {error.__class__.__name__}: {error}\"\n    clean_traceback = _create_clean_traceback(error, python_code, import_lines)\n\n    return PythonBlockError(\n        message=message,\n        error_line=line_number,\n        code_snippet=code_snippet.lstrip(\"\\n\") if code_snippet else None,\n        traceback_str=clean_traceback,\n        stdout=stdout,\n        stderr=stderr,\n    )\n\n\ndef assembly_custom_python_block(\n    block_type_name: str,\n    unique_identifier: str,\n    manifest: Type[WorkflowBlockManifest],\n    python_code: PythonCode,\n    api_key: Optional[str] = None,\n    skip_class_eval: Optional[bool] = False,\n) -> Type[WorkflowBlock]:\n\n    code_module = create_dynamic_module(\n        block_type_name=block_type_name,\n        python_code=python_code,\n        module_name=f\"dynamic_module_{unique_identifier}\",\n        api_key=api_key,\n        skip_class_eval=skip_class_eval,\n    )\n\n    if not hasattr(code_module, python_code.run_function_name):\n        raise DynamicBlockError(\n            public_message=f\"Cannot find function: {python_code.run_function_name} in declared code for \"\n            f\"dynamic block: `{block_type_name}`\",\n            context=\"workflow_compilation | dynamic_block_compilation | declared_symbols_fetching\",\n        )\n    run_function = getattr(code_module, python_code.run_function_name)\n\n    def run(self, *args, **kwargs) -> BlockResult:\n        # Check if we're using Modal remote execution\n        if WORKFLOWS_CUSTOM_PYTHON_EXECUTION_MODE == \"modal\":\n            # Remote execution via Modal - allowed even if local execution is disabled\n            from inference.core.workflows.execution_engine.v1.dynamic_blocks.modal_executor import (\n                ModalExecutor,\n            )\n\n            try:  # Get workspace_id from context if available\n                workspace_id = get_roboflow_workspace(self._api_key)\n            except WorkspaceLoadError:\n                workspace_id = None\n\n            # Fall back to \"anonymous\" for non-authenticated users\n            if not workspace_id:\n                workspace_id = MODAL_ANONYMOUS_WORKSPACE_NAME\n\n            executor = ModalExecutor(workspace_id)\n            return executor.execute_remote(\n                block_type_name=block_type_name,\n                python_code=python_code,\n                inputs=kwargs,\n                workspace_id=workspace_id,\n            )\n        else:\n            # Local execution - check if allowed\n            if not ALLOW_CUSTOM_PYTHON_EXECUTION_IN_WORKFLOWS:\n                raise WorkflowEnvironmentConfigurationError(\n                    public_message=\"Cannot use dynamic blocks with custom Python code in this installation of `workflows`. \"\n                    \"This can be changed by setting environmental variable \"\n                    \"`ALLOW_CUSTOM_PYTHON_EXECUTION_IN_WORKFLOWS=True`\",\n                    context=\"workflow_execution | step_execution | dynamic_step\",\n                )\n            stdout_buf, stderr_buf = StringIO(), StringIO()\n            try:\n                with redirect_stdout(stdout_buf), redirect_stderr(stderr_buf):\n                    return run_function(self, *args, **kwargs)\n            except Exception as error:\n                raise _create_python_block_error(\n                    error,\n                    python_code,\n                    stdout=stdout_buf.getvalue() or None,\n                    stderr=stderr_buf.getvalue() or None,\n                ) from error\n\n    if python_code.init_function_code is not None and not hasattr(\n        code_module, python_code.init_function_name\n    ):\n        raise DynamicBlockError(\n            public_message=f\"Cannot find function: {python_code.init_function_name} in declared code for \"\n            f\"dynamic block: `{block_type_name}`\",\n            context=\"workflow_compilation | dynamic_block_compilation | declared_symbols_fetching\",\n        )\n\n    init_function = getattr(code_module, python_code.init_function_name, dict)\n\n    def constructor(self, api_key: Optional[str] = None):\n        self._init_results = init_function()\n        self._api_key = api_key\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"api_key\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return manifest\n\n    return type(\n        f\"DynamicBlock[{unique_identifier}]\",\n        (WorkflowBlock,),\n        {\n            \"__init__\": constructor,\n            \"get_init_parameters\": get_init_parameters,\n            \"get_manifest\": get_manifest,\n            \"run\": run,\n        },\n    )\n\n\ndef _get_python_code_imports(python_code: PythonCode) -> str:\n    return \"\\n\".join(IMPORTS_LINES) + \"\\n\" + \"\\n\".join(python_code.imports) + \"\\n\\n\"\n\n\ndef create_dynamic_module(\n    block_type_name: str,\n    python_code: PythonCode,\n    module_name: str,\n    api_key: Optional[str] = None,\n    skip_class_eval: Optional[bool] = False,\n) -> types.ModuleType:\n\n    if skip_class_eval:\n        # Create a stub module for local reference\n        dynamic_module = types.ModuleType(module_name)\n        # Add placeholder function\n        setattr(\n            dynamic_module, python_code.run_function_name, lambda *args, **kwargs: None\n        )\n        if python_code.init_function_code:\n            setattr(dynamic_module, python_code.init_function_name, lambda: {})\n        return dynamic_module\n\n    imports = _get_python_code_imports(python_code)\n    code = python_code.run_function_code\n    if python_code.init_function_code:\n        code += \"\\n\\n\" + python_code.init_function_code\n    code = imports + code\n\n    # If using Modal and local execution is disabled, validate code remotely\n    if WORKFLOWS_CUSTOM_PYTHON_EXECUTION_MODE == \"modal\":\n        # Validate code in Modal sandbox for security\n        from inference.core.workflows.execution_engine.v1.dynamic_blocks.modal_executor import (\n            validate_code_in_modal,\n        )\n\n        try:  # Get workspace_id from context if available\n            validation_workspace = get_roboflow_workspace(api_key)\n        except WorkspaceLoadError:\n            validation_workspace = None\n\n        # Fall back to \"anonymous\" for non-authenticated users\n        if not validation_workspace:\n            validation_workspace = MODAL_ANONYMOUS_WORKSPACE_NAME\n\n        # This will raise if validation fails\n        validate_code_in_modal(python_code, validation_workspace)\n\n        # Create a stub module for local reference\n        dynamic_module = types.ModuleType(module_name)\n        # Add placeholder function\n        setattr(\n            dynamic_module, python_code.run_function_name, lambda *args, **kwargs: None\n        )\n        if python_code.init_function_code:\n            setattr(dynamic_module, python_code.init_function_name, lambda: {})\n        return dynamic_module\n    else:\n        # Local validation and module creation\n        try:\n            dynamic_module = types.ModuleType(module_name)\n            # Inject the shared globals dict into the module namespace\n            dynamic_module.__dict__[\"globals\"] = _LOCAL_SHARED_GLOBALS\n            exec(code, dynamic_module.__dict__)\n            return dynamic_module\n        except Exception as error:\n            error_line = getattr(error, \"lineno\", None)\n            code_snippet = None\n            if error_line and python_code.run_function_code:\n                snippet = extract_code_snippet(\n                    python_code.run_function_code, error_line\n                )\n                code_snippet = snippet.lstrip(\"\\n\") if snippet else None\n\n            raise PythonBlockError(\n                message=f\"{error.__class__.__name__}: {error}\",\n                block_type_name=block_type_name,\n                error_line=error_line,\n                code_snippet=code_snippet,\n            ) from error\n",
    "patch": null
  },
  {
    "trace_id": "6d52698f-0731-4950-9253-629642ebd587",
    "function_name": "_build_step_execution_error_response",
    "file_path": "inference/core/interfaces/http/error_handlers.py",
    "speedup_x": 0.1852846448642689,
    "review_quality": "high",
    "pre_optimization_commit": "6a5fec1e3ee3fc67f02b4810039100c99dc65f59",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def _build_step_execution_error_response(\n    error: StepExecutionError,\n) -> \"WorkflowErrorResponse\":\n    \"\"\"Build a WorkflowErrorResponse for StepExecutionError (runtime errors).\"\"\"\n    from inference.core.entities.responses.workflows import WorkflowErrorResponse\n\n    return WorkflowErrorResponse(\n        message=str(error.public_message),\n        error_type=error.__class__.__name__,\n        context=str(error.context),\n        inner_error_type=str(error.inner_error_type),\n        inner_error_message=str(error.inner_error),\n        blocks_errors=[\n            WorkflowBlockError(\n                block_id=error.block_id,\n                block_type=error.block_type,\n                property_name=\"Python code\",\n                property_details=str(error.inner_error),\n                block_traceback=error.block_traceback,\n            ),\n        ],\n    )\n",
    "optimized_function_code": "from inference.core.entities.responses.workflows import WorkflowErrorResponse\nfrom inference.core.workflows.errors import (StepExecutionError,\n                                             WorkflowBlockError)\n\n\ndef _build_step_execution_error_response(\n    error: StepExecutionError,\n) -> \"WorkflowErrorResponse\":\n    \"\"\"Build a WorkflowErrorResponse for StepExecutionError (runtime errors).\"\"\"\n\n    return WorkflowErrorResponse(\n        message=str(error.public_message),\n        error_type=error.__class__.__name__,\n        context=str(error.context),\n        inner_error_type=str(error.inner_error_type),\n        inner_error_message=str(error.inner_error),\n        blocks_errors=[\n            {\n                \"block_id\": error.block_id,\n                \"block_type\": error.block_type,\n                \"property_name\": \"Python code\",\n                \"property_details\": str(error.inner_error),\n                \"block_traceback\": error.block_traceback,\n            },\n        ],\n    )",
    "optimized_raw_markdown": "```python:inference/core/interfaces/http/error_handlers.py\nfrom inference.core.entities.responses.workflows import WorkflowErrorResponse\nfrom inference.core.workflows.errors import (StepExecutionError,\n                                             WorkflowBlockError)\n\n\ndef _build_step_execution_error_response(\n    error: StepExecutionError,\n) -> \"WorkflowErrorResponse\":\n    \"\"\"Build a WorkflowErrorResponse for StepExecutionError (runtime errors).\"\"\"\n\n    return WorkflowErrorResponse(\n        message=str(error.public_message),\n        error_type=error.__class__.__name__,\n        context=str(error.context),\n        inner_error_type=str(error.inner_error_type),\n        inner_error_message=str(error.inner_error),\n        blocks_errors=[\n            {\n                \"block_id\": error.block_id,\n                \"block_type\": error.block_type,\n                \"property_name\": \"Python code\",\n                \"property_details\": str(error.inner_error),\n                \"block_traceback\": error.block_traceback,\n            },\n        ],\n    )\n```",
    "optimized_function_only": "def _build_step_execution_error_response(\n    error: StepExecutionError,\n) -> \"WorkflowErrorResponse\":\n    \"\"\"Build a WorkflowErrorResponse for StepExecutionError (runtime errors).\"\"\"\n\n    return WorkflowErrorResponse(\n        message=str(error.public_message),\n        error_type=error.__class__.__name__,\n        context=str(error.context),\n        inner_error_type=str(error.inner_error_type),\n        inner_error_message=str(error.inner_error),\n        blocks_errors=[\n            {\n                \"block_id\": error.block_id,\n                \"block_type\": error.block_type,\n                \"property_name\": \"Python code\",\n                \"property_details\": str(error.inner_error),\n                \"block_traceback\": error.block_traceback,\n            },\n        ],\n    )",
    "original_file_content": "from functools import wraps\n\nfrom starlette.responses import JSONResponse\n\nfrom inference.core import logger\nfrom inference.core.entities.responses.workflows import WorkflowErrorResponse\nfrom inference.core.exceptions import (\n    ContentTypeInvalid,\n    ContentTypeMissing,\n    CreditsExceededError,\n    InferenceModelNotFound,\n    InputImageLoadError,\n    InvalidEnvironmentVariableError,\n    InvalidMaskDecodeArgument,\n    InvalidModelIDError,\n    MalformedRoboflowAPIResponseError,\n    MalformedWorkflowResponseError,\n    MissingApiKeyError,\n    MissingServiceSecretError,\n    ModelArtefactError,\n    ModelManagerLockAcquisitionError,\n    OnnxProviderNotAvailable,\n    PostProcessingError,\n    PreProcessingError,\n    RoboflowAPIConnectionError,\n    RoboflowAPIForbiddenError,\n    RoboflowAPINotAuthorizedError,\n    RoboflowAPINotNotFoundError,\n    RoboflowAPITimeoutError,\n    RoboflowAPIUnsuccessfulRequestError,\n    ServiceConfigurationError,\n    WebRTCConfigurationError,\n    WorkspaceLoadError,\n)\nfrom inference.core.interfaces.stream_manager.api.errors import (\n    ProcessesManagerAuthorisationError,\n    ProcessesManagerClientError,\n    ProcessesManagerInvalidPayload,\n    ProcessesManagerNotFoundError,\n)\nfrom inference.core.interfaces.stream_manager.manager_app.errors import (\n    CommunicationProtocolError,\n    MalformedPayloadError,\n    MessageToBigError,\n)\nfrom inference.core.workflows.core_steps.common.query_language.errors import (\n    InvalidInputTypeError,\n    OperationTypeNotRecognisedError,\n)\nfrom inference.core.workflows.errors import (\n    BlockTraceback,\n    ClientCausedStepExecutionError,\n    DynamicBlockError,\n    ExecutionGraphStructureError,\n    InvalidReferenceTargetError,\n    NotSupportedExecutionEngineError,\n    PythonBlockError,\n    ReferenceTypeError,\n    RuntimeInputError,\n    StepExecutionError,\n    StepInputDimensionalityError,\n    WorkflowBlockError,\n    WorkflowDefinitionError,\n    WorkflowError,\n    WorkflowExecutionEngineVersionError,\n    WorkflowSyntaxError,\n)\nfrom inference_models.errors import (\n    EnvironmentConfigurationError,\n    FileHashSumMissmatch,\n    InvalidEnvVariable,\n    InvalidParameterError,\n    JetsonTypeResolutionError,\n    MissingDependencyError,\n    ModelInputError,\n    ModelLoadingError,\n    ModelNotFoundError,\n    ModelPackageNegotiationError,\n    ModelRetrievalError,\n    UnauthorizedModelAccessError,\n    UntrustedFileError,\n)\n\n\ndef _build_python_block_error_response(\n    error: PythonBlockError,\n) -> \"WorkflowErrorResponse\":\n    \"\"\"Build a WorkflowErrorResponse for PythonBlockError (compilation errors).\"\"\"\n    from inference.core.entities.responses.workflows import WorkflowErrorResponse\n\n    return WorkflowErrorResponse(\n        message=\"Python code compilation failed. See block details below.\",\n        error_type=error.__class__.__name__,\n        context=\"workflow_compilation | python_code\",\n        inner_error_type=error.__class__.__name__,\n        inner_error_message=str(error),\n        blocks_errors=[\n            WorkflowBlockError(\n                block_id=error.block_type_name or \"Python Block\",\n                block_type=error.block_type_name,\n                property_name=\"Python code\",\n                property_details=str(error),\n                block_traceback=(\n                    BlockTraceback(\n                        error_line=error.error_line,\n                        code_snippet=error.code_snippet,\n                    )\n                    if error.error_line\n                    else None\n                ),\n            ),\n        ],\n    )\n\n\ndef _build_step_execution_error_response(\n    error: StepExecutionError,\n) -> \"WorkflowErrorResponse\":\n    \"\"\"Build a WorkflowErrorResponse for StepExecutionError (runtime errors).\"\"\"\n    from inference.core.entities.responses.workflows import WorkflowErrorResponse\n\n    return WorkflowErrorResponse(\n        message=str(error.public_message),\n        error_type=error.__class__.__name__,\n        context=str(error.context),\n        inner_error_type=str(error.inner_error_type),\n        inner_error_message=str(error.inner_error),\n        blocks_errors=[\n            WorkflowBlockError(\n                block_id=error.block_id,\n                block_type=error.block_type,\n                property_name=\"Python code\",\n                property_details=str(error.inner_error),\n                block_traceback=error.block_traceback,\n            ),\n        ],\n    )\n\n\ndef with_route_exceptions(route):\n    \"\"\"\n    A decorator that wraps a FastAPI route to handle specific exceptions. If an exception\n    is caught, it returns a JSON response with the error message.\n\n    Args:\n        route (Callable): The FastAPI route to be wrapped.\n\n    Returns:\n        Callable: The wrapped route.\n    \"\"\"\n\n    @wraps(route)\n    def wrapped_route(*args, **kwargs):\n        try:\n            return route(*args, **kwargs)\n        except ContentTypeInvalid as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Invalid Content-Type header provided with request.\"\n                },\n            )\n        except ContentTypeMissing as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\"message\": \"Content-Type header not provided with request.\"},\n            )\n        except InputImageLoadError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": f\"Could not load input image. Cause: {error.get_public_error_details()}\"\n                },\n            )\n        except ModelInputError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": f\"Error with model input. Cause: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except InvalidModelIDError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\"message\": \"Invalid Model ID sent in request.\"},\n            )\n        except InvalidMaskDecodeArgument as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Invalid mask decode argument sent. tradeoff_factor must be in [0.0, 1.0], \"\n                    \"mask_decode_mode: must be one of ['accurate', 'fast', 'tradeoff']\"\n                },\n            )\n        except MissingApiKeyError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Required Roboflow API key is missing. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except (\n            WorkflowSyntaxError,\n            InvalidReferenceTargetError,\n            ExecutionGraphStructureError,\n            StepInputDimensionalityError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=error.blocks_errors,\n            )\n            resp = JSONResponse(status_code=400, content=content.model_dump())\n        except PythonBlockError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = _build_python_block_error_response(error)\n            resp = JSONResponse(status_code=400, content=content.model_dump())\n        except (\n            WorkflowDefinitionError,\n            ReferenceTypeError,\n            RuntimeInputError,\n            InvalidInputTypeError,\n            OperationTypeNotRecognisedError,\n            DynamicBlockError,\n            WorkflowExecutionEngineVersionError,\n            NotSupportedExecutionEngineError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"context\": error.context,\n                    \"inner_error_type\": error.inner_error_type,\n                    \"inner_error_message\": str(error.inner_error),\n                },\n            )\n        except (\n            ProcessesManagerInvalidPayload,\n            MalformedPayloadError,\n            MessageToBigError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except (\n            RoboflowAPINotAuthorizedError,\n            ProcessesManagerAuthorisationError,\n            UnauthorizedModelAccessError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=401,\n                content={\n                    \"message\": \"Unauthorized access to roboflow API - check API key and make sure the key is valid for \"\n                    \"workspace you use. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except RoboflowAPIForbiddenError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=403,\n                content={\n                    \"message\": \"Unauthorized access to roboflow API - check API key and make sure the key is valid and \"\n                    \"have required scopes. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except (RoboflowAPINotNotFoundError, ModelNotFoundError) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=404,\n                content={\n                    \"message\": \"Requested Roboflow resource not found. Make sure that workspace, project or model \"\n                    \"you referred in request exists.\"\n                },\n            )\n        except ProcessesManagerNotFoundError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=404,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except ModelPackageNegotiationError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Could not negotiate model package - {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except (\n            InvalidEnvironmentVariableError,\n            MissingServiceSecretError,\n            ServiceConfigurationError,\n            EnvironmentConfigurationError,\n            InvalidEnvVariable,\n            JetsonTypeResolutionError,\n            MissingDependencyError,\n            InvalidParameterError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500, content={\"message\": \"Service misconfiguration.\"}\n            )\n        except (\n            PreProcessingError,\n            PostProcessingError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": \"Model configuration related to pre- or post-processing is invalid.\"\n                },\n            )\n        except ModelArtefactError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500, content={\"message\": \"Model package is broken.\"}\n            )\n        except ModelLoadingError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Model loading failed: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except (UntrustedFileError, FileHashSumMissmatch) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Issue with model package file: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except ModelRetrievalError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Could not retrieve model {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except OnnxProviderNotAvailable as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=501,\n                content={\n                    \"message\": \"Could not find requested ONNX Runtime Provider. Check that you are using \"\n                    \"the correct docker image on a supported device.\"\n                },\n            )\n        except (\n            MalformedRoboflowAPIResponseError,\n            RoboflowAPIUnsuccessfulRequestError,\n            WorkspaceLoadError,\n            MalformedWorkflowResponseError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=502,\n                content={\"message\": \"Internal error. Request to Roboflow API failed.\"},\n            )\n        except InferenceModelNotFound as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\"message\": \"Model is temporarily not ready - retry request.\"},\n                headers={\"Retry-After\": \"1\"},\n            )\n        except RoboflowAPIConnectionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\n                    \"message\": \"Internal error. Could not connect to Roboflow API.\"\n                },\n            )\n        except ModelManagerLockAcquisitionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\n                    \"message\": \"Could not acquire model manager lock due to other request performing \"\n                    \"blocking operation. Try again....\"\n                },\n                headers={\"Retry-After\": \"1\"},\n            )\n        except RoboflowAPITimeoutError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=504,\n                content={\n                    \"message\": \"Timeout when attempting to connect to Roboflow API.\"\n                },\n            )\n        except ClientCausedStepExecutionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=error.block_id,\n                    ),\n                ],\n            )\n            resp = JSONResponse(\n                status_code=error.status_code,\n                content=content.model_dump(),\n            )\n        except StepExecutionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = _build_step_execution_error_response(error)\n            resp = JSONResponse(\n                status_code=500,\n                content=content.model_dump(),\n            )\n        except WorkflowError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"context\": error.context,\n                    \"inner_error_type\": error.inner_error_type,\n                    \"inner_error_message\": str(error.inner_error),\n                },\n            )\n        except (\n            ProcessesManagerClientError,\n            CommunicationProtocolError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except WebRTCConfigurationError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": str(error),\n                    \"error_type\": \"WebRTCConfigurationError\",\n                },\n            )\n        except CreditsExceededError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=402,\n                content={\n                    \"message\": \"Not enough credits to perform this request.\",\n                    \"error_type\": \"CreditsExceededError\",\n                },\n            )\n        except Exception as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(status_code=500, content={\"message\": \"Internal error.\"})\n        return resp\n\n    return wrapped_route\n\n\ndef with_route_exceptions_async(route):\n    \"\"\"\n    A decorator that wraps a FastAPI route to handle specific exceptions. If an exception\n    is caught, it returns a JSON response with the error message.\n\n    Args:\n        route (Callable): The FastAPI route to be wrapped.\n\n    Returns:\n        Callable: The wrapped route.\n    \"\"\"\n\n    @wraps(route)\n    async def wrapped_route(*args, **kwargs):\n        try:\n            return await route(*args, **kwargs)\n        except ContentTypeInvalid as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Invalid Content-Type header provided with request.\"\n                },\n            )\n        except ContentTypeMissing as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\"message\": \"Content-Type header not provided with request.\"},\n            )\n        except InputImageLoadError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": f\"Could not load input image. Cause: {error.get_public_error_details()}\"\n                },\n            )\n        except ModelInputError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": f\"Error with model input. Cause: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except InvalidModelIDError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\"message\": \"Invalid Model ID sent in request.\"},\n            )\n        except InvalidMaskDecodeArgument as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Invalid mask decode argument sent. tradeoff_factor must be in [0.0, 1.0], \"\n                    \"mask_decode_mode: must be one of ['accurate', 'fast', 'tradeoff']\"\n                },\n            )\n        except MissingApiKeyError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": \"Required Roboflow API key is missing. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except (\n            WorkflowSyntaxError,\n            InvalidReferenceTargetError,\n            ExecutionGraphStructureError,\n            StepInputDimensionalityError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=error.blocks_errors,\n            )\n            resp = JSONResponse(status_code=400, content=content.model_dump())\n        except PythonBlockError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = _build_python_block_error_response(error)\n            resp = JSONResponse(status_code=400, content=content.model_dump())\n        except (\n            WorkflowDefinitionError,\n            ReferenceTypeError,\n            RuntimeInputError,\n            InvalidInputTypeError,\n            OperationTypeNotRecognisedError,\n            DynamicBlockError,\n            WorkflowExecutionEngineVersionError,\n            NotSupportedExecutionEngineError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"context\": error.context,\n                    \"inner_error_type\": error.inner_error_type,\n                    \"inner_error_message\": str(error.inner_error),\n                },\n            )\n        except (\n            ProcessesManagerInvalidPayload,\n            MalformedPayloadError,\n            MessageToBigError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except (\n            RoboflowAPINotAuthorizedError,\n            ProcessesManagerAuthorisationError,\n            UnauthorizedModelAccessError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=401,\n                content={\n                    \"message\": \"Unauthorized access to roboflow API - check API key and make sure the key is valid for \"\n                    \"workspace you use. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except RoboflowAPIForbiddenError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=403,\n                content={\n                    \"message\": \"Unauthorized access to roboflow API - check API key and make sure the key is valid and \"\n                    \"have required scopes. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key \"\n                    \"to learn how to retrieve one.\"\n                },\n            )\n        except (RoboflowAPINotNotFoundError, ModelNotFoundError) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=404,\n                content={\n                    \"message\": \"Requested Roboflow resource not found. Make sure that workspace, project or model \"\n                    \"you referred in request exists.\"\n                },\n            )\n        except ProcessesManagerNotFoundError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=404,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except ModelPackageNegotiationError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Could not negotiate model package - {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except (\n            InvalidEnvironmentVariableError,\n            MissingServiceSecretError,\n            ServiceConfigurationError,\n            EnvironmentConfigurationError,\n            InvalidEnvVariable,\n            JetsonTypeResolutionError,\n            MissingDependencyError,\n            InvalidParameterError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500, content={\"message\": \"Service misconfiguration.\"}\n            )\n        except (\n            PreProcessingError,\n            PostProcessingError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": \"Model configuration related to pre- or post-processing is invalid.\"\n                },\n            )\n        except ModelArtefactError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500, content={\"message\": \"Model package is broken.\"}\n            )\n        except ModelLoadingError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Model loading failed: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except (UntrustedFileError, FileHashSumMissmatch) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Issue with model package file: {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except ModelRetrievalError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": f\"Could not retrieve model {error}\",\n                    \"help_url\": error.help_url,\n                },\n            )\n        except OnnxProviderNotAvailable as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=501,\n                content={\n                    \"message\": \"Could not find requested ONNX Runtime Provider. Check that you are using \"\n                    \"the correct docker image on a supported device.\"\n                },\n            )\n        except (\n            MalformedRoboflowAPIResponseError,\n            RoboflowAPIUnsuccessfulRequestError,\n            WorkspaceLoadError,\n            MalformedWorkflowResponseError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=502,\n                content={\"message\": \"Internal error. Request to Roboflow API failed.\"},\n            )\n        except InferenceModelNotFound as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\"message\": \"Model is temporarily not ready - retry request.\"},\n                headers={\"Retry-After\": \"1\"},\n            )\n        except RoboflowAPIConnectionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\n                    \"message\": \"Internal error. Could not connect to Roboflow API.\"\n                },\n            )\n        except ModelManagerLockAcquisitionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=503,\n                content={\n                    \"message\": \"Could not acquire model manager lock due to other request performing \"\n                    \"blocking operation. Try again....\"\n                },\n                headers={\"Retry-After\": \"1\"},\n            )\n        except RoboflowAPITimeoutError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=504,\n                content={\n                    \"message\": \"Timeout when attempting to connect to Roboflow API.\"\n                },\n            )\n        except ClientCausedStepExecutionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = WorkflowErrorResponse(\n                message=str(error.public_message),\n                error_type=error.__class__.__name__,\n                context=str(error.context),\n                inner_error_type=str(error.inner_error_type),\n                inner_error_message=str(error.inner_error),\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=error.block_id,\n                    ),\n                ],\n            )\n            resp = JSONResponse(\n                status_code=error.status_code,\n                content=content.model_dump(),\n            )\n        except StepExecutionError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            content = _build_step_execution_error_response(error)\n            resp = JSONResponse(\n                status_code=500,\n                content=content.model_dump(),\n            )\n        except WorkflowError as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"context\": error.context,\n                    \"inner_error_type\": error.inner_error_type,\n                    \"inner_error_message\": str(error.inner_error),\n                },\n            )\n        except (\n            ProcessesManagerClientError,\n            CommunicationProtocolError,\n        ) as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=500,\n                content={\n                    \"message\": error.public_message,\n                    \"error_type\": error.__class__.__name__,\n                    \"inner_error_type\": error.inner_error_type,\n                },\n            )\n        except WebRTCConfigurationError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=400,\n                content={\n                    \"message\": str(error),\n                    \"error_type\": \"WebRTCConfigurationError\",\n                },\n            )\n        except CreditsExceededError as error:\n            logger.error(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(\n                status_code=402,\n                content={\n                    \"message\": \"Not enough credits to perform this request.\",\n                    \"error_type\": \"CreditsExceededError\",\n                },\n            )\n        except Exception as error:\n            logger.exception(\"%s: %s\", type(error).__name__, error)\n            resp = JSONResponse(status_code=500, content={\"message\": \"Internal error.\"})\n        return resp\n\n    return wrapped_route\n",
    "patch": null
  },
  {
    "trace_id": "3436e19e-7205-4fbd-9b48-a4103d0621c9",
    "function_name": "InferenceModelsQwen35VLAdapter.predict",
    "file_path": "inference/models/qwen3_5vl/qwen3_5vl_inference_models.py",
    "speedup_x": 2.719797915508924,
    "review_quality": "medium",
    "pre_optimization_commit": "a91e477b2c94b07c4f67f664b68dbe9b45febdb8",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def predict(self, inputs, **kwargs) -> torch.Tensor:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.generate(inputs, **mapped_kwargs)\n",
    "optimized_function_code": "import torch\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES, API_KEY)\nfrom inference.core.models.base import Model\nfrom inference.core.roboflow_api import get_extra_weights_provider_headers\nfrom inference_models.models.qwen3_5.qwen3_5_hf import Qwen35HF\n\n\nclass InferenceModelsQwen35VLAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n\n        self.task_type = \"lmm\"\n\n\n        # Cache these lookups to avoid repeated dict access\n        countinference = kwargs.get(\"countinference\")\n        service_secret = kwargs.get(\"service_secret\")\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=countinference,\n            service_secret=service_secret,\n        )\n\n\n        # Defer importing AutoModel until initialization to reduce module import time\n        from inference_models import AutoModel\n\n        self._model: Qwen35HF = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            **kwargs,\n        )\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        return kwargs\n\n    def predict(self, inputs, **kwargs) -> torch.Tensor:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.generate(inputs, **mapped_kwargs)",
    "optimized_raw_markdown": "```python:inference/models/qwen3_5vl/qwen3_5vl_inference_models.py\nimport torch\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES, API_KEY)\nfrom inference.core.models.base import Model\nfrom inference.core.roboflow_api import get_extra_weights_provider_headers\nfrom inference_models.models.qwen3_5.qwen3_5_hf import Qwen35HF\n\n\nclass InferenceModelsQwen35VLAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n\n        self.task_type = \"lmm\"\n\n\n        # Cache these lookups to avoid repeated dict access\n        countinference = kwargs.get(\"countinference\")\n        service_secret = kwargs.get(\"service_secret\")\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=countinference,\n            service_secret=service_secret,\n        )\n\n\n        # Defer importing AutoModel until initialization to reduce module import time\n        from inference_models import AutoModel\n\n        self._model: Qwen35HF = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            **kwargs,\n        )\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        return kwargs\n\n    def predict(self, inputs, **kwargs) -> torch.Tensor:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.generate(inputs, **mapped_kwargs)\n```",
    "optimized_function_only": "    def predict(self, inputs, **kwargs) -> torch.Tensor:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.generate(inputs, **mapped_kwargs)",
    "original_file_content": "from typing import Any, List\n\nimport torch\n\nfrom inference.core.entities.responses import (\n    InferenceResponseImage,\n    LMMInferenceResponse,\n)\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n    API_KEY,\n)\nfrom inference.core.models.base import Model\nfrom inference.core.models.types import PreprocessReturnMetadata\nfrom inference.core.roboflow_api import get_extra_weights_provider_headers\nfrom inference.core.utils.image_utils import load_image_bgr\nfrom inference_models import AutoModel\nfrom inference_models.models.qwen3_5.qwen3_5_hf import Qwen35HF\n\n\nclass InferenceModelsQwen35VLAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n\n        self.task_type = \"lmm\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n\n        self._model: Qwen35HF = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            **kwargs,\n        )\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        return kwargs\n\n    def preprocess(self, image: Any, prompt: str = \"\", **kwargs):\n        is_batch = isinstance(image, list)\n        if is_batch:\n            raise ValueError(\"This model does not support batched-inference.\")\n        np_image = load_image_bgr(\n            image,\n            disable_preproc_auto_orient=kwargs.get(\n                \"disable_preproc_auto_orient\", False\n            ),\n        )\n        input_shape = PreprocessReturnMetadata({\"image_dims\": np_image.shape[:2][::-1]})\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return (\n            self._model.pre_process_generation(np_image, prompt, **mapped_kwargs),\n            input_shape,\n        )\n\n    def predict(self, inputs, **kwargs) -> torch.Tensor:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.generate(inputs, **mapped_kwargs)\n\n    def postprocess(\n        self,\n        predictions: torch.Tensor,\n        preprocess_return_metadata: PreprocessReturnMetadata,\n        **kwargs,\n    ) -> List[LMMInferenceResponse]:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        result = self._model.post_process_generation(predictions, **mapped_kwargs)[0]\n        return [\n            LMMInferenceResponse(\n                response=result,\n                image=InferenceResponseImage(\n                    width=preprocess_return_metadata[\"image_dims\"][0],\n                    height=preprocess_return_metadata[\"image_dims\"][1],\n                ),\n            )\n        ]\n\n    def clear_cache(self, delete_from_disk: bool = True) -> None:\n        pass\n",
    "patch": null
  },
  {
    "trace_id": "e936cbaf-e28f-4f9d-b0e5-8aac889c5e5a",
    "function_name": "InferenceModelsQwen35VLAdapter.map_inference_kwargs",
    "file_path": "inference/models/qwen3_5vl/qwen3_5vl_inference_models.py",
    "speedup_x": 0.5295936801494229,
    "review_quality": "medium",
    "pre_optimization_commit": "a91e477b2c94b07c4f67f664b68dbe9b45febdb8",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        return kwargs\n",
    "optimized_function_code": "from inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES, API_KEY)\nfrom inference.core.models.base import Model\nfrom inference.core.roboflow_api import get_extra_weights_provider_headers\nfrom inference_models.models.qwen3_5.qwen3_5_hf import Qwen35HF\n\n\nclass InferenceModelsQwen35VLAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n\n        self.task_type = \"lmm\"\n\n\n        # cache local lookups to avoid repeated dict.get calls\n        countinference = kwargs.get(\"countinference\")\n        service_secret = kwargs.get(\"service_secret\")\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=countinference,\n            service_secret=service_secret,\n        )\n\n\n        # Delay importing AutoModel until an instance is actually created to reduce module import cost\n        from inference_models import AutoModel\n\n        self._model: Qwen35HF = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            **kwargs,\n        )\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        return kwargs",
    "optimized_raw_markdown": "```python:inference/models/qwen3_5vl/qwen3_5vl_inference_models.py\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES, API_KEY)\nfrom inference.core.models.base import Model\nfrom inference.core.roboflow_api import get_extra_weights_provider_headers\nfrom inference_models.models.qwen3_5.qwen3_5_hf import Qwen35HF\n\n\nclass InferenceModelsQwen35VLAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n\n        self.task_type = \"lmm\"\n\n\n        # cache local lookups to avoid repeated dict.get calls\n        countinference = kwargs.get(\"countinference\")\n        service_secret = kwargs.get(\"service_secret\")\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=countinference,\n            service_secret=service_secret,\n        )\n\n\n        # Delay importing AutoModel until an instance is actually created to reduce module import cost\n        from inference_models import AutoModel\n\n        self._model: Qwen35HF = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            **kwargs,\n        )\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        return kwargs\n```",
    "optimized_function_only": "    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        return kwargs",
    "original_file_content": "from typing import Any, List\n\nimport torch\n\nfrom inference.core.entities.responses import (\n    InferenceResponseImage,\n    LMMInferenceResponse,\n)\nfrom inference.core.env import (\n    ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n    ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n    API_KEY,\n)\nfrom inference.core.models.base import Model\nfrom inference.core.models.types import PreprocessReturnMetadata\nfrom inference.core.roboflow_api import get_extra_weights_provider_headers\nfrom inference.core.utils.image_utils import load_image_bgr\nfrom inference_models import AutoModel\nfrom inference_models.models.qwen3_5.qwen3_5_hf import Qwen35HF\n\n\nclass InferenceModelsQwen35VLAdapter(Model):\n    def __init__(self, model_id: str, api_key: str = None, **kwargs):\n        super().__init__()\n\n        self.metrics = {\"num_inferences\": 0, \"avg_inference_time\": 0.0}\n\n        self.api_key = api_key if api_key else API_KEY\n\n        self.task_type = \"lmm\"\n\n        extra_weights_provider_headers = get_extra_weights_provider_headers(\n            countinference=kwargs.get(\"countinference\"),\n            service_secret=kwargs.get(\"service_secret\"),\n        )\n\n        self._model: Qwen35HF = AutoModel.from_pretrained(\n            model_id_or_path=model_id,\n            api_key=self.api_key,\n            allow_untrusted_packages=ALLOW_INFERENCE_MODELS_UNTRUSTED_PACKAGES,\n            allow_direct_local_storage_loading=ALLOW_INFERENCE_MODELS_DIRECTLY_ACCESS_LOCAL_PACKAGES,\n            weights_provider_extra_headers=extra_weights_provider_headers,\n            **kwargs,\n        )\n\n    def map_inference_kwargs(self, kwargs: dict) -> dict:\n        return kwargs\n\n    def preprocess(self, image: Any, prompt: str = \"\", **kwargs):\n        is_batch = isinstance(image, list)\n        if is_batch:\n            raise ValueError(\"This model does not support batched-inference.\")\n        np_image = load_image_bgr(\n            image,\n            disable_preproc_auto_orient=kwargs.get(\n                \"disable_preproc_auto_orient\", False\n            ),\n        )\n        input_shape = PreprocessReturnMetadata({\"image_dims\": np_image.shape[:2][::-1]})\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return (\n            self._model.pre_process_generation(np_image, prompt, **mapped_kwargs),\n            input_shape,\n        )\n\n    def predict(self, inputs, **kwargs) -> torch.Tensor:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        return self._model.generate(inputs, **mapped_kwargs)\n\n    def postprocess(\n        self,\n        predictions: torch.Tensor,\n        preprocess_return_metadata: PreprocessReturnMetadata,\n        **kwargs,\n    ) -> List[LMMInferenceResponse]:\n        mapped_kwargs = self.map_inference_kwargs(kwargs)\n        result = self._model.post_process_generation(predictions, **mapped_kwargs)[0]\n        return [\n            LMMInferenceResponse(\n                response=result,\n                image=InferenceResponseImage(\n                    width=preprocess_return_metadata[\"image_dims\"][0],\n                    height=preprocess_return_metadata[\"image_dims\"][1],\n                ),\n            )\n        ]\n\n    def clear_cache(self, delete_from_disk: bool = True) -> None:\n        pass\n",
    "patch": null
  },
  {
    "trace_id": "d2351ecc-5d16-4355-bb6c-115f19a671b4",
    "function_name": "Qwen35VLBlockV1.run_remotely",
    "file_path": "inference/core/workflows/core_steps/models/foundation/qwen3_5vl/v1.py",
    "speedup_x": 4.644067304821353,
    "review_quality": "high",
    "pre_optimization_commit": "c0249b396cecd814532f6b2a4c0abb4bd6c8c4f3",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def run_remotely(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n        system_prompt: Optional[str],\n    ) -> BlockResult:\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_CORE_MODEL_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        if WORKFLOWS_REMOTE_API_TARGET == \"hosted\":\n            client.select_api_v0()\n\n        prompt = prompt or \"Describe what's in this image.\"\n        system_prompt = (\n            system_prompt\n            or \"You are a Qwen3.5-VL model that can answer questions about any image.\"\n        )\n        combined_prompt = prompt + \"<system_prompt>\" + system_prompt\n\n        predictions = []\n        for image in images:\n            result = client.infer_lmm(\n                inference_input=image.base64_image,\n                model_id=model_version,\n                prompt=combined_prompt,\n                model_id_in_path=True,\n            )\n            response_text = result.get(\"response\", result)\n            predictions.append({\"parsed_output\": response_text})\n\n        return predictions\n",
    "optimized_function_code": "##########################################################################\n# Qwen3.5-VL Workflow Block\n##########################################################################\nfrom typing import Optional\n\nfrom inference.core.env import (HOSTED_CORE_MODEL_URL, LOCAL_INFERENCE_API_URL,\n                                WORKFLOWS_REMOTE_API_TARGET)\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.entities import \\\n    StepExecutionMode\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch, WorkflowImageData)\nfrom inference.core.workflows.prototypes.block import (BlockResult,\n                                                       WorkflowBlock)\nfrom inference_sdk import InferenceHTTPClient\n\n\nclass Qwen35VLBlockV1(WorkflowBlock):\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    def run_remotely(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n        system_prompt: Optional[str],\n    ) -> BlockResult:\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_CORE_MODEL_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        if WORKFLOWS_REMOTE_API_TARGET == \"hosted\":\n            client.select_api_v0()\n\n        prompt = prompt or \"Describe what's in this image.\"\n        system_prompt = (\n            system_prompt\n            or \"You are a Qwen3.5-VL model that can answer questions about any image.\"\n        )\n        combined_prompt = prompt + \"<system_prompt>\" + system_prompt\n\n        if not images:\n            return []\n\n        image_inputs = [image.base64_image for image in images]\n\n        results = client.infer_lmm(\n            inference_input=image_inputs,\n            model_id=model_version,\n            prompt=combined_prompt,\n            model_id_in_path=True,\n        )\n\n        predictions = []\n        if isinstance(results, list):\n            for result in results:\n                response_text = result.get(\"response\", result)\n                predictions.append({\"parsed_output\": response_text})\n        else:\n            response_text = results.get(\"response\", results)\n            predictions.append({\"parsed_output\": response_text})\n\n        return predictions",
    "optimized_raw_markdown": "```python:inference_sdk/http/client.py\nfrom typing import List, Optional, Union\n\nfrom inference_sdk.http.entities import (HTTPClientMode, ImagesReference,\n                                         InferenceConfiguration)\nfrom inference_sdk.webrtc.client import WebRTCClient\n\n\nclass InferenceHTTPClient:\n\n    def __init__(\n        self,\n        api_url: str,\n        api_key: Optional[str] = None,\n    ):\n        \"\"\"Initialize a new InferenceHTTPClient instance.\n\n        Args:\n            api_url (str): The base URL for the inference API.\n            api_key (Optional[str], optional): API key for authentication. Defaults to None.\n        \"\"\"\n        self.__api_url = api_url\n        self.__api_key = api_key\n        self.__inference_configuration = InferenceConfiguration.init_default()\n        self.__client_mode = _determine_client_mode(api_url=api_url)\n        self.__selected_model: Optional[str] = None\n        self.__webrtc_client: Optional[\"WebRTCClient\"] = None\n\n    def select_api_v0(self) -> \"InferenceHTTPClient\":\n        \"\"\"Select API version 0 for client operations.\n\n        Returns:\n            InferenceHTTPClient: The client instance with API v0 selected.\n        \"\"\"\n        self.__client_mode = HTTPClientMode.V0\n        return self\n\n    @wrap_errors\n    def infer_lmm(\n        self,\n        inference_input: Union[ImagesReference, List[ImagesReference]],\n        model_id: str,\n        prompt: Optional[str] = None,\n        model_id_in_path: bool = False,\n    ) -> Union[dict, List[dict]]:\n        \"\"\"Run inference using a Large Multimodal Model (LMM).\n\n        This method supports various vision-language models including Florence-2,\n        Moondream2, SmolVLM, Qwen2.5-VL, Qwen3-VL, and PaliGemma.\n\n        Args:\n            inference_input (Union[ImagesReference, List[ImagesReference]]): Input image(s)\n                for inference. Can be file paths, URLs, base64 strings, numpy arrays, or PIL images.\n            model_id (str): The identifier of the LMM model to use. Examples include:\n                - \"florence-2-base\", \"florence-2-large\" for Florence-2\n                - \"moondream2/moondream2_2b_jul24\" for Moondream2\n                - \"smolvlm2/smolvlm-2.2b-instruct\" for SmolVLM\n                - \"qwen25-vl-7b\" for Qwen2.5-VL\n                - \"qwen3vl-2b-instruct\" for Qwen3-VL\n            prompt (Optional[str], optional): Text prompt to guide the model. Defaults to None.\n            model_id_in_path (bool, optional): If True, includes model_id in the URL path\n                (e.g., /infer/lmm/florence-2-base) which enables path-based routing.\n                If False (default), model_id is only sent in the request body.\n\n        Returns:\n            Union[dict, List[dict]]: Inference results containing the model response.\n                The structure depends on the specific model used.\n\n        Raises:\n            HTTPCallErrorError: If there is an error in the HTTP call.\n            HTTPClientError: If there is an error with the server connection.\n        \"\"\"\n        extra_payload = {\"model_id\": model_id}\n        if prompt is not None:\n            extra_payload[\"prompt\"] = prompt\n\n        if model_id_in_path:\n            endpoint = f\"/infer/lmm/{model_id}\"\n        else:\n            endpoint = \"/infer/lmm\"\n\n        result = self._post_images(\n            inference_input=inference_input,\n            endpoint=endpoint,\n            extra_payload=extra_payload,\n        )\n        return result\n```\n```python:inference/core/workflows/core_steps/models/foundation/qwen3_5vl/v1.py\n##########################################################################\n# Qwen3.5-VL Workflow Block\n##########################################################################\nfrom typing import Optional\n\nfrom inference.core.env import (HOSTED_CORE_MODEL_URL, LOCAL_INFERENCE_API_URL,\n                                WORKFLOWS_REMOTE_API_TARGET)\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.entities import \\\n    StepExecutionMode\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch, WorkflowImageData)\nfrom inference.core.workflows.prototypes.block import (BlockResult,\n                                                       WorkflowBlock)\nfrom inference_sdk import InferenceHTTPClient\n\n\nclass Qwen35VLBlockV1(WorkflowBlock):\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    def run_remotely(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n        system_prompt: Optional[str],\n    ) -> BlockResult:\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_CORE_MODEL_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        if WORKFLOWS_REMOTE_API_TARGET == \"hosted\":\n            client.select_api_v0()\n\n        prompt = prompt or \"Describe what's in this image.\"\n        system_prompt = (\n            system_prompt\n            or \"You are a Qwen3.5-VL model that can answer questions about any image.\"\n        )\n        combined_prompt = prompt + \"<system_prompt>\" + system_prompt\n\n        if not images:\n            return []\n\n        image_inputs = [image.base64_image for image in images]\n\n        results = client.infer_lmm(\n            inference_input=image_inputs,\n            model_id=model_version,\n            prompt=combined_prompt,\n            model_id_in_path=True,\n        )\n\n        predictions = []\n        if isinstance(results, list):\n            for result in results:\n                response_text = result.get(\"response\", result)\n                predictions.append({\"parsed_output\": response_text})\n        else:\n            response_text = results.get(\"response\", results)\n            predictions.append({\"parsed_output\": response_text})\n\n        return predictions\n```",
    "optimized_function_only": "    def run_remotely(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n        system_prompt: Optional[str],\n    ) -> BlockResult:\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_CORE_MODEL_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        if WORKFLOWS_REMOTE_API_TARGET == \"hosted\":\n            client.select_api_v0()\n\n        prompt = prompt or \"Describe what's in this image.\"\n        system_prompt = (\n            system_prompt\n            or \"You are a Qwen3.5-VL model that can answer questions about any image.\"\n        )\n        combined_prompt = prompt + \"<system_prompt>\" + system_prompt\n\n        if not images:\n            return []\n\n        image_inputs = [image.base64_image for image in images]\n\n        results = client.infer_lmm(\n            inference_input=image_inputs,\n            model_id=model_version,\n            prompt=combined_prompt,\n            model_id_in_path=True,\n        )\n\n        predictions = []\n        if isinstance(results, list):\n            for result in results:\n                response_text = result.get(\"response\", result)\n                predictions.append({\"parsed_output\": response_text})\n        else:\n            response_text = results.get(\"response\", results)\n            predictions.append({\"parsed_output\": response_text})\n\n        return predictions",
    "original_file_content": "import json\nfrom typing import List, Literal, Optional, Type, Union\n\nimport supervision as sv\nfrom pydantic import ConfigDict, Field\n\nfrom inference.core.entities.requests.inference import LMMInferenceRequest\nfrom inference.core.env import (\n    HOSTED_CORE_MODEL_URL,\n    LOCAL_INFERENCE_API_URL,\n    WORKFLOWS_REMOTE_API_TARGET,\n)\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.entities import StepExecutionMode\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    DICTIONARY_KIND,\n    IMAGE_KIND,\n    LANGUAGE_MODEL_OUTPUT_KIND,\n    ROBOFLOW_MODEL_ID_KIND,\n    STRING_KIND,\n    ImageInputField,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\nfrom inference_sdk import InferenceHTTPClient\n\n\n##########################################################################\n# Qwen3.5-VL Workflow Block Manifest\n##########################################################################\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Qwen3.5-VL\",\n            \"version\": \"v1\",\n            \"short_description\": \"Run Qwen3.5-VL on an image.\",\n            \"long_description\": (\n                \"This workflow block runs Qwen3.5-VL\u2014a vision language model that accepts an image \"\n                \"and an optional text prompt\u2014and returns a text answer based on a conversation template.\"\n            ),\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"model\",\n            \"search_keywords\": [\n                \"Qwen3.5\",\n                \"qwen3.5-vl\",\n                \"vision language model\",\n                \"VLM\",\n                \"Alibaba\",\n            ],\n            \"is_vlm_block\": True,\n            \"ui_manifest\": {\n                \"section\": \"model\",\n                \"icon\": \"fal fa-atom\",\n                \"blockPriority\": 5.7,\n            },\n        },\n        protected_namespaces=(),\n    )\n    type: Literal[\"roboflow_core/qwen3_5vl@v1\"]\n\n    images: Selector(kind=[IMAGE_KIND]) = ImageInputField\n    prompt: Optional[str] = Field(\n        default=None,\n        description=\"Optional text prompt to provide additional context to Qwen3.5-VL. Otherwise it will just be a default one, which may affect the desired model behavior.\",\n        examples=[\"What is in this image?\"],\n    )\n    model_version: Union[Selector(kind=[ROBOFLOW_MODEL_ID_KIND]), str] = Field(\n        default=\"qwen3_5-0.8b\",\n        description=\"The Qwen3.5-VL model to be used for inference.\",\n        examples=[\"qwen3_5-0.8b\", \"qwen3_5-2b\"],\n    )\n\n    system_prompt: Optional[str] = Field(\n        default=None,\n        description=\"Optional system prompt to provide additional context to Qwen3.5-VL.\",\n        examples=[\"You are a helpful assistant.\"],\n    )\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(\n                name=\"parsed_output\",\n                kind=[DICTIONARY_KIND],\n                description=\"A parsed version of the output, provided as a dictionary containing the text.\",\n            ),\n        ]\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        # Only images can be passed in as a list/batch\n        return [\"images\"]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\n##########################################################################\n# Qwen3.5-VL Workflow Block\n##########################################################################\nclass Qwen35VLBlockV1(WorkflowBlock):\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"model_manager\", \"api_key\", \"step_execution_mode\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n        system_prompt: Optional[str],\n    ) -> BlockResult:\n        if self._step_execution_mode == StepExecutionMode.LOCAL:\n            return self.run_locally(\n                images=images,\n                model_version=model_version,\n                prompt=prompt,\n                system_prompt=system_prompt,\n            )\n        elif self._step_execution_mode == StepExecutionMode.REMOTE:\n            return self.run_remotely(\n                images=images,\n                model_version=model_version,\n                prompt=prompt,\n                system_prompt=system_prompt,\n            )\n        else:\n            raise ValueError(\n                f\"Unknown step execution mode: {self._step_execution_mode}\"\n            )\n\n    def run_remotely(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n        system_prompt: Optional[str],\n    ) -> BlockResult:\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_CORE_MODEL_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        if WORKFLOWS_REMOTE_API_TARGET == \"hosted\":\n            client.select_api_v0()\n\n        prompt = prompt or \"Describe what's in this image.\"\n        system_prompt = (\n            system_prompt\n            or \"You are a Qwen3.5-VL model that can answer questions about any image.\"\n        )\n        combined_prompt = prompt + \"<system_prompt>\" + system_prompt\n\n        predictions = []\n        for image in images:\n            result = client.infer_lmm(\n                inference_input=image.base64_image,\n                model_id=model_version,\n                prompt=combined_prompt,\n                model_id_in_path=True,\n            )\n            response_text = result.get(\"response\", result)\n            predictions.append({\"parsed_output\": response_text})\n\n        return predictions\n\n    def run_locally(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n        system_prompt: Optional[str],\n    ) -> BlockResult:\n        # Convert each image to the format required by the model.\n        inference_images = [\n            i.to_inference_format(numpy_preferred=False) for i in images\n        ]\n        # Use the provided prompt or default to a generic image description request.\n        prompt = prompt or \"Describe what's in this image.\"\n        system_prompt = (\n            system_prompt\n            or \"You are a Qwen3.5-VL model that can answer questions about any image.\"\n        )\n        prompts = [prompt + \"<system_prompt>\" + system_prompt] * len(inference_images)\n        # Register Qwen3.5-VL with the model manager.\n        self._model_manager.add_model(model_id=model_version, api_key=self._api_key)\n\n        predictions = []\n        for image, single_prompt in zip(inference_images, prompts):\n            # Build an LMMInferenceRequest with both prompt and image.\n            request = LMMInferenceRequest(\n                api_key=self._api_key,\n                model_id=model_version,\n                image=image,\n                source=\"workflow-execution\",\n                prompt=single_prompt,\n            )\n            # Run inference.\n            prediction = self._model_manager.infer_from_request_sync(\n                model_id=model_version, request=request\n            )\n            response_text = prediction.response\n            predictions.append(\n                {\n                    \"parsed_output\": response_text,\n                }\n            )\n        return predictions\n",
    "patch": null
  },
  {
    "trace_id": "794411bc-aa4d-41c5-857d-21e57970fcb0",
    "function_name": "_fetch_workflow_spec_for_validation",
    "file_path": "inference/core/workflows/core_steps/composition/workflow_caller/v1.py",
    "speedup_x": 0.333960378863972,
    "review_quality": "high",
    "pre_optimization_commit": "2f6a10764cd3da01cb46073d710b1dec32962220",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def _fetch_workflow_spec_for_validation(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[dict]:\n    \"\"\"Fetch a workflow spec, returning None on any error.\"\"\"\n    try:\n        return get_workflow_specification(\n            api_key=api_key,\n            workspace_id=workspace_name,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n        )\n    except Exception as error:\n        logging.debug(\n            \"Could not fetch workflow '%s' for compile-time validation (error type: %s)\",\n            workflow_id,\n            type(error).__name__,\n        )\n        return None\n",
    "optimized_function_code": "import logging\nfrom typing import Optional\n\nfrom inference.core.roboflow_api import get_workflow_specification\n\n_logger = logging.getLogger(__name__)\n\ndef _fetch_workflow_spec_for_validation(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[dict]:\n    \"\"\"Fetch a workflow spec, returning None on any error.\"\"\"\n    try:\n        return get_workflow_specification(\n            api_key=api_key,\n            workspace_id=workspace_name,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n        )\n    except Exception as error:\n        if _logger.isEnabledFor(logging.DEBUG):\n            _logger.debug(\n                \"Could not fetch workflow '%s' for compile-time validation (error type: %s)\",\n                workflow_id,\n                type(error).__name__,\n            )\n        return None",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/composition/workflow_caller/v1.py\nimport logging\nfrom typing import Optional\n\nfrom inference.core.roboflow_api import get_workflow_specification\n\n_logger = logging.getLogger(__name__)\n\ndef _fetch_workflow_spec_for_validation(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[dict]:\n    \"\"\"Fetch a workflow spec, returning None on any error.\"\"\"\n    try:\n        return get_workflow_specification(\n            api_key=api_key,\n            workspace_id=workspace_name,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n        )\n    except Exception as error:\n        if _logger.isEnabledFor(logging.DEBUG):\n            _logger.debug(\n                \"Could not fetch workflow '%s' for compile-time validation (error type: %s)\",\n                workflow_id,\n                type(error).__name__,\n            )\n        return None\n```",
    "optimized_function_only": "def _fetch_workflow_spec_for_validation(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[dict]:\n    \"\"\"Fetch a workflow spec, returning None on any error.\"\"\"\n    try:\n        return get_workflow_specification(\n            api_key=api_key,\n            workspace_id=workspace_name,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n        )\n    except Exception as error:\n        if _logger.isEnabledFor(logging.DEBUG):\n            _logger.debug(\n                \"Could not fetch workflow '%s' for compile-time validation (error type: %s)\",\n                workflow_id,\n                type(error).__name__,\n            )\n        return None",
    "original_file_content": "import logging\nimport re\nfrom functools import lru_cache\nfrom typing import Any, Callable, Dict, List, Literal, Optional, Tuple, Type, Union\n\nimport requests\nfrom pydantic import ConfigDict, Field, field_validator\n\nfrom inference.core.env import LOCAL_INFERENCE_API_URL\nfrom inference.core.roboflow_api import (\n    get_roboflow_workspace,\n    get_workflow_specification,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    DICTIONARY_KIND,\n    INTEGER_KIND,\n    STRING_KIND,\n    WILDCARD_KIND,\n    Kind,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nLONG_DESCRIPTION = \"\"\"\nThe **Workflow Caller** block enables calling another Roboflow workflow from within a workflow.\nThis is useful for composing complex pipelines from smaller, reusable workflow components.\n\n### How it works\n\nThe block takes a workflow ID (from the same workspace), passes inputs (including images)\nto the target workflow, executes it via HTTP, and returns the results.\n\n### Configuration\n\nSpecify the target workflow using `workflow_id` (just the workflow slug, not a full URL). The\nworkspace is resolved automatically from the API key used to run the parent workflow.\n\n```\nworkflow_id = \"my-detection-pipeline\"\n```\n\n### Inputs\n\nPass all inputs the target workflow expects via `inputs`, including images:\n\n```\ninputs = {\n    \"image\": \"$inputs.image\",\n    \"confidence_threshold\": 0.5,\n    \"model_id\": \"$inputs.model_id\",\n}\n```\n\nUse `input_definitions` to declare the expected input types so the UI can render\nproper connectors.\n\n### Circular Dependency Protection\n\nTo prevent infinite recursion (e.g. Workflow A calls B, B calls A), the block tracks the chain\nof workflow calls using a header. If a circular reference is detected, the block returns an error\ninstead of making the call.\n\n### Dynamic Outputs\n\nWhen the target workflow_id is a static string, the block resolves the target workflow's\noutputs at compile time. Each output from the target workflow becomes a separate output on\nthis block with proper Kind types. When the workflow_id is dynamic (a selector), outputs\nfall back to a single ``result`` dict.\n\n### Limitations\n\n* Only workflows within the same workspace are supported (v1).\n* Execution is done via HTTP call, which adds network latency.\n* Subject to the same timeout constraints as the hosting environment.\n\"\"\"\n\nWORKFLOW_CALL_CHAIN_HEADER = \"X-Roboflow-Workflow-Call-Chain\"\nMAX_WORKFLOW_CALL_DEPTH = 10\nWORKFLOW_CALLER_BLOCK_TYPE = \"roboflow_core/workflow_caller@v1\"\n\n# Module-level cache mapping (workflow_id, version_id) -> {output_name: [Kind]}.\n# Populated during compile-time validation, read by get_actual_outputs() and run().\n_RESOLVED_WORKFLOW_OUTPUTS: Dict[Tuple[str, Optional[str]], Dict[str, List[Kind]]] = {}\n\n# Module-level cache mapping (workflow_id, version_id) -> list of parsed input dicts\n# from spec.  Each dict has: name, type, kind, has_default.\n_RESOLVED_WORKFLOW_INPUTS: Dict[Tuple[str, Optional[str]], List[Dict[str, Any]]] = {}\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Workflow Caller\",\n            \"version\": \"v1\",\n            \"short_description\": \"Call another Roboflow workflow from within a workflow.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"transformation\",\n            \"ui_manifest\": {\n                \"section\": \"advanced\",\n                \"icon\": \"fal fa-diagram-subtask\",\n                \"blockPriority\": 2,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/workflow_caller@v1\"]\n    workflow_id: Union[Selector(kind=[STRING_KIND]), str] = Field(\n        description=\"The workflow ID to call (must be in the same workspace).\",\n        examples=[\"my-workflow-id\", \"$inputs.workflow_id\"],\n    )\n    workflow_version_id: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Optional version ID of the target workflow. When provided, \"\n        \"the block calls the specific version instead of the latest. \"\n        \"Use this to pin a dependency to a known-good version.\",\n        examples=[\"1709234567890\", \"$inputs.workflow_version\"],\n    )\n    inputs: Dict[\n        str,\n        Union[\n            Selector(),\n            str,\n            float,\n            bool,\n            int,\n            dict,\n            list,\n        ],\n    ] = Field(\n        default_factory=dict,\n        description=\"Inputs to pass to the target workflow, keyed by input name. \"\n        \"All inputs including images should be listed here.\",\n        examples=[\n            {\"image\": \"$inputs.image\", \"confidence_threshold\": 0.5},\n            {\"image\": \"$inputs.image\", \"model_id\": \"$inputs.model_id\"},\n        ],\n    )\n    request_timeout: Union[int, Selector(kind=[INTEGER_KIND])] = Field(\n        default=30,\n        description=\"HTTP request timeout in seconds.\",\n        examples=[\"$inputs.request_timeout\", 30],\n    )\n    input_definitions: Dict[str, List[str]] = Field(\n        default_factory=dict,\n        description=(\n            \"Mapping of expected input names to their kind types. \"\n            \"Each key is an input name in the target workflow, and the value \"\n            \"is a list of kind name strings (e.g. ['float'], ['roboflow_model_id']). \"\n            \"This tells the parent workflow what inputs the target expects, \"\n            \"enabling proper UI connectors. Actual values are provided via \"\n            \"'inputs'.\"\n        ),\n        examples=[\n            {\"image\": [\"image\"], \"confidence_threshold\": [\"float\"]},\n            {\n                \"image\": [\"image\"],\n                \"class_filter\": [\"string\"],\n                \"iou_threshold\": [\"float\"],\n            },\n        ],\n    )\n    output_definitions: Dict[str, List[str]] = Field(\n        default_factory=dict,\n        description=(\n            \"Mapping of expected output names to their kind types. \"\n            \"Each key is an output name from the target workflow, and the value \"\n            \"is a list of kind name strings (e.g. ['object_detection_prediction']). \"\n            \"This tells the parent workflow what types to expect, enabling proper \"\n            \"connections to downstream blocks like visualizers.\"\n        ),\n        examples=[\n            {\"predictions\": [\"object_detection_prediction\"]},\n            {\"result_image\": [\"image\"], \"count\": [\"integer\"]},\n        ],\n    )\n\n    @field_validator(\"workflow_id\")\n    @classmethod\n    def validate_workflow_id_slug(cls, value: Any) -> Any:\n        if isinstance(value, str) and not value.startswith(\"$\"):\n            if not re.fullmatch(r\"[\\w\\-]+\", value):\n                raise ValueError(\n                    f\"`workflow_id` must be a valid slug (letters, numbers, \"\n                    f\"hyphens, and underscores only). Got: '{value}'\"\n                )\n        return value\n\n    @field_validator(\"request_timeout\")\n    @classmethod\n    def ensure_request_timeout_is_positive(cls, value: Any) -> Any:\n        if isinstance(value, int) and value <= 0:\n            raise ValueError(\"`request_timeout` must be a positive integer.\")\n        return value\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return []\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"*\"),\n        ]\n\n    def get_actual_outputs(self) -> List[OutputDefinition]:\n        base: List[OutputDefinition] = []\n        # 1. User-defined output definitions take precedence\n        if self.output_definitions:\n            kind_name_map = _build_kind_name_map()\n            for name, kind_names in self.output_definitions.items():\n                kinds = [kind_name_map[k] for k in kind_names if k in kind_name_map]\n                base.append(OutputDefinition(name=name, kind=kinds or [WILDCARD_KIND]))\n            return base\n        # 2. Fall back to auto-discovery from compile-time resolution\n        if isinstance(self.workflow_id, str) and not self.workflow_id.startswith(\"$\"):\n            version_id = self.workflow_version_id\n            if isinstance(version_id, str) and version_id.startswith(\"$\"):\n                version_id = None\n            cache_key = _make_cache_key(self.workflow_id, version_id)\n            resolved = _RESOLVED_WORKFLOW_OUTPUTS.get(cache_key)\n            if resolved is not None:\n                for name, kinds in resolved.items():\n                    base.append(OutputDefinition(name=name, kind=kinds))\n                return base\n        # 3. Fall back to generic result dict\n        base.append(OutputDefinition(name=\"result\", kind=[DICTIONARY_KIND]))\n        return base\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass WorkflowCallerBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        api_key: Optional[str],\n        workflow_call_chain: Optional[str] = None,\n    ):\n        self._api_key = api_key\n        self._workspace_name: Optional[str] = None\n        self._workflow_call_chain = workflow_call_chain or \"\"\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"api_key\", \"workflow_call_chain\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        workflow_id: str,\n        inputs: Dict[str, Any],\n        request_timeout: int,\n        input_definitions: Dict[str, List[str]],\n        output_definitions: Dict[str, List[str]],\n        workflow_version_id: Optional[str] = None,\n    ) -> BlockResult:\n        workspace_name = self._resolve_workspace_name()\n        if workspace_name is None:\n            raise RuntimeError(\n                f\"Could not resolve workspace for workflow '{workflow_id}'. \"\n                f\"Ensure a valid API key is configured.\"\n            )\n        error_status, message, raw_outputs = call_workflow(\n            api_key=self._api_key,\n            workspace_name=workspace_name,\n            workflow_id=workflow_id,\n            inputs=inputs,\n            request_timeout=request_timeout,\n            call_chain=self._workflow_call_chain,\n            workflow_version_id=workflow_version_id,\n        )\n        if error_status:\n            raise RuntimeError(f\"Workflow '{workflow_id}' execution failed: {message}\")\n        result: Dict[str, Any] = {}\n        # Determine which outputs to extract and their kinds for deserialization\n        output_kinds_map = _resolve_output_kinds_for_run(\n            output_definitions=output_definitions,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n        )\n        if output_kinds_map is not None:\n            deserializers = _build_kinds_deserializers_map()\n            for output_name, output_kinds in output_kinds_map.items():\n                raw_value = raw_outputs.get(output_name)\n                result[output_name] = _deserialize_output_value(\n                    output_name=output_name,\n                    raw_value=raw_value,\n                    output_kinds=output_kinds,\n                    deserializers=deserializers,\n                )\n        else:\n            result[\"result\"] = raw_outputs\n        return result\n\n    def _resolve_workspace_name(self) -> Optional[str]:\n        if self._workspace_name is not None:\n            return self._workspace_name\n        if not self._api_key:\n            return None\n        try:\n            self._workspace_name = get_roboflow_workspace(api_key=self._api_key)\n            return self._workspace_name\n        except Exception as error:\n            logging.warning(\n                f\"Could not resolve workspace from API key. Error: {str(error)}\"\n            )\n            return None\n\n\ndef _make_cache_key(\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Tuple[str, Optional[str]]:\n    \"\"\"Build a cache key that accounts for both workflow_id and version_id.\"\"\"\n    return (workflow_id, workflow_version_id)\n\n\ndef call_workflow(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    inputs: Dict[str, Any],\n    request_timeout: int,\n    call_chain: Optional[str] = None,\n    workflow_version_id: Optional[str] = None,\n) -> Tuple[bool, str, dict]:\n    \"\"\"Execute a workflow call and return (error_status, message, result).\n\n    This function is separated from the block's run() to facilitate testing.\n    \"\"\"\n    current_chain = call_chain or \"\"\n    chain_entries = [entry for entry in current_chain.split(\",\") if entry]\n    if workflow_id in chain_entries:\n        logging.warning(\n            f\"Circular workflow call detected: \"\n            f\"'{workflow_id}' is already in call chain [{current_chain}].\"\n        )\n        return (\n            True,\n            f\"Circular workflow call detected: '{workflow_id}' is already \"\n            f\"in the call chain [{current_chain}]. Aborting to prevent \"\n            f\"infinite recursion.\",\n            {},\n        )\n    if len(chain_entries) >= MAX_WORKFLOW_CALL_DEPTH:\n        logging.warning(\n            f\"Workflow call depth limit ({MAX_WORKFLOW_CALL_DEPTH}) reached. \"\n            f\"Call chain: [{current_chain}].\"\n        )\n        return (\n            True,\n            f\"Workflow call depth limit ({MAX_WORKFLOW_CALL_DEPTH}) reached. \"\n            f\"Call chain: [{current_chain}].\",\n            {},\n        )\n    updated_chain = \",\".join([*chain_entries, workflow_id])\n    inputs = build_workflow_inputs(inputs=inputs)\n    return execute_workflow_request(\n        api_key=api_key,\n        workspace_name=workspace_name,\n        workflow_id=workflow_id,\n        inputs=inputs,\n        request_timeout=request_timeout,\n        call_chain=updated_chain,\n        workflow_version_id=workflow_version_id,\n    )\n\n\ndef build_workflow_inputs(\n    inputs: Dict[str, Any],\n) -> Dict[str, Any]:\n    \"\"\"Build the inputs dictionary for the target workflow.\n\n    Handles ``WorkflowImageData`` objects found in ``inputs`` by\n    automatically serialising them to the ``{type: base64, value: ...}``\n    format expected by the workflow HTTP API.\n    \"\"\"\n    resolved: Dict[str, Any] = {}\n    for key, value in inputs.items():\n        if isinstance(value, WorkflowImageData):\n            resolved[key] = {\n                \"type\": \"base64\",\n                \"value\": value.base64_image,\n            }\n        else:\n            resolved[key] = value\n    return resolved\n\n\ndef execute_workflow_request(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    inputs: Dict[str, Any],\n    request_timeout: int,\n    call_chain: str,\n    workflow_version_id: Optional[str] = None,\n) -> Tuple[bool, str, dict]:\n    \"\"\"Make the HTTP request to the target workflow and return\n    (error_status, message, result).\"\"\"\n    url = build_workflow_url(\n        workspace_name=workspace_name,\n        workflow_id=workflow_id,\n    )\n    payload: Dict[str, Any] = {\"inputs\": inputs}\n    if api_key is not None:\n        payload[\"api_key\"] = api_key\n    if workflow_version_id is not None:\n        payload[\"workflow_version_id\"] = workflow_version_id\n    headers = {WORKFLOW_CALL_CHAIN_HEADER: call_chain}\n    try:\n        response = requests.post(\n            url,\n            json=payload,\n            headers=headers,\n            timeout=request_timeout,\n        )\n        response.raise_for_status()\n        response_data = response.json()\n        outputs = response_data.get(\"outputs\", [])\n        result = outputs[0] if outputs else {}\n        return (\n            False,\n            \"Workflow executed successfully\",\n            result,\n        )\n    except Exception as error:\n        logging.warning(\n            f\"Could not execute workflow '{workflow_id}'. Error: {str(error)}\"\n        )\n        error_type = type(error).__name__\n        return (\n            True,\n            f\"Failed to execute workflow '{workflow_id}': {error_type}\",\n            {},\n        )\n\n\ndef build_workflow_url(workspace_name: str, workflow_id: str) -> str:\n    \"\"\"Build the URL for calling a workflow on the local inference server.\n\n    Uses LOCAL_INFERENCE_API_URL to call the workflow on the same inference\n    server instance that is running the parent workflow.\n    \"\"\"\n    base_url = LOCAL_INFERENCE_API_URL.rstrip(\"/\")\n    return f\"{base_url}/{workspace_name}/workflows/{workflow_id}\"\n\n\n# ---------------------------------------------------------------------------\n# Compile-time validation\n# ---------------------------------------------------------------------------\n\n\ndef validate_workflow_caller_no_circular_references(\n    steps: List[WorkflowBlockManifest],\n    api_key: Optional[str],\n) -> None:\n    \"\"\"Compile-time validation: check that workflow_caller blocks with static\n    workflow_id values don't create circular dependencies, resolve the target\n    workflow's input and output interfaces, and validate that required inputs\n    are provided.\n\n    Only validates when workflow_id is a literal string (not a selector like\n    ``$inputs.workflow_id``). Errors during spec fetching are logged as warnings\n    and do not block compilation \u2014 the runtime circular dependency check via\n    the call chain header provides an additional safety net.\n    \"\"\"\n    caller_steps = _extract_workflow_caller_steps(steps=steps)\n    if not caller_steps:\n        return\n    workspace_name = _resolve_workspace_for_validation(api_key=api_key)\n    if workspace_name is None:\n        return\n    for workflow_id, version_id, step_manifest in caller_steps:\n        spec = _fetch_workflow_spec_for_validation(\n            api_key=api_key,\n            workspace_name=workspace_name,\n            workflow_id=workflow_id,\n            workflow_version_id=version_id,\n        )\n        if spec is None:\n            continue\n        _check_workflow_for_circular_references(\n            api_key=api_key,\n            workspace_name=workspace_name,\n            target_workflow_id=workflow_id,\n            target_workflow_version_id=version_id,\n            visited=set(),\n            prefetched_spec=spec,\n        )\n        cache_key = _make_cache_key(workflow_id, version_id)\n        _resolve_and_cache_workflow_outputs(\n            cache_key=cache_key,\n            spec=spec,\n        )\n        _resolve_and_cache_workflow_inputs(\n            cache_key=cache_key,\n            spec=spec,\n        )\n        _validate_required_inputs(\n            workflow_id=workflow_id,\n            workflow_version_id=version_id,\n            step_manifest=step_manifest,\n        )\n\n\ndef _extract_workflow_caller_steps(\n    steps: List[WorkflowBlockManifest],\n) -> List[Tuple[str, Optional[str], WorkflowBlockManifest]]:\n    \"\"\"Extract (workflow_id, workflow_version_id, manifest) tuples from\n    workflow_caller steps that have literal (non-selector) workflow_id values.\"\"\"\n    result = []\n    for step in steps:\n        if not isinstance(step, BlockManifest):\n            continue\n        workflow_id = step.workflow_id\n        if isinstance(workflow_id, str) and not workflow_id.startswith(\"$\"):\n            version_id = step.workflow_version_id\n            # Only use version_id if it's a literal string (not a selector)\n            if isinstance(version_id, str) and version_id.startswith(\"$\"):\n                version_id = None\n            result.append((workflow_id, version_id, step))\n    return result\n\n\ndef _fetch_workflow_spec_for_validation(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[dict]:\n    \"\"\"Fetch a workflow spec, returning None on any error.\"\"\"\n    try:\n        return get_workflow_specification(\n            api_key=api_key,\n            workspace_id=workspace_name,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n        )\n    except Exception as error:\n        logging.debug(\n            \"Could not fetch workflow '%s' for compile-time validation (error type: %s)\",\n            workflow_id,\n            type(error).__name__,\n        )\n        return None\n\n\ndef _resolve_workspace_for_validation(\n    api_key: Optional[str],\n) -> Optional[str]:\n    if not api_key:\n        return None\n    try:\n        return get_roboflow_workspace(api_key=api_key)\n    except Exception as error:\n        logging.debug(\n            \"Could not resolve workspace for compile-time workflow validation (error type: %s)\",\n            type(error).__name__,\n        )\n        return None\n\n\ndef _check_workflow_for_circular_references(\n    api_key: Optional[str],\n    workspace_name: str,\n    target_workflow_id: str,\n    visited: set,\n    target_workflow_version_id: Optional[str] = None,\n    prefetched_spec: Optional[dict] = None,\n) -> None:\n    \"\"\"Recursively check if a target workflow creates a circular call chain.\n\n    Raises ``ExecutionGraphStructureError`` if a cycle is found. Silently\n    returns on any fetch error \u2014 the runtime check will catch those cases.\n\n    When ``prefetched_spec`` is provided it is used directly instead of\n    fetching the spec again.  The caller in\n    ``validate_workflow_caller_no_circular_references`` already fetches the\n    spec for the top-level workflow, so passing it here avoids a duplicate\n    API call.\n    \"\"\"\n    from inference.core.workflows.errors import ExecutionGraphStructureError\n\n    if target_workflow_id in visited:\n        chain = \" -> \".join([*visited, target_workflow_id])\n        raise ExecutionGraphStructureError(\n            public_message=(\n                f\"Circular workflow call detected at compile time: {chain}. \"\n                f\"This would cause infinite recursion at runtime.\"\n            ),\n            context=\"workflow_compilation | workflow_caller_validation\",\n        )\n    if prefetched_spec is not None:\n        spec = prefetched_spec\n    else:\n        try:\n            spec = get_workflow_specification(\n                api_key=api_key,\n                workspace_id=workspace_name,\n                workflow_id=target_workflow_id,\n                workflow_version_id=target_workflow_version_id,\n            )\n        except Exception as error:\n            logging.debug(\n                \"Could not fetch workflow '%s' for circular dependency check (error type: %s)\",\n                target_workflow_id,\n                type(error).__name__,\n            )\n            return\n    nested_workflows = _extract_workflow_caller_ids_from_spec(spec=spec)\n    if not nested_workflows:\n        return\n    visited_with_current = visited | {target_workflow_id}\n    for nested_id, nested_version_id in nested_workflows:\n        _check_workflow_for_circular_references(\n            api_key=api_key,\n            workspace_name=workspace_name,\n            target_workflow_id=nested_id,\n            target_workflow_version_id=nested_version_id,\n            visited=visited_with_current,\n        )\n\n\ndef _extract_workflow_caller_ids_from_spec(\n    spec: dict,\n) -> List[Tuple[str, Optional[str]]]:\n    \"\"\"Extract static (workflow_id, workflow_version_id) tuples from a raw\n    workflow specification.  Only includes entries where ``workflow_id`` is a\n    literal string (not a selector).  ``workflow_version_id`` is included when\n    it is a literal string, otherwise ``None``.\"\"\"\n    steps = spec.get(\"steps\", [])\n    result: List[Tuple[str, Optional[str]]] = []\n    for step in steps:\n        step_type = step.get(\"type\", \"\")\n        if step_type != WORKFLOW_CALLER_BLOCK_TYPE:\n            continue\n        workflow_id = step.get(\"workflow_id\", \"\")\n        if not isinstance(workflow_id, str) or workflow_id.startswith(\"$\"):\n            continue\n        version_id = step.get(\"workflow_version_id\")\n        if isinstance(version_id, str) and version_id.startswith(\"$\"):\n            version_id = None\n        result.append((workflow_id, version_id))\n    return result\n\n\n# ---------------------------------------------------------------------------\n# Output interface resolution\n# ---------------------------------------------------------------------------\n\n\ndef _resolve_and_cache_workflow_outputs(\n    cache_key: Tuple[str, Optional[str]],\n    spec: dict,\n) -> None:\n    \"\"\"Resolve the target workflow's output interface from its spec and cache\n    the result in ``_RESOLVED_WORKFLOW_OUTPUTS``.\n\n    Tries ``describe_workflow_outputs()`` for proper Kind resolution. Falls\n    back to extracting output names with ``WILDCARD_KIND`` on any error.\n    \"\"\"\n    try:\n        outputs_description = _describe_outputs_from_spec(spec=spec)\n    except Exception as error:\n        logging.debug(\n            f\"Could not resolve output kinds for workflow '{cache_key}' \"\n            f\"via describe_workflow_outputs: {error}. \"\n            f\"Falling back to output names with WILDCARD_KIND.\"\n        )\n        outputs_description = None\n\n    if outputs_description is not None:\n        resolved = _convert_output_descriptions_to_kinds(\n            outputs_description=outputs_description,\n        )\n    else:\n        resolved = _extract_output_names_with_wildcard(spec=spec)\n\n    if resolved:\n        _RESOLVED_WORKFLOW_OUTPUTS[cache_key] = resolved\n\n\ndef _describe_outputs_from_spec(\n    spec: dict,\n) -> Dict[str, Union[List[str], Dict[str, List[str]]]]:\n    \"\"\"Call the standard output discovery to resolve output kinds.\"\"\"\n    from inference.core.workflows.execution_engine.v1.introspection.outputs_discovery import (\n        describe_workflow_outputs,\n    )\n\n    return describe_workflow_outputs(definition=spec)\n\n\ndef _convert_output_descriptions_to_kinds(\n    outputs_description: Dict[str, Union[List[str], Dict[str, List[str]]]],\n) -> Dict[str, List[Kind]]:\n    \"\"\"Convert ``describe_workflow_outputs()`` result (kind name strings) to\n    ``Kind`` objects.\"\"\"\n    kind_name_map = _build_kind_name_map()\n    result: Dict[str, List[Kind]] = {}\n    for name, kind_info in outputs_description.items():\n        if isinstance(kind_info, dict):\n            # Wildcard selector ($steps.step.*) \u2014 nested structure.\n            # Represent as DICTIONARY_KIND since we can't express nested\n            # typed properties in a single OutputDefinition.\n            result[name] = [DICTIONARY_KIND]\n        else:\n            kinds = [kind_name_map[k] for k in kind_info if k in kind_name_map]\n            result[name] = kinds if kinds else [WILDCARD_KIND]\n    return result\n\n\ndef _extract_output_names_with_wildcard(\n    spec: dict,\n) -> Dict[str, List[Kind]]:\n    \"\"\"Fallback: extract just the output names and assign WILDCARD_KIND.\"\"\"\n    outputs = spec.get(\"outputs\", [])\n    result: Dict[str, List[Kind]] = {}\n    for output in outputs:\n        name = output.get(\"name\")\n        if name:\n            result[name] = [WILDCARD_KIND]\n    return result\n\n\n@lru_cache(maxsize=1)\ndef _build_kind_name_map() -> Dict[str, Kind]:\n    \"\"\"Build a mapping from kind name to Kind object using the loader.\n\n    Result is cached since the set of registered kinds does not change\n    within a process.\n    \"\"\"\n    from inference.core.workflows.core_steps.loader import load_kinds\n\n    return {kind.name: kind for kind in load_kinds()}\n\n\n# ---------------------------------------------------------------------------\n# Input interface resolution\n# ---------------------------------------------------------------------------\n\n\ndef _resolve_and_cache_workflow_inputs(\n    cache_key: Tuple[str, Optional[str]],\n    spec: dict,\n) -> None:\n    \"\"\"Parse the target workflow's input interface from its spec and cache\n    the result in ``_RESOLVED_WORKFLOW_INPUTS``.\n\n    Each input is stored as a dict with keys: name, type, has_default.\n    \"\"\"\n    raw_inputs = spec.get(\"inputs\", [])\n    parsed: List[Dict[str, Any]] = []\n    for inp in raw_inputs:\n        name = inp.get(\"name\")\n        if not name:\n            continue\n        inp_type = inp.get(\"type\", \"\")\n        parsed.append(\n            {\n                \"name\": name,\n                \"type\": inp_type,\n                \"has_default\": \"default_value\" in inp,\n            }\n        )\n    _RESOLVED_WORKFLOW_INPUTS[cache_key] = parsed\n\n\ndef _validate_required_inputs(\n    workflow_id: str,\n    step_manifest: BlockManifest,\n    workflow_version_id: Optional[str] = None,\n) -> None:\n    \"\"\"Validate that the workflow caller step provides all required inputs\n    that the target workflow expects.\n\n    Raises ``ExecutionGraphStructureError`` if:\n    - The target workflow has required parameters (no default) not covered by\n      ``inputs``.\n    - The user declared ``input_definitions`` but ``inputs`` does not\n      cover all declared input names.\n    \"\"\"\n    from inference.core.workflows.errors import ExecutionGraphStructureError\n\n    input_keys = set(step_manifest.inputs.keys())\n\n    # Validate user-declared input_definitions: every declared input must be\n    # present in inputs.\n    if step_manifest.input_definitions:\n        missing_declared = [\n            name for name in step_manifest.input_definitions if name not in input_keys\n        ]\n        if missing_declared:\n            raise ExecutionGraphStructureError(\n                public_message=(\n                    f\"Workflow caller step '{step_manifest.name}' declares \"\n                    f\"input_definitions for {list(step_manifest.input_definitions.keys())}, \"\n                    f\"but input(s) {missing_declared} are not provided in \"\n                    f\"'inputs'.\"\n                ),\n                context=\"workflow_compilation | workflow_caller_validation\",\n            )\n\n    cache_key = _make_cache_key(workflow_id, workflow_version_id)\n    resolved_inputs = _RESOLVED_WORKFLOW_INPUTS.get(cache_key)\n    if resolved_inputs is None:\n        return\n\n    missing = []\n    for inp in resolved_inputs:\n        if inp[\"has_default\"]:\n            continue\n        if inp[\"name\"] not in input_keys:\n            missing.append(inp[\"name\"])\n    if missing:\n        raise ExecutionGraphStructureError(\n            public_message=(\n                f\"Target workflow '{workflow_id}' requires input(s) \"\n                f\"{missing} (no default values), but they are not provided \"\n                f\"in 'inputs' on workflow_caller step \"\n                f\"'{step_manifest.name}'.\"\n            ),\n            context=\"workflow_compilation | workflow_caller_validation\",\n        )\n\n\n# ---------------------------------------------------------------------------\n# Output resolution for runtime\n# ---------------------------------------------------------------------------\n\n\ndef _resolve_output_kinds_for_run(\n    output_definitions: Dict[str, List[str]],\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[Dict[str, List[Kind]]]:\n    \"\"\"Determine which outputs to extract and their Kind objects.\n\n    Priority:\n    1. User-declared ``output_definitions`` (explicit kind names)\n    2. Auto-discovered outputs from ``_RESOLVED_WORKFLOW_OUTPUTS`` cache\n    3. Returns ``None`` \u2192 caller should fall back to generic ``result`` dict\n    \"\"\"\n    if output_definitions:\n        kind_name_map = _build_kind_name_map()\n        result: Dict[str, List[Kind]] = {}\n        for name, kind_names in output_definitions.items():\n            kinds = [kind_name_map[k] for k in kind_names if k in kind_name_map]\n            result[name] = kinds or [WILDCARD_KIND]\n        return result\n    cache_key = _make_cache_key(workflow_id, workflow_version_id)\n    resolved = _RESOLVED_WORKFLOW_OUTPUTS.get(cache_key)\n    if resolved is not None:\n        return resolved\n    return None\n\n\n# ---------------------------------------------------------------------------\n# Output deserialization\n# ---------------------------------------------------------------------------\n\n\n@lru_cache(maxsize=1)\ndef _build_kinds_deserializers_map() -> Dict[str, Callable[[str, Any], Any]]:\n    \"\"\"Build the map of kind name -> deserializer function.\n\n    Result is cached since the set of registered deserializers does not\n    change within a process.\n    \"\"\"\n    from inference.core.workflows.execution_engine.introspection.blocks_loader import (\n        load_kinds_deserializers,\n    )\n\n    return load_kinds_deserializers()\n\n\ndef _deserialize_output_value(\n    output_name: str,\n    raw_value: Any,\n    output_kinds: List[Kind],\n    deserializers: Dict[str, Callable[[str, Any], Any]],\n) -> Any:\n    \"\"\"Deserialize a single output value using the deserializer matching its\n    resolved kind.\n\n    For outputs with known kinds, deserialization is required \u2014 failure raises\n    an error so downstream blocks don't receive unexpected raw data. For\n    WILDCARD_KIND outputs the raw value is returned as-is since we don't know\n    the expected type.\n    \"\"\"\n    if raw_value is None:\n        return None\n    if all(kind == WILDCARD_KIND for kind in output_kinds):\n        return raw_value\n    errors: List[Tuple[str, Exception]] = []\n    for kind in output_kinds:\n        if kind == WILDCARD_KIND:\n            continue\n        if kind.name not in deserializers:\n            continue\n        try:\n            return deserializers[kind.name](output_name, raw_value)\n        except Exception as error:\n            errors.append((kind.name, error))\n            continue\n    if errors:\n        error_details = \"; \".join(f\"{kind}: {error}\" for kind, error in errors)\n        raise RuntimeError(\n            f\"Failed to deserialize output '{output_name}' from target \"\n            f\"workflow. Tried deserializers for kinds \"\n            f\"{[k for k, _ in errors]} but all failed: {error_details}. \"\n            f\"This likely means the target workflow's output format doesn't \"\n            f\"match the expected kind.\"\n        )\n    return raw_value\n",
    "patch": null
  },
  {
    "trace_id": "f0c2d0c8-5b55-4e8f-be6b-50f438b26f9a",
    "function_name": "Qwen35VLBlockV1.run",
    "file_path": "inference/core/workflows/core_steps/models/foundation/qwen3_5vl/v1.py",
    "speedup_x": 0.685419097065631,
    "review_quality": "high",
    "pre_optimization_commit": "c0249b396cecd814532f6b2a4c0abb4bd6c8c4f3",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n        system_prompt: Optional[str],\n    ) -> BlockResult:\n        if self._step_execution_mode == StepExecutionMode.LOCAL:\n            return self.run_locally(\n                images=images,\n                model_version=model_version,\n                prompt=prompt,\n                system_prompt=system_prompt,\n            )\n        elif self._step_execution_mode == StepExecutionMode.REMOTE:\n            return self.run_remotely(\n                images=images,\n                model_version=model_version,\n                prompt=prompt,\n                system_prompt=system_prompt,\n            )\n        else:\n            raise ValueError(\n                f\"Unknown step execution mode: {self._step_execution_mode}\"\n            )\n",
    "optimized_function_code": "##########################################################################\n# Qwen3.5-VL Workflow Block\n##########################################################################\nfrom typing import Optional\n\nfrom inference.core.entities.requests.inference import LMMInferenceRequest\nfrom inference.core.env import (HOSTED_CORE_MODEL_URL, LOCAL_INFERENCE_API_URL,\n                                WORKFLOWS_REMOTE_API_TARGET)\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.entities import \\\n    StepExecutionMode\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch, WorkflowImageData)\nfrom inference.core.workflows.prototypes.block import (BlockResult,\n                                                       WorkflowBlock)\nfrom inference_sdk import InferenceHTTPClient\n\n\nclass Qwen35VLBlockV1(WorkflowBlock):\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n        system_prompt: Optional[str],\n    ) -> BlockResult:\n        if self._step_execution_mode == StepExecutionMode.LOCAL:\n            return self.run_locally(\n                images=images,\n                model_version=model_version,\n                prompt=prompt,\n                system_prompt=system_prompt,\n            )\n        elif self._step_execution_mode == StepExecutionMode.REMOTE:\n            return self.run_remotely(\n                images=images,\n                model_version=model_version,\n                prompt=prompt,\n                system_prompt=system_prompt,\n            )\n        else:\n            raise ValueError(\n                f\"Unknown step execution mode: {self._step_execution_mode}\"\n            )\n\n    def run_remotely(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n        system_prompt: Optional[str],\n    ) -> BlockResult:\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_CORE_MODEL_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        if WORKFLOWS_REMOTE_API_TARGET == \"hosted\":\n            client.select_api_v0()\n\n        prompt = prompt or \"Describe what's in this image.\"\n        system_prompt = (\n            system_prompt\n            or \"You are a Qwen3.5-VL model that can answer questions about any image.\"\n        )\n        combined_prompt = prompt + \"<system_prompt>\" + system_prompt\n\n        predictions = []\n        if not images:\n            return predictions\n\n        inference_inputs = [image.base64_image for image in images]\n        result = client.infer_lmm(\n            inference_input=inference_inputs,\n            model_id=model_version,\n            prompt=combined_prompt,\n            model_id_in_path=True,\n        )\n\n        if isinstance(result, list):\n            for res in result:\n                response_text = res.get(\"response\", res)\n                predictions.append({\"parsed_output\": response_text})\n        else:\n            response_text = result.get(\"response\", result)\n            predictions.append({\"parsed_output\": response_text})\n\n        return predictions\n\n    def run_locally(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n        system_prompt: Optional[str],\n    ) -> BlockResult:\n        # Convert each image to the format required by the model.\n        inference_images = [\n            i.to_inference_format(numpy_preferred=False) for i in images\n        ]\n        # Use the provided prompt or default to a generic image description request.\n        prompt = prompt or \"Describe what's in this image.\"\n        system_prompt = (\n            system_prompt\n            or \"You are a Qwen3.5-VL model that can answer questions about any image.\"\n        )\n        prompts = [prompt + \"<system_prompt>\" + system_prompt] * len(inference_images)\n        # Register Qwen3.5-VL with the model manager.\n        self._model_manager.add_model(model_id=model_version, api_key=self._api_key)\n\n        predictions = []\n        for image, single_prompt in zip(inference_images, prompts):\n            # Build an LMMInferenceRequest with both prompt and image.\n            request = LMMInferenceRequest(\n                api_key=self._api_key,\n                model_id=model_version,\n                image=image,\n                source=\"workflow-execution\",\n                prompt=single_prompt,\n            )\n            # Run inference.\n            prediction = self._model_manager.infer_from_request_sync(\n                model_id=model_version, request=request\n            )\n            response_text = prediction.response\n            predictions.append(\n                {\n                    \"parsed_output\": response_text,\n                }\n            )\n        return predictions",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/models/foundation/qwen3_5vl/v1.py\n##########################################################################\n# Qwen3.5-VL Workflow Block\n##########################################################################\nfrom typing import Optional\n\nfrom inference.core.entities.requests.inference import LMMInferenceRequest\nfrom inference.core.env import (HOSTED_CORE_MODEL_URL, LOCAL_INFERENCE_API_URL,\n                                WORKFLOWS_REMOTE_API_TARGET)\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.entities import \\\n    StepExecutionMode\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch, WorkflowImageData)\nfrom inference.core.workflows.prototypes.block import (BlockResult,\n                                                       WorkflowBlock)\nfrom inference_sdk import InferenceHTTPClient\n\n\nclass Qwen35VLBlockV1(WorkflowBlock):\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n        system_prompt: Optional[str],\n    ) -> BlockResult:\n        if self._step_execution_mode == StepExecutionMode.LOCAL:\n            return self.run_locally(\n                images=images,\n                model_version=model_version,\n                prompt=prompt,\n                system_prompt=system_prompt,\n            )\n        elif self._step_execution_mode == StepExecutionMode.REMOTE:\n            return self.run_remotely(\n                images=images,\n                model_version=model_version,\n                prompt=prompt,\n                system_prompt=system_prompt,\n            )\n        else:\n            raise ValueError(\n                f\"Unknown step execution mode: {self._step_execution_mode}\"\n            )\n\n    def run_remotely(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n        system_prompt: Optional[str],\n    ) -> BlockResult:\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_CORE_MODEL_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        if WORKFLOWS_REMOTE_API_TARGET == \"hosted\":\n            client.select_api_v0()\n\n        prompt = prompt or \"Describe what's in this image.\"\n        system_prompt = (\n            system_prompt\n            or \"You are a Qwen3.5-VL model that can answer questions about any image.\"\n        )\n        combined_prompt = prompt + \"<system_prompt>\" + system_prompt\n\n        predictions = []\n        if not images:\n            return predictions\n\n        inference_inputs = [image.base64_image for image in images]\n        result = client.infer_lmm(\n            inference_input=inference_inputs,\n            model_id=model_version,\n            prompt=combined_prompt,\n            model_id_in_path=True,\n        )\n\n        if isinstance(result, list):\n            for res in result:\n                response_text = res.get(\"response\", res)\n                predictions.append({\"parsed_output\": response_text})\n        else:\n            response_text = result.get(\"response\", result)\n            predictions.append({\"parsed_output\": response_text})\n\n        return predictions\n\n    def run_locally(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n        system_prompt: Optional[str],\n    ) -> BlockResult:\n        # Convert each image to the format required by the model.\n        inference_images = [\n            i.to_inference_format(numpy_preferred=False) for i in images\n        ]\n        # Use the provided prompt or default to a generic image description request.\n        prompt = prompt or \"Describe what's in this image.\"\n        system_prompt = (\n            system_prompt\n            or \"You are a Qwen3.5-VL model that can answer questions about any image.\"\n        )\n        prompts = [prompt + \"<system_prompt>\" + system_prompt] * len(inference_images)\n        # Register Qwen3.5-VL with the model manager.\n        self._model_manager.add_model(model_id=model_version, api_key=self._api_key)\n\n        predictions = []\n        for image, single_prompt in zip(inference_images, prompts):\n            # Build an LMMInferenceRequest with both prompt and image.\n            request = LMMInferenceRequest(\n                api_key=self._api_key,\n                model_id=model_version,\n                image=image,\n                source=\"workflow-execution\",\n                prompt=single_prompt,\n            )\n            # Run inference.\n            prediction = self._model_manager.infer_from_request_sync(\n                model_id=model_version, request=request\n            )\n            response_text = prediction.response\n            predictions.append(\n                {\n                    \"parsed_output\": response_text,\n                }\n            )\n        return predictions\n```",
    "optimized_function_only": "    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n        system_prompt: Optional[str],\n    ) -> BlockResult:\n        if self._step_execution_mode == StepExecutionMode.LOCAL:\n            return self.run_locally(\n                images=images,\n                model_version=model_version,\n                prompt=prompt,\n                system_prompt=system_prompt,\n            )\n        elif self._step_execution_mode == StepExecutionMode.REMOTE:\n            return self.run_remotely(\n                images=images,\n                model_version=model_version,\n                prompt=prompt,\n                system_prompt=system_prompt,\n            )\n        else:\n            raise ValueError(\n                f\"Unknown step execution mode: {self._step_execution_mode}\"\n            )\n",
    "original_file_content": "import json\nfrom typing import List, Literal, Optional, Type, Union\n\nimport supervision as sv\nfrom pydantic import ConfigDict, Field\n\nfrom inference.core.entities.requests.inference import LMMInferenceRequest\nfrom inference.core.env import (\n    HOSTED_CORE_MODEL_URL,\n    LOCAL_INFERENCE_API_URL,\n    WORKFLOWS_REMOTE_API_TARGET,\n)\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.entities import StepExecutionMode\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    DICTIONARY_KIND,\n    IMAGE_KIND,\n    LANGUAGE_MODEL_OUTPUT_KIND,\n    ROBOFLOW_MODEL_ID_KIND,\n    STRING_KIND,\n    ImageInputField,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\nfrom inference_sdk import InferenceHTTPClient\n\n\n##########################################################################\n# Qwen3.5-VL Workflow Block Manifest\n##########################################################################\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Qwen3.5-VL\",\n            \"version\": \"v1\",\n            \"short_description\": \"Run Qwen3.5-VL on an image.\",\n            \"long_description\": (\n                \"This workflow block runs Qwen3.5-VL\u2014a vision language model that accepts an image \"\n                \"and an optional text prompt\u2014and returns a text answer based on a conversation template.\"\n            ),\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"model\",\n            \"search_keywords\": [\n                \"Qwen3.5\",\n                \"qwen3.5-vl\",\n                \"vision language model\",\n                \"VLM\",\n                \"Alibaba\",\n            ],\n            \"is_vlm_block\": True,\n            \"ui_manifest\": {\n                \"section\": \"model\",\n                \"icon\": \"fal fa-atom\",\n                \"blockPriority\": 5.7,\n            },\n        },\n        protected_namespaces=(),\n    )\n    type: Literal[\"roboflow_core/qwen3_5vl@v1\"]\n\n    images: Selector(kind=[IMAGE_KIND]) = ImageInputField\n    prompt: Optional[str] = Field(\n        default=None,\n        description=\"Optional text prompt to provide additional context to Qwen3.5-VL. Otherwise it will just be a default one, which may affect the desired model behavior.\",\n        examples=[\"What is in this image?\"],\n    )\n    model_version: Union[Selector(kind=[ROBOFLOW_MODEL_ID_KIND]), str] = Field(\n        default=\"qwen3_5-0.8b\",\n        description=\"The Qwen3.5-VL model to be used for inference.\",\n        examples=[\"qwen3_5-0.8b\", \"qwen3_5-2b\"],\n    )\n\n    system_prompt: Optional[str] = Field(\n        default=None,\n        description=\"Optional system prompt to provide additional context to Qwen3.5-VL.\",\n        examples=[\"You are a helpful assistant.\"],\n    )\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(\n                name=\"parsed_output\",\n                kind=[DICTIONARY_KIND],\n                description=\"A parsed version of the output, provided as a dictionary containing the text.\",\n            ),\n        ]\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        # Only images can be passed in as a list/batch\n        return [\"images\"]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\n##########################################################################\n# Qwen3.5-VL Workflow Block\n##########################################################################\nclass Qwen35VLBlockV1(WorkflowBlock):\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"model_manager\", \"api_key\", \"step_execution_mode\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n        system_prompt: Optional[str],\n    ) -> BlockResult:\n        if self._step_execution_mode == StepExecutionMode.LOCAL:\n            return self.run_locally(\n                images=images,\n                model_version=model_version,\n                prompt=prompt,\n                system_prompt=system_prompt,\n            )\n        elif self._step_execution_mode == StepExecutionMode.REMOTE:\n            return self.run_remotely(\n                images=images,\n                model_version=model_version,\n                prompt=prompt,\n                system_prompt=system_prompt,\n            )\n        else:\n            raise ValueError(\n                f\"Unknown step execution mode: {self._step_execution_mode}\"\n            )\n\n    def run_remotely(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n        system_prompt: Optional[str],\n    ) -> BlockResult:\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_CORE_MODEL_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        if WORKFLOWS_REMOTE_API_TARGET == \"hosted\":\n            client.select_api_v0()\n\n        prompt = prompt or \"Describe what's in this image.\"\n        system_prompt = (\n            system_prompt\n            or \"You are a Qwen3.5-VL model that can answer questions about any image.\"\n        )\n        combined_prompt = prompt + \"<system_prompt>\" + system_prompt\n\n        predictions = []\n        for image in images:\n            result = client.infer_lmm(\n                inference_input=image.base64_image,\n                model_id=model_version,\n                prompt=combined_prompt,\n                model_id_in_path=True,\n            )\n            response_text = result.get(\"response\", result)\n            predictions.append({\"parsed_output\": response_text})\n\n        return predictions\n\n    def run_locally(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n        system_prompt: Optional[str],\n    ) -> BlockResult:\n        # Convert each image to the format required by the model.\n        inference_images = [\n            i.to_inference_format(numpy_preferred=False) for i in images\n        ]\n        # Use the provided prompt or default to a generic image description request.\n        prompt = prompt or \"Describe what's in this image.\"\n        system_prompt = (\n            system_prompt\n            or \"You are a Qwen3.5-VL model that can answer questions about any image.\"\n        )\n        prompts = [prompt + \"<system_prompt>\" + system_prompt] * len(inference_images)\n        # Register Qwen3.5-VL with the model manager.\n        self._model_manager.add_model(model_id=model_version, api_key=self._api_key)\n\n        predictions = []\n        for image, single_prompt in zip(inference_images, prompts):\n            # Build an LMMInferenceRequest with both prompt and image.\n            request = LMMInferenceRequest(\n                api_key=self._api_key,\n                model_id=model_version,\n                image=image,\n                source=\"workflow-execution\",\n                prompt=single_prompt,\n            )\n            # Run inference.\n            prediction = self._model_manager.infer_from_request_sync(\n                model_id=model_version, request=request\n            )\n            response_text = prediction.response\n            predictions.append(\n                {\n                    \"parsed_output\": response_text,\n                }\n            )\n        return predictions\n",
    "patch": null
  },
  {
    "trace_id": "a1adcc45-80c0-4cce-8fe7-7f68145d6ea4",
    "function_name": "_deserialize_output_value",
    "file_path": "inference/core/workflows/core_steps/composition/workflow_caller/v1.py",
    "speedup_x": 0.11004580529026724,
    "review_quality": "high",
    "pre_optimization_commit": "0306c6c070caef88dea09d9b680c659f63b2ccc1",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def _deserialize_output_value(\n    output_name: str,\n    raw_value: Any,\n    output_kinds: List[Kind],\n    deserializers: Dict[str, Callable[[str, Any], Any]],\n) -> Any:\n    \"\"\"Deserialize a single output value using the deserializer matching its\n    resolved kind.\n\n    For outputs with known kinds, deserialization is required \u2014 failure raises\n    an error so downstream blocks don't receive unexpected raw data. For\n    WILDCARD_KIND outputs the raw value is returned as-is since we don't know\n    the expected type.\n    \"\"\"\n    if raw_value is None:\n        return None\n    if all(kind == WILDCARD_KIND for kind in output_kinds):\n        return raw_value\n    errors: List[Tuple[str, Exception]] = []\n    for kind in output_kinds:\n        if kind == WILDCARD_KIND:\n            continue\n        if kind.name not in deserializers:\n            continue\n        try:\n            return deserializers[kind.name](output_name, raw_value)\n        except Exception as error:\n            errors.append((kind.name, error))\n            continue\n    if errors:\n        error_details = \"; \".join(\n            f\"{kind}: {error}\" for kind, error in errors\n        )\n        raise RuntimeError(\n            f\"Failed to deserialize output '{output_name}' from target \"\n            f\"workflow. Tried deserializers for kinds \"\n            f\"{[k for k, _ in errors]} but all failed: {error_details}. \"\n            f\"This likely means the target workflow's output format doesn't \"\n            f\"match the expected kind.\"\n        )\n    return raw_value\n",
    "optimized_function_code": "from typing import Any, Callable, Dict, List, Tuple\n\nfrom inference.core.workflows.execution_engine.entities.types import (\n    WILDCARD_KIND, Kind)\n\n\ndef _deserialize_output_value(\n    output_name: str,\n    raw_value: Any,\n    output_kinds: List[Kind],\n    deserializers: Dict[str, Callable[[str, Any], Any]],\n) -> Any:\n    \"\"\"Deserialize a single output value using the deserializer matching its\n    resolved kind.\n\n    For outputs with known kinds, deserialization is required \u2014 failure raises\n    an error so downstream blocks don't receive unexpected raw data. For\n    WILDCARD_KIND outputs the raw value is returned as-is since we don't know\n    the expected type.\n    \"\"\"\n    if raw_value is None:\n        return None\n    errors: List[Tuple[str, Exception]] = []\n    seen_non_wildcard = False\n\n    for kind in output_kinds:\n        if kind == WILDCARD_KIND:\n            continue\n        seen_non_wildcard = True\n        kind_name = kind.name\n        if kind_name not in deserializers:\n            continue\n        try:\n            func = deserializers[kind_name]\n            return func(output_name, raw_value)\n        except Exception as error:\n            errors.append((kind_name, error))\n            continue\n\n    if not seen_non_wildcard:\n        return raw_value\n\n    if errors:\n        error_details = \"; \".join(\n            f\"{kind}: {error}\" for kind, error in errors\n        )\n        raise RuntimeError(\n            f\"Failed to deserialize output '{output_name}' from target \"\n            f\"workflow. Tried deserializers for kinds \"\n            f\"{[k for k, _ in errors]} but all failed: {error_details}. \"\n            f\"This likely means the target workflow's output format doesn't \"\n            f\"match the expected kind.\"\n        )\n    return raw_value",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/composition/workflow_caller/v1.py\nfrom typing import Any, Callable, Dict, List, Tuple\n\nfrom inference.core.workflows.execution_engine.entities.types import (\n    WILDCARD_KIND, Kind)\n\n\ndef _deserialize_output_value(\n    output_name: str,\n    raw_value: Any,\n    output_kinds: List[Kind],\n    deserializers: Dict[str, Callable[[str, Any], Any]],\n) -> Any:\n    \"\"\"Deserialize a single output value using the deserializer matching its\n    resolved kind.\n\n    For outputs with known kinds, deserialization is required \u2014 failure raises\n    an error so downstream blocks don't receive unexpected raw data. For\n    WILDCARD_KIND outputs the raw value is returned as-is since we don't know\n    the expected type.\n    \"\"\"\n    if raw_value is None:\n        return None\n    errors: List[Tuple[str, Exception]] = []\n    seen_non_wildcard = False\n\n    for kind in output_kinds:\n        if kind == WILDCARD_KIND:\n            continue\n        seen_non_wildcard = True\n        kind_name = kind.name\n        if kind_name not in deserializers:\n            continue\n        try:\n            func = deserializers[kind_name]\n            return func(output_name, raw_value)\n        except Exception as error:\n            errors.append((kind_name, error))\n            continue\n\n    if not seen_non_wildcard:\n        return raw_value\n\n    if errors:\n        error_details = \"; \".join(\n            f\"{kind}: {error}\" for kind, error in errors\n        )\n        raise RuntimeError(\n            f\"Failed to deserialize output '{output_name}' from target \"\n            f\"workflow. Tried deserializers for kinds \"\n            f\"{[k for k, _ in errors]} but all failed: {error_details}. \"\n            f\"This likely means the target workflow's output format doesn't \"\n            f\"match the expected kind.\"\n        )\n    return raw_value\n```",
    "optimized_function_only": "def _deserialize_output_value(\n    output_name: str,\n    raw_value: Any,\n    output_kinds: List[Kind],\n    deserializers: Dict[str, Callable[[str, Any], Any]],\n) -> Any:\n    \"\"\"Deserialize a single output value using the deserializer matching its\n    resolved kind.\n\n    For outputs with known kinds, deserialization is required \u2014 failure raises\n    an error so downstream blocks don't receive unexpected raw data. For\n    WILDCARD_KIND outputs the raw value is returned as-is since we don't know\n    the expected type.\n    \"\"\"\n    if raw_value is None:\n        return None\n    errors: List[Tuple[str, Exception]] = []\n    seen_non_wildcard = False\n\n    for kind in output_kinds:\n        if kind == WILDCARD_KIND:\n            continue\n        seen_non_wildcard = True\n        kind_name = kind.name\n        if kind_name not in deserializers:\n            continue\n        try:\n            func = deserializers[kind_name]\n            return func(output_name, raw_value)\n        except Exception as error:\n            errors.append((kind_name, error))\n            continue\n\n    if not seen_non_wildcard:\n        return raw_value\n\n    if errors:\n        error_details = \"; \".join(\n            f\"{kind}: {error}\" for kind, error in errors\n        )\n        raise RuntimeError(\n            f\"Failed to deserialize output '{output_name}' from target \"\n            f\"workflow. Tried deserializers for kinds \"\n            f\"{[k for k, _ in errors]} but all failed: {error_details}. \"\n            f\"This likely means the target workflow's output format doesn't \"\n            f\"match the expected kind.\"\n        )\n    return raw_value",
    "original_file_content": "import logging\nimport re\nfrom functools import lru_cache\nfrom typing import Any, Callable, Dict, List, Literal, Optional, Tuple, Type, Union\n\nimport requests\nfrom pydantic import ConfigDict, Field, field_validator\n\nfrom inference.core.env import LOCAL_INFERENCE_API_URL\nfrom inference.core.roboflow_api import get_roboflow_workspace, get_workflow_specification\nfrom inference.core.workflows.execution_engine.entities.base import (\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    DICTIONARY_KIND,\n    INTEGER_KIND,\n    STRING_KIND,\n    WILDCARD_KIND,\n    Kind,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nLONG_DESCRIPTION = \"\"\"\nThe **Workflow Caller** block enables calling another Roboflow workflow from within a workflow.\nThis is useful for composing complex pipelines from smaller, reusable workflow components.\n\n### How it works\n\nThe block takes a workflow ID (from the same workspace), passes inputs (including images)\nto the target workflow, executes it via HTTP, and returns the results.\n\n### Configuration\n\nSpecify the target workflow using `workflow_id` (just the workflow slug, not a full URL). The\nworkspace is resolved automatically from the API key used to run the parent workflow.\n\n```\nworkflow_id = \"my-detection-pipeline\"\n```\n\n### Inputs\n\nPass all inputs the target workflow expects via `inputs`, including images:\n\n```\ninputs = {\n    \"image\": \"$inputs.image\",\n    \"confidence_threshold\": 0.5,\n    \"model_id\": \"$inputs.model_id\",\n}\n```\n\nUse `input_definitions` to declare the expected input types so the UI can render\nproper connectors.\n\n### Circular Dependency Protection\n\nTo prevent infinite recursion (e.g. Workflow A calls B, B calls A), the block tracks the chain\nof workflow calls using a header. If a circular reference is detected, the block returns an error\ninstead of making the call.\n\n### Dynamic Outputs\n\nWhen the target workflow_id is a static string, the block resolves the target workflow's\noutputs at compile time. Each output from the target workflow becomes a separate output on\nthis block with proper Kind types. When the workflow_id is dynamic (a selector), outputs\nfall back to a single ``result`` dict.\n\n### Limitations\n\n* Only workflows within the same workspace are supported (v1).\n* Execution is done via HTTP call, which adds network latency.\n* Subject to the same timeout constraints as the hosting environment.\n\"\"\"\n\nWORKFLOW_CALL_CHAIN_HEADER = \"X-Roboflow-Workflow-Call-Chain\"\nMAX_WORKFLOW_CALL_DEPTH = 10\nWORKFLOW_CALLER_BLOCK_TYPE = \"roboflow_core/workflow_caller@v1\"\n\n# Module-level cache mapping (workflow_id, version_id) -> {output_name: [Kind]}.\n# Populated during compile-time validation, read by get_actual_outputs() and run().\n_RESOLVED_WORKFLOW_OUTPUTS: Dict[Tuple[str, Optional[str]], Dict[str, List[Kind]]] = {}\n\n# Module-level cache mapping (workflow_id, version_id) -> list of parsed input dicts\n# from spec.  Each dict has: name, type, kind, has_default.\n_RESOLVED_WORKFLOW_INPUTS: Dict[Tuple[str, Optional[str]], List[Dict[str, Any]]] = {}\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Workflow Caller\",\n            \"version\": \"v1\",\n            \"short_description\": \"Call another Roboflow workflow from within a workflow.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"transformation\",\n            \"ui_manifest\": {\n                \"section\": \"advanced\",\n                \"icon\": \"fal fa-diagram-subtask\",\n                \"blockPriority\": 2,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/workflow_caller@v1\"]\n    workflow_id: Union[Selector(kind=[STRING_KIND]), str] = Field(\n        description=\"The workflow ID to call (must be in the same workspace).\",\n        examples=[\"my-workflow-id\", \"$inputs.workflow_id\"],\n    )\n    workflow_version_id: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Optional version ID of the target workflow. When provided, \"\n        \"the block calls the specific version instead of the latest. \"\n        \"Use this to pin a dependency to a known-good version.\",\n        examples=[\"1709234567890\", \"$inputs.workflow_version\"],\n    )\n    inputs: Dict[\n        str,\n        Union[\n            Selector(),\n            str,\n            float,\n            bool,\n            int,\n            dict,\n            list,\n        ],\n    ] = Field(\n        default_factory=dict,\n        description=\"Inputs to pass to the target workflow, keyed by input name. \"\n        \"All inputs including images should be listed here.\",\n        examples=[\n            {\"image\": \"$inputs.image\", \"confidence_threshold\": 0.5},\n            {\"image\": \"$inputs.image\", \"model_id\": \"$inputs.model_id\"},\n        ],\n    )\n    request_timeout: Union[int, Selector(kind=[INTEGER_KIND])] = Field(\n        default=30,\n        description=\"HTTP request timeout in seconds.\",\n        examples=[\"$inputs.request_timeout\", 30],\n    )\n    input_definitions: Dict[str, List[str]] = Field(\n        default_factory=dict,\n        description=(\n            \"Mapping of expected input names to their kind types. \"\n            \"Each key is an input name in the target workflow, and the value \"\n            \"is a list of kind name strings (e.g. ['float'], ['roboflow_model_id']). \"\n            \"This tells the parent workflow what inputs the target expects, \"\n            \"enabling proper UI connectors. Actual values are provided via \"\n            \"'inputs'.\"\n        ),\n        examples=[\n            {\"image\": [\"image\"], \"confidence_threshold\": [\"float\"]},\n            {\"image\": [\"image\"], \"class_filter\": [\"string\"], \"iou_threshold\": [\"float\"]},\n        ],\n    )\n    output_definitions: Dict[str, List[str]] = Field(\n        default_factory=dict,\n        description=(\n            \"Mapping of expected output names to their kind types. \"\n            \"Each key is an output name from the target workflow, and the value \"\n            \"is a list of kind name strings (e.g. ['object_detection_prediction']). \"\n            \"This tells the parent workflow what types to expect, enabling proper \"\n            \"connections to downstream blocks like visualizers.\"\n        ),\n        examples=[\n            {\"predictions\": [\"object_detection_prediction\"]},\n            {\"result_image\": [\"image\"], \"count\": [\"integer\"]},\n        ],\n    )\n\n    @field_validator(\"workflow_id\")\n    @classmethod\n    def validate_workflow_id_slug(cls, value: Any) -> Any:\n        if isinstance(value, str) and not value.startswith(\"$\"):\n            if not re.fullmatch(r\"[\\w\\-]+\", value):\n                raise ValueError(\n                    f\"`workflow_id` must be a valid slug (letters, numbers, \"\n                    f\"hyphens, and underscores only). Got: '{value}'\"\n                )\n        return value\n\n    @field_validator(\"request_timeout\")\n    @classmethod\n    def ensure_request_timeout_is_positive(cls, value: Any) -> Any:\n        if isinstance(value, int) and value <= 0:\n            raise ValueError(\"`request_timeout` must be a positive integer.\")\n        return value\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return []\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"*\"),\n        ]\n\n    def get_actual_outputs(self) -> List[OutputDefinition]:\n        base: List[OutputDefinition] = []\n        # 1. User-defined output definitions take precedence\n        if self.output_definitions:\n            kind_name_map = _build_kind_name_map()\n            for name, kind_names in self.output_definitions.items():\n                kinds = [\n                    kind_name_map[k] for k in kind_names if k in kind_name_map\n                ]\n                base.append(\n                    OutputDefinition(name=name, kind=kinds or [WILDCARD_KIND])\n                )\n            return base\n        # 2. Fall back to auto-discovery from compile-time resolution\n        if isinstance(self.workflow_id, str) and not self.workflow_id.startswith(\"$\"):\n            version_id = self.workflow_version_id\n            if isinstance(version_id, str) and version_id.startswith(\"$\"):\n                version_id = None\n            cache_key = _make_cache_key(self.workflow_id, version_id)\n            resolved = _RESOLVED_WORKFLOW_OUTPUTS.get(cache_key)\n            if resolved is not None:\n                for name, kinds in resolved.items():\n                    base.append(OutputDefinition(name=name, kind=kinds))\n                return base\n        # 3. Fall back to generic result dict\n        base.append(OutputDefinition(name=\"result\", kind=[DICTIONARY_KIND]))\n        return base\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass WorkflowCallerBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        api_key: Optional[str],\n        workflow_call_chain: Optional[str] = None,\n    ):\n        self._api_key = api_key\n        self._workspace_name: Optional[str] = None\n        self._workflow_call_chain = workflow_call_chain or \"\"\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"api_key\", \"workflow_call_chain\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        workflow_id: str,\n        inputs: Dict[str, Any],\n        request_timeout: int,\n        input_definitions: Dict[str, List[str]],\n        output_definitions: Dict[str, List[str]],\n        workflow_version_id: Optional[str] = None,\n    ) -> BlockResult:\n        workspace_name = self._resolve_workspace_name()\n        if workspace_name is None:\n            raise RuntimeError(\n                f\"Could not resolve workspace for workflow '{workflow_id}'. \"\n                f\"Ensure a valid API key is configured.\"\n            )\n        error_status, message, raw_outputs = call_workflow(\n            api_key=self._api_key,\n            workspace_name=workspace_name,\n            workflow_id=workflow_id,\n            inputs=inputs,\n            request_timeout=request_timeout,\n            call_chain=self._workflow_call_chain,\n            workflow_version_id=workflow_version_id,\n        )\n        if error_status:\n            raise RuntimeError(\n                f\"Workflow '{workflow_id}' execution failed: {message}\"\n            )\n        result: Dict[str, Any] = {}\n        # Determine which outputs to extract and their kinds for deserialization\n        output_kinds_map = _resolve_output_kinds_for_run(\n            output_definitions=output_definitions,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n        )\n        if output_kinds_map is not None:\n            deserializers = _build_kinds_deserializers_map()\n            for output_name, output_kinds in output_kinds_map.items():\n                raw_value = raw_outputs.get(output_name)\n                result[output_name] = _deserialize_output_value(\n                    output_name=output_name,\n                    raw_value=raw_value,\n                    output_kinds=output_kinds,\n                    deserializers=deserializers,\n                )\n        else:\n            result[\"result\"] = raw_outputs\n        return result\n\n    def _resolve_workspace_name(self) -> Optional[str]:\n        if self._workspace_name is not None:\n            return self._workspace_name\n        if not self._api_key:\n            return None\n        try:\n            self._workspace_name = get_roboflow_workspace(api_key=self._api_key)\n            return self._workspace_name\n        except Exception as error:\n            logging.warning(\n                f\"Could not resolve workspace from API key. Error: {str(error)}\"\n            )\n            return None\n\n\ndef _make_cache_key(\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Tuple[str, Optional[str]]:\n    \"\"\"Build a cache key that accounts for both workflow_id and version_id.\"\"\"\n    return (workflow_id, workflow_version_id)\n\n\ndef call_workflow(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    inputs: Dict[str, Any],\n    request_timeout: int,\n    call_chain: Optional[str] = None,\n    workflow_version_id: Optional[str] = None,\n) -> Tuple[bool, str, dict]:\n    \"\"\"Execute a workflow call and return (error_status, message, result).\n\n    This function is separated from the block's run() to facilitate testing.\n    \"\"\"\n    current_chain = call_chain or \"\"\n    chain_entries = [entry for entry in current_chain.split(\",\") if entry]\n    if workflow_id in chain_entries:\n        logging.warning(\n            f\"Circular workflow call detected: \"\n            f\"'{workflow_id}' is already in call chain [{current_chain}].\"\n        )\n        return (\n            True,\n            f\"Circular workflow call detected: '{workflow_id}' is already \"\n            f\"in the call chain [{current_chain}]. Aborting to prevent \"\n            f\"infinite recursion.\",\n            {},\n        )\n    if len(chain_entries) >= MAX_WORKFLOW_CALL_DEPTH:\n        logging.warning(\n            f\"Workflow call depth limit ({MAX_WORKFLOW_CALL_DEPTH}) reached. \"\n            f\"Call chain: [{current_chain}].\"\n        )\n        return (\n            True,\n            f\"Workflow call depth limit ({MAX_WORKFLOW_CALL_DEPTH}) reached. \"\n            f\"Call chain: [{current_chain}].\",\n            {},\n        )\n    updated_chain = \",\".join([*chain_entries, workflow_id])\n    inputs = build_workflow_inputs(inputs=inputs)\n    return execute_workflow_request(\n        api_key=api_key,\n        workspace_name=workspace_name,\n        workflow_id=workflow_id,\n        inputs=inputs,\n        request_timeout=request_timeout,\n        call_chain=updated_chain,\n        workflow_version_id=workflow_version_id,\n    )\n\n\ndef build_workflow_inputs(\n    inputs: Dict[str, Any],\n) -> Dict[str, Any]:\n    \"\"\"Build the inputs dictionary for the target workflow.\n\n    Handles ``WorkflowImageData`` objects found in ``inputs`` by\n    automatically serialising them to the ``{type: base64, value: ...}``\n    format expected by the workflow HTTP API.\n    \"\"\"\n    resolved: Dict[str, Any] = {}\n    for key, value in inputs.items():\n        if isinstance(value, WorkflowImageData):\n            resolved[key] = {\n                \"type\": \"base64\",\n                \"value\": value.base64_image,\n            }\n        else:\n            resolved[key] = value\n    return resolved\n\n\ndef execute_workflow_request(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    inputs: Dict[str, Any],\n    request_timeout: int,\n    call_chain: str,\n    workflow_version_id: Optional[str] = None,\n) -> Tuple[bool, str, dict]:\n    \"\"\"Make the HTTP request to the target workflow and return\n    (error_status, message, result).\"\"\"\n    url = build_workflow_url(\n        workspace_name=workspace_name,\n        workflow_id=workflow_id,\n    )\n    payload: Dict[str, Any] = {\"inputs\": inputs}\n    if api_key is not None:\n        payload[\"api_key\"] = api_key\n    if workflow_version_id is not None:\n        payload[\"workflow_version_id\"] = workflow_version_id\n    headers = {WORKFLOW_CALL_CHAIN_HEADER: call_chain}\n    try:\n        response = requests.post(\n            url,\n            json=payload,\n            headers=headers,\n            timeout=request_timeout,\n        )\n        response.raise_for_status()\n        response_data = response.json()\n        outputs = response_data.get(\"outputs\", [])\n        result = outputs[0] if outputs else {}\n        return (\n            False,\n            \"Workflow executed successfully\",\n            result,\n        )\n    except Exception as error:\n        logging.warning(\n            f\"Could not execute workflow '{workflow_id}'. Error: {str(error)}\"\n        )\n        error_type = type(error).__name__\n        return (\n            True,\n            f\"Failed to execute workflow '{workflow_id}': {error_type}\",\n            {},\n        )\n\n\ndef build_workflow_url(workspace_name: str, workflow_id: str) -> str:\n    \"\"\"Build the URL for calling a workflow on the local inference server.\n\n    Uses LOCAL_INFERENCE_API_URL to call the workflow on the same inference\n    server instance that is running the parent workflow.\n    \"\"\"\n    base_url = LOCAL_INFERENCE_API_URL.rstrip(\"/\")\n    return f\"{base_url}/{workspace_name}/workflows/{workflow_id}\"\n\n\n# ---------------------------------------------------------------------------\n# Compile-time validation\n# ---------------------------------------------------------------------------\n\n\ndef validate_workflow_caller_no_circular_references(\n    steps: List[WorkflowBlockManifest],\n    api_key: Optional[str],\n) -> None:\n    \"\"\"Compile-time validation: check that workflow_caller blocks with static\n    workflow_id values don't create circular dependencies, resolve the target\n    workflow's input and output interfaces, and validate that required inputs\n    are provided.\n\n    Only validates when workflow_id is a literal string (not a selector like\n    ``$inputs.workflow_id``). Errors during spec fetching are logged as warnings\n    and do not block compilation \u2014 the runtime circular dependency check via\n    the call chain header provides an additional safety net.\n    \"\"\"\n    caller_steps = _extract_workflow_caller_steps(steps=steps)\n    if not caller_steps:\n        return\n    workspace_name = _resolve_workspace_for_validation(api_key=api_key)\n    if workspace_name is None:\n        return\n    for workflow_id, version_id, step_manifest in caller_steps:\n        spec = _fetch_workflow_spec_for_validation(\n            api_key=api_key,\n            workspace_name=workspace_name,\n            workflow_id=workflow_id,\n            workflow_version_id=version_id,\n        )\n        if spec is None:\n            continue\n        _check_workflow_for_circular_references(\n            api_key=api_key,\n            workspace_name=workspace_name,\n            target_workflow_id=workflow_id,\n            target_workflow_version_id=version_id,\n            visited=set(),\n            prefetched_spec=spec,\n        )\n        cache_key = _make_cache_key(workflow_id, version_id)\n        _resolve_and_cache_workflow_outputs(\n            cache_key=cache_key,\n            spec=spec,\n        )\n        _resolve_and_cache_workflow_inputs(\n            cache_key=cache_key,\n            spec=spec,\n        )\n        _validate_required_inputs(\n            workflow_id=workflow_id,\n            workflow_version_id=version_id,\n            step_manifest=step_manifest,\n        )\n\n\ndef _extract_workflow_caller_steps(\n    steps: List[WorkflowBlockManifest],\n) -> List[Tuple[str, Optional[str], WorkflowBlockManifest]]:\n    \"\"\"Extract (workflow_id, workflow_version_id, manifest) tuples from\n    workflow_caller steps that have literal (non-selector) workflow_id values.\"\"\"\n    result = []\n    for step in steps:\n        if not isinstance(step, BlockManifest):\n            continue\n        workflow_id = step.workflow_id\n        if isinstance(workflow_id, str) and not workflow_id.startswith(\"$\"):\n            version_id = step.workflow_version_id\n            # Only use version_id if it's a literal string (not a selector)\n            if isinstance(version_id, str) and version_id.startswith(\"$\"):\n                version_id = None\n            result.append((workflow_id, version_id, step))\n    return result\n\n\ndef _fetch_workflow_spec_for_validation(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[dict]:\n    \"\"\"Fetch a workflow spec, returning None on any error.\"\"\"\n    try:\n        return get_workflow_specification(\n            api_key=api_key,\n            workspace_id=workspace_name,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n        )\n    except Exception as error:\n        logging.debug(\n            \"Could not fetch workflow '%s' for compile-time validation (error type: %s)\",\n            workflow_id,\n            type(error).__name__,\n        )\n        return None\n\n\ndef _resolve_workspace_for_validation(\n    api_key: Optional[str],\n) -> Optional[str]:\n    if not api_key:\n        return None\n    try:\n        return get_roboflow_workspace(api_key=api_key)\n    except Exception as error:\n        logging.debug(\n            \"Could not resolve workspace for compile-time workflow validation (error type: %s)\",\n            type(error).__name__,\n        )\n        return None\n\n\ndef _check_workflow_for_circular_references(\n    api_key: Optional[str],\n    workspace_name: str,\n    target_workflow_id: str,\n    visited: set,\n    target_workflow_version_id: Optional[str] = None,\n    prefetched_spec: Optional[dict] = None,\n) -> None:\n    \"\"\"Recursively check if a target workflow creates a circular call chain.\n\n    Raises ``ExecutionGraphStructureError`` if a cycle is found. Silently\n    returns on any fetch error \u2014 the runtime check will catch those cases.\n\n    When ``prefetched_spec`` is provided it is used directly instead of\n    fetching the spec again.  The caller in\n    ``validate_workflow_caller_no_circular_references`` already fetches the\n    spec for the top-level workflow, so passing it here avoids a duplicate\n    API call.\n    \"\"\"\n    from inference.core.workflows.errors import ExecutionGraphStructureError\n\n    if target_workflow_id in visited:\n        chain = \" -> \".join([*visited, target_workflow_id])\n        raise ExecutionGraphStructureError(\n            public_message=(\n                f\"Circular workflow call detected at compile time: {chain}. \"\n                f\"This would cause infinite recursion at runtime.\"\n            ),\n            context=\"workflow_compilation | workflow_caller_validation\",\n        )\n    if prefetched_spec is not None:\n        spec = prefetched_spec\n    else:\n        try:\n            spec = get_workflow_specification(\n                api_key=api_key,\n                workspace_id=workspace_name,\n                workflow_id=target_workflow_id,\n                workflow_version_id=target_workflow_version_id,\n            )\n        except Exception as error:\n            logging.debug(\n                \"Could not fetch workflow '%s' for circular dependency check (error type: %s)\",\n                target_workflow_id,\n                type(error).__name__,\n            )\n            return\n    nested_workflows = _extract_workflow_caller_ids_from_spec(spec=spec)\n    if not nested_workflows:\n        return\n    visited_with_current = visited | {target_workflow_id}\n    for nested_id, nested_version_id in nested_workflows:\n        _check_workflow_for_circular_references(\n            api_key=api_key,\n            workspace_name=workspace_name,\n            target_workflow_id=nested_id,\n            target_workflow_version_id=nested_version_id,\n            visited=visited_with_current,\n        )\n\n\ndef _extract_workflow_caller_ids_from_spec(\n    spec: dict,\n) -> List[Tuple[str, Optional[str]]]:\n    \"\"\"Extract static (workflow_id, workflow_version_id) tuples from a raw\n    workflow specification.  Only includes entries where ``workflow_id`` is a\n    literal string (not a selector).  ``workflow_version_id`` is included when\n    it is a literal string, otherwise ``None``.\"\"\"\n    steps = spec.get(\"steps\", [])\n    result: List[Tuple[str, Optional[str]]] = []\n    for step in steps:\n        step_type = step.get(\"type\", \"\")\n        if step_type != WORKFLOW_CALLER_BLOCK_TYPE:\n            continue\n        workflow_id = step.get(\"workflow_id\", \"\")\n        if not isinstance(workflow_id, str) or workflow_id.startswith(\"$\"):\n            continue\n        version_id = step.get(\"workflow_version_id\")\n        if isinstance(version_id, str) and version_id.startswith(\"$\"):\n            version_id = None\n        result.append((workflow_id, version_id))\n    return result\n\n\n# ---------------------------------------------------------------------------\n# Output interface resolution\n# ---------------------------------------------------------------------------\n\n\ndef _resolve_and_cache_workflow_outputs(\n    cache_key: Tuple[str, Optional[str]],\n    spec: dict,\n) -> None:\n    \"\"\"Resolve the target workflow's output interface from its spec and cache\n    the result in ``_RESOLVED_WORKFLOW_OUTPUTS``.\n\n    Tries ``describe_workflow_outputs()`` for proper Kind resolution. Falls\n    back to extracting output names with ``WILDCARD_KIND`` on any error.\n    \"\"\"\n    try:\n        outputs_description = _describe_outputs_from_spec(spec=spec)\n    except Exception as error:\n        logging.debug(\n            f\"Could not resolve output kinds for workflow '{cache_key}' \"\n            f\"via describe_workflow_outputs: {error}. \"\n            f\"Falling back to output names with WILDCARD_KIND.\"\n        )\n        outputs_description = None\n\n    if outputs_description is not None:\n        resolved = _convert_output_descriptions_to_kinds(\n            outputs_description=outputs_description,\n        )\n    else:\n        resolved = _extract_output_names_with_wildcard(spec=spec)\n\n    if resolved:\n        _RESOLVED_WORKFLOW_OUTPUTS[cache_key] = resolved\n\n\ndef _describe_outputs_from_spec(\n    spec: dict,\n) -> Dict[str, Union[List[str], Dict[str, List[str]]]]:\n    \"\"\"Call the standard output discovery to resolve output kinds.\"\"\"\n    from inference.core.workflows.execution_engine.v1.introspection.outputs_discovery import (\n        describe_workflow_outputs,\n    )\n\n    return describe_workflow_outputs(definition=spec)\n\n\ndef _convert_output_descriptions_to_kinds(\n    outputs_description: Dict[str, Union[List[str], Dict[str, List[str]]]],\n) -> Dict[str, List[Kind]]:\n    \"\"\"Convert ``describe_workflow_outputs()`` result (kind name strings) to\n    ``Kind`` objects.\"\"\"\n    kind_name_map = _build_kind_name_map()\n    result: Dict[str, List[Kind]] = {}\n    for name, kind_info in outputs_description.items():\n        if isinstance(kind_info, dict):\n            # Wildcard selector ($steps.step.*) \u2014 nested structure.\n            # Represent as DICTIONARY_KIND since we can't express nested\n            # typed properties in a single OutputDefinition.\n            result[name] = [DICTIONARY_KIND]\n        else:\n            kinds = [\n                kind_name_map[k]\n                for k in kind_info\n                if k in kind_name_map\n            ]\n            result[name] = kinds if kinds else [WILDCARD_KIND]\n    return result\n\n\ndef _extract_output_names_with_wildcard(\n    spec: dict,\n) -> Dict[str, List[Kind]]:\n    \"\"\"Fallback: extract just the output names and assign WILDCARD_KIND.\"\"\"\n    outputs = spec.get(\"outputs\", [])\n    result: Dict[str, List[Kind]] = {}\n    for output in outputs:\n        name = output.get(\"name\")\n        if name:\n            result[name] = [WILDCARD_KIND]\n    return result\n\n\n@lru_cache(maxsize=1)\ndef _build_kind_name_map() -> Dict[str, Kind]:\n    \"\"\"Build a mapping from kind name to Kind object using the loader.\n\n    Result is cached since the set of registered kinds does not change\n    within a process.\n    \"\"\"\n    from inference.core.workflows.core_steps.loader import load_kinds\n\n    return {kind.name: kind for kind in load_kinds()}\n\n\n# ---------------------------------------------------------------------------\n# Input interface resolution\n# ---------------------------------------------------------------------------\n\n\ndef _resolve_and_cache_workflow_inputs(\n    cache_key: Tuple[str, Optional[str]],\n    spec: dict,\n) -> None:\n    \"\"\"Parse the target workflow's input interface from its spec and cache\n    the result in ``_RESOLVED_WORKFLOW_INPUTS``.\n\n    Each input is stored as a dict with keys: name, type, has_default.\n    \"\"\"\n    raw_inputs = spec.get(\"inputs\", [])\n    parsed: List[Dict[str, Any]] = []\n    for inp in raw_inputs:\n        name = inp.get(\"name\")\n        if not name:\n            continue\n        inp_type = inp.get(\"type\", \"\")\n        parsed.append({\n            \"name\": name,\n            \"type\": inp_type,\n            \"has_default\": \"default_value\" in inp,\n        })\n    _RESOLVED_WORKFLOW_INPUTS[cache_key] = parsed\n\n\ndef _validate_required_inputs(\n    workflow_id: str,\n    step_manifest: BlockManifest,\n    workflow_version_id: Optional[str] = None,\n) -> None:\n    \"\"\"Validate that the workflow caller step provides all required inputs\n    that the target workflow expects.\n\n    Raises ``ExecutionGraphStructureError`` if:\n    - The target workflow has required parameters (no default) not covered by\n      ``inputs``.\n    - The user declared ``input_definitions`` but ``inputs`` does not\n      cover all declared input names.\n    \"\"\"\n    from inference.core.workflows.errors import ExecutionGraphStructureError\n\n    input_keys = set(step_manifest.inputs.keys())\n\n    # Validate user-declared input_definitions: every declared input must be\n    # present in inputs.\n    if step_manifest.input_definitions:\n        missing_declared = [\n            name for name in step_manifest.input_definitions\n            if name not in input_keys\n        ]\n        if missing_declared:\n            raise ExecutionGraphStructureError(\n                public_message=(\n                    f\"Workflow caller step '{step_manifest.name}' declares \"\n                    f\"input_definitions for {list(step_manifest.input_definitions.keys())}, \"\n                    f\"but input(s) {missing_declared} are not provided in \"\n                    f\"'inputs'.\"\n                ),\n                context=\"workflow_compilation | workflow_caller_validation\",\n            )\n\n    cache_key = _make_cache_key(workflow_id, workflow_version_id)\n    resolved_inputs = _RESOLVED_WORKFLOW_INPUTS.get(cache_key)\n    if resolved_inputs is None:\n        return\n\n    missing = []\n    for inp in resolved_inputs:\n        if inp[\"has_default\"]:\n            continue\n        if inp[\"name\"] not in input_keys:\n            missing.append(inp[\"name\"])\n    if missing:\n        raise ExecutionGraphStructureError(\n            public_message=(\n                f\"Target workflow '{workflow_id}' requires input(s) \"\n                f\"{missing} (no default values), but they are not provided \"\n                f\"in 'inputs' on workflow_caller step \"\n                f\"'{step_manifest.name}'.\"\n            ),\n            context=\"workflow_compilation | workflow_caller_validation\",\n        )\n\n\n# ---------------------------------------------------------------------------\n# Output resolution for runtime\n# ---------------------------------------------------------------------------\n\n\ndef _resolve_output_kinds_for_run(\n    output_definitions: Dict[str, List[str]],\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[Dict[str, List[Kind]]]:\n    \"\"\"Determine which outputs to extract and their Kind objects.\n\n    Priority:\n    1. User-declared ``output_definitions`` (explicit kind names)\n    2. Auto-discovered outputs from ``_RESOLVED_WORKFLOW_OUTPUTS`` cache\n    3. Returns ``None`` \u2192 caller should fall back to generic ``result`` dict\n    \"\"\"\n    if output_definitions:\n        kind_name_map = _build_kind_name_map()\n        result: Dict[str, List[Kind]] = {}\n        for name, kind_names in output_definitions.items():\n            kinds = [\n                kind_name_map[k] for k in kind_names if k in kind_name_map\n            ]\n            result[name] = kinds or [WILDCARD_KIND]\n        return result\n    cache_key = _make_cache_key(workflow_id, workflow_version_id)\n    resolved = _RESOLVED_WORKFLOW_OUTPUTS.get(cache_key)\n    if resolved is not None:\n        return resolved\n    return None\n\n\n# ---------------------------------------------------------------------------\n# Output deserialization\n# ---------------------------------------------------------------------------\n\n\n@lru_cache(maxsize=1)\ndef _build_kinds_deserializers_map() -> Dict[str, Callable[[str, Any], Any]]:\n    \"\"\"Build the map of kind name -> deserializer function.\n\n    Result is cached since the set of registered deserializers does not\n    change within a process.\n    \"\"\"\n    from inference.core.workflows.execution_engine.introspection.blocks_loader import (\n        load_kinds_deserializers,\n    )\n\n    return load_kinds_deserializers()\n\n\ndef _deserialize_output_value(\n    output_name: str,\n    raw_value: Any,\n    output_kinds: List[Kind],\n    deserializers: Dict[str, Callable[[str, Any], Any]],\n) -> Any:\n    \"\"\"Deserialize a single output value using the deserializer matching its\n    resolved kind.\n\n    For outputs with known kinds, deserialization is required \u2014 failure raises\n    an error so downstream blocks don't receive unexpected raw data. For\n    WILDCARD_KIND outputs the raw value is returned as-is since we don't know\n    the expected type.\n    \"\"\"\n    if raw_value is None:\n        return None\n    if all(kind == WILDCARD_KIND for kind in output_kinds):\n        return raw_value\n    errors: List[Tuple[str, Exception]] = []\n    for kind in output_kinds:\n        if kind == WILDCARD_KIND:\n            continue\n        if kind.name not in deserializers:\n            continue\n        try:\n            return deserializers[kind.name](output_name, raw_value)\n        except Exception as error:\n            errors.append((kind.name, error))\n            continue\n    if errors:\n        error_details = \"; \".join(\n            f\"{kind}: {error}\" for kind, error in errors\n        )\n        raise RuntimeError(\n            f\"Failed to deserialize output '{output_name}' from target \"\n            f\"workflow. Tried deserializers for kinds \"\n            f\"{[k for k, _ in errors]} but all failed: {error_details}. \"\n            f\"This likely means the target workflow's output format doesn't \"\n            f\"match the expected kind.\"\n        )\n    return raw_value\n",
    "patch": null
  },
  {
    "trace_id": "66462362-bc98-4f4f-b1e3-e31b073b73ab",
    "function_name": "_resolve_output_kinds_for_run",
    "file_path": "inference/core/workflows/core_steps/composition/workflow_caller/v1.py",
    "speedup_x": 0.11638574977128933,
    "review_quality": "high",
    "pre_optimization_commit": "0306c6c070caef88dea09d9b680c659f63b2ccc1",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def _resolve_output_kinds_for_run(\n    output_definitions: Dict[str, List[str]],\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[Dict[str, List[Kind]]]:\n    \"\"\"Determine which outputs to extract and their Kind objects.\n\n    Priority:\n    1. User-declared ``output_definitions`` (explicit kind names)\n    2. Auto-discovered outputs from ``_RESOLVED_WORKFLOW_OUTPUTS`` cache\n    3. Returns ``None`` \u2192 caller should fall back to generic ``result`` dict\n    \"\"\"\n    if output_definitions:\n        kind_name_map = _build_kind_name_map()\n        result: Dict[str, List[Kind]] = {}\n        for name, kind_names in output_definitions.items():\n            kinds = [\n                kind_name_map[k] for k in kind_names if k in kind_name_map\n            ]\n            result[name] = kinds or [WILDCARD_KIND]\n        return result\n    cache_key = _make_cache_key(workflow_id, workflow_version_id)\n    resolved = _RESOLVED_WORKFLOW_OUTPUTS.get(cache_key)\n    if resolved is not None:\n        return resolved\n    return None\n",
    "optimized_function_code": "from typing import Dict, List, Optional, Tuple\n\nfrom inference.core.workflows.execution_engine.entities.types import (\n    WILDCARD_KIND, Kind)\n\n_RESOLVED_WORKFLOW_OUTPUTS: Dict[Tuple[str, Optional[str]], Dict[str, List[Kind]]] = {}\n\n\n\n# Build kind name map once at module load time\n_KIND_NAME_MAP: Dict[str, Kind] = {}\n\n\ndef _initialize_kind_name_map() -> None:\n    \"\"\"Initialize the kind name map at module load time.\"\"\"\n    global _KIND_NAME_MAP\n    if not _KIND_NAME_MAP:\n        from inference.core.workflows.core_steps.loader import load_kinds\n        _KIND_NAME_MAP = {kind.name: kind for kind in load_kinds()}\n\n\ndef _make_cache_key(\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Tuple[str, Optional[str]]:\n    \"\"\"Build a cache key that accounts for both workflow_id and version_id.\"\"\"\n    return (workflow_id, workflow_version_id)\n\n\n# ---------------------------------------------------------------------------\n# Output resolution for runtime\n# ---------------------------------------------------------------------------\n\n\ndef _resolve_output_kinds_for_run(\n    output_definitions: Dict[str, List[str]],\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[Dict[str, List[Kind]]]:\n    \"\"\"Determine which outputs to extract and their Kind objects.\n\n    Priority:\n    1. User-declared ``output_definitions`` (explicit kind names)\n    2. Auto-discovered outputs from ``_RESOLVED_WORKFLOW_OUTPUTS`` cache\n    3. Returns ``None`` \u2192 caller should fall back to generic ``result`` dict\n    \"\"\"\n    if output_definitions:\n        if not _KIND_NAME_MAP:\n            _initialize_kind_name_map()\n        \n        result: Dict[str, List[Kind]] = {}\n        for name, kind_names in output_definitions.items():\n            kinds = [_KIND_NAME_MAP[k] for k in kind_names if k in _KIND_NAME_MAP]\n            result[name] = kinds or [WILDCARD_KIND]\n        return result\n    cache_key = _make_cache_key(workflow_id, workflow_version_id)\n    resolved = _RESOLVED_WORKFLOW_OUTPUTS.get(cache_key)\n    if resolved is not None:\n        return resolved\n    return None",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/composition/workflow_caller/v1.py\nfrom typing import Dict, List, Optional, Tuple\n\nfrom inference.core.workflows.execution_engine.entities.types import (\n    WILDCARD_KIND, Kind)\n\n_RESOLVED_WORKFLOW_OUTPUTS: Dict[Tuple[str, Optional[str]], Dict[str, List[Kind]]] = {}\n\n\n\n# Build kind name map once at module load time\n_KIND_NAME_MAP: Dict[str, Kind] = {}\n\n\ndef _initialize_kind_name_map() -> None:\n    \"\"\"Initialize the kind name map at module load time.\"\"\"\n    global _KIND_NAME_MAP\n    if not _KIND_NAME_MAP:\n        from inference.core.workflows.core_steps.loader import load_kinds\n        _KIND_NAME_MAP = {kind.name: kind for kind in load_kinds()}\n\n\ndef _make_cache_key(\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Tuple[str, Optional[str]]:\n    \"\"\"Build a cache key that accounts for both workflow_id and version_id.\"\"\"\n    return (workflow_id, workflow_version_id)\n\n\n# ---------------------------------------------------------------------------\n# Output resolution for runtime\n# ---------------------------------------------------------------------------\n\n\ndef _resolve_output_kinds_for_run(\n    output_definitions: Dict[str, List[str]],\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[Dict[str, List[Kind]]]:\n    \"\"\"Determine which outputs to extract and their Kind objects.\n\n    Priority:\n    1. User-declared ``output_definitions`` (explicit kind names)\n    2. Auto-discovered outputs from ``_RESOLVED_WORKFLOW_OUTPUTS`` cache\n    3. Returns ``None`` \u2192 caller should fall back to generic ``result`` dict\n    \"\"\"\n    if output_definitions:\n        if not _KIND_NAME_MAP:\n            _initialize_kind_name_map()\n        \n        result: Dict[str, List[Kind]] = {}\n        for name, kind_names in output_definitions.items():\n            kinds = [_KIND_NAME_MAP[k] for k in kind_names if k in _KIND_NAME_MAP]\n            result[name] = kinds or [WILDCARD_KIND]\n        return result\n    cache_key = _make_cache_key(workflow_id, workflow_version_id)\n    resolved = _RESOLVED_WORKFLOW_OUTPUTS.get(cache_key)\n    if resolved is not None:\n        return resolved\n    return None\n```",
    "optimized_function_only": "def _resolve_output_kinds_for_run(\n    output_definitions: Dict[str, List[str]],\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[Dict[str, List[Kind]]]:\n    \"\"\"Determine which outputs to extract and their Kind objects.\n\n    Priority:\n    1. User-declared ``output_definitions`` (explicit kind names)\n    2. Auto-discovered outputs from ``_RESOLVED_WORKFLOW_OUTPUTS`` cache\n    3. Returns ``None`` \u2192 caller should fall back to generic ``result`` dict\n    \"\"\"\n    if output_definitions:\n        if not _KIND_NAME_MAP:\n            _initialize_kind_name_map()\n        \n        result: Dict[str, List[Kind]] = {}\n        for name, kind_names in output_definitions.items():\n            kinds = [_KIND_NAME_MAP[k] for k in kind_names if k in _KIND_NAME_MAP]\n            result[name] = kinds or [WILDCARD_KIND]\n        return result\n    cache_key = _make_cache_key(workflow_id, workflow_version_id)\n    resolved = _RESOLVED_WORKFLOW_OUTPUTS.get(cache_key)\n    if resolved is not None:\n        return resolved\n    return None",
    "original_file_content": "import logging\nimport re\nfrom functools import lru_cache\nfrom typing import Any, Callable, Dict, List, Literal, Optional, Tuple, Type, Union\n\nimport requests\nfrom pydantic import ConfigDict, Field, field_validator\n\nfrom inference.core.env import LOCAL_INFERENCE_API_URL\nfrom inference.core.roboflow_api import get_roboflow_workspace, get_workflow_specification\nfrom inference.core.workflows.execution_engine.entities.base import (\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    DICTIONARY_KIND,\n    INTEGER_KIND,\n    STRING_KIND,\n    WILDCARD_KIND,\n    Kind,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nLONG_DESCRIPTION = \"\"\"\nThe **Workflow Caller** block enables calling another Roboflow workflow from within a workflow.\nThis is useful for composing complex pipelines from smaller, reusable workflow components.\n\n### How it works\n\nThe block takes a workflow ID (from the same workspace), passes inputs (including images)\nto the target workflow, executes it via HTTP, and returns the results.\n\n### Configuration\n\nSpecify the target workflow using `workflow_id` (just the workflow slug, not a full URL). The\nworkspace is resolved automatically from the API key used to run the parent workflow.\n\n```\nworkflow_id = \"my-detection-pipeline\"\n```\n\n### Inputs\n\nPass all inputs the target workflow expects via `inputs`, including images:\n\n```\ninputs = {\n    \"image\": \"$inputs.image\",\n    \"confidence_threshold\": 0.5,\n    \"model_id\": \"$inputs.model_id\",\n}\n```\n\nUse `input_definitions` to declare the expected input types so the UI can render\nproper connectors.\n\n### Circular Dependency Protection\n\nTo prevent infinite recursion (e.g. Workflow A calls B, B calls A), the block tracks the chain\nof workflow calls using a header. If a circular reference is detected, the block returns an error\ninstead of making the call.\n\n### Dynamic Outputs\n\nWhen the target workflow_id is a static string, the block resolves the target workflow's\noutputs at compile time. Each output from the target workflow becomes a separate output on\nthis block with proper Kind types. When the workflow_id is dynamic (a selector), outputs\nfall back to a single ``result`` dict.\n\n### Limitations\n\n* Only workflows within the same workspace are supported (v1).\n* Execution is done via HTTP call, which adds network latency.\n* Subject to the same timeout constraints as the hosting environment.\n\"\"\"\n\nWORKFLOW_CALL_CHAIN_HEADER = \"X-Roboflow-Workflow-Call-Chain\"\nMAX_WORKFLOW_CALL_DEPTH = 10\nWORKFLOW_CALLER_BLOCK_TYPE = \"roboflow_core/workflow_caller@v1\"\n\n# Module-level cache mapping (workflow_id, version_id) -> {output_name: [Kind]}.\n# Populated during compile-time validation, read by get_actual_outputs() and run().\n_RESOLVED_WORKFLOW_OUTPUTS: Dict[Tuple[str, Optional[str]], Dict[str, List[Kind]]] = {}\n\n# Module-level cache mapping (workflow_id, version_id) -> list of parsed input dicts\n# from spec.  Each dict has: name, type, kind, has_default.\n_RESOLVED_WORKFLOW_INPUTS: Dict[Tuple[str, Optional[str]], List[Dict[str, Any]]] = {}\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Workflow Caller\",\n            \"version\": \"v1\",\n            \"short_description\": \"Call another Roboflow workflow from within a workflow.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"transformation\",\n            \"ui_manifest\": {\n                \"section\": \"advanced\",\n                \"icon\": \"fal fa-diagram-subtask\",\n                \"blockPriority\": 2,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/workflow_caller@v1\"]\n    workflow_id: Union[Selector(kind=[STRING_KIND]), str] = Field(\n        description=\"The workflow ID to call (must be in the same workspace).\",\n        examples=[\"my-workflow-id\", \"$inputs.workflow_id\"],\n    )\n    workflow_version_id: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Optional version ID of the target workflow. When provided, \"\n        \"the block calls the specific version instead of the latest. \"\n        \"Use this to pin a dependency to a known-good version.\",\n        examples=[\"1709234567890\", \"$inputs.workflow_version\"],\n    )\n    inputs: Dict[\n        str,\n        Union[\n            Selector(),\n            str,\n            float,\n            bool,\n            int,\n            dict,\n            list,\n        ],\n    ] = Field(\n        default_factory=dict,\n        description=\"Inputs to pass to the target workflow, keyed by input name. \"\n        \"All inputs including images should be listed here.\",\n        examples=[\n            {\"image\": \"$inputs.image\", \"confidence_threshold\": 0.5},\n            {\"image\": \"$inputs.image\", \"model_id\": \"$inputs.model_id\"},\n        ],\n    )\n    request_timeout: Union[int, Selector(kind=[INTEGER_KIND])] = Field(\n        default=30,\n        description=\"HTTP request timeout in seconds.\",\n        examples=[\"$inputs.request_timeout\", 30],\n    )\n    input_definitions: Dict[str, List[str]] = Field(\n        default_factory=dict,\n        description=(\n            \"Mapping of expected input names to their kind types. \"\n            \"Each key is an input name in the target workflow, and the value \"\n            \"is a list of kind name strings (e.g. ['float'], ['roboflow_model_id']). \"\n            \"This tells the parent workflow what inputs the target expects, \"\n            \"enabling proper UI connectors. Actual values are provided via \"\n            \"'inputs'.\"\n        ),\n        examples=[\n            {\"image\": [\"image\"], \"confidence_threshold\": [\"float\"]},\n            {\"image\": [\"image\"], \"class_filter\": [\"string\"], \"iou_threshold\": [\"float\"]},\n        ],\n    )\n    output_definitions: Dict[str, List[str]] = Field(\n        default_factory=dict,\n        description=(\n            \"Mapping of expected output names to their kind types. \"\n            \"Each key is an output name from the target workflow, and the value \"\n            \"is a list of kind name strings (e.g. ['object_detection_prediction']). \"\n            \"This tells the parent workflow what types to expect, enabling proper \"\n            \"connections to downstream blocks like visualizers.\"\n        ),\n        examples=[\n            {\"predictions\": [\"object_detection_prediction\"]},\n            {\"result_image\": [\"image\"], \"count\": [\"integer\"]},\n        ],\n    )\n\n    @field_validator(\"workflow_id\")\n    @classmethod\n    def validate_workflow_id_slug(cls, value: Any) -> Any:\n        if isinstance(value, str) and not value.startswith(\"$\"):\n            if not re.fullmatch(r\"[\\w\\-]+\", value):\n                raise ValueError(\n                    f\"`workflow_id` must be a valid slug (letters, numbers, \"\n                    f\"hyphens, and underscores only). Got: '{value}'\"\n                )\n        return value\n\n    @field_validator(\"request_timeout\")\n    @classmethod\n    def ensure_request_timeout_is_positive(cls, value: Any) -> Any:\n        if isinstance(value, int) and value <= 0:\n            raise ValueError(\"`request_timeout` must be a positive integer.\")\n        return value\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return []\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"*\"),\n        ]\n\n    def get_actual_outputs(self) -> List[OutputDefinition]:\n        base: List[OutputDefinition] = []\n        # 1. User-defined output definitions take precedence\n        if self.output_definitions:\n            kind_name_map = _build_kind_name_map()\n            for name, kind_names in self.output_definitions.items():\n                kinds = [\n                    kind_name_map[k] for k in kind_names if k in kind_name_map\n                ]\n                base.append(\n                    OutputDefinition(name=name, kind=kinds or [WILDCARD_KIND])\n                )\n            return base\n        # 2. Fall back to auto-discovery from compile-time resolution\n        if isinstance(self.workflow_id, str) and not self.workflow_id.startswith(\"$\"):\n            version_id = self.workflow_version_id\n            if isinstance(version_id, str) and version_id.startswith(\"$\"):\n                version_id = None\n            cache_key = _make_cache_key(self.workflow_id, version_id)\n            resolved = _RESOLVED_WORKFLOW_OUTPUTS.get(cache_key)\n            if resolved is not None:\n                for name, kinds in resolved.items():\n                    base.append(OutputDefinition(name=name, kind=kinds))\n                return base\n        # 3. Fall back to generic result dict\n        base.append(OutputDefinition(name=\"result\", kind=[DICTIONARY_KIND]))\n        return base\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass WorkflowCallerBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        api_key: Optional[str],\n        workflow_call_chain: Optional[str] = None,\n    ):\n        self._api_key = api_key\n        self._workspace_name: Optional[str] = None\n        self._workflow_call_chain = workflow_call_chain or \"\"\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"api_key\", \"workflow_call_chain\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        workflow_id: str,\n        inputs: Dict[str, Any],\n        request_timeout: int,\n        input_definitions: Dict[str, List[str]],\n        output_definitions: Dict[str, List[str]],\n        workflow_version_id: Optional[str] = None,\n    ) -> BlockResult:\n        workspace_name = self._resolve_workspace_name()\n        if workspace_name is None:\n            raise RuntimeError(\n                f\"Could not resolve workspace for workflow '{workflow_id}'. \"\n                f\"Ensure a valid API key is configured.\"\n            )\n        error_status, message, raw_outputs = call_workflow(\n            api_key=self._api_key,\n            workspace_name=workspace_name,\n            workflow_id=workflow_id,\n            inputs=inputs,\n            request_timeout=request_timeout,\n            call_chain=self._workflow_call_chain,\n            workflow_version_id=workflow_version_id,\n        )\n        if error_status:\n            raise RuntimeError(\n                f\"Workflow '{workflow_id}' execution failed: {message}\"\n            )\n        result: Dict[str, Any] = {}\n        # Determine which outputs to extract and their kinds for deserialization\n        output_kinds_map = _resolve_output_kinds_for_run(\n            output_definitions=output_definitions,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n        )\n        if output_kinds_map is not None:\n            deserializers = _build_kinds_deserializers_map()\n            for output_name, output_kinds in output_kinds_map.items():\n                raw_value = raw_outputs.get(output_name)\n                result[output_name] = _deserialize_output_value(\n                    output_name=output_name,\n                    raw_value=raw_value,\n                    output_kinds=output_kinds,\n                    deserializers=deserializers,\n                )\n        else:\n            result[\"result\"] = raw_outputs\n        return result\n\n    def _resolve_workspace_name(self) -> Optional[str]:\n        if self._workspace_name is not None:\n            return self._workspace_name\n        if not self._api_key:\n            return None\n        try:\n            self._workspace_name = get_roboflow_workspace(api_key=self._api_key)\n            return self._workspace_name\n        except Exception as error:\n            logging.warning(\n                f\"Could not resolve workspace from API key. Error: {str(error)}\"\n            )\n            return None\n\n\ndef _make_cache_key(\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Tuple[str, Optional[str]]:\n    \"\"\"Build a cache key that accounts for both workflow_id and version_id.\"\"\"\n    return (workflow_id, workflow_version_id)\n\n\ndef call_workflow(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    inputs: Dict[str, Any],\n    request_timeout: int,\n    call_chain: Optional[str] = None,\n    workflow_version_id: Optional[str] = None,\n) -> Tuple[bool, str, dict]:\n    \"\"\"Execute a workflow call and return (error_status, message, result).\n\n    This function is separated from the block's run() to facilitate testing.\n    \"\"\"\n    current_chain = call_chain or \"\"\n    chain_entries = [entry for entry in current_chain.split(\",\") if entry]\n    if workflow_id in chain_entries:\n        logging.warning(\n            f\"Circular workflow call detected: \"\n            f\"'{workflow_id}' is already in call chain [{current_chain}].\"\n        )\n        return (\n            True,\n            f\"Circular workflow call detected: '{workflow_id}' is already \"\n            f\"in the call chain [{current_chain}]. Aborting to prevent \"\n            f\"infinite recursion.\",\n            {},\n        )\n    if len(chain_entries) >= MAX_WORKFLOW_CALL_DEPTH:\n        logging.warning(\n            f\"Workflow call depth limit ({MAX_WORKFLOW_CALL_DEPTH}) reached. \"\n            f\"Call chain: [{current_chain}].\"\n        )\n        return (\n            True,\n            f\"Workflow call depth limit ({MAX_WORKFLOW_CALL_DEPTH}) reached. \"\n            f\"Call chain: [{current_chain}].\",\n            {},\n        )\n    updated_chain = \",\".join([*chain_entries, workflow_id])\n    inputs = build_workflow_inputs(inputs=inputs)\n    return execute_workflow_request(\n        api_key=api_key,\n        workspace_name=workspace_name,\n        workflow_id=workflow_id,\n        inputs=inputs,\n        request_timeout=request_timeout,\n        call_chain=updated_chain,\n        workflow_version_id=workflow_version_id,\n    )\n\n\ndef build_workflow_inputs(\n    inputs: Dict[str, Any],\n) -> Dict[str, Any]:\n    \"\"\"Build the inputs dictionary for the target workflow.\n\n    Handles ``WorkflowImageData`` objects found in ``inputs`` by\n    automatically serialising them to the ``{type: base64, value: ...}``\n    format expected by the workflow HTTP API.\n    \"\"\"\n    resolved: Dict[str, Any] = {}\n    for key, value in inputs.items():\n        if isinstance(value, WorkflowImageData):\n            resolved[key] = {\n                \"type\": \"base64\",\n                \"value\": value.base64_image,\n            }\n        else:\n            resolved[key] = value\n    return resolved\n\n\ndef execute_workflow_request(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    inputs: Dict[str, Any],\n    request_timeout: int,\n    call_chain: str,\n    workflow_version_id: Optional[str] = None,\n) -> Tuple[bool, str, dict]:\n    \"\"\"Make the HTTP request to the target workflow and return\n    (error_status, message, result).\"\"\"\n    url = build_workflow_url(\n        workspace_name=workspace_name,\n        workflow_id=workflow_id,\n    )\n    payload: Dict[str, Any] = {\"inputs\": inputs}\n    if api_key is not None:\n        payload[\"api_key\"] = api_key\n    if workflow_version_id is not None:\n        payload[\"workflow_version_id\"] = workflow_version_id\n    headers = {WORKFLOW_CALL_CHAIN_HEADER: call_chain}\n    try:\n        response = requests.post(\n            url,\n            json=payload,\n            headers=headers,\n            timeout=request_timeout,\n        )\n        response.raise_for_status()\n        response_data = response.json()\n        outputs = response_data.get(\"outputs\", [])\n        result = outputs[0] if outputs else {}\n        return (\n            False,\n            \"Workflow executed successfully\",\n            result,\n        )\n    except Exception as error:\n        logging.warning(\n            f\"Could not execute workflow '{workflow_id}'. Error: {str(error)}\"\n        )\n        error_type = type(error).__name__\n        return (\n            True,\n            f\"Failed to execute workflow '{workflow_id}': {error_type}\",\n            {},\n        )\n\n\ndef build_workflow_url(workspace_name: str, workflow_id: str) -> str:\n    \"\"\"Build the URL for calling a workflow on the local inference server.\n\n    Uses LOCAL_INFERENCE_API_URL to call the workflow on the same inference\n    server instance that is running the parent workflow.\n    \"\"\"\n    base_url = LOCAL_INFERENCE_API_URL.rstrip(\"/\")\n    return f\"{base_url}/{workspace_name}/workflows/{workflow_id}\"\n\n\n# ---------------------------------------------------------------------------\n# Compile-time validation\n# ---------------------------------------------------------------------------\n\n\ndef validate_workflow_caller_no_circular_references(\n    steps: List[WorkflowBlockManifest],\n    api_key: Optional[str],\n) -> None:\n    \"\"\"Compile-time validation: check that workflow_caller blocks with static\n    workflow_id values don't create circular dependencies, resolve the target\n    workflow's input and output interfaces, and validate that required inputs\n    are provided.\n\n    Only validates when workflow_id is a literal string (not a selector like\n    ``$inputs.workflow_id``). Errors during spec fetching are logged as warnings\n    and do not block compilation \u2014 the runtime circular dependency check via\n    the call chain header provides an additional safety net.\n    \"\"\"\n    caller_steps = _extract_workflow_caller_steps(steps=steps)\n    if not caller_steps:\n        return\n    workspace_name = _resolve_workspace_for_validation(api_key=api_key)\n    if workspace_name is None:\n        return\n    for workflow_id, version_id, step_manifest in caller_steps:\n        spec = _fetch_workflow_spec_for_validation(\n            api_key=api_key,\n            workspace_name=workspace_name,\n            workflow_id=workflow_id,\n            workflow_version_id=version_id,\n        )\n        if spec is None:\n            continue\n        _check_workflow_for_circular_references(\n            api_key=api_key,\n            workspace_name=workspace_name,\n            target_workflow_id=workflow_id,\n            target_workflow_version_id=version_id,\n            visited=set(),\n            prefetched_spec=spec,\n        )\n        cache_key = _make_cache_key(workflow_id, version_id)\n        _resolve_and_cache_workflow_outputs(\n            cache_key=cache_key,\n            spec=spec,\n        )\n        _resolve_and_cache_workflow_inputs(\n            cache_key=cache_key,\n            spec=spec,\n        )\n        _validate_required_inputs(\n            workflow_id=workflow_id,\n            workflow_version_id=version_id,\n            step_manifest=step_manifest,\n        )\n\n\ndef _extract_workflow_caller_steps(\n    steps: List[WorkflowBlockManifest],\n) -> List[Tuple[str, Optional[str], WorkflowBlockManifest]]:\n    \"\"\"Extract (workflow_id, workflow_version_id, manifest) tuples from\n    workflow_caller steps that have literal (non-selector) workflow_id values.\"\"\"\n    result = []\n    for step in steps:\n        if not isinstance(step, BlockManifest):\n            continue\n        workflow_id = step.workflow_id\n        if isinstance(workflow_id, str) and not workflow_id.startswith(\"$\"):\n            version_id = step.workflow_version_id\n            # Only use version_id if it's a literal string (not a selector)\n            if isinstance(version_id, str) and version_id.startswith(\"$\"):\n                version_id = None\n            result.append((workflow_id, version_id, step))\n    return result\n\n\ndef _fetch_workflow_spec_for_validation(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[dict]:\n    \"\"\"Fetch a workflow spec, returning None on any error.\"\"\"\n    try:\n        return get_workflow_specification(\n            api_key=api_key,\n            workspace_id=workspace_name,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n        )\n    except Exception as error:\n        logging.debug(\n            \"Could not fetch workflow '%s' for compile-time validation (error type: %s)\",\n            workflow_id,\n            type(error).__name__,\n        )\n        return None\n\n\ndef _resolve_workspace_for_validation(\n    api_key: Optional[str],\n) -> Optional[str]:\n    if not api_key:\n        return None\n    try:\n        return get_roboflow_workspace(api_key=api_key)\n    except Exception as error:\n        logging.debug(\n            \"Could not resolve workspace for compile-time workflow validation (error type: %s)\",\n            type(error).__name__,\n        )\n        return None\n\n\ndef _check_workflow_for_circular_references(\n    api_key: Optional[str],\n    workspace_name: str,\n    target_workflow_id: str,\n    visited: set,\n    target_workflow_version_id: Optional[str] = None,\n    prefetched_spec: Optional[dict] = None,\n) -> None:\n    \"\"\"Recursively check if a target workflow creates a circular call chain.\n\n    Raises ``ExecutionGraphStructureError`` if a cycle is found. Silently\n    returns on any fetch error \u2014 the runtime check will catch those cases.\n\n    When ``prefetched_spec`` is provided it is used directly instead of\n    fetching the spec again.  The caller in\n    ``validate_workflow_caller_no_circular_references`` already fetches the\n    spec for the top-level workflow, so passing it here avoids a duplicate\n    API call.\n    \"\"\"\n    from inference.core.workflows.errors import ExecutionGraphStructureError\n\n    if target_workflow_id in visited:\n        chain = \" -> \".join([*visited, target_workflow_id])\n        raise ExecutionGraphStructureError(\n            public_message=(\n                f\"Circular workflow call detected at compile time: {chain}. \"\n                f\"This would cause infinite recursion at runtime.\"\n            ),\n            context=\"workflow_compilation | workflow_caller_validation\",\n        )\n    if prefetched_spec is not None:\n        spec = prefetched_spec\n    else:\n        try:\n            spec = get_workflow_specification(\n                api_key=api_key,\n                workspace_id=workspace_name,\n                workflow_id=target_workflow_id,\n                workflow_version_id=target_workflow_version_id,\n            )\n        except Exception as error:\n            logging.debug(\n                \"Could not fetch workflow '%s' for circular dependency check (error type: %s)\",\n                target_workflow_id,\n                type(error).__name__,\n            )\n            return\n    nested_workflows = _extract_workflow_caller_ids_from_spec(spec=spec)\n    if not nested_workflows:\n        return\n    visited_with_current = visited | {target_workflow_id}\n    for nested_id, nested_version_id in nested_workflows:\n        _check_workflow_for_circular_references(\n            api_key=api_key,\n            workspace_name=workspace_name,\n            target_workflow_id=nested_id,\n            target_workflow_version_id=nested_version_id,\n            visited=visited_with_current,\n        )\n\n\ndef _extract_workflow_caller_ids_from_spec(\n    spec: dict,\n) -> List[Tuple[str, Optional[str]]]:\n    \"\"\"Extract static (workflow_id, workflow_version_id) tuples from a raw\n    workflow specification.  Only includes entries where ``workflow_id`` is a\n    literal string (not a selector).  ``workflow_version_id`` is included when\n    it is a literal string, otherwise ``None``.\"\"\"\n    steps = spec.get(\"steps\", [])\n    result: List[Tuple[str, Optional[str]]] = []\n    for step in steps:\n        step_type = step.get(\"type\", \"\")\n        if step_type != WORKFLOW_CALLER_BLOCK_TYPE:\n            continue\n        workflow_id = step.get(\"workflow_id\", \"\")\n        if not isinstance(workflow_id, str) or workflow_id.startswith(\"$\"):\n            continue\n        version_id = step.get(\"workflow_version_id\")\n        if isinstance(version_id, str) and version_id.startswith(\"$\"):\n            version_id = None\n        result.append((workflow_id, version_id))\n    return result\n\n\n# ---------------------------------------------------------------------------\n# Output interface resolution\n# ---------------------------------------------------------------------------\n\n\ndef _resolve_and_cache_workflow_outputs(\n    cache_key: Tuple[str, Optional[str]],\n    spec: dict,\n) -> None:\n    \"\"\"Resolve the target workflow's output interface from its spec and cache\n    the result in ``_RESOLVED_WORKFLOW_OUTPUTS``.\n\n    Tries ``describe_workflow_outputs()`` for proper Kind resolution. Falls\n    back to extracting output names with ``WILDCARD_KIND`` on any error.\n    \"\"\"\n    try:\n        outputs_description = _describe_outputs_from_spec(spec=spec)\n    except Exception as error:\n        logging.debug(\n            f\"Could not resolve output kinds for workflow '{cache_key}' \"\n            f\"via describe_workflow_outputs: {error}. \"\n            f\"Falling back to output names with WILDCARD_KIND.\"\n        )\n        outputs_description = None\n\n    if outputs_description is not None:\n        resolved = _convert_output_descriptions_to_kinds(\n            outputs_description=outputs_description,\n        )\n    else:\n        resolved = _extract_output_names_with_wildcard(spec=spec)\n\n    if resolved:\n        _RESOLVED_WORKFLOW_OUTPUTS[cache_key] = resolved\n\n\ndef _describe_outputs_from_spec(\n    spec: dict,\n) -> Dict[str, Union[List[str], Dict[str, List[str]]]]:\n    \"\"\"Call the standard output discovery to resolve output kinds.\"\"\"\n    from inference.core.workflows.execution_engine.v1.introspection.outputs_discovery import (\n        describe_workflow_outputs,\n    )\n\n    return describe_workflow_outputs(definition=spec)\n\n\ndef _convert_output_descriptions_to_kinds(\n    outputs_description: Dict[str, Union[List[str], Dict[str, List[str]]]],\n) -> Dict[str, List[Kind]]:\n    \"\"\"Convert ``describe_workflow_outputs()`` result (kind name strings) to\n    ``Kind`` objects.\"\"\"\n    kind_name_map = _build_kind_name_map()\n    result: Dict[str, List[Kind]] = {}\n    for name, kind_info in outputs_description.items():\n        if isinstance(kind_info, dict):\n            # Wildcard selector ($steps.step.*) \u2014 nested structure.\n            # Represent as DICTIONARY_KIND since we can't express nested\n            # typed properties in a single OutputDefinition.\n            result[name] = [DICTIONARY_KIND]\n        else:\n            kinds = [\n                kind_name_map[k]\n                for k in kind_info\n                if k in kind_name_map\n            ]\n            result[name] = kinds if kinds else [WILDCARD_KIND]\n    return result\n\n\ndef _extract_output_names_with_wildcard(\n    spec: dict,\n) -> Dict[str, List[Kind]]:\n    \"\"\"Fallback: extract just the output names and assign WILDCARD_KIND.\"\"\"\n    outputs = spec.get(\"outputs\", [])\n    result: Dict[str, List[Kind]] = {}\n    for output in outputs:\n        name = output.get(\"name\")\n        if name:\n            result[name] = [WILDCARD_KIND]\n    return result\n\n\n@lru_cache(maxsize=1)\ndef _build_kind_name_map() -> Dict[str, Kind]:\n    \"\"\"Build a mapping from kind name to Kind object using the loader.\n\n    Result is cached since the set of registered kinds does not change\n    within a process.\n    \"\"\"\n    from inference.core.workflows.core_steps.loader import load_kinds\n\n    return {kind.name: kind for kind in load_kinds()}\n\n\n# ---------------------------------------------------------------------------\n# Input interface resolution\n# ---------------------------------------------------------------------------\n\n\ndef _resolve_and_cache_workflow_inputs(\n    cache_key: Tuple[str, Optional[str]],\n    spec: dict,\n) -> None:\n    \"\"\"Parse the target workflow's input interface from its spec and cache\n    the result in ``_RESOLVED_WORKFLOW_INPUTS``.\n\n    Each input is stored as a dict with keys: name, type, has_default.\n    \"\"\"\n    raw_inputs = spec.get(\"inputs\", [])\n    parsed: List[Dict[str, Any]] = []\n    for inp in raw_inputs:\n        name = inp.get(\"name\")\n        if not name:\n            continue\n        inp_type = inp.get(\"type\", \"\")\n        parsed.append({\n            \"name\": name,\n            \"type\": inp_type,\n            \"has_default\": \"default_value\" in inp,\n        })\n    _RESOLVED_WORKFLOW_INPUTS[cache_key] = parsed\n\n\ndef _validate_required_inputs(\n    workflow_id: str,\n    step_manifest: BlockManifest,\n    workflow_version_id: Optional[str] = None,\n) -> None:\n    \"\"\"Validate that the workflow caller step provides all required inputs\n    that the target workflow expects.\n\n    Raises ``ExecutionGraphStructureError`` if:\n    - The target workflow has required parameters (no default) not covered by\n      ``inputs``.\n    - The user declared ``input_definitions`` but ``inputs`` does not\n      cover all declared input names.\n    \"\"\"\n    from inference.core.workflows.errors import ExecutionGraphStructureError\n\n    input_keys = set(step_manifest.inputs.keys())\n\n    # Validate user-declared input_definitions: every declared input must be\n    # present in inputs.\n    if step_manifest.input_definitions:\n        missing_declared = [\n            name for name in step_manifest.input_definitions\n            if name not in input_keys\n        ]\n        if missing_declared:\n            raise ExecutionGraphStructureError(\n                public_message=(\n                    f\"Workflow caller step '{step_manifest.name}' declares \"\n                    f\"input_definitions for {list(step_manifest.input_definitions.keys())}, \"\n                    f\"but input(s) {missing_declared} are not provided in \"\n                    f\"'inputs'.\"\n                ),\n                context=\"workflow_compilation | workflow_caller_validation\",\n            )\n\n    cache_key = _make_cache_key(workflow_id, workflow_version_id)\n    resolved_inputs = _RESOLVED_WORKFLOW_INPUTS.get(cache_key)\n    if resolved_inputs is None:\n        return\n\n    missing = []\n    for inp in resolved_inputs:\n        if inp[\"has_default\"]:\n            continue\n        if inp[\"name\"] not in input_keys:\n            missing.append(inp[\"name\"])\n    if missing:\n        raise ExecutionGraphStructureError(\n            public_message=(\n                f\"Target workflow '{workflow_id}' requires input(s) \"\n                f\"{missing} (no default values), but they are not provided \"\n                f\"in 'inputs' on workflow_caller step \"\n                f\"'{step_manifest.name}'.\"\n            ),\n            context=\"workflow_compilation | workflow_caller_validation\",\n        )\n\n\n# ---------------------------------------------------------------------------\n# Output resolution for runtime\n# ---------------------------------------------------------------------------\n\n\ndef _resolve_output_kinds_for_run(\n    output_definitions: Dict[str, List[str]],\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[Dict[str, List[Kind]]]:\n    \"\"\"Determine which outputs to extract and their Kind objects.\n\n    Priority:\n    1. User-declared ``output_definitions`` (explicit kind names)\n    2. Auto-discovered outputs from ``_RESOLVED_WORKFLOW_OUTPUTS`` cache\n    3. Returns ``None`` \u2192 caller should fall back to generic ``result`` dict\n    \"\"\"\n    if output_definitions:\n        kind_name_map = _build_kind_name_map()\n        result: Dict[str, List[Kind]] = {}\n        for name, kind_names in output_definitions.items():\n            kinds = [\n                kind_name_map[k] for k in kind_names if k in kind_name_map\n            ]\n            result[name] = kinds or [WILDCARD_KIND]\n        return result\n    cache_key = _make_cache_key(workflow_id, workflow_version_id)\n    resolved = _RESOLVED_WORKFLOW_OUTPUTS.get(cache_key)\n    if resolved is not None:\n        return resolved\n    return None\n\n\n# ---------------------------------------------------------------------------\n# Output deserialization\n# ---------------------------------------------------------------------------\n\n\n@lru_cache(maxsize=1)\ndef _build_kinds_deserializers_map() -> Dict[str, Callable[[str, Any], Any]]:\n    \"\"\"Build the map of kind name -> deserializer function.\n\n    Result is cached since the set of registered deserializers does not\n    change within a process.\n    \"\"\"\n    from inference.core.workflows.execution_engine.introspection.blocks_loader import (\n        load_kinds_deserializers,\n    )\n\n    return load_kinds_deserializers()\n\n\ndef _deserialize_output_value(\n    output_name: str,\n    raw_value: Any,\n    output_kinds: List[Kind],\n    deserializers: Dict[str, Callable[[str, Any], Any]],\n) -> Any:\n    \"\"\"Deserialize a single output value using the deserializer matching its\n    resolved kind.\n\n    For outputs with known kinds, deserialization is required \u2014 failure raises\n    an error so downstream blocks don't receive unexpected raw data. For\n    WILDCARD_KIND outputs the raw value is returned as-is since we don't know\n    the expected type.\n    \"\"\"\n    if raw_value is None:\n        return None\n    if all(kind == WILDCARD_KIND for kind in output_kinds):\n        return raw_value\n    errors: List[Tuple[str, Exception]] = []\n    for kind in output_kinds:\n        if kind == WILDCARD_KIND:\n            continue\n        if kind.name not in deserializers:\n            continue\n        try:\n            return deserializers[kind.name](output_name, raw_value)\n        except Exception as error:\n            errors.append((kind.name, error))\n            continue\n    if errors:\n        error_details = \"; \".join(\n            f\"{kind}: {error}\" for kind, error in errors\n        )\n        raise RuntimeError(\n            f\"Failed to deserialize output '{output_name}' from target \"\n            f\"workflow. Tried deserializers for kinds \"\n            f\"{[k for k, _ in errors]} but all failed: {error_details}. \"\n            f\"This likely means the target workflow's output format doesn't \"\n            f\"match the expected kind.\"\n        )\n    return raw_value\n",
    "patch": null
  },
  {
    "trace_id": "966ad525-0420-4afd-b9c3-2413fc19fe9d",
    "function_name": "_convert_output_descriptions_to_kinds",
    "file_path": "inference/core/workflows/core_steps/composition/workflow_caller/v1.py",
    "speedup_x": 0.19268043275613683,
    "review_quality": "high",
    "pre_optimization_commit": "0306c6c070caef88dea09d9b680c659f63b2ccc1",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def _convert_output_descriptions_to_kinds(\n    outputs_description: Dict[str, Union[List[str], Dict[str, List[str]]]],\n) -> Dict[str, List[Kind]]:\n    \"\"\"Convert ``describe_workflow_outputs()`` result (kind name strings) to\n    ``Kind`` objects.\"\"\"\n    kind_name_map = _build_kind_name_map()\n    result: Dict[str, List[Kind]] = {}\n    for name, kind_info in outputs_description.items():\n        if isinstance(kind_info, dict):\n            # Wildcard selector ($steps.step.*) \u2014 nested structure.\n            # Represent as DICTIONARY_KIND since we can't express nested\n            # typed properties in a single OutputDefinition.\n            result[name] = [DICTIONARY_KIND]\n        else:\n            kinds = [\n                kind_name_map[k]\n                for k in kind_info\n                if k in kind_name_map\n            ]\n            result[name] = kinds if kinds else [WILDCARD_KIND]\n    return result\n",
    "optimized_function_code": "from functools import lru_cache\nfrom inference.core.workflows.execution_engine.entities.types import DICTIONARY_KIND, Kind, WILDCARD_KIND\nfrom typing import Dict, List, Union\n\n\n@lru_cache(maxsize=1)\ndef _build_kind_name_map() -> Dict[str, Kind]:\n    \"\"\"Build a mapping from kind name to Kind object using the loader.\n\n    Result is cached since the set of registered kinds does not change\n    within a process.\n    \"\"\"\n    from inference.core.workflows.core_steps.loader import load_kinds\n\n    return {kind.name: kind for kind in load_kinds()}\n\n\n# Compute the kind name map once at module load time\n_KIND_NAME_MAP = _build_kind_name_map()\n\n\ndef _convert_output_descriptions_to_kinds(\n    outputs_description: Dict[str, Union[List[str], Dict[str, List[str]]]],\n) -> Dict[str, List[Kind]]:\n    \"\"\"Convert ``describe_workflow_outputs()`` result (kind name strings) to\n    ``Kind`` objects.\"\"\"\n    result: Dict[str, List[Kind]] = {}\n    for name, kind_info in outputs_description.items():\n        if isinstance(kind_info, dict):\n            # Wildcard selector ($steps.step.*) \u2014 nested structure.\n            # Represent as DICTIONARY_KIND since we can't express nested\n            # typed properties in a single OutputDefinition.\n            result[name] = [DICTIONARY_KIND]\n        else:\n            kinds = [\n                _KIND_NAME_MAP[k]\n                for k in kind_info\n                if k in _KIND_NAME_MAP\n            ]\n            result[name] = kinds if kinds else [WILDCARD_KIND]\n    return result",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/composition/workflow_caller/v1.py\nfrom functools import lru_cache\nfrom inference.core.workflows.execution_engine.entities.types import DICTIONARY_KIND, Kind, WILDCARD_KIND\nfrom typing import Dict, List, Union\n\n\n@lru_cache(maxsize=1)\ndef _build_kind_name_map() -> Dict[str, Kind]:\n    \"\"\"Build a mapping from kind name to Kind object using the loader.\n\n    Result is cached since the set of registered kinds does not change\n    within a process.\n    \"\"\"\n    from inference.core.workflows.core_steps.loader import load_kinds\n\n    return {kind.name: kind for kind in load_kinds()}\n\n\n# Compute the kind name map once at module load time\n_KIND_NAME_MAP = _build_kind_name_map()\n\n\ndef _convert_output_descriptions_to_kinds(\n    outputs_description: Dict[str, Union[List[str], Dict[str, List[str]]]],\n) -> Dict[str, List[Kind]]:\n    \"\"\"Convert ``describe_workflow_outputs()`` result (kind name strings) to\n    ``Kind`` objects.\"\"\"\n    result: Dict[str, List[Kind]] = {}\n    for name, kind_info in outputs_description.items():\n        if isinstance(kind_info, dict):\n            # Wildcard selector ($steps.step.*) \u2014 nested structure.\n            # Represent as DICTIONARY_KIND since we can't express nested\n            # typed properties in a single OutputDefinition.\n            result[name] = [DICTIONARY_KIND]\n        else:\n            kinds = [\n                _KIND_NAME_MAP[k]\n                for k in kind_info\n                if k in _KIND_NAME_MAP\n            ]\n            result[name] = kinds if kinds else [WILDCARD_KIND]\n    return result\n```",
    "optimized_function_only": "def _convert_output_descriptions_to_kinds(\n    outputs_description: Dict[str, Union[List[str], Dict[str, List[str]]]],\n) -> Dict[str, List[Kind]]:\n    \"\"\"Convert ``describe_workflow_outputs()`` result (kind name strings) to\n    ``Kind`` objects.\"\"\"\n    result: Dict[str, List[Kind]] = {}\n    for name, kind_info in outputs_description.items():\n        if isinstance(kind_info, dict):\n            # Wildcard selector ($steps.step.*) \u2014 nested structure.\n            # Represent as DICTIONARY_KIND since we can't express nested\n            # typed properties in a single OutputDefinition.\n            result[name] = [DICTIONARY_KIND]\n        else:\n            kinds = [\n                _KIND_NAME_MAP[k]\n                for k in kind_info\n                if k in _KIND_NAME_MAP\n            ]\n            result[name] = kinds if kinds else [WILDCARD_KIND]\n    return result",
    "original_file_content": "import logging\nimport re\nfrom functools import lru_cache\nfrom typing import Any, Callable, Dict, List, Literal, Optional, Tuple, Type, Union\n\nimport requests\nfrom pydantic import ConfigDict, Field, field_validator\n\nfrom inference.core.env import LOCAL_INFERENCE_API_URL\nfrom inference.core.roboflow_api import get_roboflow_workspace, get_workflow_specification\nfrom inference.core.workflows.execution_engine.entities.base import (\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    DICTIONARY_KIND,\n    INTEGER_KIND,\n    STRING_KIND,\n    WILDCARD_KIND,\n    Kind,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nLONG_DESCRIPTION = \"\"\"\nThe **Workflow Caller** block enables calling another Roboflow workflow from within a workflow.\nThis is useful for composing complex pipelines from smaller, reusable workflow components.\n\n### How it works\n\nThe block takes a workflow ID (from the same workspace), passes inputs (including images)\nto the target workflow, executes it via HTTP, and returns the results.\n\n### Configuration\n\nSpecify the target workflow using `workflow_id` (just the workflow slug, not a full URL). The\nworkspace is resolved automatically from the API key used to run the parent workflow.\n\n```\nworkflow_id = \"my-detection-pipeline\"\n```\n\n### Inputs\n\nPass all inputs the target workflow expects via `inputs`, including images:\n\n```\ninputs = {\n    \"image\": \"$inputs.image\",\n    \"confidence_threshold\": 0.5,\n    \"model_id\": \"$inputs.model_id\",\n}\n```\n\nUse `input_definitions` to declare the expected input types so the UI can render\nproper connectors.\n\n### Circular Dependency Protection\n\nTo prevent infinite recursion (e.g. Workflow A calls B, B calls A), the block tracks the chain\nof workflow calls using a header. If a circular reference is detected, the block returns an error\ninstead of making the call.\n\n### Dynamic Outputs\n\nWhen the target workflow_id is a static string, the block resolves the target workflow's\noutputs at compile time. Each output from the target workflow becomes a separate output on\nthis block with proper Kind types. When the workflow_id is dynamic (a selector), outputs\nfall back to a single ``result`` dict.\n\n### Limitations\n\n* Only workflows within the same workspace are supported (v1).\n* Execution is done via HTTP call, which adds network latency.\n* Subject to the same timeout constraints as the hosting environment.\n\"\"\"\n\nWORKFLOW_CALL_CHAIN_HEADER = \"X-Roboflow-Workflow-Call-Chain\"\nMAX_WORKFLOW_CALL_DEPTH = 10\nWORKFLOW_CALLER_BLOCK_TYPE = \"roboflow_core/workflow_caller@v1\"\n\n# Module-level cache mapping (workflow_id, version_id) -> {output_name: [Kind]}.\n# Populated during compile-time validation, read by get_actual_outputs() and run().\n_RESOLVED_WORKFLOW_OUTPUTS: Dict[Tuple[str, Optional[str]], Dict[str, List[Kind]]] = {}\n\n# Module-level cache mapping (workflow_id, version_id) -> list of parsed input dicts\n# from spec.  Each dict has: name, type, kind, has_default.\n_RESOLVED_WORKFLOW_INPUTS: Dict[Tuple[str, Optional[str]], List[Dict[str, Any]]] = {}\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Workflow Caller\",\n            \"version\": \"v1\",\n            \"short_description\": \"Call another Roboflow workflow from within a workflow.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"transformation\",\n            \"ui_manifest\": {\n                \"section\": \"advanced\",\n                \"icon\": \"fal fa-diagram-subtask\",\n                \"blockPriority\": 2,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/workflow_caller@v1\"]\n    workflow_id: Union[Selector(kind=[STRING_KIND]), str] = Field(\n        description=\"The workflow ID to call (must be in the same workspace).\",\n        examples=[\"my-workflow-id\", \"$inputs.workflow_id\"],\n    )\n    workflow_version_id: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Optional version ID of the target workflow. When provided, \"\n        \"the block calls the specific version instead of the latest. \"\n        \"Use this to pin a dependency to a known-good version.\",\n        examples=[\"1709234567890\", \"$inputs.workflow_version\"],\n    )\n    inputs: Dict[\n        str,\n        Union[\n            Selector(),\n            str,\n            float,\n            bool,\n            int,\n            dict,\n            list,\n        ],\n    ] = Field(\n        default_factory=dict,\n        description=\"Inputs to pass to the target workflow, keyed by input name. \"\n        \"All inputs including images should be listed here.\",\n        examples=[\n            {\"image\": \"$inputs.image\", \"confidence_threshold\": 0.5},\n            {\"image\": \"$inputs.image\", \"model_id\": \"$inputs.model_id\"},\n        ],\n    )\n    request_timeout: Union[int, Selector(kind=[INTEGER_KIND])] = Field(\n        default=30,\n        description=\"HTTP request timeout in seconds.\",\n        examples=[\"$inputs.request_timeout\", 30],\n    )\n    input_definitions: Dict[str, List[str]] = Field(\n        default_factory=dict,\n        description=(\n            \"Mapping of expected input names to their kind types. \"\n            \"Each key is an input name in the target workflow, and the value \"\n            \"is a list of kind name strings (e.g. ['float'], ['roboflow_model_id']). \"\n            \"This tells the parent workflow what inputs the target expects, \"\n            \"enabling proper UI connectors. Actual values are provided via \"\n            \"'inputs'.\"\n        ),\n        examples=[\n            {\"image\": [\"image\"], \"confidence_threshold\": [\"float\"]},\n            {\"image\": [\"image\"], \"class_filter\": [\"string\"], \"iou_threshold\": [\"float\"]},\n        ],\n    )\n    output_definitions: Dict[str, List[str]] = Field(\n        default_factory=dict,\n        description=(\n            \"Mapping of expected output names to their kind types. \"\n            \"Each key is an output name from the target workflow, and the value \"\n            \"is a list of kind name strings (e.g. ['object_detection_prediction']). \"\n            \"This tells the parent workflow what types to expect, enabling proper \"\n            \"connections to downstream blocks like visualizers.\"\n        ),\n        examples=[\n            {\"predictions\": [\"object_detection_prediction\"]},\n            {\"result_image\": [\"image\"], \"count\": [\"integer\"]},\n        ],\n    )\n\n    @field_validator(\"workflow_id\")\n    @classmethod\n    def validate_workflow_id_slug(cls, value: Any) -> Any:\n        if isinstance(value, str) and not value.startswith(\"$\"):\n            if not re.fullmatch(r\"[\\w\\-]+\", value):\n                raise ValueError(\n                    f\"`workflow_id` must be a valid slug (letters, numbers, \"\n                    f\"hyphens, and underscores only). Got: '{value}'\"\n                )\n        return value\n\n    @field_validator(\"request_timeout\")\n    @classmethod\n    def ensure_request_timeout_is_positive(cls, value: Any) -> Any:\n        if isinstance(value, int) and value <= 0:\n            raise ValueError(\"`request_timeout` must be a positive integer.\")\n        return value\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return []\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"*\"),\n        ]\n\n    def get_actual_outputs(self) -> List[OutputDefinition]:\n        base: List[OutputDefinition] = []\n        # 1. User-defined output definitions take precedence\n        if self.output_definitions:\n            kind_name_map = _build_kind_name_map()\n            for name, kind_names in self.output_definitions.items():\n                kinds = [\n                    kind_name_map[k] for k in kind_names if k in kind_name_map\n                ]\n                base.append(\n                    OutputDefinition(name=name, kind=kinds or [WILDCARD_KIND])\n                )\n            return base\n        # 2. Fall back to auto-discovery from compile-time resolution\n        if isinstance(self.workflow_id, str) and not self.workflow_id.startswith(\"$\"):\n            version_id = self.workflow_version_id\n            if isinstance(version_id, str) and version_id.startswith(\"$\"):\n                version_id = None\n            cache_key = _make_cache_key(self.workflow_id, version_id)\n            resolved = _RESOLVED_WORKFLOW_OUTPUTS.get(cache_key)\n            if resolved is not None:\n                for name, kinds in resolved.items():\n                    base.append(OutputDefinition(name=name, kind=kinds))\n                return base\n        # 3. Fall back to generic result dict\n        base.append(OutputDefinition(name=\"result\", kind=[DICTIONARY_KIND]))\n        return base\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass WorkflowCallerBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        api_key: Optional[str],\n        workflow_call_chain: Optional[str] = None,\n    ):\n        self._api_key = api_key\n        self._workspace_name: Optional[str] = None\n        self._workflow_call_chain = workflow_call_chain or \"\"\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"api_key\", \"workflow_call_chain\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        workflow_id: str,\n        inputs: Dict[str, Any],\n        request_timeout: int,\n        input_definitions: Dict[str, List[str]],\n        output_definitions: Dict[str, List[str]],\n        workflow_version_id: Optional[str] = None,\n    ) -> BlockResult:\n        workspace_name = self._resolve_workspace_name()\n        if workspace_name is None:\n            raise RuntimeError(\n                f\"Could not resolve workspace for workflow '{workflow_id}'. \"\n                f\"Ensure a valid API key is configured.\"\n            )\n        error_status, message, raw_outputs = call_workflow(\n            api_key=self._api_key,\n            workspace_name=workspace_name,\n            workflow_id=workflow_id,\n            inputs=inputs,\n            request_timeout=request_timeout,\n            call_chain=self._workflow_call_chain,\n            workflow_version_id=workflow_version_id,\n        )\n        if error_status:\n            raise RuntimeError(\n                f\"Workflow '{workflow_id}' execution failed: {message}\"\n            )\n        result: Dict[str, Any] = {}\n        # Determine which outputs to extract and their kinds for deserialization\n        output_kinds_map = _resolve_output_kinds_for_run(\n            output_definitions=output_definitions,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n        )\n        if output_kinds_map is not None:\n            deserializers = _build_kinds_deserializers_map()\n            for output_name, output_kinds in output_kinds_map.items():\n                raw_value = raw_outputs.get(output_name)\n                result[output_name] = _deserialize_output_value(\n                    output_name=output_name,\n                    raw_value=raw_value,\n                    output_kinds=output_kinds,\n                    deserializers=deserializers,\n                )\n        else:\n            result[\"result\"] = raw_outputs\n        return result\n\n    def _resolve_workspace_name(self) -> Optional[str]:\n        if self._workspace_name is not None:\n            return self._workspace_name\n        if not self._api_key:\n            return None\n        try:\n            self._workspace_name = get_roboflow_workspace(api_key=self._api_key)\n            return self._workspace_name\n        except Exception as error:\n            logging.warning(\n                f\"Could not resolve workspace from API key. Error: {str(error)}\"\n            )\n            return None\n\n\ndef _make_cache_key(\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Tuple[str, Optional[str]]:\n    \"\"\"Build a cache key that accounts for both workflow_id and version_id.\"\"\"\n    return (workflow_id, workflow_version_id)\n\n\ndef call_workflow(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    inputs: Dict[str, Any],\n    request_timeout: int,\n    call_chain: Optional[str] = None,\n    workflow_version_id: Optional[str] = None,\n) -> Tuple[bool, str, dict]:\n    \"\"\"Execute a workflow call and return (error_status, message, result).\n\n    This function is separated from the block's run() to facilitate testing.\n    \"\"\"\n    current_chain = call_chain or \"\"\n    chain_entries = [entry for entry in current_chain.split(\",\") if entry]\n    if workflow_id in chain_entries:\n        logging.warning(\n            f\"Circular workflow call detected: \"\n            f\"'{workflow_id}' is already in call chain [{current_chain}].\"\n        )\n        return (\n            True,\n            f\"Circular workflow call detected: '{workflow_id}' is already \"\n            f\"in the call chain [{current_chain}]. Aborting to prevent \"\n            f\"infinite recursion.\",\n            {},\n        )\n    if len(chain_entries) >= MAX_WORKFLOW_CALL_DEPTH:\n        logging.warning(\n            f\"Workflow call depth limit ({MAX_WORKFLOW_CALL_DEPTH}) reached. \"\n            f\"Call chain: [{current_chain}].\"\n        )\n        return (\n            True,\n            f\"Workflow call depth limit ({MAX_WORKFLOW_CALL_DEPTH}) reached. \"\n            f\"Call chain: [{current_chain}].\",\n            {},\n        )\n    updated_chain = \",\".join([*chain_entries, workflow_id])\n    inputs = build_workflow_inputs(inputs=inputs)\n    return execute_workflow_request(\n        api_key=api_key,\n        workspace_name=workspace_name,\n        workflow_id=workflow_id,\n        inputs=inputs,\n        request_timeout=request_timeout,\n        call_chain=updated_chain,\n        workflow_version_id=workflow_version_id,\n    )\n\n\ndef build_workflow_inputs(\n    inputs: Dict[str, Any],\n) -> Dict[str, Any]:\n    \"\"\"Build the inputs dictionary for the target workflow.\n\n    Handles ``WorkflowImageData`` objects found in ``inputs`` by\n    automatically serialising them to the ``{type: base64, value: ...}``\n    format expected by the workflow HTTP API.\n    \"\"\"\n    resolved: Dict[str, Any] = {}\n    for key, value in inputs.items():\n        if isinstance(value, WorkflowImageData):\n            resolved[key] = {\n                \"type\": \"base64\",\n                \"value\": value.base64_image,\n            }\n        else:\n            resolved[key] = value\n    return resolved\n\n\ndef execute_workflow_request(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    inputs: Dict[str, Any],\n    request_timeout: int,\n    call_chain: str,\n    workflow_version_id: Optional[str] = None,\n) -> Tuple[bool, str, dict]:\n    \"\"\"Make the HTTP request to the target workflow and return\n    (error_status, message, result).\"\"\"\n    url = build_workflow_url(\n        workspace_name=workspace_name,\n        workflow_id=workflow_id,\n    )\n    payload: Dict[str, Any] = {\"inputs\": inputs}\n    if api_key is not None:\n        payload[\"api_key\"] = api_key\n    if workflow_version_id is not None:\n        payload[\"workflow_version_id\"] = workflow_version_id\n    headers = {WORKFLOW_CALL_CHAIN_HEADER: call_chain}\n    try:\n        response = requests.post(\n            url,\n            json=payload,\n            headers=headers,\n            timeout=request_timeout,\n        )\n        response.raise_for_status()\n        response_data = response.json()\n        outputs = response_data.get(\"outputs\", [])\n        result = outputs[0] if outputs else {}\n        return (\n            False,\n            \"Workflow executed successfully\",\n            result,\n        )\n    except Exception as error:\n        logging.warning(\n            f\"Could not execute workflow '{workflow_id}'. Error: {str(error)}\"\n        )\n        error_type = type(error).__name__\n        return (\n            True,\n            f\"Failed to execute workflow '{workflow_id}': {error_type}\",\n            {},\n        )\n\n\ndef build_workflow_url(workspace_name: str, workflow_id: str) -> str:\n    \"\"\"Build the URL for calling a workflow on the local inference server.\n\n    Uses LOCAL_INFERENCE_API_URL to call the workflow on the same inference\n    server instance that is running the parent workflow.\n    \"\"\"\n    base_url = LOCAL_INFERENCE_API_URL.rstrip(\"/\")\n    return f\"{base_url}/{workspace_name}/workflows/{workflow_id}\"\n\n\n# ---------------------------------------------------------------------------\n# Compile-time validation\n# ---------------------------------------------------------------------------\n\n\ndef validate_workflow_caller_no_circular_references(\n    steps: List[WorkflowBlockManifest],\n    api_key: Optional[str],\n) -> None:\n    \"\"\"Compile-time validation: check that workflow_caller blocks with static\n    workflow_id values don't create circular dependencies, resolve the target\n    workflow's input and output interfaces, and validate that required inputs\n    are provided.\n\n    Only validates when workflow_id is a literal string (not a selector like\n    ``$inputs.workflow_id``). Errors during spec fetching are logged as warnings\n    and do not block compilation \u2014 the runtime circular dependency check via\n    the call chain header provides an additional safety net.\n    \"\"\"\n    caller_steps = _extract_workflow_caller_steps(steps=steps)\n    if not caller_steps:\n        return\n    workspace_name = _resolve_workspace_for_validation(api_key=api_key)\n    if workspace_name is None:\n        return\n    for workflow_id, version_id, step_manifest in caller_steps:\n        spec = _fetch_workflow_spec_for_validation(\n            api_key=api_key,\n            workspace_name=workspace_name,\n            workflow_id=workflow_id,\n            workflow_version_id=version_id,\n        )\n        if spec is None:\n            continue\n        _check_workflow_for_circular_references(\n            api_key=api_key,\n            workspace_name=workspace_name,\n            target_workflow_id=workflow_id,\n            target_workflow_version_id=version_id,\n            visited=set(),\n            prefetched_spec=spec,\n        )\n        cache_key = _make_cache_key(workflow_id, version_id)\n        _resolve_and_cache_workflow_outputs(\n            cache_key=cache_key,\n            spec=spec,\n        )\n        _resolve_and_cache_workflow_inputs(\n            cache_key=cache_key,\n            spec=spec,\n        )\n        _validate_required_inputs(\n            workflow_id=workflow_id,\n            workflow_version_id=version_id,\n            step_manifest=step_manifest,\n        )\n\n\ndef _extract_workflow_caller_steps(\n    steps: List[WorkflowBlockManifest],\n) -> List[Tuple[str, Optional[str], WorkflowBlockManifest]]:\n    \"\"\"Extract (workflow_id, workflow_version_id, manifest) tuples from\n    workflow_caller steps that have literal (non-selector) workflow_id values.\"\"\"\n    result = []\n    for step in steps:\n        if not isinstance(step, BlockManifest):\n            continue\n        workflow_id = step.workflow_id\n        if isinstance(workflow_id, str) and not workflow_id.startswith(\"$\"):\n            version_id = step.workflow_version_id\n            # Only use version_id if it's a literal string (not a selector)\n            if isinstance(version_id, str) and version_id.startswith(\"$\"):\n                version_id = None\n            result.append((workflow_id, version_id, step))\n    return result\n\n\ndef _fetch_workflow_spec_for_validation(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[dict]:\n    \"\"\"Fetch a workflow spec, returning None on any error.\"\"\"\n    try:\n        return get_workflow_specification(\n            api_key=api_key,\n            workspace_id=workspace_name,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n        )\n    except Exception as error:\n        logging.debug(\n            \"Could not fetch workflow '%s' for compile-time validation (error type: %s)\",\n            workflow_id,\n            type(error).__name__,\n        )\n        return None\n\n\ndef _resolve_workspace_for_validation(\n    api_key: Optional[str],\n) -> Optional[str]:\n    if not api_key:\n        return None\n    try:\n        return get_roboflow_workspace(api_key=api_key)\n    except Exception as error:\n        logging.debug(\n            \"Could not resolve workspace for compile-time workflow validation (error type: %s)\",\n            type(error).__name__,\n        )\n        return None\n\n\ndef _check_workflow_for_circular_references(\n    api_key: Optional[str],\n    workspace_name: str,\n    target_workflow_id: str,\n    visited: set,\n    target_workflow_version_id: Optional[str] = None,\n    prefetched_spec: Optional[dict] = None,\n) -> None:\n    \"\"\"Recursively check if a target workflow creates a circular call chain.\n\n    Raises ``ExecutionGraphStructureError`` if a cycle is found. Silently\n    returns on any fetch error \u2014 the runtime check will catch those cases.\n\n    When ``prefetched_spec`` is provided it is used directly instead of\n    fetching the spec again.  The caller in\n    ``validate_workflow_caller_no_circular_references`` already fetches the\n    spec for the top-level workflow, so passing it here avoids a duplicate\n    API call.\n    \"\"\"\n    from inference.core.workflows.errors import ExecutionGraphStructureError\n\n    if target_workflow_id in visited:\n        chain = \" -> \".join([*visited, target_workflow_id])\n        raise ExecutionGraphStructureError(\n            public_message=(\n                f\"Circular workflow call detected at compile time: {chain}. \"\n                f\"This would cause infinite recursion at runtime.\"\n            ),\n            context=\"workflow_compilation | workflow_caller_validation\",\n        )\n    if prefetched_spec is not None:\n        spec = prefetched_spec\n    else:\n        try:\n            spec = get_workflow_specification(\n                api_key=api_key,\n                workspace_id=workspace_name,\n                workflow_id=target_workflow_id,\n                workflow_version_id=target_workflow_version_id,\n            )\n        except Exception as error:\n            logging.debug(\n                \"Could not fetch workflow '%s' for circular dependency check (error type: %s)\",\n                target_workflow_id,\n                type(error).__name__,\n            )\n            return\n    nested_workflows = _extract_workflow_caller_ids_from_spec(spec=spec)\n    if not nested_workflows:\n        return\n    visited_with_current = visited | {target_workflow_id}\n    for nested_id, nested_version_id in nested_workflows:\n        _check_workflow_for_circular_references(\n            api_key=api_key,\n            workspace_name=workspace_name,\n            target_workflow_id=nested_id,\n            target_workflow_version_id=nested_version_id,\n            visited=visited_with_current,\n        )\n\n\ndef _extract_workflow_caller_ids_from_spec(\n    spec: dict,\n) -> List[Tuple[str, Optional[str]]]:\n    \"\"\"Extract static (workflow_id, workflow_version_id) tuples from a raw\n    workflow specification.  Only includes entries where ``workflow_id`` is a\n    literal string (not a selector).  ``workflow_version_id`` is included when\n    it is a literal string, otherwise ``None``.\"\"\"\n    steps = spec.get(\"steps\", [])\n    result: List[Tuple[str, Optional[str]]] = []\n    for step in steps:\n        step_type = step.get(\"type\", \"\")\n        if step_type != WORKFLOW_CALLER_BLOCK_TYPE:\n            continue\n        workflow_id = step.get(\"workflow_id\", \"\")\n        if not isinstance(workflow_id, str) or workflow_id.startswith(\"$\"):\n            continue\n        version_id = step.get(\"workflow_version_id\")\n        if isinstance(version_id, str) and version_id.startswith(\"$\"):\n            version_id = None\n        result.append((workflow_id, version_id))\n    return result\n\n\n# ---------------------------------------------------------------------------\n# Output interface resolution\n# ---------------------------------------------------------------------------\n\n\ndef _resolve_and_cache_workflow_outputs(\n    cache_key: Tuple[str, Optional[str]],\n    spec: dict,\n) -> None:\n    \"\"\"Resolve the target workflow's output interface from its spec and cache\n    the result in ``_RESOLVED_WORKFLOW_OUTPUTS``.\n\n    Tries ``describe_workflow_outputs()`` for proper Kind resolution. Falls\n    back to extracting output names with ``WILDCARD_KIND`` on any error.\n    \"\"\"\n    try:\n        outputs_description = _describe_outputs_from_spec(spec=spec)\n    except Exception as error:\n        logging.debug(\n            f\"Could not resolve output kinds for workflow '{cache_key}' \"\n            f\"via describe_workflow_outputs: {error}. \"\n            f\"Falling back to output names with WILDCARD_KIND.\"\n        )\n        outputs_description = None\n\n    if outputs_description is not None:\n        resolved = _convert_output_descriptions_to_kinds(\n            outputs_description=outputs_description,\n        )\n    else:\n        resolved = _extract_output_names_with_wildcard(spec=spec)\n\n    if resolved:\n        _RESOLVED_WORKFLOW_OUTPUTS[cache_key] = resolved\n\n\ndef _describe_outputs_from_spec(\n    spec: dict,\n) -> Dict[str, Union[List[str], Dict[str, List[str]]]]:\n    \"\"\"Call the standard output discovery to resolve output kinds.\"\"\"\n    from inference.core.workflows.execution_engine.v1.introspection.outputs_discovery import (\n        describe_workflow_outputs,\n    )\n\n    return describe_workflow_outputs(definition=spec)\n\n\ndef _convert_output_descriptions_to_kinds(\n    outputs_description: Dict[str, Union[List[str], Dict[str, List[str]]]],\n) -> Dict[str, List[Kind]]:\n    \"\"\"Convert ``describe_workflow_outputs()`` result (kind name strings) to\n    ``Kind`` objects.\"\"\"\n    kind_name_map = _build_kind_name_map()\n    result: Dict[str, List[Kind]] = {}\n    for name, kind_info in outputs_description.items():\n        if isinstance(kind_info, dict):\n            # Wildcard selector ($steps.step.*) \u2014 nested structure.\n            # Represent as DICTIONARY_KIND since we can't express nested\n            # typed properties in a single OutputDefinition.\n            result[name] = [DICTIONARY_KIND]\n        else:\n            kinds = [\n                kind_name_map[k]\n                for k in kind_info\n                if k in kind_name_map\n            ]\n            result[name] = kinds if kinds else [WILDCARD_KIND]\n    return result\n\n\ndef _extract_output_names_with_wildcard(\n    spec: dict,\n) -> Dict[str, List[Kind]]:\n    \"\"\"Fallback: extract just the output names and assign WILDCARD_KIND.\"\"\"\n    outputs = spec.get(\"outputs\", [])\n    result: Dict[str, List[Kind]] = {}\n    for output in outputs:\n        name = output.get(\"name\")\n        if name:\n            result[name] = [WILDCARD_KIND]\n    return result\n\n\n@lru_cache(maxsize=1)\ndef _build_kind_name_map() -> Dict[str, Kind]:\n    \"\"\"Build a mapping from kind name to Kind object using the loader.\n\n    Result is cached since the set of registered kinds does not change\n    within a process.\n    \"\"\"\n    from inference.core.workflows.core_steps.loader import load_kinds\n\n    return {kind.name: kind for kind in load_kinds()}\n\n\n# ---------------------------------------------------------------------------\n# Input interface resolution\n# ---------------------------------------------------------------------------\n\n\ndef _resolve_and_cache_workflow_inputs(\n    cache_key: Tuple[str, Optional[str]],\n    spec: dict,\n) -> None:\n    \"\"\"Parse the target workflow's input interface from its spec and cache\n    the result in ``_RESOLVED_WORKFLOW_INPUTS``.\n\n    Each input is stored as a dict with keys: name, type, has_default.\n    \"\"\"\n    raw_inputs = spec.get(\"inputs\", [])\n    parsed: List[Dict[str, Any]] = []\n    for inp in raw_inputs:\n        name = inp.get(\"name\")\n        if not name:\n            continue\n        inp_type = inp.get(\"type\", \"\")\n        parsed.append({\n            \"name\": name,\n            \"type\": inp_type,\n            \"has_default\": \"default_value\" in inp,\n        })\n    _RESOLVED_WORKFLOW_INPUTS[cache_key] = parsed\n\n\ndef _validate_required_inputs(\n    workflow_id: str,\n    step_manifest: BlockManifest,\n    workflow_version_id: Optional[str] = None,\n) -> None:\n    \"\"\"Validate that the workflow caller step provides all required inputs\n    that the target workflow expects.\n\n    Raises ``ExecutionGraphStructureError`` if:\n    - The target workflow has required parameters (no default) not covered by\n      ``inputs``.\n    - The user declared ``input_definitions`` but ``inputs`` does not\n      cover all declared input names.\n    \"\"\"\n    from inference.core.workflows.errors import ExecutionGraphStructureError\n\n    input_keys = set(step_manifest.inputs.keys())\n\n    # Validate user-declared input_definitions: every declared input must be\n    # present in inputs.\n    if step_manifest.input_definitions:\n        missing_declared = [\n            name for name in step_manifest.input_definitions\n            if name not in input_keys\n        ]\n        if missing_declared:\n            raise ExecutionGraphStructureError(\n                public_message=(\n                    f\"Workflow caller step '{step_manifest.name}' declares \"\n                    f\"input_definitions for {list(step_manifest.input_definitions.keys())}, \"\n                    f\"but input(s) {missing_declared} are not provided in \"\n                    f\"'inputs'.\"\n                ),\n                context=\"workflow_compilation | workflow_caller_validation\",\n            )\n\n    cache_key = _make_cache_key(workflow_id, workflow_version_id)\n    resolved_inputs = _RESOLVED_WORKFLOW_INPUTS.get(cache_key)\n    if resolved_inputs is None:\n        return\n\n    missing = []\n    for inp in resolved_inputs:\n        if inp[\"has_default\"]:\n            continue\n        if inp[\"name\"] not in input_keys:\n            missing.append(inp[\"name\"])\n    if missing:\n        raise ExecutionGraphStructureError(\n            public_message=(\n                f\"Target workflow '{workflow_id}' requires input(s) \"\n                f\"{missing} (no default values), but they are not provided \"\n                f\"in 'inputs' on workflow_caller step \"\n                f\"'{step_manifest.name}'.\"\n            ),\n            context=\"workflow_compilation | workflow_caller_validation\",\n        )\n\n\n# ---------------------------------------------------------------------------\n# Output resolution for runtime\n# ---------------------------------------------------------------------------\n\n\ndef _resolve_output_kinds_for_run(\n    output_definitions: Dict[str, List[str]],\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[Dict[str, List[Kind]]]:\n    \"\"\"Determine which outputs to extract and their Kind objects.\n\n    Priority:\n    1. User-declared ``output_definitions`` (explicit kind names)\n    2. Auto-discovered outputs from ``_RESOLVED_WORKFLOW_OUTPUTS`` cache\n    3. Returns ``None`` \u2192 caller should fall back to generic ``result`` dict\n    \"\"\"\n    if output_definitions:\n        kind_name_map = _build_kind_name_map()\n        result: Dict[str, List[Kind]] = {}\n        for name, kind_names in output_definitions.items():\n            kinds = [\n                kind_name_map[k] for k in kind_names if k in kind_name_map\n            ]\n            result[name] = kinds or [WILDCARD_KIND]\n        return result\n    cache_key = _make_cache_key(workflow_id, workflow_version_id)\n    resolved = _RESOLVED_WORKFLOW_OUTPUTS.get(cache_key)\n    if resolved is not None:\n        return resolved\n    return None\n\n\n# ---------------------------------------------------------------------------\n# Output deserialization\n# ---------------------------------------------------------------------------\n\n\n@lru_cache(maxsize=1)\ndef _build_kinds_deserializers_map() -> Dict[str, Callable[[str, Any], Any]]:\n    \"\"\"Build the map of kind name -> deserializer function.\n\n    Result is cached since the set of registered deserializers does not\n    change within a process.\n    \"\"\"\n    from inference.core.workflows.execution_engine.introspection.blocks_loader import (\n        load_kinds_deserializers,\n    )\n\n    return load_kinds_deserializers()\n\n\ndef _deserialize_output_value(\n    output_name: str,\n    raw_value: Any,\n    output_kinds: List[Kind],\n    deserializers: Dict[str, Callable[[str, Any], Any]],\n) -> Any:\n    \"\"\"Deserialize a single output value using the deserializer matching its\n    resolved kind.\n\n    For outputs with known kinds, deserialization is required \u2014 failure raises\n    an error so downstream blocks don't receive unexpected raw data. For\n    WILDCARD_KIND outputs the raw value is returned as-is since we don't know\n    the expected type.\n    \"\"\"\n    if raw_value is None:\n        return None\n    if all(kind == WILDCARD_KIND for kind in output_kinds):\n        return raw_value\n    errors: List[Tuple[str, Exception]] = []\n    for kind in output_kinds:\n        if kind == WILDCARD_KIND:\n            continue\n        if kind.name not in deserializers:\n            continue\n        try:\n            return deserializers[kind.name](output_name, raw_value)\n        except Exception as error:\n            errors.append((kind.name, error))\n            continue\n    if errors:\n        error_details = \"; \".join(\n            f\"{kind}: {error}\" for kind, error in errors\n        )\n        raise RuntimeError(\n            f\"Failed to deserialize output '{output_name}' from target \"\n            f\"workflow. Tried deserializers for kinds \"\n            f\"{[k for k, _ in errors]} but all failed: {error_details}. \"\n            f\"This likely means the target workflow's output format doesn't \"\n            f\"match the expected kind.\"\n        )\n    return raw_value\n",
    "patch": null
  },
  {
    "trace_id": "6b14b394-5c2f-416b-87de-bef439c001f8",
    "function_name": "_describe_outputs_from_spec",
    "file_path": "inference/core/workflows/core_steps/composition/workflow_caller/v1.py",
    "speedup_x": 11.93871107659098,
    "review_quality": "medium",
    "pre_optimization_commit": "2f6a10764cd3da01cb46073d710b1dec32962220",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def _describe_outputs_from_spec(\n    spec: dict,\n) -> Dict[str, Union[List[str], Dict[str, List[str]]]]:\n    \"\"\"Call the standard output discovery to resolve output kinds.\"\"\"\n    from inference.core.workflows.execution_engine.v1.introspection.outputs_discovery import (\n        describe_workflow_outputs,\n    )\n\n    return describe_workflow_outputs(definition=spec)\n",
    "optimized_function_code": "from typing import Dict, List, Union\n\nfrom inference.core.workflows.errors import WorkflowDefinitionError\nfrom inference.core.workflows.execution_engine.introspection.entities import \\\n    BlocksDescription\n\n\ndef map_step_name_to_block_type(workflow_steps: List[dict]) -> Dict[str, str]:\n    result = {}\n    for step in workflow_steps:\n        if \"name\" not in step or \"type\" not in step:\n            raise WorkflowDefinitionError(\n                public_message=\"Workflow definition invalid - step without `name` or `type` defined found.\",\n                context=\"describing_workflow_outputs\",\n            )\n        result[step[\"name\"]] = step[\"type\"]\n    return result\n\n\ndef get_blocks_output_property_kinds(\n    blocks_description: BlocksDescription,\n) -> Dict[str, Dict[str, List[str]]]:\n    block_output_map = {}\n    for block in blocks_description.blocks:\n        key = block.manifest_type_identifier\n        output_property_kinds = get_output_property_kinds(block.outputs_manifest)\n        block_output_map[key] = output_property_kinds\n        for alias in block.manifest_type_identifier_aliases:\n            block_output_map[alias] = output_property_kinds\n    return block_output_map\n\n\ndef determine_workflow_outputs_kinds(\n    outputs_definitions: List[dict],\n    step_name_to_block_type: Dict[str, str],\n    block_output_map: Dict[str, Dict[str, List[str]]],\n) -> Dict[str, Union[List[str], Dict[str, List[str]]]]:\n    workflow_response_definition = {}\n    for output in outputs_definitions:\n        output_name = output[\"name\"]\n        selector = output[\"selector\"]\n        step_name, selected_property = extract_step_name_and_selected_property(\n            selector=selector,\n        )\n        if step_name not in step_name_to_block_type:\n            raise WorkflowDefinitionError(\n                public_message=f\"Could not find step referred in outputs (`{step_name}`) within Workflow steps.\",\n                context=\"describing_workflow_outputs\",\n            )\n        step_type = step_name_to_block_type[step_name]\n        output_properties = block_output_map[step_type]\n        if selected_property == \"*\":\n            property_kind = output_properties\n        else:\n            if selected_property not in output_properties:\n                raise WorkflowDefinitionError(\n                    public_message=f\"Step `{step_name}` does not declare {selected_property} in its outputs.\",\n                    context=\"describing_workflow_outputs\",\n                )\n            property_kind = output_properties[selected_property]\n        workflow_response_definition[output_name] = property_kind\n    return workflow_response_definition\n\nfrom typing import Tuple\n\nfrom inference.core.workflows.execution_engine.introspection.blocks_loader import \\\n    describe_available_blocks\nfrom inference.core.workflows.execution_engine.v1.core import \\\n    EXECUTION_ENGINE_V1_VERSION\nfrom inference.core.workflows.execution_engine.v1.dynamic_blocks.block_assembler import \\\n    compile_dynamic_blocks\n\n# Simple module-level cache to avoid re-describing available blocks repeatedly.\n# Keyed by (execution_engine_version_str, repr(dynamic_blocks_definitions))\n# Repr is used to avoid attempting to JSON-serialize potentially arbitrary objects;\n# it preserves behavior and avoids raising different exception types.\n_BLOCK_OUTPUT_MAP_CACHE: Dict[Tuple[str, str], Dict[str, Dict[str, List[str]]]] = {}\n\n\n\ndef describe_workflow_outputs(\n    definition: dict,\n) -> Dict[str, Union[List[str], Dict[str, List[str]]]]:\n    dynamic_defs = definition.get(\"dynamic_blocks_definitions\", [])\n    cache_key = (str(EXECUTION_ENGINE_V1_VERSION), repr(dynamic_defs))\n\n    block_output_map = _BLOCK_OUTPUT_MAP_CACHE.get(cache_key)\n    if block_output_map is None:\n        # Compile dynamic blocks only as needed and describe available blocks once per unique key.\n        dynamic_blocks = compile_dynamic_blocks(\n            dynamic_blocks_definitions=dynamic_defs,\n            skip_class_eval=True,\n        )\n        blocks_description = describe_available_blocks(\n            dynamic_blocks=dynamic_blocks,\n            execution_engine_version=EXECUTION_ENGINE_V1_VERSION,\n        )\n        block_output_map = get_blocks_output_property_kinds(\n            blocks_description=blocks_description\n        )\n        # Cache the computed mapping for subsequent calls with same key.\n        _BLOCK_OUTPUT_MAP_CACHE[cache_key] = block_output_map\n\n    try:\n        step_name_to_block_type = map_step_name_to_block_type(\n            workflow_steps=definition[\"steps\"]\n        )\n        return determine_workflow_outputs_kinds(\n            outputs_definitions=definition[\"outputs\"],\n            step_name_to_block_type=step_name_to_block_type,\n            block_output_map=block_output_map,\n        )\n    except KeyError as error:\n        raise WorkflowDefinitionError(\n            public_message=f\"Workflow definition invalid - missing property `{error}`.\",\n            inner_error=error,\n            context=\"describing_workflow_outputs\",\n        )",
    "optimized_raw_markdown": "```python:inference/core/workflows/execution_engine/v1/introspection/outputs_discovery.py\nfrom typing import Dict, List, Union\n\nfrom inference.core.workflows.errors import WorkflowDefinitionError\nfrom inference.core.workflows.execution_engine.introspection.entities import \\\n    BlocksDescription\n\n\ndef map_step_name_to_block_type(workflow_steps: List[dict]) -> Dict[str, str]:\n    result = {}\n    for step in workflow_steps:\n        if \"name\" not in step or \"type\" not in step:\n            raise WorkflowDefinitionError(\n                public_message=\"Workflow definition invalid - step without `name` or `type` defined found.\",\n                context=\"describing_workflow_outputs\",\n            )\n        result[step[\"name\"]] = step[\"type\"]\n    return result\n\n\ndef get_blocks_output_property_kinds(\n    blocks_description: BlocksDescription,\n) -> Dict[str, Dict[str, List[str]]]:\n    block_output_map = {}\n    for block in blocks_description.blocks:\n        key = block.manifest_type_identifier\n        output_property_kinds = get_output_property_kinds(block.outputs_manifest)\n        block_output_map[key] = output_property_kinds\n        for alias in block.manifest_type_identifier_aliases:\n            block_output_map[alias] = output_property_kinds\n    return block_output_map\n\n\ndef determine_workflow_outputs_kinds(\n    outputs_definitions: List[dict],\n    step_name_to_block_type: Dict[str, str],\n    block_output_map: Dict[str, Dict[str, List[str]]],\n) -> Dict[str, Union[List[str], Dict[str, List[str]]]]:\n    workflow_response_definition = {}\n    for output in outputs_definitions:\n        output_name = output[\"name\"]\n        selector = output[\"selector\"]\n        step_name, selected_property = extract_step_name_and_selected_property(\n            selector=selector,\n        )\n        if step_name not in step_name_to_block_type:\n            raise WorkflowDefinitionError(\n                public_message=f\"Could not find step referred in outputs (`{step_name}`) within Workflow steps.\",\n                context=\"describing_workflow_outputs\",\n            )\n        step_type = step_name_to_block_type[step_name]\n        output_properties = block_output_map[step_type]\n        if selected_property == \"*\":\n            property_kind = output_properties\n        else:\n            if selected_property not in output_properties:\n                raise WorkflowDefinitionError(\n                    public_message=f\"Step `{step_name}` does not declare {selected_property} in its outputs.\",\n                    context=\"describing_workflow_outputs\",\n                )\n            property_kind = output_properties[selected_property]\n        workflow_response_definition[output_name] = property_kind\n    return workflow_response_definition\n\nfrom typing import Tuple\n\nfrom inference.core.workflows.execution_engine.introspection.blocks_loader import \\\n    describe_available_blocks\nfrom inference.core.workflows.execution_engine.v1.core import \\\n    EXECUTION_ENGINE_V1_VERSION\nfrom inference.core.workflows.execution_engine.v1.dynamic_blocks.block_assembler import \\\n    compile_dynamic_blocks\n\n# Simple module-level cache to avoid re-describing available blocks repeatedly.\n# Keyed by (execution_engine_version_str, repr(dynamic_blocks_definitions))\n# Repr is used to avoid attempting to JSON-serialize potentially arbitrary objects;\n# it preserves behavior and avoids raising different exception types.\n_BLOCK_OUTPUT_MAP_CACHE: Dict[Tuple[str, str], Dict[str, Dict[str, List[str]]]] = {}\n\n\n\ndef describe_workflow_outputs(\n    definition: dict,\n) -> Dict[str, Union[List[str], Dict[str, List[str]]]]:\n    dynamic_defs = definition.get(\"dynamic_blocks_definitions\", [])\n    cache_key = (str(EXECUTION_ENGINE_V1_VERSION), repr(dynamic_defs))\n\n    block_output_map = _BLOCK_OUTPUT_MAP_CACHE.get(cache_key)\n    if block_output_map is None:\n        # Compile dynamic blocks only as needed and describe available blocks once per unique key.\n        dynamic_blocks = compile_dynamic_blocks(\n            dynamic_blocks_definitions=dynamic_defs,\n            skip_class_eval=True,\n        )\n        blocks_description = describe_available_blocks(\n            dynamic_blocks=dynamic_blocks,\n            execution_engine_version=EXECUTION_ENGINE_V1_VERSION,\n        )\n        block_output_map = get_blocks_output_property_kinds(\n            blocks_description=blocks_description\n        )\n        # Cache the computed mapping for subsequent calls with same key.\n        _BLOCK_OUTPUT_MAP_CACHE[cache_key] = block_output_map\n\n    try:\n        step_name_to_block_type = map_step_name_to_block_type(\n            workflow_steps=definition[\"steps\"]\n        )\n        return determine_workflow_outputs_kinds(\n            outputs_definitions=definition[\"outputs\"],\n            step_name_to_block_type=step_name_to_block_type,\n            block_output_map=block_output_map,\n        )\n    except KeyError as error:\n        raise WorkflowDefinitionError(\n            public_message=f\"Workflow definition invalid - missing property `{error}`.\",\n            inner_error=error,\n            context=\"describing_workflow_outputs\",\n        )\n```",
    "optimized_function_only": null,
    "original_file_content": "import logging\nimport re\nfrom functools import lru_cache\nfrom typing import Any, Callable, Dict, List, Literal, Optional, Tuple, Type, Union\n\nimport requests\nfrom pydantic import ConfigDict, Field, field_validator\n\nfrom inference.core.env import LOCAL_INFERENCE_API_URL\nfrom inference.core.roboflow_api import (\n    get_roboflow_workspace,\n    get_workflow_specification,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    DICTIONARY_KIND,\n    INTEGER_KIND,\n    STRING_KIND,\n    WILDCARD_KIND,\n    Kind,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nLONG_DESCRIPTION = \"\"\"\nThe **Workflow Caller** block enables calling another Roboflow workflow from within a workflow.\nThis is useful for composing complex pipelines from smaller, reusable workflow components.\n\n### How it works\n\nThe block takes a workflow ID (from the same workspace), passes inputs (including images)\nto the target workflow, executes it via HTTP, and returns the results.\n\n### Configuration\n\nSpecify the target workflow using `workflow_id` (just the workflow slug, not a full URL). The\nworkspace is resolved automatically from the API key used to run the parent workflow.\n\n```\nworkflow_id = \"my-detection-pipeline\"\n```\n\n### Inputs\n\nPass all inputs the target workflow expects via `inputs`, including images:\n\n```\ninputs = {\n    \"image\": \"$inputs.image\",\n    \"confidence_threshold\": 0.5,\n    \"model_id\": \"$inputs.model_id\",\n}\n```\n\nUse `input_definitions` to declare the expected input types so the UI can render\nproper connectors.\n\n### Circular Dependency Protection\n\nTo prevent infinite recursion (e.g. Workflow A calls B, B calls A), the block tracks the chain\nof workflow calls using a header. If a circular reference is detected, the block returns an error\ninstead of making the call.\n\n### Dynamic Outputs\n\nWhen the target workflow_id is a static string, the block resolves the target workflow's\noutputs at compile time. Each output from the target workflow becomes a separate output on\nthis block with proper Kind types. When the workflow_id is dynamic (a selector), outputs\nfall back to a single ``result`` dict.\n\n### Limitations\n\n* Only workflows within the same workspace are supported (v1).\n* Execution is done via HTTP call, which adds network latency.\n* Subject to the same timeout constraints as the hosting environment.\n\"\"\"\n\nWORKFLOW_CALL_CHAIN_HEADER = \"X-Roboflow-Workflow-Call-Chain\"\nMAX_WORKFLOW_CALL_DEPTH = 10\nWORKFLOW_CALLER_BLOCK_TYPE = \"roboflow_core/workflow_caller@v1\"\n\n# Module-level cache mapping (workflow_id, version_id) -> {output_name: [Kind]}.\n# Populated during compile-time validation, read by get_actual_outputs() and run().\n_RESOLVED_WORKFLOW_OUTPUTS: Dict[Tuple[str, Optional[str]], Dict[str, List[Kind]]] = {}\n\n# Module-level cache mapping (workflow_id, version_id) -> list of parsed input dicts\n# from spec.  Each dict has: name, type, kind, has_default.\n_RESOLVED_WORKFLOW_INPUTS: Dict[Tuple[str, Optional[str]], List[Dict[str, Any]]] = {}\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Workflow Caller\",\n            \"version\": \"v1\",\n            \"short_description\": \"Call another Roboflow workflow from within a workflow.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"transformation\",\n            \"ui_manifest\": {\n                \"section\": \"advanced\",\n                \"icon\": \"fal fa-diagram-subtask\",\n                \"blockPriority\": 2,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/workflow_caller@v1\"]\n    workflow_id: Union[Selector(kind=[STRING_KIND]), str] = Field(\n        description=\"The workflow ID to call (must be in the same workspace).\",\n        examples=[\"my-workflow-id\", \"$inputs.workflow_id\"],\n    )\n    workflow_version_id: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Optional version ID of the target workflow. When provided, \"\n        \"the block calls the specific version instead of the latest. \"\n        \"Use this to pin a dependency to a known-good version.\",\n        examples=[\"1709234567890\", \"$inputs.workflow_version\"],\n    )\n    inputs: Dict[\n        str,\n        Union[\n            Selector(),\n            str,\n            float,\n            bool,\n            int,\n            dict,\n            list,\n        ],\n    ] = Field(\n        default_factory=dict,\n        description=\"Inputs to pass to the target workflow, keyed by input name. \"\n        \"All inputs including images should be listed here.\",\n        examples=[\n            {\"image\": \"$inputs.image\", \"confidence_threshold\": 0.5},\n            {\"image\": \"$inputs.image\", \"model_id\": \"$inputs.model_id\"},\n        ],\n    )\n    request_timeout: Union[int, Selector(kind=[INTEGER_KIND])] = Field(\n        default=30,\n        description=\"HTTP request timeout in seconds.\",\n        examples=[\"$inputs.request_timeout\", 30],\n    )\n    input_definitions: Dict[str, List[str]] = Field(\n        default_factory=dict,\n        description=(\n            \"Mapping of expected input names to their kind types. \"\n            \"Each key is an input name in the target workflow, and the value \"\n            \"is a list of kind name strings (e.g. ['float'], ['roboflow_model_id']). \"\n            \"This tells the parent workflow what inputs the target expects, \"\n            \"enabling proper UI connectors. Actual values are provided via \"\n            \"'inputs'.\"\n        ),\n        examples=[\n            {\"image\": [\"image\"], \"confidence_threshold\": [\"float\"]},\n            {\n                \"image\": [\"image\"],\n                \"class_filter\": [\"string\"],\n                \"iou_threshold\": [\"float\"],\n            },\n        ],\n    )\n    output_definitions: Dict[str, List[str]] = Field(\n        default_factory=dict,\n        description=(\n            \"Mapping of expected output names to their kind types. \"\n            \"Each key is an output name from the target workflow, and the value \"\n            \"is a list of kind name strings (e.g. ['object_detection_prediction']). \"\n            \"This tells the parent workflow what types to expect, enabling proper \"\n            \"connections to downstream blocks like visualizers.\"\n        ),\n        examples=[\n            {\"predictions\": [\"object_detection_prediction\"]},\n            {\"result_image\": [\"image\"], \"count\": [\"integer\"]},\n        ],\n    )\n\n    @field_validator(\"workflow_id\")\n    @classmethod\n    def validate_workflow_id_slug(cls, value: Any) -> Any:\n        if isinstance(value, str) and not value.startswith(\"$\"):\n            if not re.fullmatch(r\"[\\w\\-]+\", value):\n                raise ValueError(\n                    f\"`workflow_id` must be a valid slug (letters, numbers, \"\n                    f\"hyphens, and underscores only). Got: '{value}'\"\n                )\n        return value\n\n    @field_validator(\"request_timeout\")\n    @classmethod\n    def ensure_request_timeout_is_positive(cls, value: Any) -> Any:\n        if isinstance(value, int) and value <= 0:\n            raise ValueError(\"`request_timeout` must be a positive integer.\")\n        return value\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return []\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"*\"),\n        ]\n\n    def get_actual_outputs(self) -> List[OutputDefinition]:\n        base: List[OutputDefinition] = []\n        # 1. User-defined output definitions take precedence\n        if self.output_definitions:\n            kind_name_map = _build_kind_name_map()\n            for name, kind_names in self.output_definitions.items():\n                kinds = [kind_name_map[k] for k in kind_names if k in kind_name_map]\n                base.append(OutputDefinition(name=name, kind=kinds or [WILDCARD_KIND]))\n            return base\n        # 2. Fall back to auto-discovery from compile-time resolution\n        if isinstance(self.workflow_id, str) and not self.workflow_id.startswith(\"$\"):\n            version_id = self.workflow_version_id\n            if isinstance(version_id, str) and version_id.startswith(\"$\"):\n                version_id = None\n            cache_key = _make_cache_key(self.workflow_id, version_id)\n            resolved = _RESOLVED_WORKFLOW_OUTPUTS.get(cache_key)\n            if resolved is not None:\n                for name, kinds in resolved.items():\n                    base.append(OutputDefinition(name=name, kind=kinds))\n                return base\n        # 3. Fall back to generic result dict\n        base.append(OutputDefinition(name=\"result\", kind=[DICTIONARY_KIND]))\n        return base\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass WorkflowCallerBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        api_key: Optional[str],\n        workflow_call_chain: Optional[str] = None,\n    ):\n        self._api_key = api_key\n        self._workspace_name: Optional[str] = None\n        self._workflow_call_chain = workflow_call_chain or \"\"\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"api_key\", \"workflow_call_chain\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        workflow_id: str,\n        inputs: Dict[str, Any],\n        request_timeout: int,\n        input_definitions: Dict[str, List[str]],\n        output_definitions: Dict[str, List[str]],\n        workflow_version_id: Optional[str] = None,\n    ) -> BlockResult:\n        workspace_name = self._resolve_workspace_name()\n        if workspace_name is None:\n            raise RuntimeError(\n                f\"Could not resolve workspace for workflow '{workflow_id}'. \"\n                f\"Ensure a valid API key is configured.\"\n            )\n        error_status, message, raw_outputs = call_workflow(\n            api_key=self._api_key,\n            workspace_name=workspace_name,\n            workflow_id=workflow_id,\n            inputs=inputs,\n            request_timeout=request_timeout,\n            call_chain=self._workflow_call_chain,\n            workflow_version_id=workflow_version_id,\n        )\n        if error_status:\n            raise RuntimeError(f\"Workflow '{workflow_id}' execution failed: {message}\")\n        result: Dict[str, Any] = {}\n        # Determine which outputs to extract and their kinds for deserialization\n        output_kinds_map = _resolve_output_kinds_for_run(\n            output_definitions=output_definitions,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n        )\n        if output_kinds_map is not None:\n            deserializers = _build_kinds_deserializers_map()\n            for output_name, output_kinds in output_kinds_map.items():\n                raw_value = raw_outputs.get(output_name)\n                result[output_name] = _deserialize_output_value(\n                    output_name=output_name,\n                    raw_value=raw_value,\n                    output_kinds=output_kinds,\n                    deserializers=deserializers,\n                )\n        else:\n            result[\"result\"] = raw_outputs\n        return result\n\n    def _resolve_workspace_name(self) -> Optional[str]:\n        if self._workspace_name is not None:\n            return self._workspace_name\n        if not self._api_key:\n            return None\n        try:\n            self._workspace_name = get_roboflow_workspace(api_key=self._api_key)\n            return self._workspace_name\n        except Exception as error:\n            logging.warning(\n                f\"Could not resolve workspace from API key. Error: {str(error)}\"\n            )\n            return None\n\n\ndef _make_cache_key(\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Tuple[str, Optional[str]]:\n    \"\"\"Build a cache key that accounts for both workflow_id and version_id.\"\"\"\n    return (workflow_id, workflow_version_id)\n\n\ndef call_workflow(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    inputs: Dict[str, Any],\n    request_timeout: int,\n    call_chain: Optional[str] = None,\n    workflow_version_id: Optional[str] = None,\n) -> Tuple[bool, str, dict]:\n    \"\"\"Execute a workflow call and return (error_status, message, result).\n\n    This function is separated from the block's run() to facilitate testing.\n    \"\"\"\n    current_chain = call_chain or \"\"\n    chain_entries = [entry for entry in current_chain.split(\",\") if entry]\n    if workflow_id in chain_entries:\n        logging.warning(\n            f\"Circular workflow call detected: \"\n            f\"'{workflow_id}' is already in call chain [{current_chain}].\"\n        )\n        return (\n            True,\n            f\"Circular workflow call detected: '{workflow_id}' is already \"\n            f\"in the call chain [{current_chain}]. Aborting to prevent \"\n            f\"infinite recursion.\",\n            {},\n        )\n    if len(chain_entries) >= MAX_WORKFLOW_CALL_DEPTH:\n        logging.warning(\n            f\"Workflow call depth limit ({MAX_WORKFLOW_CALL_DEPTH}) reached. \"\n            f\"Call chain: [{current_chain}].\"\n        )\n        return (\n            True,\n            f\"Workflow call depth limit ({MAX_WORKFLOW_CALL_DEPTH}) reached. \"\n            f\"Call chain: [{current_chain}].\",\n            {},\n        )\n    updated_chain = \",\".join([*chain_entries, workflow_id])\n    inputs = build_workflow_inputs(inputs=inputs)\n    return execute_workflow_request(\n        api_key=api_key,\n        workspace_name=workspace_name,\n        workflow_id=workflow_id,\n        inputs=inputs,\n        request_timeout=request_timeout,\n        call_chain=updated_chain,\n        workflow_version_id=workflow_version_id,\n    )\n\n\ndef build_workflow_inputs(\n    inputs: Dict[str, Any],\n) -> Dict[str, Any]:\n    \"\"\"Build the inputs dictionary for the target workflow.\n\n    Handles ``WorkflowImageData`` objects found in ``inputs`` by\n    automatically serialising them to the ``{type: base64, value: ...}``\n    format expected by the workflow HTTP API.\n    \"\"\"\n    resolved: Dict[str, Any] = {}\n    for key, value in inputs.items():\n        if isinstance(value, WorkflowImageData):\n            resolved[key] = {\n                \"type\": \"base64\",\n                \"value\": value.base64_image,\n            }\n        else:\n            resolved[key] = value\n    return resolved\n\n\ndef execute_workflow_request(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    inputs: Dict[str, Any],\n    request_timeout: int,\n    call_chain: str,\n    workflow_version_id: Optional[str] = None,\n) -> Tuple[bool, str, dict]:\n    \"\"\"Make the HTTP request to the target workflow and return\n    (error_status, message, result).\"\"\"\n    url = build_workflow_url(\n        workspace_name=workspace_name,\n        workflow_id=workflow_id,\n    )\n    payload: Dict[str, Any] = {\"inputs\": inputs}\n    if api_key is not None:\n        payload[\"api_key\"] = api_key\n    if workflow_version_id is not None:\n        payload[\"workflow_version_id\"] = workflow_version_id\n    headers = {WORKFLOW_CALL_CHAIN_HEADER: call_chain}\n    try:\n        response = requests.post(\n            url,\n            json=payload,\n            headers=headers,\n            timeout=request_timeout,\n        )\n        response.raise_for_status()\n        response_data = response.json()\n        outputs = response_data.get(\"outputs\", [])\n        result = outputs[0] if outputs else {}\n        return (\n            False,\n            \"Workflow executed successfully\",\n            result,\n        )\n    except Exception as error:\n        logging.warning(\n            f\"Could not execute workflow '{workflow_id}'. Error: {str(error)}\"\n        )\n        error_type = type(error).__name__\n        return (\n            True,\n            f\"Failed to execute workflow '{workflow_id}': {error_type}\",\n            {},\n        )\n\n\ndef build_workflow_url(workspace_name: str, workflow_id: str) -> str:\n    \"\"\"Build the URL for calling a workflow on the local inference server.\n\n    Uses LOCAL_INFERENCE_API_URL to call the workflow on the same inference\n    server instance that is running the parent workflow.\n    \"\"\"\n    base_url = LOCAL_INFERENCE_API_URL.rstrip(\"/\")\n    return f\"{base_url}/{workspace_name}/workflows/{workflow_id}\"\n\n\n# ---------------------------------------------------------------------------\n# Compile-time validation\n# ---------------------------------------------------------------------------\n\n\ndef validate_workflow_caller_no_circular_references(\n    steps: List[WorkflowBlockManifest],\n    api_key: Optional[str],\n) -> None:\n    \"\"\"Compile-time validation: check that workflow_caller blocks with static\n    workflow_id values don't create circular dependencies, resolve the target\n    workflow's input and output interfaces, and validate that required inputs\n    are provided.\n\n    Only validates when workflow_id is a literal string (not a selector like\n    ``$inputs.workflow_id``). Errors during spec fetching are logged as warnings\n    and do not block compilation \u2014 the runtime circular dependency check via\n    the call chain header provides an additional safety net.\n    \"\"\"\n    caller_steps = _extract_workflow_caller_steps(steps=steps)\n    if not caller_steps:\n        return\n    workspace_name = _resolve_workspace_for_validation(api_key=api_key)\n    if workspace_name is None:\n        return\n    for workflow_id, version_id, step_manifest in caller_steps:\n        spec = _fetch_workflow_spec_for_validation(\n            api_key=api_key,\n            workspace_name=workspace_name,\n            workflow_id=workflow_id,\n            workflow_version_id=version_id,\n        )\n        if spec is None:\n            continue\n        _check_workflow_for_circular_references(\n            api_key=api_key,\n            workspace_name=workspace_name,\n            target_workflow_id=workflow_id,\n            target_workflow_version_id=version_id,\n            visited=set(),\n            prefetched_spec=spec,\n        )\n        cache_key = _make_cache_key(workflow_id, version_id)\n        _resolve_and_cache_workflow_outputs(\n            cache_key=cache_key,\n            spec=spec,\n        )\n        _resolve_and_cache_workflow_inputs(\n            cache_key=cache_key,\n            spec=spec,\n        )\n        _validate_required_inputs(\n            workflow_id=workflow_id,\n            workflow_version_id=version_id,\n            step_manifest=step_manifest,\n        )\n\n\ndef _extract_workflow_caller_steps(\n    steps: List[WorkflowBlockManifest],\n) -> List[Tuple[str, Optional[str], WorkflowBlockManifest]]:\n    \"\"\"Extract (workflow_id, workflow_version_id, manifest) tuples from\n    workflow_caller steps that have literal (non-selector) workflow_id values.\"\"\"\n    result = []\n    for step in steps:\n        if not isinstance(step, BlockManifest):\n            continue\n        workflow_id = step.workflow_id\n        if isinstance(workflow_id, str) and not workflow_id.startswith(\"$\"):\n            version_id = step.workflow_version_id\n            # Only use version_id if it's a literal string (not a selector)\n            if isinstance(version_id, str) and version_id.startswith(\"$\"):\n                version_id = None\n            result.append((workflow_id, version_id, step))\n    return result\n\n\ndef _fetch_workflow_spec_for_validation(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[dict]:\n    \"\"\"Fetch a workflow spec, returning None on any error.\"\"\"\n    try:\n        return get_workflow_specification(\n            api_key=api_key,\n            workspace_id=workspace_name,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n        )\n    except Exception as error:\n        logging.debug(\n            \"Could not fetch workflow '%s' for compile-time validation (error type: %s)\",\n            workflow_id,\n            type(error).__name__,\n        )\n        return None\n\n\ndef _resolve_workspace_for_validation(\n    api_key: Optional[str],\n) -> Optional[str]:\n    if not api_key:\n        return None\n    try:\n        return get_roboflow_workspace(api_key=api_key)\n    except Exception as error:\n        logging.debug(\n            \"Could not resolve workspace for compile-time workflow validation (error type: %s)\",\n            type(error).__name__,\n        )\n        return None\n\n\ndef _check_workflow_for_circular_references(\n    api_key: Optional[str],\n    workspace_name: str,\n    target_workflow_id: str,\n    visited: set,\n    target_workflow_version_id: Optional[str] = None,\n    prefetched_spec: Optional[dict] = None,\n) -> None:\n    \"\"\"Recursively check if a target workflow creates a circular call chain.\n\n    Raises ``ExecutionGraphStructureError`` if a cycle is found. Silently\n    returns on any fetch error \u2014 the runtime check will catch those cases.\n\n    When ``prefetched_spec`` is provided it is used directly instead of\n    fetching the spec again.  The caller in\n    ``validate_workflow_caller_no_circular_references`` already fetches the\n    spec for the top-level workflow, so passing it here avoids a duplicate\n    API call.\n    \"\"\"\n    from inference.core.workflows.errors import ExecutionGraphStructureError\n\n    if target_workflow_id in visited:\n        chain = \" -> \".join([*visited, target_workflow_id])\n        raise ExecutionGraphStructureError(\n            public_message=(\n                f\"Circular workflow call detected at compile time: {chain}. \"\n                f\"This would cause infinite recursion at runtime.\"\n            ),\n            context=\"workflow_compilation | workflow_caller_validation\",\n        )\n    if prefetched_spec is not None:\n        spec = prefetched_spec\n    else:\n        try:\n            spec = get_workflow_specification(\n                api_key=api_key,\n                workspace_id=workspace_name,\n                workflow_id=target_workflow_id,\n                workflow_version_id=target_workflow_version_id,\n            )\n        except Exception as error:\n            logging.debug(\n                \"Could not fetch workflow '%s' for circular dependency check (error type: %s)\",\n                target_workflow_id,\n                type(error).__name__,\n            )\n            return\n    nested_workflows = _extract_workflow_caller_ids_from_spec(spec=spec)\n    if not nested_workflows:\n        return\n    visited_with_current = visited | {target_workflow_id}\n    for nested_id, nested_version_id in nested_workflows:\n        _check_workflow_for_circular_references(\n            api_key=api_key,\n            workspace_name=workspace_name,\n            target_workflow_id=nested_id,\n            target_workflow_version_id=nested_version_id,\n            visited=visited_with_current,\n        )\n\n\ndef _extract_workflow_caller_ids_from_spec(\n    spec: dict,\n) -> List[Tuple[str, Optional[str]]]:\n    \"\"\"Extract static (workflow_id, workflow_version_id) tuples from a raw\n    workflow specification.  Only includes entries where ``workflow_id`` is a\n    literal string (not a selector).  ``workflow_version_id`` is included when\n    it is a literal string, otherwise ``None``.\"\"\"\n    steps = spec.get(\"steps\", [])\n    result: List[Tuple[str, Optional[str]]] = []\n    for step in steps:\n        step_type = step.get(\"type\", \"\")\n        if step_type != WORKFLOW_CALLER_BLOCK_TYPE:\n            continue\n        workflow_id = step.get(\"workflow_id\", \"\")\n        if not isinstance(workflow_id, str) or workflow_id.startswith(\"$\"):\n            continue\n        version_id = step.get(\"workflow_version_id\")\n        if isinstance(version_id, str) and version_id.startswith(\"$\"):\n            version_id = None\n        result.append((workflow_id, version_id))\n    return result\n\n\n# ---------------------------------------------------------------------------\n# Output interface resolution\n# ---------------------------------------------------------------------------\n\n\ndef _resolve_and_cache_workflow_outputs(\n    cache_key: Tuple[str, Optional[str]],\n    spec: dict,\n) -> None:\n    \"\"\"Resolve the target workflow's output interface from its spec and cache\n    the result in ``_RESOLVED_WORKFLOW_OUTPUTS``.\n\n    Tries ``describe_workflow_outputs()`` for proper Kind resolution. Falls\n    back to extracting output names with ``WILDCARD_KIND`` on any error.\n    \"\"\"\n    try:\n        outputs_description = _describe_outputs_from_spec(spec=spec)\n    except Exception as error:\n        logging.debug(\n            f\"Could not resolve output kinds for workflow '{cache_key}' \"\n            f\"via describe_workflow_outputs: {error}. \"\n            f\"Falling back to output names with WILDCARD_KIND.\"\n        )\n        outputs_description = None\n\n    if outputs_description is not None:\n        resolved = _convert_output_descriptions_to_kinds(\n            outputs_description=outputs_description,\n        )\n    else:\n        resolved = _extract_output_names_with_wildcard(spec=spec)\n\n    if resolved:\n        _RESOLVED_WORKFLOW_OUTPUTS[cache_key] = resolved\n\n\ndef _describe_outputs_from_spec(\n    spec: dict,\n) -> Dict[str, Union[List[str], Dict[str, List[str]]]]:\n    \"\"\"Call the standard output discovery to resolve output kinds.\"\"\"\n    from inference.core.workflows.execution_engine.v1.introspection.outputs_discovery import (\n        describe_workflow_outputs,\n    )\n\n    return describe_workflow_outputs(definition=spec)\n\n\ndef _convert_output_descriptions_to_kinds(\n    outputs_description: Dict[str, Union[List[str], Dict[str, List[str]]]],\n) -> Dict[str, List[Kind]]:\n    \"\"\"Convert ``describe_workflow_outputs()`` result (kind name strings) to\n    ``Kind`` objects.\"\"\"\n    kind_name_map = _build_kind_name_map()\n    result: Dict[str, List[Kind]] = {}\n    for name, kind_info in outputs_description.items():\n        if isinstance(kind_info, dict):\n            # Wildcard selector ($steps.step.*) \u2014 nested structure.\n            # Represent as DICTIONARY_KIND since we can't express nested\n            # typed properties in a single OutputDefinition.\n            result[name] = [DICTIONARY_KIND]\n        else:\n            kinds = [kind_name_map[k] for k in kind_info if k in kind_name_map]\n            result[name] = kinds if kinds else [WILDCARD_KIND]\n    return result\n\n\ndef _extract_output_names_with_wildcard(\n    spec: dict,\n) -> Dict[str, List[Kind]]:\n    \"\"\"Fallback: extract just the output names and assign WILDCARD_KIND.\"\"\"\n    outputs = spec.get(\"outputs\", [])\n    result: Dict[str, List[Kind]] = {}\n    for output in outputs:\n        name = output.get(\"name\")\n        if name:\n            result[name] = [WILDCARD_KIND]\n    return result\n\n\n@lru_cache(maxsize=1)\ndef _build_kind_name_map() -> Dict[str, Kind]:\n    \"\"\"Build a mapping from kind name to Kind object using the loader.\n\n    Result is cached since the set of registered kinds does not change\n    within a process.\n    \"\"\"\n    from inference.core.workflows.core_steps.loader import load_kinds\n\n    return {kind.name: kind for kind in load_kinds()}\n\n\n# ---------------------------------------------------------------------------\n# Input interface resolution\n# ---------------------------------------------------------------------------\n\n\ndef _resolve_and_cache_workflow_inputs(\n    cache_key: Tuple[str, Optional[str]],\n    spec: dict,\n) -> None:\n    \"\"\"Parse the target workflow's input interface from its spec and cache\n    the result in ``_RESOLVED_WORKFLOW_INPUTS``.\n\n    Each input is stored as a dict with keys: name, type, has_default.\n    \"\"\"\n    raw_inputs = spec.get(\"inputs\", [])\n    parsed: List[Dict[str, Any]] = []\n    for inp in raw_inputs:\n        name = inp.get(\"name\")\n        if not name:\n            continue\n        inp_type = inp.get(\"type\", \"\")\n        parsed.append(\n            {\n                \"name\": name,\n                \"type\": inp_type,\n                \"has_default\": \"default_value\" in inp,\n            }\n        )\n    _RESOLVED_WORKFLOW_INPUTS[cache_key] = parsed\n\n\ndef _validate_required_inputs(\n    workflow_id: str,\n    step_manifest: BlockManifest,\n    workflow_version_id: Optional[str] = None,\n) -> None:\n    \"\"\"Validate that the workflow caller step provides all required inputs\n    that the target workflow expects.\n\n    Raises ``ExecutionGraphStructureError`` if:\n    - The target workflow has required parameters (no default) not covered by\n      ``inputs``.\n    - The user declared ``input_definitions`` but ``inputs`` does not\n      cover all declared input names.\n    \"\"\"\n    from inference.core.workflows.errors import ExecutionGraphStructureError\n\n    input_keys = set(step_manifest.inputs.keys())\n\n    # Validate user-declared input_definitions: every declared input must be\n    # present in inputs.\n    if step_manifest.input_definitions:\n        missing_declared = [\n            name for name in step_manifest.input_definitions if name not in input_keys\n        ]\n        if missing_declared:\n            raise ExecutionGraphStructureError(\n                public_message=(\n                    f\"Workflow caller step '{step_manifest.name}' declares \"\n                    f\"input_definitions for {list(step_manifest.input_definitions.keys())}, \"\n                    f\"but input(s) {missing_declared} are not provided in \"\n                    f\"'inputs'.\"\n                ),\n                context=\"workflow_compilation | workflow_caller_validation\",\n            )\n\n    cache_key = _make_cache_key(workflow_id, workflow_version_id)\n    resolved_inputs = _RESOLVED_WORKFLOW_INPUTS.get(cache_key)\n    if resolved_inputs is None:\n        return\n\n    missing = []\n    for inp in resolved_inputs:\n        if inp[\"has_default\"]:\n            continue\n        if inp[\"name\"] not in input_keys:\n            missing.append(inp[\"name\"])\n    if missing:\n        raise ExecutionGraphStructureError(\n            public_message=(\n                f\"Target workflow '{workflow_id}' requires input(s) \"\n                f\"{missing} (no default values), but they are not provided \"\n                f\"in 'inputs' on workflow_caller step \"\n                f\"'{step_manifest.name}'.\"\n            ),\n            context=\"workflow_compilation | workflow_caller_validation\",\n        )\n\n\n# ---------------------------------------------------------------------------\n# Output resolution for runtime\n# ---------------------------------------------------------------------------\n\n\ndef _resolve_output_kinds_for_run(\n    output_definitions: Dict[str, List[str]],\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[Dict[str, List[Kind]]]:\n    \"\"\"Determine which outputs to extract and their Kind objects.\n\n    Priority:\n    1. User-declared ``output_definitions`` (explicit kind names)\n    2. Auto-discovered outputs from ``_RESOLVED_WORKFLOW_OUTPUTS`` cache\n    3. Returns ``None`` \u2192 caller should fall back to generic ``result`` dict\n    \"\"\"\n    if output_definitions:\n        kind_name_map = _build_kind_name_map()\n        result: Dict[str, List[Kind]] = {}\n        for name, kind_names in output_definitions.items():\n            kinds = [kind_name_map[k] for k in kind_names if k in kind_name_map]\n            result[name] = kinds or [WILDCARD_KIND]\n        return result\n    cache_key = _make_cache_key(workflow_id, workflow_version_id)\n    resolved = _RESOLVED_WORKFLOW_OUTPUTS.get(cache_key)\n    if resolved is not None:\n        return resolved\n    return None\n\n\n# ---------------------------------------------------------------------------\n# Output deserialization\n# ---------------------------------------------------------------------------\n\n\n@lru_cache(maxsize=1)\ndef _build_kinds_deserializers_map() -> Dict[str, Callable[[str, Any], Any]]:\n    \"\"\"Build the map of kind name -> deserializer function.\n\n    Result is cached since the set of registered deserializers does not\n    change within a process.\n    \"\"\"\n    from inference.core.workflows.execution_engine.introspection.blocks_loader import (\n        load_kinds_deserializers,\n    )\n\n    return load_kinds_deserializers()\n\n\ndef _deserialize_output_value(\n    output_name: str,\n    raw_value: Any,\n    output_kinds: List[Kind],\n    deserializers: Dict[str, Callable[[str, Any], Any]],\n) -> Any:\n    \"\"\"Deserialize a single output value using the deserializer matching its\n    resolved kind.\n\n    For outputs with known kinds, deserialization is required \u2014 failure raises\n    an error so downstream blocks don't receive unexpected raw data. For\n    WILDCARD_KIND outputs the raw value is returned as-is since we don't know\n    the expected type.\n    \"\"\"\n    if raw_value is None:\n        return None\n    if all(kind == WILDCARD_KIND for kind in output_kinds):\n        return raw_value\n    errors: List[Tuple[str, Exception]] = []\n    for kind in output_kinds:\n        if kind == WILDCARD_KIND:\n            continue\n        if kind.name not in deserializers:\n            continue\n        try:\n            return deserializers[kind.name](output_name, raw_value)\n        except Exception as error:\n            errors.append((kind.name, error))\n            continue\n    if errors:\n        error_details = \"; \".join(f\"{kind}: {error}\" for kind, error in errors)\n        raise RuntimeError(\n            f\"Failed to deserialize output '{output_name}' from target \"\n            f\"workflow. Tried deserializers for kinds \"\n            f\"{[k for k, _ in errors]} but all failed: {error_details}. \"\n            f\"This likely means the target workflow's output format doesn't \"\n            f\"match the expected kind.\"\n        )\n    return raw_value\n",
    "patch": null
  },
  {
    "trace_id": "b25c2c26-46de-4858-b0a1-d4e4483a9d32",
    "function_name": "_extract_workflow_caller_ids_from_spec",
    "file_path": "inference/core/workflows/core_steps/composition/workflow_caller/v1.py",
    "speedup_x": 0.340764780696051,
    "review_quality": "high",
    "pre_optimization_commit": "2f6a10764cd3da01cb46073d710b1dec32962220",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def _extract_workflow_caller_ids_from_spec(\n    spec: dict,\n) -> List[Tuple[str, Optional[str]]]:\n    \"\"\"Extract static (workflow_id, workflow_version_id) tuples from a raw\n    workflow specification.  Only includes entries where ``workflow_id`` is a\n    literal string (not a selector).  ``workflow_version_id`` is included when\n    it is a literal string, otherwise ``None``.\"\"\"\n    steps = spec.get(\"steps\", [])\n    result: List[Tuple[str, Optional[str]]] = []\n    for step in steps:\n        step_type = step.get(\"type\", \"\")\n        if step_type != WORKFLOW_CALLER_BLOCK_TYPE:\n            continue\n        workflow_id = step.get(\"workflow_id\", \"\")\n        if not isinstance(workflow_id, str) or workflow_id.startswith(\"$\"):\n            continue\n        version_id = step.get(\"workflow_version_id\")\n        if isinstance(version_id, str) and version_id.startswith(\"$\"):\n            version_id = None\n        result.append((workflow_id, version_id))\n    return result\n",
    "optimized_function_code": "from typing import List, Optional, Tuple\n\nWORKFLOW_CALLER_BLOCK_TYPE = \"roboflow_core/workflow_caller@v1\"\n\n\ndef _extract_workflow_caller_ids_from_spec(\n    spec: dict,\n) -> List[Tuple[str, Optional[str]]]:\n    \"\"\"Extract static (workflow_id, workflow_version_id) tuples from a raw\n    workflow specification.  Only includes entries where ``workflow_id`` is a\n    literal string (not a selector).  ``workflow_version_id`` is included when\n    it is a literal string, otherwise ``None``.\"\"\"\n    steps = spec.get(\"steps\", [])\n    result: List[Tuple[str, Optional[str]]] = []\n    # Localize the frequently-used constant to reduce global lookup overhead.\n    block_type = WORKFLOW_CALLER_BLOCK_TYPE\n    for step in steps:\n        step_type = step.get(\"type\", \"\")\n        if step_type != block_type:\n            continue\n        workflow_id = step.get(\"workflow_id\", \"\")\n        # Preserve original semantics: require a str and skip if it starts with \"$\".\n        # Use a first-character check which is slightly faster than startswith.\n        if not isinstance(workflow_id, str) or (workflow_id and workflow_id[0] == \"$\"):\n            continue\n        version_id = step.get(\"workflow_version_id\")\n        # If version_id is a string that starts with \"$\", treat it as None.\n        if isinstance(version_id, str) and version_id and version_id[0] == \"$\":\n            version_id = None\n        result.append((workflow_id, version_id))\n    return result",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/composition/workflow_caller/v1.py\nfrom typing import List, Optional, Tuple\n\nWORKFLOW_CALLER_BLOCK_TYPE = \"roboflow_core/workflow_caller@v1\"\n\n\ndef _extract_workflow_caller_ids_from_spec(\n    spec: dict,\n) -> List[Tuple[str, Optional[str]]]:\n    \"\"\"Extract static (workflow_id, workflow_version_id) tuples from a raw\n    workflow specification.  Only includes entries where ``workflow_id`` is a\n    literal string (not a selector).  ``workflow_version_id`` is included when\n    it is a literal string, otherwise ``None``.\"\"\"\n    steps = spec.get(\"steps\", [])\n    result: List[Tuple[str, Optional[str]]] = []\n    # Localize the frequently-used constant to reduce global lookup overhead.\n    block_type = WORKFLOW_CALLER_BLOCK_TYPE\n    for step in steps:\n        step_type = step.get(\"type\", \"\")\n        if step_type != block_type:\n            continue\n        workflow_id = step.get(\"workflow_id\", \"\")\n        # Preserve original semantics: require a str and skip if it starts with \"$\".\n        # Use a first-character check which is slightly faster than startswith.\n        if not isinstance(workflow_id, str) or (workflow_id and workflow_id[0] == \"$\"):\n            continue\n        version_id = step.get(\"workflow_version_id\")\n        # If version_id is a string that starts with \"$\", treat it as None.\n        if isinstance(version_id, str) and version_id and version_id[0] == \"$\":\n            version_id = None\n        result.append((workflow_id, version_id))\n    return result\n```",
    "optimized_function_only": "def _extract_workflow_caller_ids_from_spec(\n    spec: dict,\n) -> List[Tuple[str, Optional[str]]]:\n    \"\"\"Extract static (workflow_id, workflow_version_id) tuples from a raw\n    workflow specification.  Only includes entries where ``workflow_id`` is a\n    literal string (not a selector).  ``workflow_version_id`` is included when\n    it is a literal string, otherwise ``None``.\"\"\"\n    steps = spec.get(\"steps\", [])\n    result: List[Tuple[str, Optional[str]]] = []\n    # Localize the frequently-used constant to reduce global lookup overhead.\n    block_type = WORKFLOW_CALLER_BLOCK_TYPE\n    for step in steps:\n        step_type = step.get(\"type\", \"\")\n        if step_type != block_type:\n            continue\n        workflow_id = step.get(\"workflow_id\", \"\")\n        # Preserve original semantics: require a str and skip if it starts with \"$\".\n        # Use a first-character check which is slightly faster than startswith.\n        if not isinstance(workflow_id, str) or (workflow_id and workflow_id[0] == \"$\"):\n            continue\n        version_id = step.get(\"workflow_version_id\")\n        # If version_id is a string that starts with \"$\", treat it as None.\n        if isinstance(version_id, str) and version_id and version_id[0] == \"$\":\n            version_id = None\n        result.append((workflow_id, version_id))\n    return result",
    "original_file_content": "import logging\nimport re\nfrom functools import lru_cache\nfrom typing import Any, Callable, Dict, List, Literal, Optional, Tuple, Type, Union\n\nimport requests\nfrom pydantic import ConfigDict, Field, field_validator\n\nfrom inference.core.env import LOCAL_INFERENCE_API_URL\nfrom inference.core.roboflow_api import (\n    get_roboflow_workspace,\n    get_workflow_specification,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    DICTIONARY_KIND,\n    INTEGER_KIND,\n    STRING_KIND,\n    WILDCARD_KIND,\n    Kind,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nLONG_DESCRIPTION = \"\"\"\nThe **Workflow Caller** block enables calling another Roboflow workflow from within a workflow.\nThis is useful for composing complex pipelines from smaller, reusable workflow components.\n\n### How it works\n\nThe block takes a workflow ID (from the same workspace), passes inputs (including images)\nto the target workflow, executes it via HTTP, and returns the results.\n\n### Configuration\n\nSpecify the target workflow using `workflow_id` (just the workflow slug, not a full URL). The\nworkspace is resolved automatically from the API key used to run the parent workflow.\n\n```\nworkflow_id = \"my-detection-pipeline\"\n```\n\n### Inputs\n\nPass all inputs the target workflow expects via `inputs`, including images:\n\n```\ninputs = {\n    \"image\": \"$inputs.image\",\n    \"confidence_threshold\": 0.5,\n    \"model_id\": \"$inputs.model_id\",\n}\n```\n\nUse `input_definitions` to declare the expected input types so the UI can render\nproper connectors.\n\n### Circular Dependency Protection\n\nTo prevent infinite recursion (e.g. Workflow A calls B, B calls A), the block tracks the chain\nof workflow calls using a header. If a circular reference is detected, the block returns an error\ninstead of making the call.\n\n### Dynamic Outputs\n\nWhen the target workflow_id is a static string, the block resolves the target workflow's\noutputs at compile time. Each output from the target workflow becomes a separate output on\nthis block with proper Kind types. When the workflow_id is dynamic (a selector), outputs\nfall back to a single ``result`` dict.\n\n### Limitations\n\n* Only workflows within the same workspace are supported (v1).\n* Execution is done via HTTP call, which adds network latency.\n* Subject to the same timeout constraints as the hosting environment.\n\"\"\"\n\nWORKFLOW_CALL_CHAIN_HEADER = \"X-Roboflow-Workflow-Call-Chain\"\nMAX_WORKFLOW_CALL_DEPTH = 10\nWORKFLOW_CALLER_BLOCK_TYPE = \"roboflow_core/workflow_caller@v1\"\n\n# Module-level cache mapping (workflow_id, version_id) -> {output_name: [Kind]}.\n# Populated during compile-time validation, read by get_actual_outputs() and run().\n_RESOLVED_WORKFLOW_OUTPUTS: Dict[Tuple[str, Optional[str]], Dict[str, List[Kind]]] = {}\n\n# Module-level cache mapping (workflow_id, version_id) -> list of parsed input dicts\n# from spec.  Each dict has: name, type, kind, has_default.\n_RESOLVED_WORKFLOW_INPUTS: Dict[Tuple[str, Optional[str]], List[Dict[str, Any]]] = {}\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Workflow Caller\",\n            \"version\": \"v1\",\n            \"short_description\": \"Call another Roboflow workflow from within a workflow.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"transformation\",\n            \"ui_manifest\": {\n                \"section\": \"advanced\",\n                \"icon\": \"fal fa-diagram-subtask\",\n                \"blockPriority\": 2,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/workflow_caller@v1\"]\n    workflow_id: Union[Selector(kind=[STRING_KIND]), str] = Field(\n        description=\"The workflow ID to call (must be in the same workspace).\",\n        examples=[\"my-workflow-id\", \"$inputs.workflow_id\"],\n    )\n    workflow_version_id: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Optional version ID of the target workflow. When provided, \"\n        \"the block calls the specific version instead of the latest. \"\n        \"Use this to pin a dependency to a known-good version.\",\n        examples=[\"1709234567890\", \"$inputs.workflow_version\"],\n    )\n    inputs: Dict[\n        str,\n        Union[\n            Selector(),\n            str,\n            float,\n            bool,\n            int,\n            dict,\n            list,\n        ],\n    ] = Field(\n        default_factory=dict,\n        description=\"Inputs to pass to the target workflow, keyed by input name. \"\n        \"All inputs including images should be listed here.\",\n        examples=[\n            {\"image\": \"$inputs.image\", \"confidence_threshold\": 0.5},\n            {\"image\": \"$inputs.image\", \"model_id\": \"$inputs.model_id\"},\n        ],\n    )\n    request_timeout: Union[int, Selector(kind=[INTEGER_KIND])] = Field(\n        default=30,\n        description=\"HTTP request timeout in seconds.\",\n        examples=[\"$inputs.request_timeout\", 30],\n    )\n    input_definitions: Dict[str, List[str]] = Field(\n        default_factory=dict,\n        description=(\n            \"Mapping of expected input names to their kind types. \"\n            \"Each key is an input name in the target workflow, and the value \"\n            \"is a list of kind name strings (e.g. ['float'], ['roboflow_model_id']). \"\n            \"This tells the parent workflow what inputs the target expects, \"\n            \"enabling proper UI connectors. Actual values are provided via \"\n            \"'inputs'.\"\n        ),\n        examples=[\n            {\"image\": [\"image\"], \"confidence_threshold\": [\"float\"]},\n            {\n                \"image\": [\"image\"],\n                \"class_filter\": [\"string\"],\n                \"iou_threshold\": [\"float\"],\n            },\n        ],\n    )\n    output_definitions: Dict[str, List[str]] = Field(\n        default_factory=dict,\n        description=(\n            \"Mapping of expected output names to their kind types. \"\n            \"Each key is an output name from the target workflow, and the value \"\n            \"is a list of kind name strings (e.g. ['object_detection_prediction']). \"\n            \"This tells the parent workflow what types to expect, enabling proper \"\n            \"connections to downstream blocks like visualizers.\"\n        ),\n        examples=[\n            {\"predictions\": [\"object_detection_prediction\"]},\n            {\"result_image\": [\"image\"], \"count\": [\"integer\"]},\n        ],\n    )\n\n    @field_validator(\"workflow_id\")\n    @classmethod\n    def validate_workflow_id_slug(cls, value: Any) -> Any:\n        if isinstance(value, str) and not value.startswith(\"$\"):\n            if not re.fullmatch(r\"[\\w\\-]+\", value):\n                raise ValueError(\n                    f\"`workflow_id` must be a valid slug (letters, numbers, \"\n                    f\"hyphens, and underscores only). Got: '{value}'\"\n                )\n        return value\n\n    @field_validator(\"request_timeout\")\n    @classmethod\n    def ensure_request_timeout_is_positive(cls, value: Any) -> Any:\n        if isinstance(value, int) and value <= 0:\n            raise ValueError(\"`request_timeout` must be a positive integer.\")\n        return value\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return []\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"*\"),\n        ]\n\n    def get_actual_outputs(self) -> List[OutputDefinition]:\n        base: List[OutputDefinition] = []\n        # 1. User-defined output definitions take precedence\n        if self.output_definitions:\n            kind_name_map = _build_kind_name_map()\n            for name, kind_names in self.output_definitions.items():\n                kinds = [kind_name_map[k] for k in kind_names if k in kind_name_map]\n                base.append(OutputDefinition(name=name, kind=kinds or [WILDCARD_KIND]))\n            return base\n        # 2. Fall back to auto-discovery from compile-time resolution\n        if isinstance(self.workflow_id, str) and not self.workflow_id.startswith(\"$\"):\n            version_id = self.workflow_version_id\n            if isinstance(version_id, str) and version_id.startswith(\"$\"):\n                version_id = None\n            cache_key = _make_cache_key(self.workflow_id, version_id)\n            resolved = _RESOLVED_WORKFLOW_OUTPUTS.get(cache_key)\n            if resolved is not None:\n                for name, kinds in resolved.items():\n                    base.append(OutputDefinition(name=name, kind=kinds))\n                return base\n        # 3. Fall back to generic result dict\n        base.append(OutputDefinition(name=\"result\", kind=[DICTIONARY_KIND]))\n        return base\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass WorkflowCallerBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        api_key: Optional[str],\n        workflow_call_chain: Optional[str] = None,\n    ):\n        self._api_key = api_key\n        self._workspace_name: Optional[str] = None\n        self._workflow_call_chain = workflow_call_chain or \"\"\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"api_key\", \"workflow_call_chain\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        workflow_id: str,\n        inputs: Dict[str, Any],\n        request_timeout: int,\n        input_definitions: Dict[str, List[str]],\n        output_definitions: Dict[str, List[str]],\n        workflow_version_id: Optional[str] = None,\n    ) -> BlockResult:\n        workspace_name = self._resolve_workspace_name()\n        if workspace_name is None:\n            raise RuntimeError(\n                f\"Could not resolve workspace for workflow '{workflow_id}'. \"\n                f\"Ensure a valid API key is configured.\"\n            )\n        error_status, message, raw_outputs = call_workflow(\n            api_key=self._api_key,\n            workspace_name=workspace_name,\n            workflow_id=workflow_id,\n            inputs=inputs,\n            request_timeout=request_timeout,\n            call_chain=self._workflow_call_chain,\n            workflow_version_id=workflow_version_id,\n        )\n        if error_status:\n            raise RuntimeError(f\"Workflow '{workflow_id}' execution failed: {message}\")\n        result: Dict[str, Any] = {}\n        # Determine which outputs to extract and their kinds for deserialization\n        output_kinds_map = _resolve_output_kinds_for_run(\n            output_definitions=output_definitions,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n        )\n        if output_kinds_map is not None:\n            deserializers = _build_kinds_deserializers_map()\n            for output_name, output_kinds in output_kinds_map.items():\n                raw_value = raw_outputs.get(output_name)\n                result[output_name] = _deserialize_output_value(\n                    output_name=output_name,\n                    raw_value=raw_value,\n                    output_kinds=output_kinds,\n                    deserializers=deserializers,\n                )\n        else:\n            result[\"result\"] = raw_outputs\n        return result\n\n    def _resolve_workspace_name(self) -> Optional[str]:\n        if self._workspace_name is not None:\n            return self._workspace_name\n        if not self._api_key:\n            return None\n        try:\n            self._workspace_name = get_roboflow_workspace(api_key=self._api_key)\n            return self._workspace_name\n        except Exception as error:\n            logging.warning(\n                f\"Could not resolve workspace from API key. Error: {str(error)}\"\n            )\n            return None\n\n\ndef _make_cache_key(\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Tuple[str, Optional[str]]:\n    \"\"\"Build a cache key that accounts for both workflow_id and version_id.\"\"\"\n    return (workflow_id, workflow_version_id)\n\n\ndef call_workflow(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    inputs: Dict[str, Any],\n    request_timeout: int,\n    call_chain: Optional[str] = None,\n    workflow_version_id: Optional[str] = None,\n) -> Tuple[bool, str, dict]:\n    \"\"\"Execute a workflow call and return (error_status, message, result).\n\n    This function is separated from the block's run() to facilitate testing.\n    \"\"\"\n    current_chain = call_chain or \"\"\n    chain_entries = [entry for entry in current_chain.split(\",\") if entry]\n    if workflow_id in chain_entries:\n        logging.warning(\n            f\"Circular workflow call detected: \"\n            f\"'{workflow_id}' is already in call chain [{current_chain}].\"\n        )\n        return (\n            True,\n            f\"Circular workflow call detected: '{workflow_id}' is already \"\n            f\"in the call chain [{current_chain}]. Aborting to prevent \"\n            f\"infinite recursion.\",\n            {},\n        )\n    if len(chain_entries) >= MAX_WORKFLOW_CALL_DEPTH:\n        logging.warning(\n            f\"Workflow call depth limit ({MAX_WORKFLOW_CALL_DEPTH}) reached. \"\n            f\"Call chain: [{current_chain}].\"\n        )\n        return (\n            True,\n            f\"Workflow call depth limit ({MAX_WORKFLOW_CALL_DEPTH}) reached. \"\n            f\"Call chain: [{current_chain}].\",\n            {},\n        )\n    updated_chain = \",\".join([*chain_entries, workflow_id])\n    inputs = build_workflow_inputs(inputs=inputs)\n    return execute_workflow_request(\n        api_key=api_key,\n        workspace_name=workspace_name,\n        workflow_id=workflow_id,\n        inputs=inputs,\n        request_timeout=request_timeout,\n        call_chain=updated_chain,\n        workflow_version_id=workflow_version_id,\n    )\n\n\ndef build_workflow_inputs(\n    inputs: Dict[str, Any],\n) -> Dict[str, Any]:\n    \"\"\"Build the inputs dictionary for the target workflow.\n\n    Handles ``WorkflowImageData`` objects found in ``inputs`` by\n    automatically serialising them to the ``{type: base64, value: ...}``\n    format expected by the workflow HTTP API.\n    \"\"\"\n    resolved: Dict[str, Any] = {}\n    for key, value in inputs.items():\n        if isinstance(value, WorkflowImageData):\n            resolved[key] = {\n                \"type\": \"base64\",\n                \"value\": value.base64_image,\n            }\n        else:\n            resolved[key] = value\n    return resolved\n\n\ndef execute_workflow_request(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    inputs: Dict[str, Any],\n    request_timeout: int,\n    call_chain: str,\n    workflow_version_id: Optional[str] = None,\n) -> Tuple[bool, str, dict]:\n    \"\"\"Make the HTTP request to the target workflow and return\n    (error_status, message, result).\"\"\"\n    url = build_workflow_url(\n        workspace_name=workspace_name,\n        workflow_id=workflow_id,\n    )\n    payload: Dict[str, Any] = {\"inputs\": inputs}\n    if api_key is not None:\n        payload[\"api_key\"] = api_key\n    if workflow_version_id is not None:\n        payload[\"workflow_version_id\"] = workflow_version_id\n    headers = {WORKFLOW_CALL_CHAIN_HEADER: call_chain}\n    try:\n        response = requests.post(\n            url,\n            json=payload,\n            headers=headers,\n            timeout=request_timeout,\n        )\n        response.raise_for_status()\n        response_data = response.json()\n        outputs = response_data.get(\"outputs\", [])\n        result = outputs[0] if outputs else {}\n        return (\n            False,\n            \"Workflow executed successfully\",\n            result,\n        )\n    except Exception as error:\n        logging.warning(\n            f\"Could not execute workflow '{workflow_id}'. Error: {str(error)}\"\n        )\n        error_type = type(error).__name__\n        return (\n            True,\n            f\"Failed to execute workflow '{workflow_id}': {error_type}\",\n            {},\n        )\n\n\ndef build_workflow_url(workspace_name: str, workflow_id: str) -> str:\n    \"\"\"Build the URL for calling a workflow on the local inference server.\n\n    Uses LOCAL_INFERENCE_API_URL to call the workflow on the same inference\n    server instance that is running the parent workflow.\n    \"\"\"\n    base_url = LOCAL_INFERENCE_API_URL.rstrip(\"/\")\n    return f\"{base_url}/{workspace_name}/workflows/{workflow_id}\"\n\n\n# ---------------------------------------------------------------------------\n# Compile-time validation\n# ---------------------------------------------------------------------------\n\n\ndef validate_workflow_caller_no_circular_references(\n    steps: List[WorkflowBlockManifest],\n    api_key: Optional[str],\n) -> None:\n    \"\"\"Compile-time validation: check that workflow_caller blocks with static\n    workflow_id values don't create circular dependencies, resolve the target\n    workflow's input and output interfaces, and validate that required inputs\n    are provided.\n\n    Only validates when workflow_id is a literal string (not a selector like\n    ``$inputs.workflow_id``). Errors during spec fetching are logged as warnings\n    and do not block compilation \u2014 the runtime circular dependency check via\n    the call chain header provides an additional safety net.\n    \"\"\"\n    caller_steps = _extract_workflow_caller_steps(steps=steps)\n    if not caller_steps:\n        return\n    workspace_name = _resolve_workspace_for_validation(api_key=api_key)\n    if workspace_name is None:\n        return\n    for workflow_id, version_id, step_manifest in caller_steps:\n        spec = _fetch_workflow_spec_for_validation(\n            api_key=api_key,\n            workspace_name=workspace_name,\n            workflow_id=workflow_id,\n            workflow_version_id=version_id,\n        )\n        if spec is None:\n            continue\n        _check_workflow_for_circular_references(\n            api_key=api_key,\n            workspace_name=workspace_name,\n            target_workflow_id=workflow_id,\n            target_workflow_version_id=version_id,\n            visited=set(),\n            prefetched_spec=spec,\n        )\n        cache_key = _make_cache_key(workflow_id, version_id)\n        _resolve_and_cache_workflow_outputs(\n            cache_key=cache_key,\n            spec=spec,\n        )\n        _resolve_and_cache_workflow_inputs(\n            cache_key=cache_key,\n            spec=spec,\n        )\n        _validate_required_inputs(\n            workflow_id=workflow_id,\n            workflow_version_id=version_id,\n            step_manifest=step_manifest,\n        )\n\n\ndef _extract_workflow_caller_steps(\n    steps: List[WorkflowBlockManifest],\n) -> List[Tuple[str, Optional[str], WorkflowBlockManifest]]:\n    \"\"\"Extract (workflow_id, workflow_version_id, manifest) tuples from\n    workflow_caller steps that have literal (non-selector) workflow_id values.\"\"\"\n    result = []\n    for step in steps:\n        if not isinstance(step, BlockManifest):\n            continue\n        workflow_id = step.workflow_id\n        if isinstance(workflow_id, str) and not workflow_id.startswith(\"$\"):\n            version_id = step.workflow_version_id\n            # Only use version_id if it's a literal string (not a selector)\n            if isinstance(version_id, str) and version_id.startswith(\"$\"):\n                version_id = None\n            result.append((workflow_id, version_id, step))\n    return result\n\n\ndef _fetch_workflow_spec_for_validation(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[dict]:\n    \"\"\"Fetch a workflow spec, returning None on any error.\"\"\"\n    try:\n        return get_workflow_specification(\n            api_key=api_key,\n            workspace_id=workspace_name,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n        )\n    except Exception as error:\n        logging.debug(\n            \"Could not fetch workflow '%s' for compile-time validation (error type: %s)\",\n            workflow_id,\n            type(error).__name__,\n        )\n        return None\n\n\ndef _resolve_workspace_for_validation(\n    api_key: Optional[str],\n) -> Optional[str]:\n    if not api_key:\n        return None\n    try:\n        return get_roboflow_workspace(api_key=api_key)\n    except Exception as error:\n        logging.debug(\n            \"Could not resolve workspace for compile-time workflow validation (error type: %s)\",\n            type(error).__name__,\n        )\n        return None\n\n\ndef _check_workflow_for_circular_references(\n    api_key: Optional[str],\n    workspace_name: str,\n    target_workflow_id: str,\n    visited: set,\n    target_workflow_version_id: Optional[str] = None,\n    prefetched_spec: Optional[dict] = None,\n) -> None:\n    \"\"\"Recursively check if a target workflow creates a circular call chain.\n\n    Raises ``ExecutionGraphStructureError`` if a cycle is found. Silently\n    returns on any fetch error \u2014 the runtime check will catch those cases.\n\n    When ``prefetched_spec`` is provided it is used directly instead of\n    fetching the spec again.  The caller in\n    ``validate_workflow_caller_no_circular_references`` already fetches the\n    spec for the top-level workflow, so passing it here avoids a duplicate\n    API call.\n    \"\"\"\n    from inference.core.workflows.errors import ExecutionGraphStructureError\n\n    if target_workflow_id in visited:\n        chain = \" -> \".join([*visited, target_workflow_id])\n        raise ExecutionGraphStructureError(\n            public_message=(\n                f\"Circular workflow call detected at compile time: {chain}. \"\n                f\"This would cause infinite recursion at runtime.\"\n            ),\n            context=\"workflow_compilation | workflow_caller_validation\",\n        )\n    if prefetched_spec is not None:\n        spec = prefetched_spec\n    else:\n        try:\n            spec = get_workflow_specification(\n                api_key=api_key,\n                workspace_id=workspace_name,\n                workflow_id=target_workflow_id,\n                workflow_version_id=target_workflow_version_id,\n            )\n        except Exception as error:\n            logging.debug(\n                \"Could not fetch workflow '%s' for circular dependency check (error type: %s)\",\n                target_workflow_id,\n                type(error).__name__,\n            )\n            return\n    nested_workflows = _extract_workflow_caller_ids_from_spec(spec=spec)\n    if not nested_workflows:\n        return\n    visited_with_current = visited | {target_workflow_id}\n    for nested_id, nested_version_id in nested_workflows:\n        _check_workflow_for_circular_references(\n            api_key=api_key,\n            workspace_name=workspace_name,\n            target_workflow_id=nested_id,\n            target_workflow_version_id=nested_version_id,\n            visited=visited_with_current,\n        )\n\n\ndef _extract_workflow_caller_ids_from_spec(\n    spec: dict,\n) -> List[Tuple[str, Optional[str]]]:\n    \"\"\"Extract static (workflow_id, workflow_version_id) tuples from a raw\n    workflow specification.  Only includes entries where ``workflow_id`` is a\n    literal string (not a selector).  ``workflow_version_id`` is included when\n    it is a literal string, otherwise ``None``.\"\"\"\n    steps = spec.get(\"steps\", [])\n    result: List[Tuple[str, Optional[str]]] = []\n    for step in steps:\n        step_type = step.get(\"type\", \"\")\n        if step_type != WORKFLOW_CALLER_BLOCK_TYPE:\n            continue\n        workflow_id = step.get(\"workflow_id\", \"\")\n        if not isinstance(workflow_id, str) or workflow_id.startswith(\"$\"):\n            continue\n        version_id = step.get(\"workflow_version_id\")\n        if isinstance(version_id, str) and version_id.startswith(\"$\"):\n            version_id = None\n        result.append((workflow_id, version_id))\n    return result\n\n\n# ---------------------------------------------------------------------------\n# Output interface resolution\n# ---------------------------------------------------------------------------\n\n\ndef _resolve_and_cache_workflow_outputs(\n    cache_key: Tuple[str, Optional[str]],\n    spec: dict,\n) -> None:\n    \"\"\"Resolve the target workflow's output interface from its spec and cache\n    the result in ``_RESOLVED_WORKFLOW_OUTPUTS``.\n\n    Tries ``describe_workflow_outputs()`` for proper Kind resolution. Falls\n    back to extracting output names with ``WILDCARD_KIND`` on any error.\n    \"\"\"\n    try:\n        outputs_description = _describe_outputs_from_spec(spec=spec)\n    except Exception as error:\n        logging.debug(\n            f\"Could not resolve output kinds for workflow '{cache_key}' \"\n            f\"via describe_workflow_outputs: {error}. \"\n            f\"Falling back to output names with WILDCARD_KIND.\"\n        )\n        outputs_description = None\n\n    if outputs_description is not None:\n        resolved = _convert_output_descriptions_to_kinds(\n            outputs_description=outputs_description,\n        )\n    else:\n        resolved = _extract_output_names_with_wildcard(spec=spec)\n\n    if resolved:\n        _RESOLVED_WORKFLOW_OUTPUTS[cache_key] = resolved\n\n\ndef _describe_outputs_from_spec(\n    spec: dict,\n) -> Dict[str, Union[List[str], Dict[str, List[str]]]]:\n    \"\"\"Call the standard output discovery to resolve output kinds.\"\"\"\n    from inference.core.workflows.execution_engine.v1.introspection.outputs_discovery import (\n        describe_workflow_outputs,\n    )\n\n    return describe_workflow_outputs(definition=spec)\n\n\ndef _convert_output_descriptions_to_kinds(\n    outputs_description: Dict[str, Union[List[str], Dict[str, List[str]]]],\n) -> Dict[str, List[Kind]]:\n    \"\"\"Convert ``describe_workflow_outputs()`` result (kind name strings) to\n    ``Kind`` objects.\"\"\"\n    kind_name_map = _build_kind_name_map()\n    result: Dict[str, List[Kind]] = {}\n    for name, kind_info in outputs_description.items():\n        if isinstance(kind_info, dict):\n            # Wildcard selector ($steps.step.*) \u2014 nested structure.\n            # Represent as DICTIONARY_KIND since we can't express nested\n            # typed properties in a single OutputDefinition.\n            result[name] = [DICTIONARY_KIND]\n        else:\n            kinds = [kind_name_map[k] for k in kind_info if k in kind_name_map]\n            result[name] = kinds if kinds else [WILDCARD_KIND]\n    return result\n\n\ndef _extract_output_names_with_wildcard(\n    spec: dict,\n) -> Dict[str, List[Kind]]:\n    \"\"\"Fallback: extract just the output names and assign WILDCARD_KIND.\"\"\"\n    outputs = spec.get(\"outputs\", [])\n    result: Dict[str, List[Kind]] = {}\n    for output in outputs:\n        name = output.get(\"name\")\n        if name:\n            result[name] = [WILDCARD_KIND]\n    return result\n\n\n@lru_cache(maxsize=1)\ndef _build_kind_name_map() -> Dict[str, Kind]:\n    \"\"\"Build a mapping from kind name to Kind object using the loader.\n\n    Result is cached since the set of registered kinds does not change\n    within a process.\n    \"\"\"\n    from inference.core.workflows.core_steps.loader import load_kinds\n\n    return {kind.name: kind for kind in load_kinds()}\n\n\n# ---------------------------------------------------------------------------\n# Input interface resolution\n# ---------------------------------------------------------------------------\n\n\ndef _resolve_and_cache_workflow_inputs(\n    cache_key: Tuple[str, Optional[str]],\n    spec: dict,\n) -> None:\n    \"\"\"Parse the target workflow's input interface from its spec and cache\n    the result in ``_RESOLVED_WORKFLOW_INPUTS``.\n\n    Each input is stored as a dict with keys: name, type, has_default.\n    \"\"\"\n    raw_inputs = spec.get(\"inputs\", [])\n    parsed: List[Dict[str, Any]] = []\n    for inp in raw_inputs:\n        name = inp.get(\"name\")\n        if not name:\n            continue\n        inp_type = inp.get(\"type\", \"\")\n        parsed.append(\n            {\n                \"name\": name,\n                \"type\": inp_type,\n                \"has_default\": \"default_value\" in inp,\n            }\n        )\n    _RESOLVED_WORKFLOW_INPUTS[cache_key] = parsed\n\n\ndef _validate_required_inputs(\n    workflow_id: str,\n    step_manifest: BlockManifest,\n    workflow_version_id: Optional[str] = None,\n) -> None:\n    \"\"\"Validate that the workflow caller step provides all required inputs\n    that the target workflow expects.\n\n    Raises ``ExecutionGraphStructureError`` if:\n    - The target workflow has required parameters (no default) not covered by\n      ``inputs``.\n    - The user declared ``input_definitions`` but ``inputs`` does not\n      cover all declared input names.\n    \"\"\"\n    from inference.core.workflows.errors import ExecutionGraphStructureError\n\n    input_keys = set(step_manifest.inputs.keys())\n\n    # Validate user-declared input_definitions: every declared input must be\n    # present in inputs.\n    if step_manifest.input_definitions:\n        missing_declared = [\n            name for name in step_manifest.input_definitions if name not in input_keys\n        ]\n        if missing_declared:\n            raise ExecutionGraphStructureError(\n                public_message=(\n                    f\"Workflow caller step '{step_manifest.name}' declares \"\n                    f\"input_definitions for {list(step_manifest.input_definitions.keys())}, \"\n                    f\"but input(s) {missing_declared} are not provided in \"\n                    f\"'inputs'.\"\n                ),\n                context=\"workflow_compilation | workflow_caller_validation\",\n            )\n\n    cache_key = _make_cache_key(workflow_id, workflow_version_id)\n    resolved_inputs = _RESOLVED_WORKFLOW_INPUTS.get(cache_key)\n    if resolved_inputs is None:\n        return\n\n    missing = []\n    for inp in resolved_inputs:\n        if inp[\"has_default\"]:\n            continue\n        if inp[\"name\"] not in input_keys:\n            missing.append(inp[\"name\"])\n    if missing:\n        raise ExecutionGraphStructureError(\n            public_message=(\n                f\"Target workflow '{workflow_id}' requires input(s) \"\n                f\"{missing} (no default values), but they are not provided \"\n                f\"in 'inputs' on workflow_caller step \"\n                f\"'{step_manifest.name}'.\"\n            ),\n            context=\"workflow_compilation | workflow_caller_validation\",\n        )\n\n\n# ---------------------------------------------------------------------------\n# Output resolution for runtime\n# ---------------------------------------------------------------------------\n\n\ndef _resolve_output_kinds_for_run(\n    output_definitions: Dict[str, List[str]],\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[Dict[str, List[Kind]]]:\n    \"\"\"Determine which outputs to extract and their Kind objects.\n\n    Priority:\n    1. User-declared ``output_definitions`` (explicit kind names)\n    2. Auto-discovered outputs from ``_RESOLVED_WORKFLOW_OUTPUTS`` cache\n    3. Returns ``None`` \u2192 caller should fall back to generic ``result`` dict\n    \"\"\"\n    if output_definitions:\n        kind_name_map = _build_kind_name_map()\n        result: Dict[str, List[Kind]] = {}\n        for name, kind_names in output_definitions.items():\n            kinds = [kind_name_map[k] for k in kind_names if k in kind_name_map]\n            result[name] = kinds or [WILDCARD_KIND]\n        return result\n    cache_key = _make_cache_key(workflow_id, workflow_version_id)\n    resolved = _RESOLVED_WORKFLOW_OUTPUTS.get(cache_key)\n    if resolved is not None:\n        return resolved\n    return None\n\n\n# ---------------------------------------------------------------------------\n# Output deserialization\n# ---------------------------------------------------------------------------\n\n\n@lru_cache(maxsize=1)\ndef _build_kinds_deserializers_map() -> Dict[str, Callable[[str, Any], Any]]:\n    \"\"\"Build the map of kind name -> deserializer function.\n\n    Result is cached since the set of registered deserializers does not\n    change within a process.\n    \"\"\"\n    from inference.core.workflows.execution_engine.introspection.blocks_loader import (\n        load_kinds_deserializers,\n    )\n\n    return load_kinds_deserializers()\n\n\ndef _deserialize_output_value(\n    output_name: str,\n    raw_value: Any,\n    output_kinds: List[Kind],\n    deserializers: Dict[str, Callable[[str, Any], Any]],\n) -> Any:\n    \"\"\"Deserialize a single output value using the deserializer matching its\n    resolved kind.\n\n    For outputs with known kinds, deserialization is required \u2014 failure raises\n    an error so downstream blocks don't receive unexpected raw data. For\n    WILDCARD_KIND outputs the raw value is returned as-is since we don't know\n    the expected type.\n    \"\"\"\n    if raw_value is None:\n        return None\n    if all(kind == WILDCARD_KIND for kind in output_kinds):\n        return raw_value\n    errors: List[Tuple[str, Exception]] = []\n    for kind in output_kinds:\n        if kind == WILDCARD_KIND:\n            continue\n        if kind.name not in deserializers:\n            continue\n        try:\n            return deserializers[kind.name](output_name, raw_value)\n        except Exception as error:\n            errors.append((kind.name, error))\n            continue\n    if errors:\n        error_details = \"; \".join(f\"{kind}: {error}\" for kind, error in errors)\n        raise RuntimeError(\n            f\"Failed to deserialize output '{output_name}' from target \"\n            f\"workflow. Tried deserializers for kinds \"\n            f\"{[k for k, _ in errors]} but all failed: {error_details}. \"\n            f\"This likely means the target workflow's output format doesn't \"\n            f\"match the expected kind.\"\n        )\n    return raw_value\n",
    "patch": null
  },
  {
    "trace_id": "ff0d25d7-9227-4de0-bc1d-7334507bff41",
    "function_name": "_check_workflow_for_circular_references",
    "file_path": "inference/core/workflows/core_steps/composition/workflow_caller/v1.py",
    "speedup_x": 10.840016169502496,
    "review_quality": "high",
    "pre_optimization_commit": "8b1ad0050d9355954c2fabb7418e30927c22e19d",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def _check_workflow_for_circular_references(\n    api_key: Optional[str],\n    workspace_name: str,\n    target_workflow_id: str,\n    visited: set,\n    target_workflow_version_id: Optional[str] = None,\n    prefetched_spec: Optional[dict] = None,\n) -> None:\n    \"\"\"Recursively check if a target workflow creates a circular call chain.\n\n    Raises ``ExecutionGraphStructureError`` if a cycle is found. Silently\n    returns on any fetch error \u2014 the runtime check will catch those cases.\n\n    When ``prefetched_spec`` is provided it is used directly instead of\n    fetching the spec again.  The caller in\n    ``validate_workflow_caller_no_circular_references`` already fetches the\n    spec for the top-level workflow, so passing it here avoids a duplicate\n    API call.\n    \"\"\"\n    from inference.core.workflows.errors import ExecutionGraphStructureError\n\n    if target_workflow_id in visited:\n        chain = \" -> \".join([*visited, target_workflow_id])\n        raise ExecutionGraphStructureError(\n            public_message=(\n                f\"Circular workflow call detected at compile time: {chain}. \"\n                f\"This would cause infinite recursion at runtime.\"\n            ),\n            context=\"workflow_compilation | workflow_caller_validation\",\n        )\n    if prefetched_spec is not None:\n        spec = prefetched_spec\n    else:\n        try:\n            spec = get_workflow_specification(\n                api_key=api_key,\n                workspace_id=workspace_name,\n                workflow_id=target_workflow_id,\n                workflow_version_id=target_workflow_version_id,\n            )\n        except Exception as error:\n            logging.debug(\n                f\"Could not fetch workflow '{target_workflow_id}' for circular \"\n                f\"dependency check: {error}\"\n            )\n            return\n    nested_workflows = _extract_workflow_caller_ids_from_spec(spec=spec)\n    if not nested_workflows:\n        return\n    visited_with_current = visited | {target_workflow_id}\n    for nested_id, nested_version_id in nested_workflows:\n        _check_workflow_for_circular_references(\n            api_key=api_key,\n            workspace_name=workspace_name,\n            target_workflow_id=nested_id,\n            target_workflow_version_id=nested_version_id,\n            visited=visited_with_current,\n        )\n",
    "optimized_function_code": "import logging\nfrom typing import List, Optional, Tuple\n\nfrom inference.core.roboflow_api import get_workflow_specification\n\nWORKFLOW_CALLER_BLOCK_TYPE = \"roboflow_core/workflow_caller@v1\"\n\n\ndef _check_workflow_for_circular_references(\n    api_key: Optional[str],\n    workspace_name: str,\n    target_workflow_id: str,\n    visited: frozenset,\n    target_workflow_version_id: Optional[str] = None,\n    prefetched_spec: Optional[dict] = None,\n) -> None:\n    \"\"\"Recursively check if a target workflow creates a circular call chain.\n\n    Raises ``ExecutionGraphStructureError`` if a cycle is found. Silently\n    returns on any fetch error \u2014 the runtime check will catch those cases.\n\n    When ``prefetched_spec`` is provided it is used directly instead of\n    fetching the spec again.  The caller in\n    ``validate_workflow_caller_no_circular_references`` already fetches the\n    spec for the top-level workflow, so passing it here avoids a duplicate\n    API call.\n    \"\"\"\n    from inference.core.workflows.errors import ExecutionGraphStructureError\n\n    if target_workflow_id in visited:\n        chain = \" -> \".join([*visited, target_workflow_id])\n        raise ExecutionGraphStructureError(\n            public_message=(\n                f\"Circular workflow call detected at compile time: {chain}. \"\n                f\"This would cause infinite recursion at runtime.\"\n            ),\n            context=\"workflow_compilation | workflow_caller_validation\",\n        )\n    if prefetched_spec is not None:\n        spec = prefetched_spec\n    else:\n        try:\n            spec = get_workflow_specification(\n                api_key=api_key,\n                workspace_id=workspace_name,\n                workflow_id=target_workflow_id,\n                workflow_version_id=target_workflow_version_id,\n            )\n        except Exception as error:\n            logging.debug(\n                f\"Could not fetch workflow '{target_workflow_id}' for circular \"\n                f\"dependency check: {error}\"\n            )\n            return\n    nested_workflows = _extract_workflow_caller_ids_from_spec(spec=spec)\n    if not nested_workflows:\n        return\n    visited_with_current = visited | {target_workflow_id}\n    for nested_id, nested_version_id in nested_workflows:\n        _check_workflow_for_circular_references(\n            api_key=api_key,\n            workspace_name=workspace_name,\n            target_workflow_id=nested_id,\n            target_workflow_version_id=nested_version_id,\n            visited=visited_with_current,\n        )\n\n\ndef _extract_workflow_caller_ids_from_spec(\n    spec: dict,\n) -> List[Tuple[str, Optional[str]]]:\n    \"\"\"Extract static (workflow_id, workflow_version_id) tuples from a raw\n    workflow specification.  Only includes entries where ``workflow_id`` is a\n    literal string (not a selector).  ``workflow_version_id`` is included when\n    it is a literal string, otherwise ``None``.\"\"\"\n    steps = spec.get(\"steps\", [])\n    if not steps:\n        return []\n    \n    result: List[Tuple[str, Optional[str]]] = []\n    for step in steps:\n        if step.get(\"type\") != WORKFLOW_CALLER_BLOCK_TYPE:\n            continue\n        workflow_id = step.get(\"workflow_id\", \"\")\n        if not isinstance(workflow_id, str) or not workflow_id or workflow_id[0] == \"$\":\n            continue\n        version_id = step.get(\"workflow_version_id\")\n        if isinstance(version_id, str) and version_id and version_id[0] == \"$\":\n            version_id = None\n        result.append((workflow_id, version_id))\n    return result",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/composition/workflow_caller/v1.py\nimport logging\nfrom typing import List, Optional, Tuple\n\nfrom inference.core.roboflow_api import get_workflow_specification\n\nWORKFLOW_CALLER_BLOCK_TYPE = \"roboflow_core/workflow_caller@v1\"\n\n\ndef _check_workflow_for_circular_references(\n    api_key: Optional[str],\n    workspace_name: str,\n    target_workflow_id: str,\n    visited: frozenset,\n    target_workflow_version_id: Optional[str] = None,\n    prefetched_spec: Optional[dict] = None,\n) -> None:\n    \"\"\"Recursively check if a target workflow creates a circular call chain.\n\n    Raises ``ExecutionGraphStructureError`` if a cycle is found. Silently\n    returns on any fetch error \u2014 the runtime check will catch those cases.\n\n    When ``prefetched_spec`` is provided it is used directly instead of\n    fetching the spec again.  The caller in\n    ``validate_workflow_caller_no_circular_references`` already fetches the\n    spec for the top-level workflow, so passing it here avoids a duplicate\n    API call.\n    \"\"\"\n    from inference.core.workflows.errors import ExecutionGraphStructureError\n\n    if target_workflow_id in visited:\n        chain = \" -> \".join([*visited, target_workflow_id])\n        raise ExecutionGraphStructureError(\n            public_message=(\n                f\"Circular workflow call detected at compile time: {chain}. \"\n                f\"This would cause infinite recursion at runtime.\"\n            ),\n            context=\"workflow_compilation | workflow_caller_validation\",\n        )\n    if prefetched_spec is not None:\n        spec = prefetched_spec\n    else:\n        try:\n            spec = get_workflow_specification(\n                api_key=api_key,\n                workspace_id=workspace_name,\n                workflow_id=target_workflow_id,\n                workflow_version_id=target_workflow_version_id,\n            )\n        except Exception as error:\n            logging.debug(\n                f\"Could not fetch workflow '{target_workflow_id}' for circular \"\n                f\"dependency check: {error}\"\n            )\n            return\n    nested_workflows = _extract_workflow_caller_ids_from_spec(spec=spec)\n    if not nested_workflows:\n        return\n    visited_with_current = visited | {target_workflow_id}\n    for nested_id, nested_version_id in nested_workflows:\n        _check_workflow_for_circular_references(\n            api_key=api_key,\n            workspace_name=workspace_name,\n            target_workflow_id=nested_id,\n            target_workflow_version_id=nested_version_id,\n            visited=visited_with_current,\n        )\n\n\ndef _extract_workflow_caller_ids_from_spec(\n    spec: dict,\n) -> List[Tuple[str, Optional[str]]]:\n    \"\"\"Extract static (workflow_id, workflow_version_id) tuples from a raw\n    workflow specification.  Only includes entries where ``workflow_id`` is a\n    literal string (not a selector).  ``workflow_version_id`` is included when\n    it is a literal string, otherwise ``None``.\"\"\"\n    steps = spec.get(\"steps\", [])\n    if not steps:\n        return []\n    \n    result: List[Tuple[str, Optional[str]]] = []\n    for step in steps:\n        if step.get(\"type\") != WORKFLOW_CALLER_BLOCK_TYPE:\n            continue\n        workflow_id = step.get(\"workflow_id\", \"\")\n        if not isinstance(workflow_id, str) or not workflow_id or workflow_id[0] == \"$\":\n            continue\n        version_id = step.get(\"workflow_version_id\")\n        if isinstance(version_id, str) and version_id and version_id[0] == \"$\":\n            version_id = None\n        result.append((workflow_id, version_id))\n    return result\n```",
    "optimized_function_only": "def _check_workflow_for_circular_references(\n    api_key: Optional[str],\n    workspace_name: str,\n    target_workflow_id: str,\n    visited: frozenset,\n    target_workflow_version_id: Optional[str] = None,\n    prefetched_spec: Optional[dict] = None,\n) -> None:\n    \"\"\"Recursively check if a target workflow creates a circular call chain.\n\n    Raises ``ExecutionGraphStructureError`` if a cycle is found. Silently\n    returns on any fetch error \u2014 the runtime check will catch those cases.\n\n    When ``prefetched_spec`` is provided it is used directly instead of\n    fetching the spec again.  The caller in\n    ``validate_workflow_caller_no_circular_references`` already fetches the\n    spec for the top-level workflow, so passing it here avoids a duplicate\n    API call.\n    \"\"\"\n    from inference.core.workflows.errors import ExecutionGraphStructureError\n\n    if target_workflow_id in visited:\n        chain = \" -> \".join([*visited, target_workflow_id])\n        raise ExecutionGraphStructureError(\n            public_message=(\n                f\"Circular workflow call detected at compile time: {chain}. \"\n                f\"This would cause infinite recursion at runtime.\"\n            ),\n            context=\"workflow_compilation | workflow_caller_validation\",\n        )\n    if prefetched_spec is not None:\n        spec = prefetched_spec\n    else:\n        try:\n            spec = get_workflow_specification(\n                api_key=api_key,\n                workspace_id=workspace_name,\n                workflow_id=target_workflow_id,\n                workflow_version_id=target_workflow_version_id,\n            )\n        except Exception as error:\n            logging.debug(\n                f\"Could not fetch workflow '{target_workflow_id}' for circular \"\n                f\"dependency check: {error}\"\n            )\n            return\n    nested_workflows = _extract_workflow_caller_ids_from_spec(spec=spec)\n    if not nested_workflows:\n        return\n    visited_with_current = visited | {target_workflow_id}\n    for nested_id, nested_version_id in nested_workflows:\n        _check_workflow_for_circular_references(\n            api_key=api_key,\n            workspace_name=workspace_name,\n            target_workflow_id=nested_id,\n            target_workflow_version_id=nested_version_id,\n            visited=visited_with_current,\n        )\n",
    "original_file_content": "import logging\nimport re\nfrom functools import lru_cache\nfrom typing import Any, Callable, Dict, List, Literal, Optional, Tuple, Type, Union\n\nimport requests\nfrom pydantic import ConfigDict, Field, field_validator\n\nfrom inference.core.env import LOCAL_INFERENCE_API_URL\nfrom inference.core.roboflow_api import get_roboflow_workspace, get_workflow_specification\nfrom inference.core.workflows.execution_engine.entities.base import (\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    DICTIONARY_KIND,\n    INTEGER_KIND,\n    STRING_KIND,\n    WILDCARD_KIND,\n    Kind,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nLONG_DESCRIPTION = \"\"\"\nThe **Workflow Caller** block enables calling another Roboflow workflow from within a workflow.\nThis is useful for composing complex pipelines from smaller, reusable workflow components.\n\n### How it works\n\nThe block takes a workflow ID (from the same workspace), passes inputs (including images)\nto the target workflow, executes it via HTTP, and returns the results.\n\n### Configuration\n\nSpecify the target workflow using `workflow_id` (just the workflow slug, not a full URL). The\nworkspace is resolved automatically from the API key used to run the parent workflow.\n\n```\nworkflow_id = \"my-detection-pipeline\"\n```\n\n### Inputs\n\nPass all inputs the target workflow expects via `inputs`, including images:\n\n```\ninputs = {\n    \"image\": \"$inputs.image\",\n    \"confidence_threshold\": 0.5,\n    \"model_id\": \"$inputs.model_id\",\n}\n```\n\nUse `input_definitions` to declare the expected input types so the UI can render\nproper connectors.\n\n### Circular Dependency Protection\n\nTo prevent infinite recursion (e.g. Workflow A calls B, B calls A), the block tracks the chain\nof workflow calls using a header. If a circular reference is detected, the block returns an error\ninstead of making the call.\n\n### Dynamic Outputs\n\nWhen the target workflow_id is a static string, the block resolves the target workflow's\noutputs at compile time. Each output from the target workflow becomes a separate output on\nthis block with proper Kind types. When the workflow_id is dynamic (a selector), outputs\nfall back to a single ``result`` dict.\n\n### Limitations\n\n* Only workflows within the same workspace are supported (v1).\n* Execution is done via HTTP call, which adds network latency.\n* Subject to the same timeout constraints as the hosting environment.\n\"\"\"\n\nWORKFLOW_CALL_CHAIN_HEADER = \"X-Roboflow-Workflow-Call-Chain\"\nMAX_WORKFLOW_CALL_DEPTH = 10\nWORKFLOW_CALLER_BLOCK_TYPE = \"roboflow_core/workflow_caller@v1\"\n\n# Module-level cache mapping (workflow_id, version_id) -> {output_name: [Kind]}.\n# Populated during compile-time validation, read by get_actual_outputs() and run().\n_RESOLVED_WORKFLOW_OUTPUTS: Dict[Tuple[str, Optional[str]], Dict[str, List[Kind]]] = {}\n\n# Module-level cache mapping (workflow_id, version_id) -> list of parsed input dicts\n# from spec.  Each dict has: name, type, kind, has_default.\n_RESOLVED_WORKFLOW_INPUTS: Dict[Tuple[str, Optional[str]], List[Dict[str, Any]]] = {}\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Workflow Caller\",\n            \"version\": \"v1\",\n            \"short_description\": \"Call another Roboflow workflow from within a workflow.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"transformation\",\n            \"ui_manifest\": {\n                \"section\": \"advanced\",\n                \"icon\": \"fal fa-diagram-subtask\",\n                \"blockPriority\": 2,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/workflow_caller@v1\"]\n    workflow_id: Union[Selector(kind=[STRING_KIND]), str] = Field(\n        description=\"The workflow ID to call (must be in the same workspace).\",\n        examples=[\"my-workflow-id\", \"$inputs.workflow_id\"],\n    )\n    workflow_version_id: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Optional version ID of the target workflow. When provided, \"\n        \"the block calls the specific version instead of the latest. \"\n        \"Use this to pin a dependency to a known-good version.\",\n        examples=[\"1709234567890\", \"$inputs.workflow_version\"],\n    )\n    inputs: Dict[\n        str,\n        Union[\n            Selector(),\n            str,\n            float,\n            bool,\n            int,\n            dict,\n            list,\n        ],\n    ] = Field(\n        default_factory=dict,\n        description=\"Inputs to pass to the target workflow, keyed by input name. \"\n        \"All inputs including images should be listed here.\",\n        examples=[\n            {\"image\": \"$inputs.image\", \"confidence_threshold\": 0.5},\n            {\"image\": \"$inputs.image\", \"model_id\": \"$inputs.model_id\"},\n        ],\n    )\n    request_timeout: Union[int, Selector(kind=[INTEGER_KIND])] = Field(\n        default=30,\n        description=\"HTTP request timeout in seconds.\",\n        examples=[\"$inputs.request_timeout\", 30],\n    )\n    input_definitions: Dict[str, List[str]] = Field(\n        default_factory=dict,\n        description=(\n            \"Mapping of expected input names to their kind types. \"\n            \"Each key is an input name in the target workflow, and the value \"\n            \"is a list of kind name strings (e.g. ['float'], ['roboflow_model_id']). \"\n            \"This tells the parent workflow what inputs the target expects, \"\n            \"enabling proper UI connectors. Actual values are provided via \"\n            \"'inputs'.\"\n        ),\n        examples=[\n            {\"image\": [\"image\"], \"confidence_threshold\": [\"float\"]},\n            {\"image\": [\"image\"], \"class_filter\": [\"string\"], \"iou_threshold\": [\"float\"]},\n        ],\n    )\n    output_definitions: Dict[str, List[str]] = Field(\n        default_factory=dict,\n        description=(\n            \"Mapping of expected output names to their kind types. \"\n            \"Each key is an output name from the target workflow, and the value \"\n            \"is a list of kind name strings (e.g. ['object_detection_prediction']). \"\n            \"This tells the parent workflow what types to expect, enabling proper \"\n            \"connections to downstream blocks like visualizers.\"\n        ),\n        examples=[\n            {\"predictions\": [\"object_detection_prediction\"]},\n            {\"result_image\": [\"image\"], \"count\": [\"integer\"]},\n        ],\n    )\n\n    @field_validator(\"workflow_id\")\n    @classmethod\n    def validate_workflow_id_slug(cls, value: Any) -> Any:\n        if isinstance(value, str) and not value.startswith(\"$\"):\n            if not re.fullmatch(r\"[\\w\\-]+\", value):\n                raise ValueError(\n                    f\"`workflow_id` must be a valid slug (letters, numbers, \"\n                    f\"hyphens, and underscores only). Got: '{value}'\"\n                )\n        return value\n\n    @field_validator(\"request_timeout\")\n    @classmethod\n    def ensure_request_timeout_is_positive(cls, value: Any) -> Any:\n        if isinstance(value, int) and value <= 0:\n            raise ValueError(\"`request_timeout` must be a positive integer.\")\n        return value\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return []\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"*\"),\n        ]\n\n    def get_actual_outputs(self) -> List[OutputDefinition]:\n        base: List[OutputDefinition] = []\n        # 1. User-defined output definitions take precedence\n        if self.output_definitions:\n            kind_name_map = _build_kind_name_map()\n            for name, kind_names in self.output_definitions.items():\n                kinds = [\n                    kind_name_map[k] for k in kind_names if k in kind_name_map\n                ]\n                base.append(\n                    OutputDefinition(name=name, kind=kinds or [WILDCARD_KIND])\n                )\n            return base\n        # 2. Fall back to auto-discovery from compile-time resolution\n        if isinstance(self.workflow_id, str) and not self.workflow_id.startswith(\"$\"):\n            version_id = self.workflow_version_id\n            if isinstance(version_id, str) and version_id.startswith(\"$\"):\n                version_id = None\n            cache_key = _make_cache_key(self.workflow_id, version_id)\n            resolved = _RESOLVED_WORKFLOW_OUTPUTS.get(cache_key)\n            if resolved is not None:\n                for name, kinds in resolved.items():\n                    base.append(OutputDefinition(name=name, kind=kinds))\n                return base\n        # 3. Fall back to generic result dict\n        base.append(OutputDefinition(name=\"result\", kind=[DICTIONARY_KIND]))\n        return base\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass WorkflowCallerBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        api_key: Optional[str],\n        workflow_call_chain: Optional[str] = None,\n    ):\n        self._api_key = api_key\n        self._workspace_name: Optional[str] = None\n        self._workflow_call_chain = workflow_call_chain or \"\"\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"api_key\", \"workflow_call_chain\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        workflow_id: str,\n        inputs: Dict[str, Any],\n        request_timeout: int,\n        input_definitions: Dict[str, List[str]],\n        output_definitions: Dict[str, List[str]],\n        workflow_version_id: Optional[str] = None,\n    ) -> BlockResult:\n        workspace_name = self._resolve_workspace_name()\n        if workspace_name is None:\n            raise RuntimeError(\n                f\"Could not resolve workspace for workflow '{workflow_id}'. \"\n                f\"Ensure a valid API key is configured.\"\n            )\n        error_status, message, raw_outputs = call_workflow(\n            api_key=self._api_key,\n            workspace_name=workspace_name,\n            workflow_id=workflow_id,\n            inputs=inputs,\n            request_timeout=request_timeout,\n            call_chain=self._workflow_call_chain,\n            workflow_version_id=workflow_version_id,\n        )\n        if error_status:\n            raise RuntimeError(\n                f\"Workflow '{workflow_id}' execution failed: {message}\"\n            )\n        result: Dict[str, Any] = {}\n        # Determine which outputs to extract and their kinds for deserialization\n        output_kinds_map = _resolve_output_kinds_for_run(\n            output_definitions=output_definitions,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n        )\n        if output_kinds_map is not None:\n            deserializers = _build_kinds_deserializers_map()\n            for output_name, output_kinds in output_kinds_map.items():\n                raw_value = raw_outputs.get(output_name)\n                result[output_name] = _deserialize_output_value(\n                    output_name=output_name,\n                    raw_value=raw_value,\n                    output_kinds=output_kinds,\n                    deserializers=deserializers,\n                )\n        else:\n            result[\"result\"] = raw_outputs\n        return result\n\n    def _resolve_workspace_name(self) -> Optional[str]:\n        if self._workspace_name is not None:\n            return self._workspace_name\n        if not self._api_key:\n            return None\n        try:\n            self._workspace_name = get_roboflow_workspace(api_key=self._api_key)\n            return self._workspace_name\n        except Exception as error:\n            logging.warning(\n                f\"Could not resolve workspace from API key. Error: {str(error)}\"\n            )\n            return None\n\n\ndef _make_cache_key(\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Tuple[str, Optional[str]]:\n    \"\"\"Build a cache key that accounts for both workflow_id and version_id.\"\"\"\n    return (workflow_id, workflow_version_id)\n\n\ndef call_workflow(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    inputs: Dict[str, Any],\n    request_timeout: int,\n    call_chain: Optional[str] = None,\n    workflow_version_id: Optional[str] = None,\n) -> Tuple[bool, str, dict]:\n    \"\"\"Execute a workflow call and return (error_status, message, result).\n\n    This function is separated from the block's run() to facilitate testing.\n    \"\"\"\n    current_chain = call_chain or \"\"\n    chain_entries = [entry for entry in current_chain.split(\",\") if entry]\n    if workflow_id in chain_entries:\n        logging.warning(\n            f\"Circular workflow call detected: \"\n            f\"'{workflow_id}' is already in call chain [{current_chain}].\"\n        )\n        return (\n            True,\n            f\"Circular workflow call detected: '{workflow_id}' is already \"\n            f\"in the call chain [{current_chain}]. Aborting to prevent \"\n            f\"infinite recursion.\",\n            {},\n        )\n    if len(chain_entries) >= MAX_WORKFLOW_CALL_DEPTH:\n        logging.warning(\n            f\"Workflow call depth limit ({MAX_WORKFLOW_CALL_DEPTH}) reached. \"\n            f\"Call chain: [{current_chain}].\"\n        )\n        return (\n            True,\n            f\"Workflow call depth limit ({MAX_WORKFLOW_CALL_DEPTH}) reached. \"\n            f\"Call chain: [{current_chain}].\",\n            {},\n        )\n    updated_chain = \",\".join([*chain_entries, workflow_id])\n    inputs = build_workflow_inputs(inputs=inputs)\n    return execute_workflow_request(\n        api_key=api_key,\n        workspace_name=workspace_name,\n        workflow_id=workflow_id,\n        inputs=inputs,\n        request_timeout=request_timeout,\n        call_chain=updated_chain,\n        workflow_version_id=workflow_version_id,\n    )\n\n\ndef build_workflow_inputs(\n    inputs: Dict[str, Any],\n) -> Dict[str, Any]:\n    \"\"\"Build the inputs dictionary for the target workflow.\n\n    Handles ``WorkflowImageData`` objects found in ``inputs`` by\n    automatically serialising them to the ``{type: base64, value: ...}``\n    format expected by the workflow HTTP API.\n    \"\"\"\n    resolved: Dict[str, Any] = {}\n    for key, value in inputs.items():\n        if isinstance(value, WorkflowImageData):\n            resolved[key] = {\n                \"type\": \"base64\",\n                \"value\": value.base64_image,\n            }\n        else:\n            resolved[key] = value\n    return resolved\n\n\ndef execute_workflow_request(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    inputs: Dict[str, Any],\n    request_timeout: int,\n    call_chain: str,\n    workflow_version_id: Optional[str] = None,\n) -> Tuple[bool, str, dict]:\n    \"\"\"Make the HTTP request to the target workflow and return\n    (error_status, message, result).\"\"\"\n    url = build_workflow_url(\n        workspace_name=workspace_name,\n        workflow_id=workflow_id,\n    )\n    payload: Dict[str, Any] = {\"inputs\": inputs}\n    if api_key is not None:\n        payload[\"api_key\"] = api_key\n    if workflow_version_id is not None:\n        payload[\"workflow_version_id\"] = workflow_version_id\n    headers = {WORKFLOW_CALL_CHAIN_HEADER: call_chain}\n    try:\n        response = requests.post(\n            url,\n            json=payload,\n            headers=headers,\n            timeout=request_timeout,\n        )\n        response.raise_for_status()\n        response_data = response.json()\n        outputs = response_data.get(\"outputs\", [])\n        result = outputs[0] if outputs else {}\n        return (\n            False,\n            \"Workflow executed successfully\",\n            result,\n        )\n    except Exception as error:\n        logging.warning(\n            f\"Could not execute workflow '{workflow_id}'. Error: {str(error)}\"\n        )\n        error_type = type(error).__name__\n        return (\n            True,\n            f\"Failed to execute workflow '{workflow_id}': {error_type}\",\n            {},\n        )\n\n\ndef build_workflow_url(workspace_name: str, workflow_id: str) -> str:\n    \"\"\"Build the URL for calling a workflow on the local inference server.\n\n    Uses LOCAL_INFERENCE_API_URL to call the workflow on the same inference\n    server instance that is running the parent workflow.\n    \"\"\"\n    base_url = LOCAL_INFERENCE_API_URL.rstrip(\"/\")\n    return f\"{base_url}/{workspace_name}/workflows/{workflow_id}\"\n\n\n# ---------------------------------------------------------------------------\n# Compile-time validation\n# ---------------------------------------------------------------------------\n\n\ndef validate_workflow_caller_no_circular_references(\n    steps: List[WorkflowBlockManifest],\n    api_key: Optional[str],\n) -> None:\n    \"\"\"Compile-time validation: check that workflow_caller blocks with static\n    workflow_id values don't create circular dependencies, resolve the target\n    workflow's input and output interfaces, and validate that required inputs\n    are provided.\n\n    Only validates when workflow_id is a literal string (not a selector like\n    ``$inputs.workflow_id``). Errors during spec fetching are logged as warnings\n    and do not block compilation \u2014 the runtime circular dependency check via\n    the call chain header provides an additional safety net.\n    \"\"\"\n    caller_steps = _extract_workflow_caller_steps(steps=steps)\n    if not caller_steps:\n        return\n    workspace_name = _resolve_workspace_for_validation(api_key=api_key)\n    if workspace_name is None:\n        return\n    for workflow_id, version_id, step_manifest in caller_steps:\n        spec = _fetch_workflow_spec_for_validation(\n            api_key=api_key,\n            workspace_name=workspace_name,\n            workflow_id=workflow_id,\n            workflow_version_id=version_id,\n        )\n        if spec is None:\n            continue\n        _check_workflow_for_circular_references(\n            api_key=api_key,\n            workspace_name=workspace_name,\n            target_workflow_id=workflow_id,\n            target_workflow_version_id=version_id,\n            visited=set(),\n            prefetched_spec=spec,\n        )\n        cache_key = _make_cache_key(workflow_id, version_id)\n        _resolve_and_cache_workflow_outputs(\n            cache_key=cache_key,\n            spec=spec,\n        )\n        _resolve_and_cache_workflow_inputs(\n            cache_key=cache_key,\n            spec=spec,\n        )\n        _validate_required_inputs(\n            workflow_id=workflow_id,\n            workflow_version_id=version_id,\n            step_manifest=step_manifest,\n        )\n\n\ndef _extract_workflow_caller_steps(\n    steps: List[WorkflowBlockManifest],\n) -> List[Tuple[str, Optional[str], WorkflowBlockManifest]]:\n    \"\"\"Extract (workflow_id, workflow_version_id, manifest) tuples from\n    workflow_caller steps that have literal (non-selector) workflow_id values.\"\"\"\n    result = []\n    for step in steps:\n        if not isinstance(step, BlockManifest):\n            continue\n        workflow_id = step.workflow_id\n        if isinstance(workflow_id, str) and not workflow_id.startswith(\"$\"):\n            version_id = step.workflow_version_id\n            # Only use version_id if it's a literal string (not a selector)\n            if isinstance(version_id, str) and version_id.startswith(\"$\"):\n                version_id = None\n            result.append((workflow_id, version_id, step))\n    return result\n\n\ndef _fetch_workflow_spec_for_validation(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[dict]:\n    \"\"\"Fetch a workflow spec, returning None on any error.\"\"\"\n    try:\n        return get_workflow_specification(\n            api_key=api_key,\n            workspace_id=workspace_name,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n        )\n    except Exception as error:\n        logging.debug(\n            f\"Could not fetch workflow '{workflow_id}' for compile-time \"\n            f\"validation: {error}\"\n        )\n        return None\n\n\ndef _resolve_workspace_for_validation(\n    api_key: Optional[str],\n) -> Optional[str]:\n    if not api_key:\n        return None\n    try:\n        return get_roboflow_workspace(api_key=api_key)\n    except Exception as error:\n        logging.debug(\n            f\"Could not resolve workspace for compile-time workflow validation: \"\n            f\"{error}\"\n        )\n        return None\n\n\ndef _check_workflow_for_circular_references(\n    api_key: Optional[str],\n    workspace_name: str,\n    target_workflow_id: str,\n    visited: set,\n    target_workflow_version_id: Optional[str] = None,\n    prefetched_spec: Optional[dict] = None,\n) -> None:\n    \"\"\"Recursively check if a target workflow creates a circular call chain.\n\n    Raises ``ExecutionGraphStructureError`` if a cycle is found. Silently\n    returns on any fetch error \u2014 the runtime check will catch those cases.\n\n    When ``prefetched_spec`` is provided it is used directly instead of\n    fetching the spec again.  The caller in\n    ``validate_workflow_caller_no_circular_references`` already fetches the\n    spec for the top-level workflow, so passing it here avoids a duplicate\n    API call.\n    \"\"\"\n    from inference.core.workflows.errors import ExecutionGraphStructureError\n\n    if target_workflow_id in visited:\n        chain = \" -> \".join([*visited, target_workflow_id])\n        raise ExecutionGraphStructureError(\n            public_message=(\n                f\"Circular workflow call detected at compile time: {chain}. \"\n                f\"This would cause infinite recursion at runtime.\"\n            ),\n            context=\"workflow_compilation | workflow_caller_validation\",\n        )\n    if prefetched_spec is not None:\n        spec = prefetched_spec\n    else:\n        try:\n            spec = get_workflow_specification(\n                api_key=api_key,\n                workspace_id=workspace_name,\n                workflow_id=target_workflow_id,\n                workflow_version_id=target_workflow_version_id,\n            )\n        except Exception as error:\n            logging.debug(\n                f\"Could not fetch workflow '{target_workflow_id}' for circular \"\n                f\"dependency check: {error}\"\n            )\n            return\n    nested_workflows = _extract_workflow_caller_ids_from_spec(spec=spec)\n    if not nested_workflows:\n        return\n    visited_with_current = visited | {target_workflow_id}\n    for nested_id, nested_version_id in nested_workflows:\n        _check_workflow_for_circular_references(\n            api_key=api_key,\n            workspace_name=workspace_name,\n            target_workflow_id=nested_id,\n            target_workflow_version_id=nested_version_id,\n            visited=visited_with_current,\n        )\n\n\ndef _extract_workflow_caller_ids_from_spec(\n    spec: dict,\n) -> List[Tuple[str, Optional[str]]]:\n    \"\"\"Extract static (workflow_id, workflow_version_id) tuples from a raw\n    workflow specification.  Only includes entries where ``workflow_id`` is a\n    literal string (not a selector).  ``workflow_version_id`` is included when\n    it is a literal string, otherwise ``None``.\"\"\"\n    steps = spec.get(\"steps\", [])\n    result: List[Tuple[str, Optional[str]]] = []\n    for step in steps:\n        step_type = step.get(\"type\", \"\")\n        if step_type != WORKFLOW_CALLER_BLOCK_TYPE:\n            continue\n        workflow_id = step.get(\"workflow_id\", \"\")\n        if not isinstance(workflow_id, str) or workflow_id.startswith(\"$\"):\n            continue\n        version_id = step.get(\"workflow_version_id\")\n        if isinstance(version_id, str) and version_id.startswith(\"$\"):\n            version_id = None\n        result.append((workflow_id, version_id))\n    return result\n\n\n# ---------------------------------------------------------------------------\n# Output interface resolution\n# ---------------------------------------------------------------------------\n\n\ndef _resolve_and_cache_workflow_outputs(\n    cache_key: Tuple[str, Optional[str]],\n    spec: dict,\n) -> None:\n    \"\"\"Resolve the target workflow's output interface from its spec and cache\n    the result in ``_RESOLVED_WORKFLOW_OUTPUTS``.\n\n    Tries ``describe_workflow_outputs()`` for proper Kind resolution. Falls\n    back to extracting output names with ``WILDCARD_KIND`` on any error.\n    \"\"\"\n    try:\n        outputs_description = _describe_outputs_from_spec(spec=spec)\n    except Exception as error:\n        logging.debug(\n            f\"Could not resolve output kinds for workflow '{cache_key}' \"\n            f\"via describe_workflow_outputs: {error}. \"\n            f\"Falling back to output names with WILDCARD_KIND.\"\n        )\n        outputs_description = None\n\n    if outputs_description is not None:\n        resolved = _convert_output_descriptions_to_kinds(\n            outputs_description=outputs_description,\n        )\n    else:\n        resolved = _extract_output_names_with_wildcard(spec=spec)\n\n    if resolved:\n        _RESOLVED_WORKFLOW_OUTPUTS[cache_key] = resolved\n\n\ndef _describe_outputs_from_spec(\n    spec: dict,\n) -> Dict[str, Union[List[str], Dict[str, List[str]]]]:\n    \"\"\"Call the standard output discovery to resolve output kinds.\"\"\"\n    from inference.core.workflows.execution_engine.v1.introspection.outputs_discovery import (\n        describe_workflow_outputs,\n    )\n\n    return describe_workflow_outputs(definition=spec)\n\n\ndef _convert_output_descriptions_to_kinds(\n    outputs_description: Dict[str, Union[List[str], Dict[str, List[str]]]],\n) -> Dict[str, List[Kind]]:\n    \"\"\"Convert ``describe_workflow_outputs()`` result (kind name strings) to\n    ``Kind`` objects.\"\"\"\n    kind_name_map = _build_kind_name_map()\n    result: Dict[str, List[Kind]] = {}\n    for name, kind_info in outputs_description.items():\n        if isinstance(kind_info, dict):\n            # Wildcard selector ($steps.step.*) \u2014 nested structure.\n            # Represent as DICTIONARY_KIND since we can't express nested\n            # typed properties in a single OutputDefinition.\n            result[name] = [DICTIONARY_KIND]\n        else:\n            kinds = [\n                kind_name_map[k]\n                for k in kind_info\n                if k in kind_name_map\n            ]\n            result[name] = kinds if kinds else [WILDCARD_KIND]\n    return result\n\n\ndef _extract_output_names_with_wildcard(\n    spec: dict,\n) -> Dict[str, List[Kind]]:\n    \"\"\"Fallback: extract just the output names and assign WILDCARD_KIND.\"\"\"\n    outputs = spec.get(\"outputs\", [])\n    result: Dict[str, List[Kind]] = {}\n    for output in outputs:\n        name = output.get(\"name\")\n        if name:\n            result[name] = [WILDCARD_KIND]\n    return result\n\n\n@lru_cache(maxsize=1)\ndef _build_kind_name_map() -> Dict[str, Kind]:\n    \"\"\"Build a mapping from kind name to Kind object using the loader.\n\n    Result is cached since the set of registered kinds does not change\n    within a process.\n    \"\"\"\n    from inference.core.workflows.core_steps.loader import load_kinds\n\n    return {kind.name: kind for kind in load_kinds()}\n\n\n# ---------------------------------------------------------------------------\n# Input interface resolution\n# ---------------------------------------------------------------------------\n\n\ndef _resolve_and_cache_workflow_inputs(\n    cache_key: Tuple[str, Optional[str]],\n    spec: dict,\n) -> None:\n    \"\"\"Parse the target workflow's input interface from its spec and cache\n    the result in ``_RESOLVED_WORKFLOW_INPUTS``.\n\n    Each input is stored as a dict with keys: name, type, has_default.\n    \"\"\"\n    raw_inputs = spec.get(\"inputs\", [])\n    parsed: List[Dict[str, Any]] = []\n    for inp in raw_inputs:\n        name = inp.get(\"name\")\n        if not name:\n            continue\n        inp_type = inp.get(\"type\", \"\")\n        parsed.append({\n            \"name\": name,\n            \"type\": inp_type,\n            \"has_default\": \"default_value\" in inp,\n        })\n    _RESOLVED_WORKFLOW_INPUTS[cache_key] = parsed\n\n\ndef _validate_required_inputs(\n    workflow_id: str,\n    step_manifest: BlockManifest,\n    workflow_version_id: Optional[str] = None,\n) -> None:\n    \"\"\"Validate that the workflow caller step provides all required inputs\n    that the target workflow expects.\n\n    Raises ``ExecutionGraphStructureError`` if:\n    - The target workflow has required parameters (no default) not covered by\n      ``inputs``.\n    - The user declared ``input_definitions`` but ``inputs`` does not\n      cover all declared input names.\n    \"\"\"\n    from inference.core.workflows.errors import ExecutionGraphStructureError\n\n    input_keys = set(step_manifest.inputs.keys())\n\n    # Validate user-declared input_definitions: every declared input must be\n    # present in inputs.\n    if step_manifest.input_definitions:\n        missing_declared = [\n            name for name in step_manifest.input_definitions\n            if name not in input_keys\n        ]\n        if missing_declared:\n            raise ExecutionGraphStructureError(\n                public_message=(\n                    f\"Workflow caller step '{step_manifest.name}' declares \"\n                    f\"input_definitions for {list(step_manifest.input_definitions.keys())}, \"\n                    f\"but input(s) {missing_declared} are not provided in \"\n                    f\"'inputs'.\"\n                ),\n                context=\"workflow_compilation | workflow_caller_validation\",\n            )\n\n    cache_key = _make_cache_key(workflow_id, workflow_version_id)\n    resolved_inputs = _RESOLVED_WORKFLOW_INPUTS.get(cache_key)\n    if resolved_inputs is None:\n        return\n\n    missing = []\n    for inp in resolved_inputs:\n        if inp[\"has_default\"]:\n            continue\n        if inp[\"name\"] not in input_keys:\n            missing.append(inp[\"name\"])\n    if missing:\n        raise ExecutionGraphStructureError(\n            public_message=(\n                f\"Target workflow '{workflow_id}' requires input(s) \"\n                f\"{missing} (no default values), but they are not provided \"\n                f\"in 'inputs' on workflow_caller step \"\n                f\"'{step_manifest.name}'.\"\n            ),\n            context=\"workflow_compilation | workflow_caller_validation\",\n        )\n\n\n# ---------------------------------------------------------------------------\n# Output resolution for runtime\n# ---------------------------------------------------------------------------\n\n\ndef _resolve_output_kinds_for_run(\n    output_definitions: Dict[str, List[str]],\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[Dict[str, List[Kind]]]:\n    \"\"\"Determine which outputs to extract and their Kind objects.\n\n    Priority:\n    1. User-declared ``output_definitions`` (explicit kind names)\n    2. Auto-discovered outputs from ``_RESOLVED_WORKFLOW_OUTPUTS`` cache\n    3. Returns ``None`` \u2192 caller should fall back to generic ``result`` dict\n    \"\"\"\n    if output_definitions:\n        kind_name_map = _build_kind_name_map()\n        result: Dict[str, List[Kind]] = {}\n        for name, kind_names in output_definitions.items():\n            kinds = [\n                kind_name_map[k] for k in kind_names if k in kind_name_map\n            ]\n            result[name] = kinds or [WILDCARD_KIND]\n        return result\n    cache_key = _make_cache_key(workflow_id, workflow_version_id)\n    resolved = _RESOLVED_WORKFLOW_OUTPUTS.get(cache_key)\n    if resolved is not None:\n        return resolved\n    return None\n\n\n# ---------------------------------------------------------------------------\n# Output deserialization\n# ---------------------------------------------------------------------------\n\n\n@lru_cache(maxsize=1)\ndef _build_kinds_deserializers_map() -> Dict[str, Callable[[str, Any], Any]]:\n    \"\"\"Build the map of kind name -> deserializer function.\n\n    Result is cached since the set of registered deserializers does not\n    change within a process.\n    \"\"\"\n    from inference.core.workflows.execution_engine.introspection.blocks_loader import (\n        load_kinds_deserializers,\n    )\n\n    return load_kinds_deserializers()\n\n\ndef _deserialize_output_value(\n    output_name: str,\n    raw_value: Any,\n    output_kinds: List[Kind],\n    deserializers: Dict[str, Callable[[str, Any], Any]],\n) -> Any:\n    \"\"\"Deserialize a single output value using the deserializer matching its\n    resolved kind.\n\n    For outputs with known kinds, deserialization is required \u2014 failure raises\n    an error so downstream blocks don't receive unexpected raw data. For\n    WILDCARD_KIND outputs the raw value is returned as-is since we don't know\n    the expected type.\n    \"\"\"\n    if raw_value is None:\n        return None\n    if all(kind == WILDCARD_KIND for kind in output_kinds):\n        return raw_value\n    errors: List[Tuple[str, Exception]] = []\n    for kind in output_kinds:\n        if kind == WILDCARD_KIND:\n            continue\n        if kind.name not in deserializers:\n            continue\n        try:\n            return deserializers[kind.name](output_name, raw_value)\n        except Exception as error:\n            errors.append((kind.name, error))\n            continue\n    if errors:\n        error_details = \"; \".join(\n            f\"{kind}: {error}\" for kind, error in errors\n        )\n        raise RuntimeError(\n            f\"Failed to deserialize output '{output_name}' from target \"\n            f\"workflow. Tried deserializers for kinds \"\n            f\"{[k for k, _ in errors]} but all failed: {error_details}. \"\n            f\"This likely means the target workflow's output format doesn't \"\n            f\"match the expected kind.\"\n        )\n    return raw_value\n",
    "patch": null
  },
  {
    "trace_id": "8547ec74-8748-4d1a-9fd4-e5cae83c9ef3",
    "function_name": "build_workflow_url",
    "file_path": "inference/core/workflows/core_steps/composition/workflow_caller/v1.py",
    "speedup_x": 0.2895681220682626,
    "review_quality": "medium",
    "pre_optimization_commit": "2f6a10764cd3da01cb46073d710b1dec32962220",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def build_workflow_url(workspace_name: str, workflow_id: str) -> str:\n    \"\"\"Build the URL for calling a workflow on the local inference server.\n\n    Uses LOCAL_INFERENCE_API_URL to call the workflow on the same inference\n    server instance that is running the parent workflow.\n    \"\"\"\n    base_url = LOCAL_INFERENCE_API_URL.rstrip(\"/\")\n    return f\"{base_url}/{workspace_name}/workflows/{workflow_id}\"\n",
    "optimized_function_code": "from inference.core.env import LOCAL_INFERENCE_API_URL\n\n# Cached raw and stripped values to avoid repeated rstrip() calls.\n_cached_raw_local_inference_api_url = None\n_cached_stripped_base_url = None\n\ndef build_workflow_url(workspace_name: str, workflow_id: str) -> str:\n    \"\"\"Build the URL for calling a workflow on the local inference server.\n\n    Uses LOCAL_INFERENCE_API_URL to call the workflow on the same inference\n    server instance that is running the parent workflow.\n    \"\"\"\n    global _cached_raw_local_inference_api_url, _cached_stripped_base_url\n\n    # Read the imported value into a local variable to minimize global lookups.\n    raw = LOCAL_INFERENCE_API_URL\n\n    # Update cache only when the imported value changes. Use equality check so\n    # behavior remains correct if a new but equal string object is provided.\n    if raw != _cached_raw_local_inference_api_url:\n        _cached_stripped_base_url = raw.rstrip(\"/\")\n        _cached_raw_local_inference_api_url = raw\n\n    base_url = _cached_stripped_base_url\n    return f\"{base_url}/{workspace_name}/workflows/{workflow_id}\"",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/composition/workflow_caller/v1.py\nfrom inference.core.env import LOCAL_INFERENCE_API_URL\n\n# Cached raw and stripped values to avoid repeated rstrip() calls.\n_cached_raw_local_inference_api_url = None\n_cached_stripped_base_url = None\n\ndef build_workflow_url(workspace_name: str, workflow_id: str) -> str:\n    \"\"\"Build the URL for calling a workflow on the local inference server.\n\n    Uses LOCAL_INFERENCE_API_URL to call the workflow on the same inference\n    server instance that is running the parent workflow.\n    \"\"\"\n    global _cached_raw_local_inference_api_url, _cached_stripped_base_url\n\n    # Read the imported value into a local variable to minimize global lookups.\n    raw = LOCAL_INFERENCE_API_URL\n\n    # Update cache only when the imported value changes. Use equality check so\n    # behavior remains correct if a new but equal string object is provided.\n    if raw != _cached_raw_local_inference_api_url:\n        _cached_stripped_base_url = raw.rstrip(\"/\")\n        _cached_raw_local_inference_api_url = raw\n\n    base_url = _cached_stripped_base_url\n    return f\"{base_url}/{workspace_name}/workflows/{workflow_id}\"\n```",
    "optimized_function_only": "def build_workflow_url(workspace_name: str, workflow_id: str) -> str:\n    \"\"\"Build the URL for calling a workflow on the local inference server.\n\n    Uses LOCAL_INFERENCE_API_URL to call the workflow on the same inference\n    server instance that is running the parent workflow.\n    \"\"\"\n    global _cached_raw_local_inference_api_url, _cached_stripped_base_url\n\n    # Read the imported value into a local variable to minimize global lookups.\n    raw = LOCAL_INFERENCE_API_URL\n\n    # Update cache only when the imported value changes. Use equality check so\n    # behavior remains correct if a new but equal string object is provided.\n    if raw != _cached_raw_local_inference_api_url:\n        _cached_stripped_base_url = raw.rstrip(\"/\")\n        _cached_raw_local_inference_api_url = raw\n\n    base_url = _cached_stripped_base_url\n    return f\"{base_url}/{workspace_name}/workflows/{workflow_id}\"",
    "original_file_content": "import logging\nimport re\nfrom functools import lru_cache\nfrom typing import Any, Callable, Dict, List, Literal, Optional, Tuple, Type, Union\n\nimport requests\nfrom pydantic import ConfigDict, Field, field_validator\n\nfrom inference.core.env import LOCAL_INFERENCE_API_URL\nfrom inference.core.roboflow_api import (\n    get_roboflow_workspace,\n    get_workflow_specification,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    DICTIONARY_KIND,\n    INTEGER_KIND,\n    STRING_KIND,\n    WILDCARD_KIND,\n    Kind,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nLONG_DESCRIPTION = \"\"\"\nThe **Workflow Caller** block enables calling another Roboflow workflow from within a workflow.\nThis is useful for composing complex pipelines from smaller, reusable workflow components.\n\n### How it works\n\nThe block takes a workflow ID (from the same workspace), passes inputs (including images)\nto the target workflow, executes it via HTTP, and returns the results.\n\n### Configuration\n\nSpecify the target workflow using `workflow_id` (just the workflow slug, not a full URL). The\nworkspace is resolved automatically from the API key used to run the parent workflow.\n\n```\nworkflow_id = \"my-detection-pipeline\"\n```\n\n### Inputs\n\nPass all inputs the target workflow expects via `inputs`, including images:\n\n```\ninputs = {\n    \"image\": \"$inputs.image\",\n    \"confidence_threshold\": 0.5,\n    \"model_id\": \"$inputs.model_id\",\n}\n```\n\nUse `input_definitions` to declare the expected input types so the UI can render\nproper connectors.\n\n### Circular Dependency Protection\n\nTo prevent infinite recursion (e.g. Workflow A calls B, B calls A), the block tracks the chain\nof workflow calls using a header. If a circular reference is detected, the block returns an error\ninstead of making the call.\n\n### Dynamic Outputs\n\nWhen the target workflow_id is a static string, the block resolves the target workflow's\noutputs at compile time. Each output from the target workflow becomes a separate output on\nthis block with proper Kind types. When the workflow_id is dynamic (a selector), outputs\nfall back to a single ``result`` dict.\n\n### Limitations\n\n* Only workflows within the same workspace are supported (v1).\n* Execution is done via HTTP call, which adds network latency.\n* Subject to the same timeout constraints as the hosting environment.\n\"\"\"\n\nWORKFLOW_CALL_CHAIN_HEADER = \"X-Roboflow-Workflow-Call-Chain\"\nMAX_WORKFLOW_CALL_DEPTH = 10\nWORKFLOW_CALLER_BLOCK_TYPE = \"roboflow_core/workflow_caller@v1\"\n\n# Module-level cache mapping (workflow_id, version_id) -> {output_name: [Kind]}.\n# Populated during compile-time validation, read by get_actual_outputs() and run().\n_RESOLVED_WORKFLOW_OUTPUTS: Dict[Tuple[str, Optional[str]], Dict[str, List[Kind]]] = {}\n\n# Module-level cache mapping (workflow_id, version_id) -> list of parsed input dicts\n# from spec.  Each dict has: name, type, kind, has_default.\n_RESOLVED_WORKFLOW_INPUTS: Dict[Tuple[str, Optional[str]], List[Dict[str, Any]]] = {}\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Workflow Caller\",\n            \"version\": \"v1\",\n            \"short_description\": \"Call another Roboflow workflow from within a workflow.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"transformation\",\n            \"ui_manifest\": {\n                \"section\": \"advanced\",\n                \"icon\": \"fal fa-diagram-subtask\",\n                \"blockPriority\": 2,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/workflow_caller@v1\"]\n    workflow_id: Union[Selector(kind=[STRING_KIND]), str] = Field(\n        description=\"The workflow ID to call (must be in the same workspace).\",\n        examples=[\"my-workflow-id\", \"$inputs.workflow_id\"],\n    )\n    workflow_version_id: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Optional version ID of the target workflow. When provided, \"\n        \"the block calls the specific version instead of the latest. \"\n        \"Use this to pin a dependency to a known-good version.\",\n        examples=[\"1709234567890\", \"$inputs.workflow_version\"],\n    )\n    inputs: Dict[\n        str,\n        Union[\n            Selector(),\n            str,\n            float,\n            bool,\n            int,\n            dict,\n            list,\n        ],\n    ] = Field(\n        default_factory=dict,\n        description=\"Inputs to pass to the target workflow, keyed by input name. \"\n        \"All inputs including images should be listed here.\",\n        examples=[\n            {\"image\": \"$inputs.image\", \"confidence_threshold\": 0.5},\n            {\"image\": \"$inputs.image\", \"model_id\": \"$inputs.model_id\"},\n        ],\n    )\n    request_timeout: Union[int, Selector(kind=[INTEGER_KIND])] = Field(\n        default=30,\n        description=\"HTTP request timeout in seconds.\",\n        examples=[\"$inputs.request_timeout\", 30],\n    )\n    input_definitions: Dict[str, List[str]] = Field(\n        default_factory=dict,\n        description=(\n            \"Mapping of expected input names to their kind types. \"\n            \"Each key is an input name in the target workflow, and the value \"\n            \"is a list of kind name strings (e.g. ['float'], ['roboflow_model_id']). \"\n            \"This tells the parent workflow what inputs the target expects, \"\n            \"enabling proper UI connectors. Actual values are provided via \"\n            \"'inputs'.\"\n        ),\n        examples=[\n            {\"image\": [\"image\"], \"confidence_threshold\": [\"float\"]},\n            {\n                \"image\": [\"image\"],\n                \"class_filter\": [\"string\"],\n                \"iou_threshold\": [\"float\"],\n            },\n        ],\n    )\n    output_definitions: Dict[str, List[str]] = Field(\n        default_factory=dict,\n        description=(\n            \"Mapping of expected output names to their kind types. \"\n            \"Each key is an output name from the target workflow, and the value \"\n            \"is a list of kind name strings (e.g. ['object_detection_prediction']). \"\n            \"This tells the parent workflow what types to expect, enabling proper \"\n            \"connections to downstream blocks like visualizers.\"\n        ),\n        examples=[\n            {\"predictions\": [\"object_detection_prediction\"]},\n            {\"result_image\": [\"image\"], \"count\": [\"integer\"]},\n        ],\n    )\n\n    @field_validator(\"workflow_id\")\n    @classmethod\n    def validate_workflow_id_slug(cls, value: Any) -> Any:\n        if isinstance(value, str) and not value.startswith(\"$\"):\n            if not re.fullmatch(r\"[\\w\\-]+\", value):\n                raise ValueError(\n                    f\"`workflow_id` must be a valid slug (letters, numbers, \"\n                    f\"hyphens, and underscores only). Got: '{value}'\"\n                )\n        return value\n\n    @field_validator(\"request_timeout\")\n    @classmethod\n    def ensure_request_timeout_is_positive(cls, value: Any) -> Any:\n        if isinstance(value, int) and value <= 0:\n            raise ValueError(\"`request_timeout` must be a positive integer.\")\n        return value\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return []\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"*\"),\n        ]\n\n    def get_actual_outputs(self) -> List[OutputDefinition]:\n        base: List[OutputDefinition] = []\n        # 1. User-defined output definitions take precedence\n        if self.output_definitions:\n            kind_name_map = _build_kind_name_map()\n            for name, kind_names in self.output_definitions.items():\n                kinds = [kind_name_map[k] for k in kind_names if k in kind_name_map]\n                base.append(OutputDefinition(name=name, kind=kinds or [WILDCARD_KIND]))\n            return base\n        # 2. Fall back to auto-discovery from compile-time resolution\n        if isinstance(self.workflow_id, str) and not self.workflow_id.startswith(\"$\"):\n            version_id = self.workflow_version_id\n            if isinstance(version_id, str) and version_id.startswith(\"$\"):\n                version_id = None\n            cache_key = _make_cache_key(self.workflow_id, version_id)\n            resolved = _RESOLVED_WORKFLOW_OUTPUTS.get(cache_key)\n            if resolved is not None:\n                for name, kinds in resolved.items():\n                    base.append(OutputDefinition(name=name, kind=kinds))\n                return base\n        # 3. Fall back to generic result dict\n        base.append(OutputDefinition(name=\"result\", kind=[DICTIONARY_KIND]))\n        return base\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass WorkflowCallerBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        api_key: Optional[str],\n        workflow_call_chain: Optional[str] = None,\n    ):\n        self._api_key = api_key\n        self._workspace_name: Optional[str] = None\n        self._workflow_call_chain = workflow_call_chain or \"\"\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"api_key\", \"workflow_call_chain\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        workflow_id: str,\n        inputs: Dict[str, Any],\n        request_timeout: int,\n        input_definitions: Dict[str, List[str]],\n        output_definitions: Dict[str, List[str]],\n        workflow_version_id: Optional[str] = None,\n    ) -> BlockResult:\n        workspace_name = self._resolve_workspace_name()\n        if workspace_name is None:\n            raise RuntimeError(\n                f\"Could not resolve workspace for workflow '{workflow_id}'. \"\n                f\"Ensure a valid API key is configured.\"\n            )\n        error_status, message, raw_outputs = call_workflow(\n            api_key=self._api_key,\n            workspace_name=workspace_name,\n            workflow_id=workflow_id,\n            inputs=inputs,\n            request_timeout=request_timeout,\n            call_chain=self._workflow_call_chain,\n            workflow_version_id=workflow_version_id,\n        )\n        if error_status:\n            raise RuntimeError(f\"Workflow '{workflow_id}' execution failed: {message}\")\n        result: Dict[str, Any] = {}\n        # Determine which outputs to extract and their kinds for deserialization\n        output_kinds_map = _resolve_output_kinds_for_run(\n            output_definitions=output_definitions,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n        )\n        if output_kinds_map is not None:\n            deserializers = _build_kinds_deserializers_map()\n            for output_name, output_kinds in output_kinds_map.items():\n                raw_value = raw_outputs.get(output_name)\n                result[output_name] = _deserialize_output_value(\n                    output_name=output_name,\n                    raw_value=raw_value,\n                    output_kinds=output_kinds,\n                    deserializers=deserializers,\n                )\n        else:\n            result[\"result\"] = raw_outputs\n        return result\n\n    def _resolve_workspace_name(self) -> Optional[str]:\n        if self._workspace_name is not None:\n            return self._workspace_name\n        if not self._api_key:\n            return None\n        try:\n            self._workspace_name = get_roboflow_workspace(api_key=self._api_key)\n            return self._workspace_name\n        except Exception as error:\n            logging.warning(\n                f\"Could not resolve workspace from API key. Error: {str(error)}\"\n            )\n            return None\n\n\ndef _make_cache_key(\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Tuple[str, Optional[str]]:\n    \"\"\"Build a cache key that accounts for both workflow_id and version_id.\"\"\"\n    return (workflow_id, workflow_version_id)\n\n\ndef call_workflow(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    inputs: Dict[str, Any],\n    request_timeout: int,\n    call_chain: Optional[str] = None,\n    workflow_version_id: Optional[str] = None,\n) -> Tuple[bool, str, dict]:\n    \"\"\"Execute a workflow call and return (error_status, message, result).\n\n    This function is separated from the block's run() to facilitate testing.\n    \"\"\"\n    current_chain = call_chain or \"\"\n    chain_entries = [entry for entry in current_chain.split(\",\") if entry]\n    if workflow_id in chain_entries:\n        logging.warning(\n            f\"Circular workflow call detected: \"\n            f\"'{workflow_id}' is already in call chain [{current_chain}].\"\n        )\n        return (\n            True,\n            f\"Circular workflow call detected: '{workflow_id}' is already \"\n            f\"in the call chain [{current_chain}]. Aborting to prevent \"\n            f\"infinite recursion.\",\n            {},\n        )\n    if len(chain_entries) >= MAX_WORKFLOW_CALL_DEPTH:\n        logging.warning(\n            f\"Workflow call depth limit ({MAX_WORKFLOW_CALL_DEPTH}) reached. \"\n            f\"Call chain: [{current_chain}].\"\n        )\n        return (\n            True,\n            f\"Workflow call depth limit ({MAX_WORKFLOW_CALL_DEPTH}) reached. \"\n            f\"Call chain: [{current_chain}].\",\n            {},\n        )\n    updated_chain = \",\".join([*chain_entries, workflow_id])\n    inputs = build_workflow_inputs(inputs=inputs)\n    return execute_workflow_request(\n        api_key=api_key,\n        workspace_name=workspace_name,\n        workflow_id=workflow_id,\n        inputs=inputs,\n        request_timeout=request_timeout,\n        call_chain=updated_chain,\n        workflow_version_id=workflow_version_id,\n    )\n\n\ndef build_workflow_inputs(\n    inputs: Dict[str, Any],\n) -> Dict[str, Any]:\n    \"\"\"Build the inputs dictionary for the target workflow.\n\n    Handles ``WorkflowImageData`` objects found in ``inputs`` by\n    automatically serialising them to the ``{type: base64, value: ...}``\n    format expected by the workflow HTTP API.\n    \"\"\"\n    resolved: Dict[str, Any] = {}\n    for key, value in inputs.items():\n        if isinstance(value, WorkflowImageData):\n            resolved[key] = {\n                \"type\": \"base64\",\n                \"value\": value.base64_image,\n            }\n        else:\n            resolved[key] = value\n    return resolved\n\n\ndef execute_workflow_request(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    inputs: Dict[str, Any],\n    request_timeout: int,\n    call_chain: str,\n    workflow_version_id: Optional[str] = None,\n) -> Tuple[bool, str, dict]:\n    \"\"\"Make the HTTP request to the target workflow and return\n    (error_status, message, result).\"\"\"\n    url = build_workflow_url(\n        workspace_name=workspace_name,\n        workflow_id=workflow_id,\n    )\n    payload: Dict[str, Any] = {\"inputs\": inputs}\n    if api_key is not None:\n        payload[\"api_key\"] = api_key\n    if workflow_version_id is not None:\n        payload[\"workflow_version_id\"] = workflow_version_id\n    headers = {WORKFLOW_CALL_CHAIN_HEADER: call_chain}\n    try:\n        response = requests.post(\n            url,\n            json=payload,\n            headers=headers,\n            timeout=request_timeout,\n        )\n        response.raise_for_status()\n        response_data = response.json()\n        outputs = response_data.get(\"outputs\", [])\n        result = outputs[0] if outputs else {}\n        return (\n            False,\n            \"Workflow executed successfully\",\n            result,\n        )\n    except Exception as error:\n        logging.warning(\n            f\"Could not execute workflow '{workflow_id}'. Error: {str(error)}\"\n        )\n        error_type = type(error).__name__\n        return (\n            True,\n            f\"Failed to execute workflow '{workflow_id}': {error_type}\",\n            {},\n        )\n\n\ndef build_workflow_url(workspace_name: str, workflow_id: str) -> str:\n    \"\"\"Build the URL for calling a workflow on the local inference server.\n\n    Uses LOCAL_INFERENCE_API_URL to call the workflow on the same inference\n    server instance that is running the parent workflow.\n    \"\"\"\n    base_url = LOCAL_INFERENCE_API_URL.rstrip(\"/\")\n    return f\"{base_url}/{workspace_name}/workflows/{workflow_id}\"\n\n\n# ---------------------------------------------------------------------------\n# Compile-time validation\n# ---------------------------------------------------------------------------\n\n\ndef validate_workflow_caller_no_circular_references(\n    steps: List[WorkflowBlockManifest],\n    api_key: Optional[str],\n) -> None:\n    \"\"\"Compile-time validation: check that workflow_caller blocks with static\n    workflow_id values don't create circular dependencies, resolve the target\n    workflow's input and output interfaces, and validate that required inputs\n    are provided.\n\n    Only validates when workflow_id is a literal string (not a selector like\n    ``$inputs.workflow_id``). Errors during spec fetching are logged as warnings\n    and do not block compilation \u2014 the runtime circular dependency check via\n    the call chain header provides an additional safety net.\n    \"\"\"\n    caller_steps = _extract_workflow_caller_steps(steps=steps)\n    if not caller_steps:\n        return\n    workspace_name = _resolve_workspace_for_validation(api_key=api_key)\n    if workspace_name is None:\n        return\n    for workflow_id, version_id, step_manifest in caller_steps:\n        spec = _fetch_workflow_spec_for_validation(\n            api_key=api_key,\n            workspace_name=workspace_name,\n            workflow_id=workflow_id,\n            workflow_version_id=version_id,\n        )\n        if spec is None:\n            continue\n        _check_workflow_for_circular_references(\n            api_key=api_key,\n            workspace_name=workspace_name,\n            target_workflow_id=workflow_id,\n            target_workflow_version_id=version_id,\n            visited=set(),\n            prefetched_spec=spec,\n        )\n        cache_key = _make_cache_key(workflow_id, version_id)\n        _resolve_and_cache_workflow_outputs(\n            cache_key=cache_key,\n            spec=spec,\n        )\n        _resolve_and_cache_workflow_inputs(\n            cache_key=cache_key,\n            spec=spec,\n        )\n        _validate_required_inputs(\n            workflow_id=workflow_id,\n            workflow_version_id=version_id,\n            step_manifest=step_manifest,\n        )\n\n\ndef _extract_workflow_caller_steps(\n    steps: List[WorkflowBlockManifest],\n) -> List[Tuple[str, Optional[str], WorkflowBlockManifest]]:\n    \"\"\"Extract (workflow_id, workflow_version_id, manifest) tuples from\n    workflow_caller steps that have literal (non-selector) workflow_id values.\"\"\"\n    result = []\n    for step in steps:\n        if not isinstance(step, BlockManifest):\n            continue\n        workflow_id = step.workflow_id\n        if isinstance(workflow_id, str) and not workflow_id.startswith(\"$\"):\n            version_id = step.workflow_version_id\n            # Only use version_id if it's a literal string (not a selector)\n            if isinstance(version_id, str) and version_id.startswith(\"$\"):\n                version_id = None\n            result.append((workflow_id, version_id, step))\n    return result\n\n\ndef _fetch_workflow_spec_for_validation(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[dict]:\n    \"\"\"Fetch a workflow spec, returning None on any error.\"\"\"\n    try:\n        return get_workflow_specification(\n            api_key=api_key,\n            workspace_id=workspace_name,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n        )\n    except Exception as error:\n        logging.debug(\n            \"Could not fetch workflow '%s' for compile-time validation (error type: %s)\",\n            workflow_id,\n            type(error).__name__,\n        )\n        return None\n\n\ndef _resolve_workspace_for_validation(\n    api_key: Optional[str],\n) -> Optional[str]:\n    if not api_key:\n        return None\n    try:\n        return get_roboflow_workspace(api_key=api_key)\n    except Exception as error:\n        logging.debug(\n            \"Could not resolve workspace for compile-time workflow validation (error type: %s)\",\n            type(error).__name__,\n        )\n        return None\n\n\ndef _check_workflow_for_circular_references(\n    api_key: Optional[str],\n    workspace_name: str,\n    target_workflow_id: str,\n    visited: set,\n    target_workflow_version_id: Optional[str] = None,\n    prefetched_spec: Optional[dict] = None,\n) -> None:\n    \"\"\"Recursively check if a target workflow creates a circular call chain.\n\n    Raises ``ExecutionGraphStructureError`` if a cycle is found. Silently\n    returns on any fetch error \u2014 the runtime check will catch those cases.\n\n    When ``prefetched_spec`` is provided it is used directly instead of\n    fetching the spec again.  The caller in\n    ``validate_workflow_caller_no_circular_references`` already fetches the\n    spec for the top-level workflow, so passing it here avoids a duplicate\n    API call.\n    \"\"\"\n    from inference.core.workflows.errors import ExecutionGraphStructureError\n\n    if target_workflow_id in visited:\n        chain = \" -> \".join([*visited, target_workflow_id])\n        raise ExecutionGraphStructureError(\n            public_message=(\n                f\"Circular workflow call detected at compile time: {chain}. \"\n                f\"This would cause infinite recursion at runtime.\"\n            ),\n            context=\"workflow_compilation | workflow_caller_validation\",\n        )\n    if prefetched_spec is not None:\n        spec = prefetched_spec\n    else:\n        try:\n            spec = get_workflow_specification(\n                api_key=api_key,\n                workspace_id=workspace_name,\n                workflow_id=target_workflow_id,\n                workflow_version_id=target_workflow_version_id,\n            )\n        except Exception as error:\n            logging.debug(\n                \"Could not fetch workflow '%s' for circular dependency check (error type: %s)\",\n                target_workflow_id,\n                type(error).__name__,\n            )\n            return\n    nested_workflows = _extract_workflow_caller_ids_from_spec(spec=spec)\n    if not nested_workflows:\n        return\n    visited_with_current = visited | {target_workflow_id}\n    for nested_id, nested_version_id in nested_workflows:\n        _check_workflow_for_circular_references(\n            api_key=api_key,\n            workspace_name=workspace_name,\n            target_workflow_id=nested_id,\n            target_workflow_version_id=nested_version_id,\n            visited=visited_with_current,\n        )\n\n\ndef _extract_workflow_caller_ids_from_spec(\n    spec: dict,\n) -> List[Tuple[str, Optional[str]]]:\n    \"\"\"Extract static (workflow_id, workflow_version_id) tuples from a raw\n    workflow specification.  Only includes entries where ``workflow_id`` is a\n    literal string (not a selector).  ``workflow_version_id`` is included when\n    it is a literal string, otherwise ``None``.\"\"\"\n    steps = spec.get(\"steps\", [])\n    result: List[Tuple[str, Optional[str]]] = []\n    for step in steps:\n        step_type = step.get(\"type\", \"\")\n        if step_type != WORKFLOW_CALLER_BLOCK_TYPE:\n            continue\n        workflow_id = step.get(\"workflow_id\", \"\")\n        if not isinstance(workflow_id, str) or workflow_id.startswith(\"$\"):\n            continue\n        version_id = step.get(\"workflow_version_id\")\n        if isinstance(version_id, str) and version_id.startswith(\"$\"):\n            version_id = None\n        result.append((workflow_id, version_id))\n    return result\n\n\n# ---------------------------------------------------------------------------\n# Output interface resolution\n# ---------------------------------------------------------------------------\n\n\ndef _resolve_and_cache_workflow_outputs(\n    cache_key: Tuple[str, Optional[str]],\n    spec: dict,\n) -> None:\n    \"\"\"Resolve the target workflow's output interface from its spec and cache\n    the result in ``_RESOLVED_WORKFLOW_OUTPUTS``.\n\n    Tries ``describe_workflow_outputs()`` for proper Kind resolution. Falls\n    back to extracting output names with ``WILDCARD_KIND`` on any error.\n    \"\"\"\n    try:\n        outputs_description = _describe_outputs_from_spec(spec=spec)\n    except Exception as error:\n        logging.debug(\n            f\"Could not resolve output kinds for workflow '{cache_key}' \"\n            f\"via describe_workflow_outputs: {error}. \"\n            f\"Falling back to output names with WILDCARD_KIND.\"\n        )\n        outputs_description = None\n\n    if outputs_description is not None:\n        resolved = _convert_output_descriptions_to_kinds(\n            outputs_description=outputs_description,\n        )\n    else:\n        resolved = _extract_output_names_with_wildcard(spec=spec)\n\n    if resolved:\n        _RESOLVED_WORKFLOW_OUTPUTS[cache_key] = resolved\n\n\ndef _describe_outputs_from_spec(\n    spec: dict,\n) -> Dict[str, Union[List[str], Dict[str, List[str]]]]:\n    \"\"\"Call the standard output discovery to resolve output kinds.\"\"\"\n    from inference.core.workflows.execution_engine.v1.introspection.outputs_discovery import (\n        describe_workflow_outputs,\n    )\n\n    return describe_workflow_outputs(definition=spec)\n\n\ndef _convert_output_descriptions_to_kinds(\n    outputs_description: Dict[str, Union[List[str], Dict[str, List[str]]]],\n) -> Dict[str, List[Kind]]:\n    \"\"\"Convert ``describe_workflow_outputs()`` result (kind name strings) to\n    ``Kind`` objects.\"\"\"\n    kind_name_map = _build_kind_name_map()\n    result: Dict[str, List[Kind]] = {}\n    for name, kind_info in outputs_description.items():\n        if isinstance(kind_info, dict):\n            # Wildcard selector ($steps.step.*) \u2014 nested structure.\n            # Represent as DICTIONARY_KIND since we can't express nested\n            # typed properties in a single OutputDefinition.\n            result[name] = [DICTIONARY_KIND]\n        else:\n            kinds = [kind_name_map[k] for k in kind_info if k in kind_name_map]\n            result[name] = kinds if kinds else [WILDCARD_KIND]\n    return result\n\n\ndef _extract_output_names_with_wildcard(\n    spec: dict,\n) -> Dict[str, List[Kind]]:\n    \"\"\"Fallback: extract just the output names and assign WILDCARD_KIND.\"\"\"\n    outputs = spec.get(\"outputs\", [])\n    result: Dict[str, List[Kind]] = {}\n    for output in outputs:\n        name = output.get(\"name\")\n        if name:\n            result[name] = [WILDCARD_KIND]\n    return result\n\n\n@lru_cache(maxsize=1)\ndef _build_kind_name_map() -> Dict[str, Kind]:\n    \"\"\"Build a mapping from kind name to Kind object using the loader.\n\n    Result is cached since the set of registered kinds does not change\n    within a process.\n    \"\"\"\n    from inference.core.workflows.core_steps.loader import load_kinds\n\n    return {kind.name: kind for kind in load_kinds()}\n\n\n# ---------------------------------------------------------------------------\n# Input interface resolution\n# ---------------------------------------------------------------------------\n\n\ndef _resolve_and_cache_workflow_inputs(\n    cache_key: Tuple[str, Optional[str]],\n    spec: dict,\n) -> None:\n    \"\"\"Parse the target workflow's input interface from its spec and cache\n    the result in ``_RESOLVED_WORKFLOW_INPUTS``.\n\n    Each input is stored as a dict with keys: name, type, has_default.\n    \"\"\"\n    raw_inputs = spec.get(\"inputs\", [])\n    parsed: List[Dict[str, Any]] = []\n    for inp in raw_inputs:\n        name = inp.get(\"name\")\n        if not name:\n            continue\n        inp_type = inp.get(\"type\", \"\")\n        parsed.append(\n            {\n                \"name\": name,\n                \"type\": inp_type,\n                \"has_default\": \"default_value\" in inp,\n            }\n        )\n    _RESOLVED_WORKFLOW_INPUTS[cache_key] = parsed\n\n\ndef _validate_required_inputs(\n    workflow_id: str,\n    step_manifest: BlockManifest,\n    workflow_version_id: Optional[str] = None,\n) -> None:\n    \"\"\"Validate that the workflow caller step provides all required inputs\n    that the target workflow expects.\n\n    Raises ``ExecutionGraphStructureError`` if:\n    - The target workflow has required parameters (no default) not covered by\n      ``inputs``.\n    - The user declared ``input_definitions`` but ``inputs`` does not\n      cover all declared input names.\n    \"\"\"\n    from inference.core.workflows.errors import ExecutionGraphStructureError\n\n    input_keys = set(step_manifest.inputs.keys())\n\n    # Validate user-declared input_definitions: every declared input must be\n    # present in inputs.\n    if step_manifest.input_definitions:\n        missing_declared = [\n            name for name in step_manifest.input_definitions if name not in input_keys\n        ]\n        if missing_declared:\n            raise ExecutionGraphStructureError(\n                public_message=(\n                    f\"Workflow caller step '{step_manifest.name}' declares \"\n                    f\"input_definitions for {list(step_manifest.input_definitions.keys())}, \"\n                    f\"but input(s) {missing_declared} are not provided in \"\n                    f\"'inputs'.\"\n                ),\n                context=\"workflow_compilation | workflow_caller_validation\",\n            )\n\n    cache_key = _make_cache_key(workflow_id, workflow_version_id)\n    resolved_inputs = _RESOLVED_WORKFLOW_INPUTS.get(cache_key)\n    if resolved_inputs is None:\n        return\n\n    missing = []\n    for inp in resolved_inputs:\n        if inp[\"has_default\"]:\n            continue\n        if inp[\"name\"] not in input_keys:\n            missing.append(inp[\"name\"])\n    if missing:\n        raise ExecutionGraphStructureError(\n            public_message=(\n                f\"Target workflow '{workflow_id}' requires input(s) \"\n                f\"{missing} (no default values), but they are not provided \"\n                f\"in 'inputs' on workflow_caller step \"\n                f\"'{step_manifest.name}'.\"\n            ),\n            context=\"workflow_compilation | workflow_caller_validation\",\n        )\n\n\n# ---------------------------------------------------------------------------\n# Output resolution for runtime\n# ---------------------------------------------------------------------------\n\n\ndef _resolve_output_kinds_for_run(\n    output_definitions: Dict[str, List[str]],\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[Dict[str, List[Kind]]]:\n    \"\"\"Determine which outputs to extract and their Kind objects.\n\n    Priority:\n    1. User-declared ``output_definitions`` (explicit kind names)\n    2. Auto-discovered outputs from ``_RESOLVED_WORKFLOW_OUTPUTS`` cache\n    3. Returns ``None`` \u2192 caller should fall back to generic ``result`` dict\n    \"\"\"\n    if output_definitions:\n        kind_name_map = _build_kind_name_map()\n        result: Dict[str, List[Kind]] = {}\n        for name, kind_names in output_definitions.items():\n            kinds = [kind_name_map[k] for k in kind_names if k in kind_name_map]\n            result[name] = kinds or [WILDCARD_KIND]\n        return result\n    cache_key = _make_cache_key(workflow_id, workflow_version_id)\n    resolved = _RESOLVED_WORKFLOW_OUTPUTS.get(cache_key)\n    if resolved is not None:\n        return resolved\n    return None\n\n\n# ---------------------------------------------------------------------------\n# Output deserialization\n# ---------------------------------------------------------------------------\n\n\n@lru_cache(maxsize=1)\ndef _build_kinds_deserializers_map() -> Dict[str, Callable[[str, Any], Any]]:\n    \"\"\"Build the map of kind name -> deserializer function.\n\n    Result is cached since the set of registered deserializers does not\n    change within a process.\n    \"\"\"\n    from inference.core.workflows.execution_engine.introspection.blocks_loader import (\n        load_kinds_deserializers,\n    )\n\n    return load_kinds_deserializers()\n\n\ndef _deserialize_output_value(\n    output_name: str,\n    raw_value: Any,\n    output_kinds: List[Kind],\n    deserializers: Dict[str, Callable[[str, Any], Any]],\n) -> Any:\n    \"\"\"Deserialize a single output value using the deserializer matching its\n    resolved kind.\n\n    For outputs with known kinds, deserialization is required \u2014 failure raises\n    an error so downstream blocks don't receive unexpected raw data. For\n    WILDCARD_KIND outputs the raw value is returned as-is since we don't know\n    the expected type.\n    \"\"\"\n    if raw_value is None:\n        return None\n    if all(kind == WILDCARD_KIND for kind in output_kinds):\n        return raw_value\n    errors: List[Tuple[str, Exception]] = []\n    for kind in output_kinds:\n        if kind == WILDCARD_KIND:\n            continue\n        if kind.name not in deserializers:\n            continue\n        try:\n            return deserializers[kind.name](output_name, raw_value)\n        except Exception as error:\n            errors.append((kind.name, error))\n            continue\n    if errors:\n        error_details = \"; \".join(f\"{kind}: {error}\" for kind, error in errors)\n        raise RuntimeError(\n            f\"Failed to deserialize output '{output_name}' from target \"\n            f\"workflow. Tried deserializers for kinds \"\n            f\"{[k for k, _ in errors]} but all failed: {error_details}. \"\n            f\"This likely means the target workflow's output format doesn't \"\n            f\"match the expected kind.\"\n        )\n    return raw_value\n",
    "patch": null
  },
  {
    "trace_id": "1276bc70-8ad4-4e69-b624-7bee0efe621c",
    "function_name": "WorkflowCallerBlockV1.run",
    "file_path": "inference/core/workflows/core_steps/composition/workflow_caller/v1.py",
    "speedup_x": 0.12703817992586777,
    "review_quality": "medium",
    "pre_optimization_commit": "0306c6c070caef88dea09d9b680c659f63b2ccc1",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def run(\n        self,\n        workflow_id: str,\n        inputs: Dict[str, Any],\n        request_timeout: int,\n        input_definitions: Dict[str, List[str]],\n        output_definitions: Dict[str, List[str]],\n        workflow_version_id: Optional[str] = None,\n    ) -> BlockResult:\n        workspace_name = self._resolve_workspace_name()\n        if workspace_name is None:\n            raise RuntimeError(\n                f\"Could not resolve workspace for workflow '{workflow_id}'. \"\n                f\"Ensure a valid API key is configured.\"\n            )\n        error_status, message, raw_outputs = call_workflow(\n            api_key=self._api_key,\n            workspace_name=workspace_name,\n            workflow_id=workflow_id,\n            inputs=inputs,\n            request_timeout=request_timeout,\n            call_chain=self._workflow_call_chain,\n            workflow_version_id=workflow_version_id,\n        )\n        if error_status:\n            raise RuntimeError(\n                f\"Workflow '{workflow_id}' execution failed: {message}\"\n            )\n        result: Dict[str, Any] = {}\n        # Determine which outputs to extract and their kinds for deserialization\n        output_kinds_map = _resolve_output_kinds_for_run(\n            output_definitions=output_definitions,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n        )\n        if output_kinds_map is not None:\n            deserializers = _build_kinds_deserializers_map()\n            for output_name, output_kinds in output_kinds_map.items():\n                raw_value = raw_outputs.get(output_name)\n                result[output_name] = _deserialize_output_value(\n                    output_name=output_name,\n                    raw_value=raw_value,\n                    output_kinds=output_kinds,\n                    deserializers=deserializers,\n                )\n        else:\n            result[\"result\"] = raw_outputs\n        return result\n",
    "optimized_function_code": "import logging\nfrom functools import lru_cache\nfrom typing import Any, Callable, Dict, List, Optional, Tuple\n\nfrom inference.core.roboflow_api import get_roboflow_workspace\nfrom inference.core.workflows.execution_engine.entities.types import (\n    WILDCARD_KIND, Kind)\nfrom inference.core.workflows.prototypes.block import (BlockResult,\n                                                       WorkflowBlock)\n\nWORKFLOW_CALL_CHAIN_HEADER = \"X-Roboflow-Workflow-Call-Chain\"\nMAX_WORKFLOW_CALL_DEPTH = 10\n\n# Module-level cache mapping (workflow_id, version_id) -> {output_name: [Kind]}.\n# Populated during compile-time validation, read by get_actual_outputs() and run().\n_RESOLVED_WORKFLOW_OUTPUTS: Dict[Tuple[str, Optional[str]], Dict[str, List[Kind]]] = {}\n\n\nclass WorkflowCallerBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        api_key: Optional[str],\n        workflow_call_chain: Optional[str] = None,\n    ):\n        self._api_key = api_key\n        self._workspace_name: Optional[str] = None\n        self._workflow_call_chain = workflow_call_chain or \"\"\n\n    def run(\n        self,\n        workflow_id: str,\n        inputs: Dict[str, Any],\n        request_timeout: int,\n        input_definitions: Dict[str, List[str]],\n        output_definitions: Dict[str, List[str]],\n        workflow_version_id: Optional[str] = None,\n    ) -> BlockResult:\n        workspace_name = self._resolve_workspace_name()\n        if workspace_name is None:\n            raise RuntimeError(\n                f\"Could not resolve workspace for workflow '{workflow_id}'. \"\n                f\"Ensure a valid API key is configured.\"\n            )\n        error_status, message, raw_outputs = call_workflow(\n            api_key=self._api_key,\n            workspace_name=workspace_name,\n            workflow_id=workflow_id,\n            inputs=inputs,\n            request_timeout=request_timeout,\n            call_chain=self._workflow_call_chain,\n            workflow_version_id=workflow_version_id,\n        )\n        if error_status:\n            raise RuntimeError(\n                f\"Workflow '{workflow_id}' execution failed: {message}\"\n            )\n        result: Dict[str, Any] = {}\n        # Determine which outputs to extract and their kinds for deserialization\n        output_kinds_map = _resolve_output_kinds_for_run(\n            output_definitions=output_definitions,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n        )\n        if output_kinds_map is not None:\n            # Avoid building deserializers map if every declared output kind is a wildcard.\n            any_non_wildcard = False\n            for kinds in output_kinds_map.values():\n                for kind in kinds:\n                    if kind != WILDCARD_KIND:\n                        any_non_wildcard = True\n                        break\n                if any_non_wildcard:\n                    break\n\n            deserializers = _build_kinds_deserializers_map() if any_non_wildcard else None\n            raw_get = raw_outputs.get\n            for output_name, output_kinds in output_kinds_map.items():\n                raw_value = raw_get(output_name)\n                if deserializers is None:\n                    result[output_name] = raw_value\n                else:\n                    result[output_name] = _deserialize_output_value(\n                        output_name=output_name,\n                        raw_value=raw_value,\n                        output_kinds=output_kinds,\n                        deserializers=deserializers,\n                    )\n        else:\n            result[\"result\"] = raw_outputs\n        return result\n\n    def _resolve_workspace_name(self) -> Optional[str]:\n        if self._workspace_name is not None:\n            return self._workspace_name\n        if not self._api_key:\n            return None\n        try:\n            self._workspace_name = get_roboflow_workspace(api_key=self._api_key)\n            return self._workspace_name\n        except Exception as error:\n            logging.warning(\n                f\"Could not resolve workspace from API key. Error: {str(error)}\"\n            )\n            return None\n\n\ndef call_workflow(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    inputs: Dict[str, Any],\n    request_timeout: int,\n    call_chain: Optional[str] = None,\n    workflow_version_id: Optional[str] = None,\n) -> Tuple[bool, str, dict]:\n    \"\"\"Execute a workflow call and return (error_status, message, result).\n\n    This function is separated from the block's run() to facilitate testing.\n    \"\"\"\n    current_chain = call_chain or \"\"\n    chain_entries = [entry for entry in current_chain.split(\",\") if entry]\n    if workflow_id in chain_entries:\n        logging.warning(\n            f\"Circular workflow call detected: \"\n            f\"'{workflow_id}' is already in call chain [{current_chain}].\"\n        )\n        return (\n            True,\n            f\"Circular workflow call detected: '{workflow_id}' is already \"\n            f\"in the call chain [{current_chain}]. Aborting to prevent \"\n            f\"infinite recursion.\",\n            {},\n        )\n    if len(chain_entries) >= MAX_WORKFLOW_CALL_DEPTH:\n        logging.warning(\n            f\"Workflow call depth limit ({MAX_WORKFLOW_CALL_DEPTH}) reached. \"\n            f\"Call chain: [{current_chain}].\"\n        )\n        return (\n            True,\n            f\"Workflow call depth limit ({MAX_WORKFLOW_CALL_DEPTH}) reached. \"\n            f\"Call chain: [{current_chain}].\",\n            {},\n        )\n    updated_chain = \",\".join([*chain_entries, workflow_id])\n    inputs = build_workflow_inputs(inputs=inputs)\n    return execute_workflow_request(\n        api_key=api_key,\n        workspace_name=workspace_name,\n        workflow_id=workflow_id,\n        inputs=inputs,\n        request_timeout=request_timeout,\n        call_chain=updated_chain,\n        workflow_version_id=workflow_version_id,\n    )\n\n\n# ---------------------------------------------------------------------------\n# Output resolution for runtime\n# ---------------------------------------------------------------------------\n\n\ndef _resolve_output_kinds_for_run(\n    output_definitions: Dict[str, List[str]],\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[Dict[str, List[Kind]]]:\n    \"\"\"Determine which outputs to extract and their Kind objects.\n\n    Priority:\n    1. User-declared ``output_definitions`` (explicit kind names)\n    2. Auto-discovered outputs from ``_RESOLVED_WORKFLOW_OUTPUTS`` cache\n    3. Returns ``None`` \u2192 caller should fall back to generic ``result`` dict\n    \"\"\"\n    if output_definitions:\n        kind_name_map = _build_kind_name_map()\n        result: Dict[str, List[Kind]] = {}\n        for name, kind_names in output_definitions.items():\n            kinds = [\n                kind_name_map[k] for k in kind_names if k in kind_name_map\n            ]\n            result[name] = kinds or [WILDCARD_KIND]\n        return result\n    cache_key = _make_cache_key(workflow_id, workflow_version_id)\n    resolved = _RESOLVED_WORKFLOW_OUTPUTS.get(cache_key)\n    if resolved is not None:\n        return resolved\n    return None\n\n\n# ---------------------------------------------------------------------------\n# Output deserialization\n# ---------------------------------------------------------------------------\n\n\n@lru_cache(maxsize=1)\ndef _build_kinds_deserializers_map() -> Dict[str, Callable[[str, Any], Any]]:\n    \"\"\"Build the map of kind name -> deserializer function.\n\n    Result is cached since the set of registered deserializers does not\n    change within a process.\n    \"\"\"\n    from inference.core.workflows.execution_engine.introspection.blocks_loader import \\\n        load_kinds_deserializers\n\n    return load_kinds_deserializers()\n\n\ndef _deserialize_output_value(\n    output_name: str,\n    raw_value: Any,\n    output_kinds: List[Kind],\n    deserializers: Dict[str, Callable[[str, Any], Any]],\n) -> Any:\n    \"\"\"Deserialize a single output value using the deserializer matching its\n    resolved kind.\n\n    For outputs with known kinds, deserialization is required \u2014 failure raises\n    an error so downstream blocks don't receive unexpected raw data. For\n    WILDCARD_KIND outputs the raw value is returned as-is since we don't know\n    the expected type.\n    \"\"\"\n    if raw_value is None:\n        return None\n    errors: List[Tuple[str, Exception]] = []\n    non_wildcard_seen = False\n    for kind in output_kinds:\n        if kind == WILDCARD_KIND:\n            continue\n        non_wildcard_seen = True\n        des = deserializers.get(kind.name)\n        if des is None:\n            continue\n        try:\n            return des(output_name, raw_value)\n        except Exception as error:\n            errors.append((kind.name, error))\n            continue\n\n    # If there were no non-wildcard kinds declared, return raw value (matches original behavior for empty lists)\n    if not non_wildcard_seen:\n        return raw_value\n\n    if errors:\n        error_details = \"; \".join(\n            f\"{kind}: {error}\" for kind, error in errors\n        )\n        raise RuntimeError(\n            f\"Failed to deserialize output '{output_name}' from target \"\n            f\"workflow. Tried deserializers for kinds \"\n            f\"{[k for k, _ in errors]} but all failed: {error_details}. \"\n            f\"This likely means the target workflow's output format doesn't \"\n            f\"match the expected kind.\"\n        )\n    return raw_value",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/composition/workflow_caller/v1.py\nimport logging\nfrom functools import lru_cache\nfrom typing import Any, Callable, Dict, List, Optional, Tuple\n\nfrom inference.core.roboflow_api import get_roboflow_workspace\nfrom inference.core.workflows.execution_engine.entities.types import (\n    WILDCARD_KIND, Kind)\nfrom inference.core.workflows.prototypes.block import (BlockResult,\n                                                       WorkflowBlock)\n\nWORKFLOW_CALL_CHAIN_HEADER = \"X-Roboflow-Workflow-Call-Chain\"\nMAX_WORKFLOW_CALL_DEPTH = 10\n\n# Module-level cache mapping (workflow_id, version_id) -> {output_name: [Kind]}.\n# Populated during compile-time validation, read by get_actual_outputs() and run().\n_RESOLVED_WORKFLOW_OUTPUTS: Dict[Tuple[str, Optional[str]], Dict[str, List[Kind]]] = {}\n\n\nclass WorkflowCallerBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        api_key: Optional[str],\n        workflow_call_chain: Optional[str] = None,\n    ):\n        self._api_key = api_key\n        self._workspace_name: Optional[str] = None\n        self._workflow_call_chain = workflow_call_chain or \"\"\n\n    def run(\n        self,\n        workflow_id: str,\n        inputs: Dict[str, Any],\n        request_timeout: int,\n        input_definitions: Dict[str, List[str]],\n        output_definitions: Dict[str, List[str]],\n        workflow_version_id: Optional[str] = None,\n    ) -> BlockResult:\n        workspace_name = self._resolve_workspace_name()\n        if workspace_name is None:\n            raise RuntimeError(\n                f\"Could not resolve workspace for workflow '{workflow_id}'. \"\n                f\"Ensure a valid API key is configured.\"\n            )\n        error_status, message, raw_outputs = call_workflow(\n            api_key=self._api_key,\n            workspace_name=workspace_name,\n            workflow_id=workflow_id,\n            inputs=inputs,\n            request_timeout=request_timeout,\n            call_chain=self._workflow_call_chain,\n            workflow_version_id=workflow_version_id,\n        )\n        if error_status:\n            raise RuntimeError(\n                f\"Workflow '{workflow_id}' execution failed: {message}\"\n            )\n        result: Dict[str, Any] = {}\n        # Determine which outputs to extract and their kinds for deserialization\n        output_kinds_map = _resolve_output_kinds_for_run(\n            output_definitions=output_definitions,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n        )\n        if output_kinds_map is not None:\n            # Avoid building deserializers map if every declared output kind is a wildcard.\n            any_non_wildcard = False\n            for kinds in output_kinds_map.values():\n                for kind in kinds:\n                    if kind != WILDCARD_KIND:\n                        any_non_wildcard = True\n                        break\n                if any_non_wildcard:\n                    break\n\n            deserializers = _build_kinds_deserializers_map() if any_non_wildcard else None\n            raw_get = raw_outputs.get\n            for output_name, output_kinds in output_kinds_map.items():\n                raw_value = raw_get(output_name)\n                if deserializers is None:\n                    result[output_name] = raw_value\n                else:\n                    result[output_name] = _deserialize_output_value(\n                        output_name=output_name,\n                        raw_value=raw_value,\n                        output_kinds=output_kinds,\n                        deserializers=deserializers,\n                    )\n        else:\n            result[\"result\"] = raw_outputs\n        return result\n\n    def _resolve_workspace_name(self) -> Optional[str]:\n        if self._workspace_name is not None:\n            return self._workspace_name\n        if not self._api_key:\n            return None\n        try:\n            self._workspace_name = get_roboflow_workspace(api_key=self._api_key)\n            return self._workspace_name\n        except Exception as error:\n            logging.warning(\n                f\"Could not resolve workspace from API key. Error: {str(error)}\"\n            )\n            return None\n\n\ndef call_workflow(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    inputs: Dict[str, Any],\n    request_timeout: int,\n    call_chain: Optional[str] = None,\n    workflow_version_id: Optional[str] = None,\n) -> Tuple[bool, str, dict]:\n    \"\"\"Execute a workflow call and return (error_status, message, result).\n\n    This function is separated from the block's run() to facilitate testing.\n    \"\"\"\n    current_chain = call_chain or \"\"\n    chain_entries = [entry for entry in current_chain.split(\",\") if entry]\n    if workflow_id in chain_entries:\n        logging.warning(\n            f\"Circular workflow call detected: \"\n            f\"'{workflow_id}' is already in call chain [{current_chain}].\"\n        )\n        return (\n            True,\n            f\"Circular workflow call detected: '{workflow_id}' is already \"\n            f\"in the call chain [{current_chain}]. Aborting to prevent \"\n            f\"infinite recursion.\",\n            {},\n        )\n    if len(chain_entries) >= MAX_WORKFLOW_CALL_DEPTH:\n        logging.warning(\n            f\"Workflow call depth limit ({MAX_WORKFLOW_CALL_DEPTH}) reached. \"\n            f\"Call chain: [{current_chain}].\"\n        )\n        return (\n            True,\n            f\"Workflow call depth limit ({MAX_WORKFLOW_CALL_DEPTH}) reached. \"\n            f\"Call chain: [{current_chain}].\",\n            {},\n        )\n    updated_chain = \",\".join([*chain_entries, workflow_id])\n    inputs = build_workflow_inputs(inputs=inputs)\n    return execute_workflow_request(\n        api_key=api_key,\n        workspace_name=workspace_name,\n        workflow_id=workflow_id,\n        inputs=inputs,\n        request_timeout=request_timeout,\n        call_chain=updated_chain,\n        workflow_version_id=workflow_version_id,\n    )\n\n\n# ---------------------------------------------------------------------------\n# Output resolution for runtime\n# ---------------------------------------------------------------------------\n\n\ndef _resolve_output_kinds_for_run(\n    output_definitions: Dict[str, List[str]],\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[Dict[str, List[Kind]]]:\n    \"\"\"Determine which outputs to extract and their Kind objects.\n\n    Priority:\n    1. User-declared ``output_definitions`` (explicit kind names)\n    2. Auto-discovered outputs from ``_RESOLVED_WORKFLOW_OUTPUTS`` cache\n    3. Returns ``None`` \u2192 caller should fall back to generic ``result`` dict\n    \"\"\"\n    if output_definitions:\n        kind_name_map = _build_kind_name_map()\n        result: Dict[str, List[Kind]] = {}\n        for name, kind_names in output_definitions.items():\n            kinds = [\n                kind_name_map[k] for k in kind_names if k in kind_name_map\n            ]\n            result[name] = kinds or [WILDCARD_KIND]\n        return result\n    cache_key = _make_cache_key(workflow_id, workflow_version_id)\n    resolved = _RESOLVED_WORKFLOW_OUTPUTS.get(cache_key)\n    if resolved is not None:\n        return resolved\n    return None\n\n\n# ---------------------------------------------------------------------------\n# Output deserialization\n# ---------------------------------------------------------------------------\n\n\n@lru_cache(maxsize=1)\ndef _build_kinds_deserializers_map() -> Dict[str, Callable[[str, Any], Any]]:\n    \"\"\"Build the map of kind name -> deserializer function.\n\n    Result is cached since the set of registered deserializers does not\n    change within a process.\n    \"\"\"\n    from inference.core.workflows.execution_engine.introspection.blocks_loader import \\\n        load_kinds_deserializers\n\n    return load_kinds_deserializers()\n\n\ndef _deserialize_output_value(\n    output_name: str,\n    raw_value: Any,\n    output_kinds: List[Kind],\n    deserializers: Dict[str, Callable[[str, Any], Any]],\n) -> Any:\n    \"\"\"Deserialize a single output value using the deserializer matching its\n    resolved kind.\n\n    For outputs with known kinds, deserialization is required \u2014 failure raises\n    an error so downstream blocks don't receive unexpected raw data. For\n    WILDCARD_KIND outputs the raw value is returned as-is since we don't know\n    the expected type.\n    \"\"\"\n    if raw_value is None:\n        return None\n    errors: List[Tuple[str, Exception]] = []\n    non_wildcard_seen = False\n    for kind in output_kinds:\n        if kind == WILDCARD_KIND:\n            continue\n        non_wildcard_seen = True\n        des = deserializers.get(kind.name)\n        if des is None:\n            continue\n        try:\n            return des(output_name, raw_value)\n        except Exception as error:\n            errors.append((kind.name, error))\n            continue\n\n    # If there were no non-wildcard kinds declared, return raw value (matches original behavior for empty lists)\n    if not non_wildcard_seen:\n        return raw_value\n\n    if errors:\n        error_details = \"; \".join(\n            f\"{kind}: {error}\" for kind, error in errors\n        )\n        raise RuntimeError(\n            f\"Failed to deserialize output '{output_name}' from target \"\n            f\"workflow. Tried deserializers for kinds \"\n            f\"{[k for k, _ in errors]} but all failed: {error_details}. \"\n            f\"This likely means the target workflow's output format doesn't \"\n            f\"match the expected kind.\"\n        )\n    return raw_value\n```",
    "optimized_function_only": "    def run(\n        self,\n        workflow_id: str,\n        inputs: Dict[str, Any],\n        request_timeout: int,\n        input_definitions: Dict[str, List[str]],\n        output_definitions: Dict[str, List[str]],\n        workflow_version_id: Optional[str] = None,\n    ) -> BlockResult:\n        workspace_name = self._resolve_workspace_name()\n        if workspace_name is None:\n            raise RuntimeError(\n                f\"Could not resolve workspace for workflow '{workflow_id}'. \"\n                f\"Ensure a valid API key is configured.\"\n            )\n        error_status, message, raw_outputs = call_workflow(\n            api_key=self._api_key,\n            workspace_name=workspace_name,\n            workflow_id=workflow_id,\n            inputs=inputs,\n            request_timeout=request_timeout,\n            call_chain=self._workflow_call_chain,\n            workflow_version_id=workflow_version_id,\n        )\n        if error_status:\n            raise RuntimeError(\n                f\"Workflow '{workflow_id}' execution failed: {message}\"\n            )\n        result: Dict[str, Any] = {}\n        # Determine which outputs to extract and their kinds for deserialization\n        output_kinds_map = _resolve_output_kinds_for_run(\n            output_definitions=output_definitions,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n        )\n        if output_kinds_map is not None:\n            # Avoid building deserializers map if every declared output kind is a wildcard.\n            any_non_wildcard = False\n            for kinds in output_kinds_map.values():\n                for kind in kinds:\n                    if kind != WILDCARD_KIND:\n                        any_non_wildcard = True\n                        break\n                if any_non_wildcard:\n                    break\n\n            deserializers = _build_kinds_deserializers_map() if any_non_wildcard else None\n            raw_get = raw_outputs.get\n            for output_name, output_kinds in output_kinds_map.items():\n                raw_value = raw_get(output_name)\n                if deserializers is None:\n                    result[output_name] = raw_value\n                else:\n                    result[output_name] = _deserialize_output_value(\n                        output_name=output_name,\n                        raw_value=raw_value,\n                        output_kinds=output_kinds,\n                        deserializers=deserializers,\n                    )\n        else:\n            result[\"result\"] = raw_outputs\n        return result\n",
    "original_file_content": "import logging\nimport re\nfrom functools import lru_cache\nfrom typing import Any, Callable, Dict, List, Literal, Optional, Tuple, Type, Union\n\nimport requests\nfrom pydantic import ConfigDict, Field, field_validator\n\nfrom inference.core.env import LOCAL_INFERENCE_API_URL\nfrom inference.core.roboflow_api import get_roboflow_workspace, get_workflow_specification\nfrom inference.core.workflows.execution_engine.entities.base import (\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    DICTIONARY_KIND,\n    INTEGER_KIND,\n    STRING_KIND,\n    WILDCARD_KIND,\n    Kind,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nLONG_DESCRIPTION = \"\"\"\nThe **Workflow Caller** block enables calling another Roboflow workflow from within a workflow.\nThis is useful for composing complex pipelines from smaller, reusable workflow components.\n\n### How it works\n\nThe block takes a workflow ID (from the same workspace), passes inputs (including images)\nto the target workflow, executes it via HTTP, and returns the results.\n\n### Configuration\n\nSpecify the target workflow using `workflow_id` (just the workflow slug, not a full URL). The\nworkspace is resolved automatically from the API key used to run the parent workflow.\n\n```\nworkflow_id = \"my-detection-pipeline\"\n```\n\n### Inputs\n\nPass all inputs the target workflow expects via `inputs`, including images:\n\n```\ninputs = {\n    \"image\": \"$inputs.image\",\n    \"confidence_threshold\": 0.5,\n    \"model_id\": \"$inputs.model_id\",\n}\n```\n\nUse `input_definitions` to declare the expected input types so the UI can render\nproper connectors.\n\n### Circular Dependency Protection\n\nTo prevent infinite recursion (e.g. Workflow A calls B, B calls A), the block tracks the chain\nof workflow calls using a header. If a circular reference is detected, the block returns an error\ninstead of making the call.\n\n### Dynamic Outputs\n\nWhen the target workflow_id is a static string, the block resolves the target workflow's\noutputs at compile time. Each output from the target workflow becomes a separate output on\nthis block with proper Kind types. When the workflow_id is dynamic (a selector), outputs\nfall back to a single ``result`` dict.\n\n### Limitations\n\n* Only workflows within the same workspace are supported (v1).\n* Execution is done via HTTP call, which adds network latency.\n* Subject to the same timeout constraints as the hosting environment.\n\"\"\"\n\nWORKFLOW_CALL_CHAIN_HEADER = \"X-Roboflow-Workflow-Call-Chain\"\nMAX_WORKFLOW_CALL_DEPTH = 10\nWORKFLOW_CALLER_BLOCK_TYPE = \"roboflow_core/workflow_caller@v1\"\n\n# Module-level cache mapping (workflow_id, version_id) -> {output_name: [Kind]}.\n# Populated during compile-time validation, read by get_actual_outputs() and run().\n_RESOLVED_WORKFLOW_OUTPUTS: Dict[Tuple[str, Optional[str]], Dict[str, List[Kind]]] = {}\n\n# Module-level cache mapping (workflow_id, version_id) -> list of parsed input dicts\n# from spec.  Each dict has: name, type, kind, has_default.\n_RESOLVED_WORKFLOW_INPUTS: Dict[Tuple[str, Optional[str]], List[Dict[str, Any]]] = {}\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Workflow Caller\",\n            \"version\": \"v1\",\n            \"short_description\": \"Call another Roboflow workflow from within a workflow.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"transformation\",\n            \"ui_manifest\": {\n                \"section\": \"advanced\",\n                \"icon\": \"fal fa-diagram-subtask\",\n                \"blockPriority\": 2,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/workflow_caller@v1\"]\n    workflow_id: Union[Selector(kind=[STRING_KIND]), str] = Field(\n        description=\"The workflow ID to call (must be in the same workspace).\",\n        examples=[\"my-workflow-id\", \"$inputs.workflow_id\"],\n    )\n    workflow_version_id: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Optional version ID of the target workflow. When provided, \"\n        \"the block calls the specific version instead of the latest. \"\n        \"Use this to pin a dependency to a known-good version.\",\n        examples=[\"1709234567890\", \"$inputs.workflow_version\"],\n    )\n    inputs: Dict[\n        str,\n        Union[\n            Selector(),\n            str,\n            float,\n            bool,\n            int,\n            dict,\n            list,\n        ],\n    ] = Field(\n        default_factory=dict,\n        description=\"Inputs to pass to the target workflow, keyed by input name. \"\n        \"All inputs including images should be listed here.\",\n        examples=[\n            {\"image\": \"$inputs.image\", \"confidence_threshold\": 0.5},\n            {\"image\": \"$inputs.image\", \"model_id\": \"$inputs.model_id\"},\n        ],\n    )\n    request_timeout: Union[int, Selector(kind=[INTEGER_KIND])] = Field(\n        default=30,\n        description=\"HTTP request timeout in seconds.\",\n        examples=[\"$inputs.request_timeout\", 30],\n    )\n    input_definitions: Dict[str, List[str]] = Field(\n        default_factory=dict,\n        description=(\n            \"Mapping of expected input names to their kind types. \"\n            \"Each key is an input name in the target workflow, and the value \"\n            \"is a list of kind name strings (e.g. ['float'], ['roboflow_model_id']). \"\n            \"This tells the parent workflow what inputs the target expects, \"\n            \"enabling proper UI connectors. Actual values are provided via \"\n            \"'inputs'.\"\n        ),\n        examples=[\n            {\"image\": [\"image\"], \"confidence_threshold\": [\"float\"]},\n            {\"image\": [\"image\"], \"class_filter\": [\"string\"], \"iou_threshold\": [\"float\"]},\n        ],\n    )\n    output_definitions: Dict[str, List[str]] = Field(\n        default_factory=dict,\n        description=(\n            \"Mapping of expected output names to their kind types. \"\n            \"Each key is an output name from the target workflow, and the value \"\n            \"is a list of kind name strings (e.g. ['object_detection_prediction']). \"\n            \"This tells the parent workflow what types to expect, enabling proper \"\n            \"connections to downstream blocks like visualizers.\"\n        ),\n        examples=[\n            {\"predictions\": [\"object_detection_prediction\"]},\n            {\"result_image\": [\"image\"], \"count\": [\"integer\"]},\n        ],\n    )\n\n    @field_validator(\"workflow_id\")\n    @classmethod\n    def validate_workflow_id_slug(cls, value: Any) -> Any:\n        if isinstance(value, str) and not value.startswith(\"$\"):\n            if not re.fullmatch(r\"[\\w\\-]+\", value):\n                raise ValueError(\n                    f\"`workflow_id` must be a valid slug (letters, numbers, \"\n                    f\"hyphens, and underscores only). Got: '{value}'\"\n                )\n        return value\n\n    @field_validator(\"request_timeout\")\n    @classmethod\n    def ensure_request_timeout_is_positive(cls, value: Any) -> Any:\n        if isinstance(value, int) and value <= 0:\n            raise ValueError(\"`request_timeout` must be a positive integer.\")\n        return value\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return []\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"*\"),\n        ]\n\n    def get_actual_outputs(self) -> List[OutputDefinition]:\n        base: List[OutputDefinition] = []\n        # 1. User-defined output definitions take precedence\n        if self.output_definitions:\n            kind_name_map = _build_kind_name_map()\n            for name, kind_names in self.output_definitions.items():\n                kinds = [\n                    kind_name_map[k] for k in kind_names if k in kind_name_map\n                ]\n                base.append(\n                    OutputDefinition(name=name, kind=kinds or [WILDCARD_KIND])\n                )\n            return base\n        # 2. Fall back to auto-discovery from compile-time resolution\n        if isinstance(self.workflow_id, str) and not self.workflow_id.startswith(\"$\"):\n            version_id = self.workflow_version_id\n            if isinstance(version_id, str) and version_id.startswith(\"$\"):\n                version_id = None\n            cache_key = _make_cache_key(self.workflow_id, version_id)\n            resolved = _RESOLVED_WORKFLOW_OUTPUTS.get(cache_key)\n            if resolved is not None:\n                for name, kinds in resolved.items():\n                    base.append(OutputDefinition(name=name, kind=kinds))\n                return base\n        # 3. Fall back to generic result dict\n        base.append(OutputDefinition(name=\"result\", kind=[DICTIONARY_KIND]))\n        return base\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass WorkflowCallerBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        api_key: Optional[str],\n        workflow_call_chain: Optional[str] = None,\n    ):\n        self._api_key = api_key\n        self._workspace_name: Optional[str] = None\n        self._workflow_call_chain = workflow_call_chain or \"\"\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"api_key\", \"workflow_call_chain\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        workflow_id: str,\n        inputs: Dict[str, Any],\n        request_timeout: int,\n        input_definitions: Dict[str, List[str]],\n        output_definitions: Dict[str, List[str]],\n        workflow_version_id: Optional[str] = None,\n    ) -> BlockResult:\n        workspace_name = self._resolve_workspace_name()\n        if workspace_name is None:\n            raise RuntimeError(\n                f\"Could not resolve workspace for workflow '{workflow_id}'. \"\n                f\"Ensure a valid API key is configured.\"\n            )\n        error_status, message, raw_outputs = call_workflow(\n            api_key=self._api_key,\n            workspace_name=workspace_name,\n            workflow_id=workflow_id,\n            inputs=inputs,\n            request_timeout=request_timeout,\n            call_chain=self._workflow_call_chain,\n            workflow_version_id=workflow_version_id,\n        )\n        if error_status:\n            raise RuntimeError(\n                f\"Workflow '{workflow_id}' execution failed: {message}\"\n            )\n        result: Dict[str, Any] = {}\n        # Determine which outputs to extract and their kinds for deserialization\n        output_kinds_map = _resolve_output_kinds_for_run(\n            output_definitions=output_definitions,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n        )\n        if output_kinds_map is not None:\n            deserializers = _build_kinds_deserializers_map()\n            for output_name, output_kinds in output_kinds_map.items():\n                raw_value = raw_outputs.get(output_name)\n                result[output_name] = _deserialize_output_value(\n                    output_name=output_name,\n                    raw_value=raw_value,\n                    output_kinds=output_kinds,\n                    deserializers=deserializers,\n                )\n        else:\n            result[\"result\"] = raw_outputs\n        return result\n\n    def _resolve_workspace_name(self) -> Optional[str]:\n        if self._workspace_name is not None:\n            return self._workspace_name\n        if not self._api_key:\n            return None\n        try:\n            self._workspace_name = get_roboflow_workspace(api_key=self._api_key)\n            return self._workspace_name\n        except Exception as error:\n            logging.warning(\n                f\"Could not resolve workspace from API key. Error: {str(error)}\"\n            )\n            return None\n\n\ndef _make_cache_key(\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Tuple[str, Optional[str]]:\n    \"\"\"Build a cache key that accounts for both workflow_id and version_id.\"\"\"\n    return (workflow_id, workflow_version_id)\n\n\ndef call_workflow(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    inputs: Dict[str, Any],\n    request_timeout: int,\n    call_chain: Optional[str] = None,\n    workflow_version_id: Optional[str] = None,\n) -> Tuple[bool, str, dict]:\n    \"\"\"Execute a workflow call and return (error_status, message, result).\n\n    This function is separated from the block's run() to facilitate testing.\n    \"\"\"\n    current_chain = call_chain or \"\"\n    chain_entries = [entry for entry in current_chain.split(\",\") if entry]\n    if workflow_id in chain_entries:\n        logging.warning(\n            f\"Circular workflow call detected: \"\n            f\"'{workflow_id}' is already in call chain [{current_chain}].\"\n        )\n        return (\n            True,\n            f\"Circular workflow call detected: '{workflow_id}' is already \"\n            f\"in the call chain [{current_chain}]. Aborting to prevent \"\n            f\"infinite recursion.\",\n            {},\n        )\n    if len(chain_entries) >= MAX_WORKFLOW_CALL_DEPTH:\n        logging.warning(\n            f\"Workflow call depth limit ({MAX_WORKFLOW_CALL_DEPTH}) reached. \"\n            f\"Call chain: [{current_chain}].\"\n        )\n        return (\n            True,\n            f\"Workflow call depth limit ({MAX_WORKFLOW_CALL_DEPTH}) reached. \"\n            f\"Call chain: [{current_chain}].\",\n            {},\n        )\n    updated_chain = \",\".join([*chain_entries, workflow_id])\n    inputs = build_workflow_inputs(inputs=inputs)\n    return execute_workflow_request(\n        api_key=api_key,\n        workspace_name=workspace_name,\n        workflow_id=workflow_id,\n        inputs=inputs,\n        request_timeout=request_timeout,\n        call_chain=updated_chain,\n        workflow_version_id=workflow_version_id,\n    )\n\n\ndef build_workflow_inputs(\n    inputs: Dict[str, Any],\n) -> Dict[str, Any]:\n    \"\"\"Build the inputs dictionary for the target workflow.\n\n    Handles ``WorkflowImageData`` objects found in ``inputs`` by\n    automatically serialising them to the ``{type: base64, value: ...}``\n    format expected by the workflow HTTP API.\n    \"\"\"\n    resolved: Dict[str, Any] = {}\n    for key, value in inputs.items():\n        if isinstance(value, WorkflowImageData):\n            resolved[key] = {\n                \"type\": \"base64\",\n                \"value\": value.base64_image,\n            }\n        else:\n            resolved[key] = value\n    return resolved\n\n\ndef execute_workflow_request(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    inputs: Dict[str, Any],\n    request_timeout: int,\n    call_chain: str,\n    workflow_version_id: Optional[str] = None,\n) -> Tuple[bool, str, dict]:\n    \"\"\"Make the HTTP request to the target workflow and return\n    (error_status, message, result).\"\"\"\n    url = build_workflow_url(\n        workspace_name=workspace_name,\n        workflow_id=workflow_id,\n    )\n    payload: Dict[str, Any] = {\"inputs\": inputs}\n    if api_key is not None:\n        payload[\"api_key\"] = api_key\n    if workflow_version_id is not None:\n        payload[\"workflow_version_id\"] = workflow_version_id\n    headers = {WORKFLOW_CALL_CHAIN_HEADER: call_chain}\n    try:\n        response = requests.post(\n            url,\n            json=payload,\n            headers=headers,\n            timeout=request_timeout,\n        )\n        response.raise_for_status()\n        response_data = response.json()\n        outputs = response_data.get(\"outputs\", [])\n        result = outputs[0] if outputs else {}\n        return (\n            False,\n            \"Workflow executed successfully\",\n            result,\n        )\n    except Exception as error:\n        logging.warning(\n            f\"Could not execute workflow '{workflow_id}'. Error: {str(error)}\"\n        )\n        error_type = type(error).__name__\n        return (\n            True,\n            f\"Failed to execute workflow '{workflow_id}': {error_type}\",\n            {},\n        )\n\n\ndef build_workflow_url(workspace_name: str, workflow_id: str) -> str:\n    \"\"\"Build the URL for calling a workflow on the local inference server.\n\n    Uses LOCAL_INFERENCE_API_URL to call the workflow on the same inference\n    server instance that is running the parent workflow.\n    \"\"\"\n    base_url = LOCAL_INFERENCE_API_URL.rstrip(\"/\")\n    return f\"{base_url}/{workspace_name}/workflows/{workflow_id}\"\n\n\n# ---------------------------------------------------------------------------\n# Compile-time validation\n# ---------------------------------------------------------------------------\n\n\ndef validate_workflow_caller_no_circular_references(\n    steps: List[WorkflowBlockManifest],\n    api_key: Optional[str],\n) -> None:\n    \"\"\"Compile-time validation: check that workflow_caller blocks with static\n    workflow_id values don't create circular dependencies, resolve the target\n    workflow's input and output interfaces, and validate that required inputs\n    are provided.\n\n    Only validates when workflow_id is a literal string (not a selector like\n    ``$inputs.workflow_id``). Errors during spec fetching are logged as warnings\n    and do not block compilation \u2014 the runtime circular dependency check via\n    the call chain header provides an additional safety net.\n    \"\"\"\n    caller_steps = _extract_workflow_caller_steps(steps=steps)\n    if not caller_steps:\n        return\n    workspace_name = _resolve_workspace_for_validation(api_key=api_key)\n    if workspace_name is None:\n        return\n    for workflow_id, version_id, step_manifest in caller_steps:\n        spec = _fetch_workflow_spec_for_validation(\n            api_key=api_key,\n            workspace_name=workspace_name,\n            workflow_id=workflow_id,\n            workflow_version_id=version_id,\n        )\n        if spec is None:\n            continue\n        _check_workflow_for_circular_references(\n            api_key=api_key,\n            workspace_name=workspace_name,\n            target_workflow_id=workflow_id,\n            target_workflow_version_id=version_id,\n            visited=set(),\n            prefetched_spec=spec,\n        )\n        cache_key = _make_cache_key(workflow_id, version_id)\n        _resolve_and_cache_workflow_outputs(\n            cache_key=cache_key,\n            spec=spec,\n        )\n        _resolve_and_cache_workflow_inputs(\n            cache_key=cache_key,\n            spec=spec,\n        )\n        _validate_required_inputs(\n            workflow_id=workflow_id,\n            workflow_version_id=version_id,\n            step_manifest=step_manifest,\n        )\n\n\ndef _extract_workflow_caller_steps(\n    steps: List[WorkflowBlockManifest],\n) -> List[Tuple[str, Optional[str], WorkflowBlockManifest]]:\n    \"\"\"Extract (workflow_id, workflow_version_id, manifest) tuples from\n    workflow_caller steps that have literal (non-selector) workflow_id values.\"\"\"\n    result = []\n    for step in steps:\n        if not isinstance(step, BlockManifest):\n            continue\n        workflow_id = step.workflow_id\n        if isinstance(workflow_id, str) and not workflow_id.startswith(\"$\"):\n            version_id = step.workflow_version_id\n            # Only use version_id if it's a literal string (not a selector)\n            if isinstance(version_id, str) and version_id.startswith(\"$\"):\n                version_id = None\n            result.append((workflow_id, version_id, step))\n    return result\n\n\ndef _fetch_workflow_spec_for_validation(\n    api_key: Optional[str],\n    workspace_name: str,\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[dict]:\n    \"\"\"Fetch a workflow spec, returning None on any error.\"\"\"\n    try:\n        return get_workflow_specification(\n            api_key=api_key,\n            workspace_id=workspace_name,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n        )\n    except Exception as error:\n        logging.debug(\n            \"Could not fetch workflow '%s' for compile-time validation (error type: %s)\",\n            workflow_id,\n            type(error).__name__,\n        )\n        return None\n\n\ndef _resolve_workspace_for_validation(\n    api_key: Optional[str],\n) -> Optional[str]:\n    if not api_key:\n        return None\n    try:\n        return get_roboflow_workspace(api_key=api_key)\n    except Exception as error:\n        logging.debug(\n            \"Could not resolve workspace for compile-time workflow validation (error type: %s)\",\n            type(error).__name__,\n        )\n        return None\n\n\ndef _check_workflow_for_circular_references(\n    api_key: Optional[str],\n    workspace_name: str,\n    target_workflow_id: str,\n    visited: set,\n    target_workflow_version_id: Optional[str] = None,\n    prefetched_spec: Optional[dict] = None,\n) -> None:\n    \"\"\"Recursively check if a target workflow creates a circular call chain.\n\n    Raises ``ExecutionGraphStructureError`` if a cycle is found. Silently\n    returns on any fetch error \u2014 the runtime check will catch those cases.\n\n    When ``prefetched_spec`` is provided it is used directly instead of\n    fetching the spec again.  The caller in\n    ``validate_workflow_caller_no_circular_references`` already fetches the\n    spec for the top-level workflow, so passing it here avoids a duplicate\n    API call.\n    \"\"\"\n    from inference.core.workflows.errors import ExecutionGraphStructureError\n\n    if target_workflow_id in visited:\n        chain = \" -> \".join([*visited, target_workflow_id])\n        raise ExecutionGraphStructureError(\n            public_message=(\n                f\"Circular workflow call detected at compile time: {chain}. \"\n                f\"This would cause infinite recursion at runtime.\"\n            ),\n            context=\"workflow_compilation | workflow_caller_validation\",\n        )\n    if prefetched_spec is not None:\n        spec = prefetched_spec\n    else:\n        try:\n            spec = get_workflow_specification(\n                api_key=api_key,\n                workspace_id=workspace_name,\n                workflow_id=target_workflow_id,\n                workflow_version_id=target_workflow_version_id,\n            )\n        except Exception as error:\n            logging.debug(\n                \"Could not fetch workflow '%s' for circular dependency check (error type: %s)\",\n                target_workflow_id,\n                type(error).__name__,\n            )\n            return\n    nested_workflows = _extract_workflow_caller_ids_from_spec(spec=spec)\n    if not nested_workflows:\n        return\n    visited_with_current = visited | {target_workflow_id}\n    for nested_id, nested_version_id in nested_workflows:\n        _check_workflow_for_circular_references(\n            api_key=api_key,\n            workspace_name=workspace_name,\n            target_workflow_id=nested_id,\n            target_workflow_version_id=nested_version_id,\n            visited=visited_with_current,\n        )\n\n\ndef _extract_workflow_caller_ids_from_spec(\n    spec: dict,\n) -> List[Tuple[str, Optional[str]]]:\n    \"\"\"Extract static (workflow_id, workflow_version_id) tuples from a raw\n    workflow specification.  Only includes entries where ``workflow_id`` is a\n    literal string (not a selector).  ``workflow_version_id`` is included when\n    it is a literal string, otherwise ``None``.\"\"\"\n    steps = spec.get(\"steps\", [])\n    result: List[Tuple[str, Optional[str]]] = []\n    for step in steps:\n        step_type = step.get(\"type\", \"\")\n        if step_type != WORKFLOW_CALLER_BLOCK_TYPE:\n            continue\n        workflow_id = step.get(\"workflow_id\", \"\")\n        if not isinstance(workflow_id, str) or workflow_id.startswith(\"$\"):\n            continue\n        version_id = step.get(\"workflow_version_id\")\n        if isinstance(version_id, str) and version_id.startswith(\"$\"):\n            version_id = None\n        result.append((workflow_id, version_id))\n    return result\n\n\n# ---------------------------------------------------------------------------\n# Output interface resolution\n# ---------------------------------------------------------------------------\n\n\ndef _resolve_and_cache_workflow_outputs(\n    cache_key: Tuple[str, Optional[str]],\n    spec: dict,\n) -> None:\n    \"\"\"Resolve the target workflow's output interface from its spec and cache\n    the result in ``_RESOLVED_WORKFLOW_OUTPUTS``.\n\n    Tries ``describe_workflow_outputs()`` for proper Kind resolution. Falls\n    back to extracting output names with ``WILDCARD_KIND`` on any error.\n    \"\"\"\n    try:\n        outputs_description = _describe_outputs_from_spec(spec=spec)\n    except Exception as error:\n        logging.debug(\n            f\"Could not resolve output kinds for workflow '{cache_key}' \"\n            f\"via describe_workflow_outputs: {error}. \"\n            f\"Falling back to output names with WILDCARD_KIND.\"\n        )\n        outputs_description = None\n\n    if outputs_description is not None:\n        resolved = _convert_output_descriptions_to_kinds(\n            outputs_description=outputs_description,\n        )\n    else:\n        resolved = _extract_output_names_with_wildcard(spec=spec)\n\n    if resolved:\n        _RESOLVED_WORKFLOW_OUTPUTS[cache_key] = resolved\n\n\ndef _describe_outputs_from_spec(\n    spec: dict,\n) -> Dict[str, Union[List[str], Dict[str, List[str]]]]:\n    \"\"\"Call the standard output discovery to resolve output kinds.\"\"\"\n    from inference.core.workflows.execution_engine.v1.introspection.outputs_discovery import (\n        describe_workflow_outputs,\n    )\n\n    return describe_workflow_outputs(definition=spec)\n\n\ndef _convert_output_descriptions_to_kinds(\n    outputs_description: Dict[str, Union[List[str], Dict[str, List[str]]]],\n) -> Dict[str, List[Kind]]:\n    \"\"\"Convert ``describe_workflow_outputs()`` result (kind name strings) to\n    ``Kind`` objects.\"\"\"\n    kind_name_map = _build_kind_name_map()\n    result: Dict[str, List[Kind]] = {}\n    for name, kind_info in outputs_description.items():\n        if isinstance(kind_info, dict):\n            # Wildcard selector ($steps.step.*) \u2014 nested structure.\n            # Represent as DICTIONARY_KIND since we can't express nested\n            # typed properties in a single OutputDefinition.\n            result[name] = [DICTIONARY_KIND]\n        else:\n            kinds = [\n                kind_name_map[k]\n                for k in kind_info\n                if k in kind_name_map\n            ]\n            result[name] = kinds if kinds else [WILDCARD_KIND]\n    return result\n\n\ndef _extract_output_names_with_wildcard(\n    spec: dict,\n) -> Dict[str, List[Kind]]:\n    \"\"\"Fallback: extract just the output names and assign WILDCARD_KIND.\"\"\"\n    outputs = spec.get(\"outputs\", [])\n    result: Dict[str, List[Kind]] = {}\n    for output in outputs:\n        name = output.get(\"name\")\n        if name:\n            result[name] = [WILDCARD_KIND]\n    return result\n\n\n@lru_cache(maxsize=1)\ndef _build_kind_name_map() -> Dict[str, Kind]:\n    \"\"\"Build a mapping from kind name to Kind object using the loader.\n\n    Result is cached since the set of registered kinds does not change\n    within a process.\n    \"\"\"\n    from inference.core.workflows.core_steps.loader import load_kinds\n\n    return {kind.name: kind for kind in load_kinds()}\n\n\n# ---------------------------------------------------------------------------\n# Input interface resolution\n# ---------------------------------------------------------------------------\n\n\ndef _resolve_and_cache_workflow_inputs(\n    cache_key: Tuple[str, Optional[str]],\n    spec: dict,\n) -> None:\n    \"\"\"Parse the target workflow's input interface from its spec and cache\n    the result in ``_RESOLVED_WORKFLOW_INPUTS``.\n\n    Each input is stored as a dict with keys: name, type, has_default.\n    \"\"\"\n    raw_inputs = spec.get(\"inputs\", [])\n    parsed: List[Dict[str, Any]] = []\n    for inp in raw_inputs:\n        name = inp.get(\"name\")\n        if not name:\n            continue\n        inp_type = inp.get(\"type\", \"\")\n        parsed.append({\n            \"name\": name,\n            \"type\": inp_type,\n            \"has_default\": \"default_value\" in inp,\n        })\n    _RESOLVED_WORKFLOW_INPUTS[cache_key] = parsed\n\n\ndef _validate_required_inputs(\n    workflow_id: str,\n    step_manifest: BlockManifest,\n    workflow_version_id: Optional[str] = None,\n) -> None:\n    \"\"\"Validate that the workflow caller step provides all required inputs\n    that the target workflow expects.\n\n    Raises ``ExecutionGraphStructureError`` if:\n    - The target workflow has required parameters (no default) not covered by\n      ``inputs``.\n    - The user declared ``input_definitions`` but ``inputs`` does not\n      cover all declared input names.\n    \"\"\"\n    from inference.core.workflows.errors import ExecutionGraphStructureError\n\n    input_keys = set(step_manifest.inputs.keys())\n\n    # Validate user-declared input_definitions: every declared input must be\n    # present in inputs.\n    if step_manifest.input_definitions:\n        missing_declared = [\n            name for name in step_manifest.input_definitions\n            if name not in input_keys\n        ]\n        if missing_declared:\n            raise ExecutionGraphStructureError(\n                public_message=(\n                    f\"Workflow caller step '{step_manifest.name}' declares \"\n                    f\"input_definitions for {list(step_manifest.input_definitions.keys())}, \"\n                    f\"but input(s) {missing_declared} are not provided in \"\n                    f\"'inputs'.\"\n                ),\n                context=\"workflow_compilation | workflow_caller_validation\",\n            )\n\n    cache_key = _make_cache_key(workflow_id, workflow_version_id)\n    resolved_inputs = _RESOLVED_WORKFLOW_INPUTS.get(cache_key)\n    if resolved_inputs is None:\n        return\n\n    missing = []\n    for inp in resolved_inputs:\n        if inp[\"has_default\"]:\n            continue\n        if inp[\"name\"] not in input_keys:\n            missing.append(inp[\"name\"])\n    if missing:\n        raise ExecutionGraphStructureError(\n            public_message=(\n                f\"Target workflow '{workflow_id}' requires input(s) \"\n                f\"{missing} (no default values), but they are not provided \"\n                f\"in 'inputs' on workflow_caller step \"\n                f\"'{step_manifest.name}'.\"\n            ),\n            context=\"workflow_compilation | workflow_caller_validation\",\n        )\n\n\n# ---------------------------------------------------------------------------\n# Output resolution for runtime\n# ---------------------------------------------------------------------------\n\n\ndef _resolve_output_kinds_for_run(\n    output_definitions: Dict[str, List[str]],\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[Dict[str, List[Kind]]]:\n    \"\"\"Determine which outputs to extract and their Kind objects.\n\n    Priority:\n    1. User-declared ``output_definitions`` (explicit kind names)\n    2. Auto-discovered outputs from ``_RESOLVED_WORKFLOW_OUTPUTS`` cache\n    3. Returns ``None`` \u2192 caller should fall back to generic ``result`` dict\n    \"\"\"\n    if output_definitions:\n        kind_name_map = _build_kind_name_map()\n        result: Dict[str, List[Kind]] = {}\n        for name, kind_names in output_definitions.items():\n            kinds = [\n                kind_name_map[k] for k in kind_names if k in kind_name_map\n            ]\n            result[name] = kinds or [WILDCARD_KIND]\n        return result\n    cache_key = _make_cache_key(workflow_id, workflow_version_id)\n    resolved = _RESOLVED_WORKFLOW_OUTPUTS.get(cache_key)\n    if resolved is not None:\n        return resolved\n    return None\n\n\n# ---------------------------------------------------------------------------\n# Output deserialization\n# ---------------------------------------------------------------------------\n\n\n@lru_cache(maxsize=1)\ndef _build_kinds_deserializers_map() -> Dict[str, Callable[[str, Any], Any]]:\n    \"\"\"Build the map of kind name -> deserializer function.\n\n    Result is cached since the set of registered deserializers does not\n    change within a process.\n    \"\"\"\n    from inference.core.workflows.execution_engine.introspection.blocks_loader import (\n        load_kinds_deserializers,\n    )\n\n    return load_kinds_deserializers()\n\n\ndef _deserialize_output_value(\n    output_name: str,\n    raw_value: Any,\n    output_kinds: List[Kind],\n    deserializers: Dict[str, Callable[[str, Any], Any]],\n) -> Any:\n    \"\"\"Deserialize a single output value using the deserializer matching its\n    resolved kind.\n\n    For outputs with known kinds, deserialization is required \u2014 failure raises\n    an error so downstream blocks don't receive unexpected raw data. For\n    WILDCARD_KIND outputs the raw value is returned as-is since we don't know\n    the expected type.\n    \"\"\"\n    if raw_value is None:\n        return None\n    if all(kind == WILDCARD_KIND for kind in output_kinds):\n        return raw_value\n    errors: List[Tuple[str, Exception]] = []\n    for kind in output_kinds:\n        if kind == WILDCARD_KIND:\n            continue\n        if kind.name not in deserializers:\n            continue\n        try:\n            return deserializers[kind.name](output_name, raw_value)\n        except Exception as error:\n            errors.append((kind.name, error))\n            continue\n    if errors:\n        error_details = \"; \".join(\n            f\"{kind}: {error}\" for kind, error in errors\n        )\n        raise RuntimeError(\n            f\"Failed to deserialize output '{output_name}' from target \"\n            f\"workflow. Tried deserializers for kinds \"\n            f\"{[k for k, _ in errors]} but all failed: {error_details}. \"\n            f\"This likely means the target workflow's output format doesn't \"\n            f\"match the expected kind.\"\n        )\n    return raw_value\n",
    "patch": null
  },
  {
    "trace_id": "787c6104-2099-4fcc-8ede-cbe79283478b",
    "function_name": "InferencePipeline.init_with_workflow",
    "file_path": "inference/core/interfaces/stream/inference_pipeline.py",
    "speedup_x": 0.10083993313419748,
    "review_quality": "high",
    "pre_optimization_commit": "6f0d879cb9af0cdbd55e1fd2c2a461016dae21f8",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def init_with_workflow(\n        cls,\n        video_reference: Union[str, int, List[Union[str, int]]],\n        workflow_specification: Optional[dict] = None,\n        workspace_name: Optional[str] = None,\n        workflow_id: Optional[str] = None,\n        api_key: Optional[str] = None,\n        image_input_name: str = \"image\",\n        workflows_parameters: Optional[Dict[str, Any]] = None,\n        on_prediction: SinkHandler = None,\n        max_fps: Optional[Union[float, int]] = None,\n        watchdog: Optional[PipelineWatchDog] = None,\n        status_update_handlers: Optional[List[Callable[[StatusUpdate], None]]] = None,\n        source_buffer_filling_strategy: Optional[BufferFillingStrategy] = None,\n        source_buffer_consumption_strategy: Optional[BufferConsumptionStrategy] = None,\n        video_source_properties: Optional[Dict[str, float]] = None,\n        workflow_init_parameters: Optional[Dict[str, Any]] = None,\n        workflows_thread_pool_workers: int = 4,\n        cancel_thread_pool_tasks_on_exit: bool = True,\n        video_metadata_input_name: str = \"video_metadata\",\n        batch_collection_timeout: Optional[float] = None,\n        profiling_directory: str = \"./inference_profiling\",\n        use_workflow_definition_cache: bool = True,\n        serialize_results: bool = False,\n        predictions_queue_size: int = PREDICTIONS_QUEUE_SIZE,\n        decoding_buffer_size: int = DEFAULT_BUFFER_SIZE,\n        model_manager: Optional[ModelManager] = None,\n        _is_preview: bool = False,\n        workflow_version_id: Optional[str] = None,\n    ) -> \"InferencePipeline\":\n        \"\"\"\n        This class creates the abstraction for making inferences from given workflow against video stream.\n        The way of how `InferencePipeline` works is displayed in `InferencePipeline.init(...)` initializer\n        method.\n\n        Args:\n            video_reference (Union[str, int, List[Union[str, int]]]): Reference of source to be used to make predictions\n                against. It can be video file path, stream URL and device (like camera) id\n                (we handle whatever cv2 handles). It can also be a list of references (since v0.13.0) - and then\n                it will trigger parallel processing of multiple sources. It has some implication on sinks. See:\n                `sink_mode` parameter comments.\n            workflow_specification (Optional[dict]): Valid specification of workflow. See [workflow docs](https://github.com/roboflow/inference/tree/main/inference/enterprise/workflows).\n                It can be provided optionally, but if not given, both `workspace_name` and `workflow_id`\n                must be provided.\n            workspace_name (Optional[str]): When using registered workflows - Roboflow workspace name needs to be given.\n            workflow_id (Optional[str]): When using registered workflows - Roboflow workflow id needs to be given.\n            api_key (Optional[str]): Roboflow API key - if not passed - will be looked in env under \"ROBOFLOW_API_KEY\"\n                and \"API_KEY\" variables. API key, passed in some form is required.\n            image_input_name (str): Name of input image defined in `workflow_specification` or Workflow definition saved\n                on the Roboflow Platform. `InferencePipeline` will be injecting video frames to workflow through that\n                parameter name.\n            workflows_parameters (Optional[Dict[str, Any]]): Dictionary with additional parameters that can be\n                defined within `workflow_specification`.\n            on_prediction (Callable[AnyPrediction, VideoFrame], None]): Function to be called\n                once prediction is ready - passing both decoded frame, their metadata and dict with workflow output.\n            max_fps (Optional[Union[float, int]]): Specific value passed as this parameter will be used to\n                dictate max FPS of each video source.\n                The implementation details of this option has been changed in release `v0.26.0`. Prior to the release\n                this value, when applied to video files caused the processing to wait `1 / max_fps` seconds before next\n                frame is processed - the new implementation drops the intermediate frames, which seems to be more\n                aligned with peoples expectations.\n                New behaviour is now enabled in experimental mode, by setting environmental variable flag\n                `ENABLE_FRAME_DROP_ON_VIDEO_FILE_RATE_LIMITING=True`. Please note that the new behaviour will\n                be the default one end of Q4 2024!\n            watchdog (Optional[PipelineWatchDog]): Implementation of class that allows profiling of\n                inference pipeline - if not given null implementation (doing nothing) will be used.\n            status_update_handlers (Optional[List[Callable[[StatusUpdate], None]]]): List of handlers to intercept\n                status updates of all elements of the pipeline. Should be used only if detailed inspection of\n                pipeline behaviour in time is needed. Please point out that handlers should be possible to be executed\n                fast - otherwise they will impair pipeline performance. All errors will be logged as warnings\n                without re-raising. Default: None.\n            source_buffer_filling_strategy (Optional[BufferFillingStrategy]): Parameter dictating strategy for\n                video stream decoding behaviour. By default - tweaked to the type of source given.\n                Please find detailed explanation in docs of [`VideoSource`](/reference/inference/core/interfaces/camera/video_source/#inference.core.interfaces.camera.video_source.VideoSource)\n            source_buffer_consumption_strategy (Optional[BufferConsumptionStrategy]): Parameter dictating strategy for\n                video stream frames consumption. By default - tweaked to the type of source given.\n                Please find detailed explanation in docs of [`VideoSource`](/reference/inference/core/interfaces/camera/video_source/#inference.core.interfaces.camera.video_source.VideoSource)\n            video_source_properties (Optional[dict[str, float]]): Optional source properties to set up the video source,\n                corresponding to cv2 VideoCapture properties cv2.CAP_PROP_*. If not given, defaults for the video source\n                will be used.\n                Example valid properties are: {\"frame_width\": 1920, \"frame_height\": 1080, \"fps\": 30.0}\n            workflow_init_parameters (Optional[Dict[str, Any]]): Additional init parameters to be used by\n                workflows Execution Engine to init steps of your workflow - may be required when running workflows\n                with custom plugins.\n            workflows_thread_pool_workers (int): Number of workers for workflows thread pool which is used\n                by workflows blocks to run background tasks.\n            cancel_thread_pool_tasks_on_exit (bool): Flag to decide if unstated background tasks should be\n                canceled at the end of InferencePipeline processing. By default, when video file ends or\n                pipeline is stopped, tasks that has not started will be cancelled.\n            video_metadata_input_name (str): Name of input for video metadata defined in `workflow_specification` or\n                Workflow definition saved  on the Roboflow Platform. `InferencePipeline` will be injecting video frames\n                metadata to workflows through that parameter name.\n            batch_collection_timeout (Optional[float]): Parameter of multiplex_videos(...) dictating how long process\n                to grab frames from multiple sources can wait for batch to be filled before yielding already collected\n                frames. Please set this value in PRODUCTION to avoid performance drops when specific sources shows\n                unstable latency. Visit `multiplex_videos(...)` for more information about multiplexing process.\n            profiling_directory (str): Directory where workflows profiler traces will be dumped. To enable profiling\n                export `ENABLE_WORKFLOWS_PROFILING=True` environmental variable. You may specify number of workflow\n                runs in a buffer with environmental variable `WORKFLOWS_PROFILER_BUFFER_SIZE=n` - making last `n`\n                frames to be present in buffer on processing end.\n            use_workflow_definition_cache (bool): Controls usage of cache for workflow definitions. Set this to False\n                when you frequently modify definition saved in Roboflow app and want to fetch the\n                newest version for the request. Only applies for Workflows definitions saved on Roboflow platform.\n            serialize_results (bool): Boolean flag to decide if ExecutionEngine run should serialize workflow\n                results for each frame. If that is set true, sinks will receive serialized workflow responses.\n            predictions_queue_size int: Size of buffer for predictions that are ready for dispatching\n                default value is taken from INFERENCE_PIPELINE_PREDICTIONS_QUEUE_SIZE env variable\n            decoding_buffer_size (int): size of video source decoding buffer\n                default value is taken from VIDEO_SOURCE_BUFFER_SIZE env variable\n            model_manager (Optional[ModelManager]): Model manager to be used by InferencePipeline, defaults to\n                BackgroundTaskActiveLearningManager with WithFixedSizeCache\n\n        Other ENV variables involved in low-level configuration:\n        * INFERENCE_PIPELINE_PREDICTIONS_QUEUE_SIZE - size of buffer for predictions that are ready for dispatching\n        * INFERENCE_PIPELINE_RESTART_ATTEMPT_DELAY - delay for restarts on stream connection drop\n\n        Returns: Instance of InferencePipeline\n\n        Throws:\n            * SourceConnectionError if source cannot be connected at start, however it attempts to reconnect\n                always if connection to stream is lost.\n            * ValueError if workflow specification not provided and registered workflow not pointed out\n            * NotImplementedError if workflow used against multiple videos which is not supported yet\n            * MissingApiKeyError - if API key is not provided in situation when retrieving workflow definition\n                from Roboflow API is needed\n        \"\"\"\n        if ENABLE_WORKFLOWS_PROFILING:\n            profiler = BaseWorkflowsProfiler.init(\n                max_runs_in_buffer=WORKFLOWS_PROFILER_BUFFER_SIZE\n            )\n        else:\n            profiler = NullWorkflowsProfiler.init()\n        if api_key is None:\n            api_key = API_KEY\n        named_workflow_specified = (workspace_name is not None) and (\n            workflow_id is not None\n        )\n        if not named_workflow_specified and not workflow_specification:\n            raise ValueError(\n                \"Either (`workspace_name`, `workflow_id`) or `workflow_specification` must be provided.\"\n            )\n        try:\n            from inference.core.interfaces.stream.model_handlers.workflows import (\n                WorkflowRunner,\n            )\n            from inference.core.roboflow_api import get_workflow_specification\n            from inference.core.workflows.execution_engine.core import ExecutionEngine\n\n            if workflow_specification is None:\n                if api_key is None:\n                    raise MissingApiKeyError(\n                        \"Roboflow API key needs to be provided either as parameter or via env variable \"\n                        \"ROBOFLOW_API_KEY. If you do not know how to get API key - visit \"\n                        \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to \"\n                        \"retrieve one.\"\n                    )\n                with profiler.profile_execution_phase(\n                    name=\"workflow_definition_fetching\",\n                    categories=[\"inference_package_operation\"],\n                ):\n                    workflow_specification = get_workflow_specification(\n                        api_key=api_key,\n                        workspace_id=workspace_name,\n                        workflow_id=workflow_id,\n                        workflow_version_id=workflow_version_id,\n                        use_cache=use_workflow_definition_cache,\n                    )\n            model_registry = RoboflowModelRegistry(ROBOFLOW_MODEL_TYPES)\n            if model_manager is None:\n                model_manager = BackgroundTaskActiveLearningManager(\n                    model_registry=model_registry, cache=cache\n                )\n                model_manager = WithFixedSizeCache(\n                    model_manager,\n                    max_size=MAX_ACTIVE_MODELS,\n                )\n            if workflow_init_parameters is None:\n                workflow_init_parameters = {}\n            thread_pool_executor = ThreadPoolExecutor(\n                max_workers=workflows_thread_pool_workers\n            )\n            workflow_init_parameters[\"workflows_core.model_manager\"] = model_manager\n            workflow_init_parameters[\"workflows_core.api_key\"] = api_key\n            workflow_init_parameters[\"workflows_core.thread_pool_executor\"] = (\n                thread_pool_executor\n            )\n            workflow_init_parameters.setdefault(\n                \"workflows_core.workflow_call_chain\", None\n            )\n            execution_engine = ExecutionEngine.init(\n                workflow_definition=workflow_specification,\n                init_parameters=workflow_init_parameters,\n                workflow_id=workflow_id,\n                profiler=profiler,\n            )\n            workflow_runner = WorkflowRunner()\n            on_video_frame = partial(\n                workflow_runner.run_workflow,\n                workflows_parameters=workflows_parameters,\n                execution_engine=execution_engine,\n                image_input_name=image_input_name,\n                video_metadata_input_name=video_metadata_input_name,\n                serialize_results=serialize_results,\n                _is_preview=_is_preview,\n            )\n        except ImportError as error:\n            raise CannotInitialiseModelError(\n                f\"Could not initialise workflow processing due to lack of dependencies required. \"\n                f\"Please provide an issue report under https://github.com/roboflow/inference/issues\"\n            ) from error\n        on_pipeline_end_closure = partial(\n            on_pipeline_end,\n            thread_pool_executor=thread_pool_executor,\n            cancel_thread_pool_tasks_on_exit=cancel_thread_pool_tasks_on_exit,\n            profiler=profiler,\n            profiling_directory=profiling_directory,\n        )\n        return cls.init_with_custom_logic(\n            video_reference=video_reference,\n            on_video_frame=on_video_frame,\n            on_prediction=on_prediction,\n            on_pipeline_start=None,\n            on_pipeline_end=on_pipeline_end_closure,\n            max_fps=max_fps,\n            watchdog=watchdog,\n            status_update_handlers=status_update_handlers,\n            source_buffer_filling_strategy=source_buffer_filling_strategy,\n            source_buffer_consumption_strategy=source_buffer_consumption_strategy,\n            video_source_properties=video_source_properties,\n            batch_collection_timeout=batch_collection_timeout,\n            predictions_queue_size=predictions_queue_size,\n            decoding_buffer_size=decoding_buffer_size,\n        )\n",
    "optimized_function_code": "import time\nfrom abc import ABC, abstractmethod\nfrom collections import deque\nfrom contextlib import contextmanager\nfrom typing import Deque, Dict, Generator, List, Optional, Union\n\n\nclass WorkflowsProfiler(ABC):\n\n    @classmethod\n    @abstractmethod\n    def init(cls, **kwargs) -> \"WorkflowsProfiler\":\n        pass\n\n    @abstractmethod\n    def start_workflow_run(self) -> None:\n        pass\n\n    @abstractmethod\n    def end_workflow_run(self) -> None:\n        pass\n\n    @abstractmethod\n    @contextmanager\n    def profile_execution_phase(\n        self,\n        name: str,\n        categories: Optional[List[str]] = None,\n        metadata: Optional[Dict[str, Union[str, int, float, bool, list, dict]]] = None,\n    ) -> Generator[None, None, None]:\n        pass\n\n    @abstractmethod\n    def start_execution_phase(\n        self,\n        name: str,\n        categories: Optional[List[str]] = None,\n        metadata: Optional[Dict[str, Union[str, int, float, bool, list, dict]]] = None,\n    ) -> None:\n        pass\n\n    @abstractmethod\n    def end_execution_phase(\n        self,\n        name: str,\n        categories: Optional[List[str]] = None,\n        metadata: Optional[Dict[str, Union[str, int, float, bool, list, dict]]] = None,\n    ) -> None:\n        pass\n\n    @abstractmethod\n    def notify_event(\n        self,\n        name: str,\n        categories: Optional[List[str]] = None,\n        metadata: Optional[Dict[str, Union[str, int, float, bool, list, dict]]] = None,\n    ) -> None:\n        pass\n\n    @abstractmethod\n    def export_trace(self) -> List[dict]:\n        pass\n\n\nclass NullWorkflowsProfiler(WorkflowsProfiler):\n\n    @classmethod\n    def init(cls, **kwargs) -> \"NullWorkflowsProfiler\":\n        return cls()\n\n\n    def start_workflow_run(self) -> None:\n        return None\n\n    def end_workflow_run(self) -> None:\n        return None\n\n    @contextmanager\n    def profile_execution_phase(\n        self,\n        name: str,\n        categories: Optional[List[str]] = None,\n        metadata: Optional[Dict[str, Union[str, int, float, bool, list, dict]]] = None,\n    ) -> Generator[None, None, None]:\n        yield None\n\n\n\n    def start_execution_phase(\n        self,\n        name: str,\n        categories: Optional[List[str]] = None,\n        metadata: Optional[Dict[str, Union[str, int, float, bool, list, dict]]] = None,\n    ) -> None:\n        return None\n\n    def end_execution_phase(\n        self,\n        name: str,\n        categories: Optional[List[str]] = None,\n        metadata: Optional[Dict[str, Union[str, int, float, bool, list, dict]]] = None,\n    ) -> None:\n        return None\n\n    def notify_event(\n        self,\n        name: str,\n        categories: Optional[List[str]] = None,\n        metadata: Optional[Dict[str, Union[str, int, float, bool, list, dict]]] = None,\n    ) -> None:\n        return None\n\n    def export_trace(self) -> List[dict]:\n        return []\n\n\nclass BaseWorkflowsProfiler(WorkflowsProfiler):\n\n    @classmethod\n    def init(\n        cls,\n        max_runs_in_buffer: int = 32,\n        **kwargs,\n    ) -> \"BaseWorkflowsProfiler\":\n        runs_buffer = deque(maxlen=max_runs_in_buffer)\n        return cls(runs_buffer=runs_buffer)\n\n    def __init__(self, runs_buffer: Deque[List[dict]]):\n        self._runs_buffer = runs_buffer\n        # events collected for the current workflow run\n        self._current_run_events: List[dict] = []\n        # active phases stored as name -> stack of start records (to support nesting)\n        self._active_phases: Dict[str, List[dict]] = {}\n\n    def start_workflow_run(self) -> None:\n        # start a fresh current run event list\n        self._current_run_events = []\n\n    def end_workflow_run(self) -> None:\n        # push a snapshot of current run events into circular buffer\n        # copy to avoid subsequent mutations affecting stored runs\n        self._runs_buffer.append(list(self._current_run_events))\n        self._current_run_events = []\n\n    @contextmanager\n    def profile_execution_phase(\n        self,\n        name: str,\n        categories: Optional[List[str]] = None,\n        metadata: Optional[Dict[str, Union[str, int, float, bool, list, dict]]] = None,\n    ) -> Generator[None, None, None]:\n        start_ts = round(time.monotonic() * 10**6)\n        try:\n            yield None\n        except Exception as e:\n            # notify error event and re-raise\n            try:\n                self.notify_event(name=f\"{name}_error\")\n            except Exception:\n                # Ensure we don't swallow the original exception if notify_event fails\n                pass\n            raise\n        finally:\n            duration = round(time.monotonic() * 10**6) - start_ts\n            self._add_event(\n                name=name,\n                event_type=\"X\",\n                categories=categories,\n                metadata=metadata,\n                extra_event_fields={\"dur\": duration},\n                timestamp=start_ts,\n            )\n\n    def start_execution_phase(\n        self,\n        name: str,\n        categories: Optional[List[str]] = None,\n        metadata: Optional[Dict[str, Union[str, int, float, bool, list, dict]]] = None,\n    ) -> None:\n        start_ts = round(time.monotonic() * 10**6)\n        if name not in self._active_phases:\n            self._active_phases[name] = []\n        # store a small record for this phase start\n        self._active_phases[name].append(\n            {\"ts\": start_ts, \"categories\": categories, \"metadata\": metadata}\n        )\n\n    def end_execution_phase(\n        self,\n        name: str,\n        categories: Optional[List[str]] = None,\n        metadata: Optional[Dict[str, Union[str, int, float, bool, list, dict]]] = None,\n    ) -> None:\n        stack = self._active_phases.get(name)\n        if not stack:\n            # nothing to end\n            return None\n        record = stack.pop()\n        start_ts = record.get(\"ts\")\n        duration = round(time.monotonic() * 10**6) - start_ts\n        # prefer metadata/categories passed to end over the ones at start if provided\n        event_categories = categories if categories is not None else record.get(\"categories\")\n        event_metadata = metadata if metadata is not None else record.get(\"metadata\")\n        self._add_event(\n            name=name,\n            event_type=\"X\",\n            categories=event_categories,\n            metadata=event_metadata,\n            extra_event_fields={\"dur\": duration},\n            timestamp=start_ts,\n        )\n        if not stack:\n            # clean empty stacks to avoid growth\n            del self._active_phases[name]\n\n    def notify_event(\n        self,\n        name: str,\n        categories: Optional[List[str]] = None,\n        metadata: Optional[Dict[str, Union[str, int, float, bool, list, dict]]] = None,\n    ) -> None:\n        # instantaneous event with current timestamp\n        self._add_event(\n            name=name,\n            event_type=\"i\",\n            categories=categories,\n            metadata=metadata,\n            extra_event_fields=None,\n            timestamp=round(time.monotonic() * 10**6),\n        )\n\n    def export_trace(self) -> List[dict]:\n        # produce a shallow copy list of stored runs to avoid exposing internal deque\n        return list(self._runs_buffer)\n\n    def _add_event(\n        self,\n        name: str,\n        event_type: str,\n        categories: Optional[List[str]] = None,\n        metadata: Optional[Dict[str, Union[str, int, float, bool, list, dict]]] = None,\n        extra_event_fields: Optional[dict] = None,\n        timestamp: Optional[int] = None,\n    ) -> None:\n        # Build event dict directly and append to current run\n        event: dict = {\"name\": name, \"event_type\": event_type}\n        if timestamp is not None:\n            event[\"timestamp\"] = int(timestamp)\n        if categories is not None:\n            event[\"categories\"] = categories\n        if metadata is not None:\n            event[\"metadata\"] = metadata\n        if extra_event_fields:\n            # merge additional fields such as duration\n            event.update(extra_event_fields)\n        self._current_run_events.append(event)",
    "optimized_raw_markdown": "```python:inference/core/workflows/execution_engine/profiling/core.py\nimport time\nfrom abc import ABC, abstractmethod\nfrom collections import deque\nfrom contextlib import contextmanager\nfrom typing import Deque, Dict, Generator, List, Optional, Union\n\n\nclass WorkflowsProfiler(ABC):\n\n    @classmethod\n    @abstractmethod\n    def init(cls, **kwargs) -> \"WorkflowsProfiler\":\n        pass\n\n    @abstractmethod\n    def start_workflow_run(self) -> None:\n        pass\n\n    @abstractmethod\n    def end_workflow_run(self) -> None:\n        pass\n\n    @abstractmethod\n    @contextmanager\n    def profile_execution_phase(\n        self,\n        name: str,\n        categories: Optional[List[str]] = None,\n        metadata: Optional[Dict[str, Union[str, int, float, bool, list, dict]]] = None,\n    ) -> Generator[None, None, None]:\n        pass\n\n    @abstractmethod\n    def start_execution_phase(\n        self,\n        name: str,\n        categories: Optional[List[str]] = None,\n        metadata: Optional[Dict[str, Union[str, int, float, bool, list, dict]]] = None,\n    ) -> None:\n        pass\n\n    @abstractmethod\n    def end_execution_phase(\n        self,\n        name: str,\n        categories: Optional[List[str]] = None,\n        metadata: Optional[Dict[str, Union[str, int, float, bool, list, dict]]] = None,\n    ) -> None:\n        pass\n\n    @abstractmethod\n    def notify_event(\n        self,\n        name: str,\n        categories: Optional[List[str]] = None,\n        metadata: Optional[Dict[str, Union[str, int, float, bool, list, dict]]] = None,\n    ) -> None:\n        pass\n\n    @abstractmethod\n    def export_trace(self) -> List[dict]:\n        pass\n\n\nclass NullWorkflowsProfiler(WorkflowsProfiler):\n\n    @classmethod\n    def init(cls, **kwargs) -> \"NullWorkflowsProfiler\":\n        return cls()\n\n\n    def start_workflow_run(self) -> None:\n        return None\n\n    def end_workflow_run(self) -> None:\n        return None\n\n    @contextmanager\n    def profile_execution_phase(\n        self,\n        name: str,\n        categories: Optional[List[str]] = None,\n        metadata: Optional[Dict[str, Union[str, int, float, bool, list, dict]]] = None,\n    ) -> Generator[None, None, None]:\n        yield None\n\n\n\n    def start_execution_phase(\n        self,\n        name: str,\n        categories: Optional[List[str]] = None,\n        metadata: Optional[Dict[str, Union[str, int, float, bool, list, dict]]] = None,\n    ) -> None:\n        return None\n\n    def end_execution_phase(\n        self,\n        name: str,\n        categories: Optional[List[str]] = None,\n        metadata: Optional[Dict[str, Union[str, int, float, bool, list, dict]]] = None,\n    ) -> None:\n        return None\n\n    def notify_event(\n        self,\n        name: str,\n        categories: Optional[List[str]] = None,\n        metadata: Optional[Dict[str, Union[str, int, float, bool, list, dict]]] = None,\n    ) -> None:\n        return None\n\n    def export_trace(self) -> List[dict]:\n        return []\n\n\nclass BaseWorkflowsProfiler(WorkflowsProfiler):\n\n    @classmethod\n    def init(\n        cls,\n        max_runs_in_buffer: int = 32,\n        **kwargs,\n    ) -> \"BaseWorkflowsProfiler\":\n        runs_buffer = deque(maxlen=max_runs_in_buffer)\n        return cls(runs_buffer=runs_buffer)\n\n    def __init__(self, runs_buffer: Deque[List[dict]]):\n        self._runs_buffer = runs_buffer\n        # events collected for the current workflow run\n        self._current_run_events: List[dict] = []\n        # active phases stored as name -> stack of start records (to support nesting)\n        self._active_phases: Dict[str, List[dict]] = {}\n\n    def start_workflow_run(self) -> None:\n        # start a fresh current run event list\n        self._current_run_events = []\n\n    def end_workflow_run(self) -> None:\n        # push a snapshot of current run events into circular buffer\n        # copy to avoid subsequent mutations affecting stored runs\n        self._runs_buffer.append(list(self._current_run_events))\n        self._current_run_events = []\n\n    @contextmanager\n    def profile_execution_phase(\n        self,\n        name: str,\n        categories: Optional[List[str]] = None,\n        metadata: Optional[Dict[str, Union[str, int, float, bool, list, dict]]] = None,\n    ) -> Generator[None, None, None]:\n        start_ts = round(time.monotonic() * 10**6)\n        try:\n            yield None\n        except Exception as e:\n            # notify error event and re-raise\n            try:\n                self.notify_event(name=f\"{name}_error\")\n            except Exception:\n                # Ensure we don't swallow the original exception if notify_event fails\n                pass\n            raise\n        finally:\n            duration = round(time.monotonic() * 10**6) - start_ts\n            self._add_event(\n                name=name,\n                event_type=\"X\",\n                categories=categories,\n                metadata=metadata,\n                extra_event_fields={\"dur\": duration},\n                timestamp=start_ts,\n            )\n\n    def start_execution_phase(\n        self,\n        name: str,\n        categories: Optional[List[str]] = None,\n        metadata: Optional[Dict[str, Union[str, int, float, bool, list, dict]]] = None,\n    ) -> None:\n        start_ts = round(time.monotonic() * 10**6)\n        if name not in self._active_phases:\n            self._active_phases[name] = []\n        # store a small record for this phase start\n        self._active_phases[name].append(\n            {\"ts\": start_ts, \"categories\": categories, \"metadata\": metadata}\n        )\n\n    def end_execution_phase(\n        self,\n        name: str,\n        categories: Optional[List[str]] = None,\n        metadata: Optional[Dict[str, Union[str, int, float, bool, list, dict]]] = None,\n    ) -> None:\n        stack = self._active_phases.get(name)\n        if not stack:\n            # nothing to end\n            return None\n        record = stack.pop()\n        start_ts = record.get(\"ts\")\n        duration = round(time.monotonic() * 10**6) - start_ts\n        # prefer metadata/categories passed to end over the ones at start if provided\n        event_categories = categories if categories is not None else record.get(\"categories\")\n        event_metadata = metadata if metadata is not None else record.get(\"metadata\")\n        self._add_event(\n            name=name,\n            event_type=\"X\",\n            categories=event_categories,\n            metadata=event_metadata,\n            extra_event_fields={\"dur\": duration},\n            timestamp=start_ts,\n        )\n        if not stack:\n            # clean empty stacks to avoid growth\n            del self._active_phases[name]\n\n    def notify_event(\n        self,\n        name: str,\n        categories: Optional[List[str]] = None,\n        metadata: Optional[Dict[str, Union[str, int, float, bool, list, dict]]] = None,\n    ) -> None:\n        # instantaneous event with current timestamp\n        self._add_event(\n            name=name,\n            event_type=\"i\",\n            categories=categories,\n            metadata=metadata,\n            extra_event_fields=None,\n            timestamp=round(time.monotonic() * 10**6),\n        )\n\n    def export_trace(self) -> List[dict]:\n        # produce a shallow copy list of stored runs to avoid exposing internal deque\n        return list(self._runs_buffer)\n\n    def _add_event(\n        self,\n        name: str,\n        event_type: str,\n        categories: Optional[List[str]] = None,\n        metadata: Optional[Dict[str, Union[str, int, float, bool, list, dict]]] = None,\n        extra_event_fields: Optional[dict] = None,\n        timestamp: Optional[int] = None,\n    ) -> None:\n        # Build event dict directly and append to current run\n        event: dict = {\"name\": name, \"event_type\": event_type}\n        if timestamp is not None:\n            event[\"timestamp\"] = int(timestamp)\n        if categories is not None:\n            event[\"categories\"] = categories\n        if metadata is not None:\n            event[\"metadata\"] = metadata\n        if extra_event_fields:\n            # merge additional fields such as duration\n            event.update(extra_event_fields)\n        self._current_run_events.append(event)\n```",
    "optimized_function_only": null,
    "original_file_content": "from concurrent.futures import ThreadPoolExecutor\nfrom datetime import datetime\nfrom enum import Enum\nfrom functools import partial\nfrom queue import Queue\nfrom threading import Thread\nfrom typing import Any, Callable, Dict, Generator, List, Optional, Tuple, Union\n\nfrom inference.core import logger\nfrom inference.core.active_learning.middlewares import (\n    NullActiveLearningMiddleware,\n    ThreadingActiveLearningMiddleware,\n)\nfrom inference.core.cache import cache\nfrom inference.core.env import (\n    ACTIVE_LEARNING_ENABLED,\n    API_KEY,\n    DEFAULT_BUFFER_SIZE,\n    DISABLE_PREPROC_AUTO_ORIENT,\n    ENABLE_FRAME_DROP_ON_VIDEO_FILE_RATE_LIMITING,\n    ENABLE_WORKFLOWS_PROFILING,\n    MAX_ACTIVE_MODELS,\n    PREDICTIONS_QUEUE_SIZE,\n    WORKFLOWS_PROFILER_BUFFER_SIZE,\n)\nfrom inference.core.exceptions import CannotInitialiseModelError, MissingApiKeyError\nfrom inference.core.interfaces.camera.entities import (\n    StatusUpdate,\n    UpdateSeverity,\n    VideoFrame,\n    VideoSourceIdentifier,\n)\nfrom inference.core.interfaces.camera.utils import multiplex_videos\nfrom inference.core.interfaces.camera.video_source import (\n    BufferConsumptionStrategy,\n    BufferFillingStrategy,\n    VideoSource,\n)\nfrom inference.core.interfaces.stream.entities import (\n    AnyPrediction,\n    InferenceHandler,\n    ModelConfig,\n    SinkHandler,\n)\nfrom inference.core.interfaces.stream.model_handlers.roboflow_models import (\n    default_process_frame,\n)\nfrom inference.core.interfaces.stream.sinks import active_learning_sink, multi_sink\nfrom inference.core.interfaces.stream.utils import (\n    on_pipeline_end,\n    prepare_video_sources,\n)\nfrom inference.core.interfaces.stream.watchdog import (\n    NullPipelineWatchdog,\n    PipelineWatchDog,\n)\nfrom inference.core.managers.active_learning import BackgroundTaskActiveLearningManager\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.managers.decorators.fixed_size_cache import WithFixedSizeCache\nfrom inference.core.registries.roboflow import RoboflowModelRegistry\nfrom inference.core.utils.function import experimental\nfrom inference.core.workflows.core_steps.common.entities import StepExecutionMode\nfrom inference.core.workflows.execution_engine.profiling.core import (\n    BaseWorkflowsProfiler,\n    NullWorkflowsProfiler,\n)\nfrom inference.models.aliases import resolve_roboflow_model_alias\nfrom inference.models.utils import ROBOFLOW_MODEL_TYPES, get_model\n\nINFERENCE_PIPELINE_CONTEXT = \"inference_pipeline\"\nSOURCE_CONNECTION_ATTEMPT_FAILED_EVENT = \"SOURCE_CONNECTION_ATTEMPT_FAILED\"\nSOURCE_CONNECTION_LOST_EVENT = \"SOURCE_CONNECTION_LOST\"\nINFERENCE_RESULTS_DISPATCHING_ERROR_EVENT = \"INFERENCE_RESULTS_DISPATCHING_ERROR\"\nINFERENCE_THREAD_STARTED_EVENT = \"INFERENCE_THREAD_STARTED\"\nINFERENCE_THREAD_FINISHED_EVENT = \"INFERENCE_THREAD_FINISHED\"\nINFERENCE_COMPLETED_EVENT = \"INFERENCE_COMPLETED\"\nINFERENCE_ERROR_EVENT = \"INFERENCE_ERROR\"\n\n\nclass SinkMode(Enum):\n    ADAPTIVE = \"adaptive\"\n    BATCH = \"batch\"\n    SEQUENTIAL = \"sequential\"\n\n\nclass InferencePipeline:\n    @classmethod\n    def init(\n        cls,\n        video_reference: Union[VideoSourceIdentifier, List[VideoSourceIdentifier]],\n        model_id: str,\n        on_prediction: SinkHandler = None,\n        api_key: Optional[str] = None,\n        max_fps: Optional[Union[float, int]] = None,\n        watchdog: Optional[PipelineWatchDog] = None,\n        status_update_handlers: Optional[List[Callable[[StatusUpdate], None]]] = None,\n        source_buffer_filling_strategy: Optional[BufferFillingStrategy] = None,\n        source_buffer_consumption_strategy: Optional[BufferConsumptionStrategy] = None,\n        class_agnostic_nms: Optional[bool] = None,\n        confidence: Optional[float] = None,\n        iou_threshold: Optional[float] = None,\n        max_candidates: Optional[int] = None,\n        max_detections: Optional[int] = None,\n        mask_decode_mode: Optional[str] = \"accurate\",\n        tradeoff_factor: Optional[float] = 0.0,\n        active_learning_enabled: Optional[bool] = None,\n        video_source_properties: Optional[\n            Union[Dict[str, float], List[Optional[Dict[str, float]]]]\n        ] = None,\n        active_learning_target_dataset: Optional[str] = None,\n        batch_collection_timeout: Optional[float] = None,\n        sink_mode: SinkMode = SinkMode.ADAPTIVE,\n        predictions_queue_size: int = PREDICTIONS_QUEUE_SIZE,\n        decoding_buffer_size: int = DEFAULT_BUFFER_SIZE,\n    ) -> \"InferencePipeline\":\n        \"\"\"\n        This class creates the abstraction for making inferences from Roboflow models against video stream.\n        It allows to choose model from Roboflow platform and run predictions against\n        video streams - just by the price of specifying which model to use and what to do with predictions.\n\n        It allows to set the model post-processing parameters (via .init() or env) and intercept updates\n        related to state of pipeline via `PipelineWatchDog` abstraction (although that is something probably\n        useful only for advanced use-cases).\n\n        For maximum efficiency, all separate chunks of processing: video decoding, inference, results dispatching\n        are handled by separate threads.\n\n        Given that reference to stream is passed and connectivity is lost - it attempts to re-connect with delay.\n\n        Since version 0.9.11 it works not only for object detection models but is also compatible with stubs,\n        classification, instance-segmentation and keypoint-detection models.\n\n        Since version 0.9.18, `InferencePipeline` is capable of handling multiple video sources at once. If multiple\n        sources are provided - source multiplexing will happen. One of the change introduced in that release is switch\n        from `get_video_frames_generator(...)` as video frames provider into `multiplex_videos(...)`. For a single\n        video source, the behaviour of `InferencePipeline` is remained unchanged when default parameters are used.\n        For multiple videos - frames are multiplexed, and we can adjust the pipeline behaviour using new configuration\n        options. `batch_collection_timeout` is one of the new option - it is the parameter of `multiplex_videos(...)`\n        that dictates how long the batch frames collection process may wait for all sources to provide video frame.\n        It can be set infinite (None) or with specific value representing fraction of second. We advise that value to\n        be set in production solutions to avoid processing slow-down caused by source with unstable latency spikes.\n        For more information on multiplexing process - please visit `multiplex_videos(...)` function docs.\n        Another change is the way on how sinks work. They can work in `SinkMode.ADAPTIVE` - which means that\n        video frames and predictions will be either provided to sink as list of objects, or specific elements -\n        and the determining factor is number of sources (it will behave SEQUENTIAL for one source and BATCH if multiple\n        ones are provided). All old sinks were adjusted to work in both modes, custom ones should be migrated\n        to reflect changes in sink function signature.\n\n        Args:\n            model_id (str): Name and version of model on the Roboflow platform (example: \"my-model/3\")\n            video_reference (Union[str, int, List[Union[str, int]]]): Reference of source or sources to be used to make\n                predictions against. It can be video file path, stream URL and device (like camera) id\n                (we handle whatever cv2 handles). It can also be a list of references (since v0.9.18) - and then\n                it will trigger parallel processing of multiple sources. It has some implication on sinks. See:\n                `sink_mode` parameter comments.\n            on_prediction (Callable[AnyPrediction, VideoFrame], None]): Function to be called\n                once prediction is ready - passing both decoded frame, their metadata and dict with standard\n                Roboflow model prediction (different for specific types of models).\n            api_key (Optional[str]): Roboflow API key - if not passed - will be looked in env under \"ROBOFLOW_API_KEY\"\n                and \"API_KEY\" variables. API key, passed in some form is required.\n            max_fps (Optional[Union[float, int]]): Specific value passed as this parameter will be used to\n                dictate max FPS of each video source.\n                The implementation details of this option has been changed in release `v0.26.0`. Prior to the release\n                this value, when applied to video files caused the processing to wait `1 / max_fps` seconds before next\n                frame is processed - the new implementation drops the intermediate frames, which seems to be more\n                aligned with peoples expectations.\n                New behaviour is now enabled in experimental mode, by setting environmental variable flag\n                `ENABLE_FRAME_DROP_ON_VIDEO_FILE_RATE_LIMITING=True`. Please note that the new behaviour will\n                be the default one end of Q4 2024!\n            watchdog (Optional[PipelineWatchDog]): Implementation of class that allows profiling of\n                inference pipeline - if not given null implementation (doing nothing) will be used.\n            status_update_handlers (Optional[List[Callable[[StatusUpdate], None]]]): List of handlers to intercept\n                status updates of all elements of the pipeline. Should be used only if detailed inspection of\n                pipeline behaviour in time is needed. Please point out that handlers should be possible to be executed\n                fast - otherwise they will impair pipeline performance. All errors will be logged as warnings\n                without re-raising. Default: None.\n            source_buffer_filling_strategy (Optional[BufferFillingStrategy]): Parameter dictating strategy for\n                video stream decoding behaviour. By default - tweaked to the type of source given.\n                Please find detailed explanation in docs of [`VideoSource`](/reference/inference/core/interfaces/camera/video_source/#inference.core.interfaces.camera.video_source.VideoSource)\n            source_buffer_consumption_strategy (Optional[BufferConsumptionStrategy]): Parameter dictating strategy for\n                video stream frames consumption. By default - tweaked to the type of source given.\n                Please find detailed explanation in docs of [`VideoSource`](/reference/inference/core/interfaces/camera/video_source/#inference.core.interfaces.camera.video_source.VideoSource)\n            class_agnostic_nms (Optional[bool]): Parameter of model post-processing. If not given - value checked in\n                env variable \"CLASS_AGNOSTIC_NMS\" with default \"False\"\n            confidence (Optional[float]): Parameter of model post-processing. If not given - value checked in\n                env variable \"CONFIDENCE\" with default \"0.5\"\n            iou_threshold (Optional[float]): Parameter of model post-processing. If not given - value checked in\n                env variable \"IOU_THRESHOLD\" with default \"0.5\"\n            max_candidates (Optional[int]): Parameter of model post-processing. If not given - value checked in\n                env variable \"MAX_CANDIDATES\" with default \"3000\"\n            max_detections (Optional[int]): Parameter of model post-processing. If not given - value checked in\n                env variable \"MAX_DETECTIONS\" with default \"300\"\n            mask_decode_mode: (Optional[str]): Parameter of model post-processing. If not given - model \"accurate\" is\n                used. Applicable for instance segmentation models\n            tradeoff_factor (Optional[float]): Parameter of model post-processing. If not 0.0 - model default is used.\n                Applicable for instance segmentation models\n            active_learning_enabled (Optional[bool]): Flag to enable / disable Active Learning middleware (setting it\n                true does not guarantee any data to be collected, as data collection is controlled by Roboflow backend -\n                it just enables middleware intercepting predictions). If not given, env variable\n                `ACTIVE_LEARNING_ENABLED` will be used. Please point out that Active Learning will be forcefully\n                disabled in a scenario when Roboflow API key is not given, as Roboflow account is required\n                for this feature to be operational.\n            video_source_properties (Optional[Union[Dict[str, float], List[Optional[Dict[str, float]]]]]):\n                Optional source properties to set up the video source, corresponding to cv2 VideoCapture properties\n                cv2.CAP_PROP_*. If not given, defaults for the video source will be used.\n                It is optional and if provided can be provided as single dict (applicable for all sources) or\n                as list of configs. Then the list must be of length of `video_reference` and may also contain None\n                values to denote that specific source should remain not configured.\n                Example valid properties are: {\"frame_width\": 1920, \"frame_height\": 1080, \"fps\": 30.0}\n            active_learning_target_dataset (Optional[str]): Parameter to be used when Active Learning data registration\n                should happen against different dataset than the one pointed by model_id\n            batch_collection_timeout (Optional[float]): Parameter of multiplex_videos(...) dictating how long process\n                to grab frames from multiple sources can wait for batch to be filled before yielding already collected\n                frames. Please set this value in PRODUCTION to avoid performance drops when specific sources shows\n                unstable latency. Visit `multiplex_videos(...)` for more information about multiplexing process.\n            sink_mode (SinkMode): Parameter that controls how video frames and predictions will be passed to sink\n                handler. With SinkMode.SEQUENTIAL - each frame and prediction triggers separate call for sink,\n                in case of SinkMode.BATCH - list of frames and predictions will be provided to sink, always aligned\n                in the order of video sources - with None values in the place of vide_frames / predictions that\n                were skipped due to `batch_collection_timeout`.\n                `SinkMode.ADAPTIVE` is a middle ground (and default mode) - all old sources will work in that mode\n                against a single video input, as the pipeline will behave as if running in `SinkMode.SEQUENTIAL`.\n                To handle multiple videos - sink needs to accept `predictions: List[Optional[dict]]` and\n                `video_frame: List[Optional[VideoFrame]]`. It is also possible to process multiple videos using\n                old sinks - but then `SinkMode.SEQUENTIAL` is to be used, causing sink to be called on each\n                prediction element.\n            predictions_queue_size int: Size of buffer for predictions that are ready for dispatching\n                default value is taken from INFERENCE_PIPELINE_PREDICTIONS_QUEUE_SIZE env variable\n            decoding_buffer_size (int): size of video source decoding buffer\n                default value is taken from VIDEO_SOURCE_BUFFER_SIZE env variable\n\n        Other ENV variables involved in low-level configuration:\n        * INFERENCE_PIPELINE_PREDICTIONS_QUEUE_SIZE - size of buffer for predictions that are ready for dispatching\n        * INFERENCE_PIPELINE_RESTART_ATTEMPT_DELAY - delay for restarts on stream connection drop\n        * ACTIVE_LEARNING_ENABLED - controls Active Learning middleware if explicit parameter not given\n\n        Returns: Instance of InferencePipeline\n\n        Throws:\n            * SourceConnectionError if source cannot be connected at start, however it attempts to reconnect\n                always if connection to stream is lost.\n        \"\"\"\n        if api_key is None:\n            api_key = API_KEY\n        inference_config = ModelConfig.init(\n            class_agnostic_nms=class_agnostic_nms,\n            confidence=confidence,\n            iou_threshold=iou_threshold,\n            max_candidates=max_candidates,\n            max_detections=max_detections,\n            mask_decode_mode=mask_decode_mode,\n            tradeoff_factor=tradeoff_factor,\n        )\n        model = get_model(model_id=model_id, api_key=api_key)\n        on_video_frame = partial(\n            default_process_frame, model=model, inference_config=inference_config\n        )\n        active_learning_middleware = NullActiveLearningMiddleware()\n        if active_learning_enabled is None:\n            logger.info(\n                f\"`active_learning_enabled` parameter not set - using env `ACTIVE_LEARNING_ENABLED` \"\n                f\"with value: {ACTIVE_LEARNING_ENABLED}\"\n            )\n            active_learning_enabled = ACTIVE_LEARNING_ENABLED\n        if api_key is None:\n            logger.info(\n                f\"Roboflow API key not given - Active Learning is forced to be disabled.\"\n            )\n            active_learning_enabled = False\n        if active_learning_enabled is True:\n            resolved_model_id = resolve_roboflow_model_alias(model_id=model_id)\n            target_dataset = (\n                active_learning_target_dataset or resolved_model_id.split(\"/\")[0]\n            )\n            active_learning_middleware = ThreadingActiveLearningMiddleware.init(\n                api_key=api_key,\n                target_dataset=target_dataset,\n                model_id=resolved_model_id,\n                cache=cache,\n            )\n            al_sink = partial(\n                active_learning_sink,\n                active_learning_middleware=active_learning_middleware,\n                model_type=model.task_type,\n                disable_preproc_auto_orient=DISABLE_PREPROC_AUTO_ORIENT,\n            )\n            logger.info(\n                \"AL enabled - wrapping `on_prediction` with multi_sink() and active_learning_sink()\"\n            )\n            on_prediction = partial(multi_sink, sinks=[on_prediction, al_sink])\n        on_pipeline_start = active_learning_middleware.start_registration_thread\n        on_pipeline_end = active_learning_middleware.stop_registration_thread\n        return cls.init_with_custom_logic(\n            video_reference=video_reference,\n            on_video_frame=on_video_frame,\n            on_prediction=on_prediction,\n            on_pipeline_start=on_pipeline_start,\n            on_pipeline_end=on_pipeline_end,\n            max_fps=max_fps,\n            watchdog=watchdog,\n            status_update_handlers=status_update_handlers,\n            source_buffer_filling_strategy=source_buffer_filling_strategy,\n            source_buffer_consumption_strategy=source_buffer_consumption_strategy,\n            video_source_properties=video_source_properties,\n            batch_collection_timeout=batch_collection_timeout,\n            sink_mode=sink_mode,\n            predictions_queue_size=predictions_queue_size,\n            decoding_buffer_size=decoding_buffer_size,\n        )\n\n    @classmethod\n    def init_with_yolo_world(\n        cls,\n        video_reference: Union[str, int, List[Union[str, int]]],\n        classes: List[str],\n        model_size: str = \"s\",\n        on_prediction: SinkHandler = None,\n        max_fps: Optional[Union[float, int]] = None,\n        watchdog: Optional[PipelineWatchDog] = None,\n        status_update_handlers: Optional[List[Callable[[StatusUpdate], None]]] = None,\n        source_buffer_filling_strategy: Optional[BufferFillingStrategy] = None,\n        source_buffer_consumption_strategy: Optional[BufferConsumptionStrategy] = None,\n        class_agnostic_nms: Optional[bool] = None,\n        confidence: Optional[float] = None,\n        iou_threshold: Optional[float] = None,\n        max_candidates: Optional[int] = None,\n        max_detections: Optional[int] = None,\n        video_source_properties: Optional[Dict[str, float]] = None,\n        batch_collection_timeout: Optional[float] = None,\n        sink_mode: SinkMode = SinkMode.ADAPTIVE,\n        predictions_queue_size: int = PREDICTIONS_QUEUE_SIZE,\n        decoding_buffer_size: int = DEFAULT_BUFFER_SIZE,\n    ) -> \"InferencePipeline\":\n        \"\"\"\n        This class creates the abstraction for making inferences from YoloWorld against video stream.\n        The way of how `InferencePipeline` works is displayed in `InferencePipeline.init(...)` initializer\n        method.\n\n        Args:\n            video_reference (Union[str, int, List[Union[str, int]]]): Reference of source or sources to be used to make\n                predictions against. It can be video file path, stream URL and device (like camera) id\n                (we handle whatever cv2 handles). It can also be a list of references (since v0.9.18) - and then\n                it will trigger parallel processing of multiple sources. It has some implication on sinks. See:\n                `sink_mode` parameter comments.\n            classes (List[str]): List of classes to execute zero-shot detection against\n            model_size (str): version of model - to be chosen from `s`, `m`, `l`\n            on_prediction (Callable[AnyPrediction, VideoFrame], None]): Function to be called\n                once prediction is ready - passing both decoded frame, their metadata and dict with standard\n                Roboflow Object Detection prediction.\n            max_fps (Optional[Union[float, int]]): Specific value passed as this parameter will be used to\n                dictate max FPS of each video source.\n                The implementation details of this option has been changed in release `v0.26.0`. Prior to the release\n                this value, when applied to video files caused the processing to wait `1 / max_fps` seconds before next\n                frame is processed - the new implementation drops the intermediate frames, which seems to be more\n                aligned with peoples expectations.\n                New behaviour is now enabled in experimental mode, by setting environmental variable flag\n                `ENABLE_FRAME_DROP_ON_VIDEO_FILE_RATE_LIMITING=True`. Please note that the new behaviour will\n                be the default one end of Q4 2024!\n            watchdog (Optional[PipelineWatchDog]): Implementation of class that allows profiling of\n                inference pipeline - if not given null implementation (doing nothing) will be used.\n            status_update_handlers (Optional[List[Callable[[StatusUpdate], None]]]): List of handlers to intercept\n                status updates of all elements of the pipeline. Should be used only if detailed inspection of\n                pipeline behaviour in time is needed. Please point out that handlers should be possible to be executed\n                fast - otherwise they will impair pipeline performance. All errors will be logged as warnings\n                without re-raising. Default: None.\n            source_buffer_filling_strategy (Optional[BufferFillingStrategy]): Parameter dictating strategy for\n                video stream decoding behaviour. By default - tweaked to the type of source given.\n                Please find detailed explanation in docs of [`VideoSource`](/reference/inference/core/interfaces/camera/video_source/#inference.core.interfaces.camera.video_source.VideoSource)\n            source_buffer_consumption_strategy (Optional[BufferConsumptionStrategy]): Parameter dictating strategy for\n                video stream frames consumption. By default - tweaked to the type of source given.\n                Please find detailed explanation in docs of [`VideoSource`](/reference/inference/core/interfaces/camera/video_source/#inference.core.interfaces.camera.video_source.VideoSource)\n            class_agnostic_nms (Optional[bool]): Parameter of model post-processing. If not given - value checked in\n                env variable \"CLASS_AGNOSTIC_NMS\" with default \"False\"\n            confidence (Optional[float]): Parameter of model post-processing. If not given - value checked in\n                env variable \"CONFIDENCE\" with default \"0.5\"\n            iou_threshold (Optional[float]): Parameter of model post-processing. If not given - value checked in\n                env variable \"IOU_THRESHOLD\" with default \"0.5\"\n            max_candidates (Optional[int]): Parameter of model post-processing. If not given - value checked in\n                env variable \"MAX_CANDIDATES\" with default \"3000\"\n            max_detections (Optional[int]): Parameter of model post-processing. If not given - value checked in\n                env variable \"MAX_DETECTIONS\" with default \"300\"\n            video_source_properties (Optional[Union[Dict[str, float], List[Optional[Dict[str, float]]]]]):\n                Optional source properties to set up the video source, corresponding to cv2 VideoCapture properties\n                cv2.CAP_PROP_*. If not given, defaults for the video source will be used.\n                It is optional and if provided can be provided as single dict (applicable for all sources) or\n                as list of configs. Then the list must be of length of `video_reference` and may also contain None\n                values to denote that specific source should remain not configured.\n                Example valid properties are: {\"frame_width\": 1920, \"frame_height\": 1080, \"fps\": 30.0}\n            batch_collection_timeout (Optional[float]): Parameter of multiplex_videos(...) dictating how long process\n                to grab frames from multiple sources can wait for batch to be filled before yielding already collected\n                frames. Please set this value in PRODUCTION to avoid performance drops when specific sources shows\n                unstable latency. Visit `multiplex_videos(...)` for more information about multiplexing process.\n            sink_mode (SinkMode): Parameter that controls how video frames and predictions will be passed to sink\n                handler. With SinkMode.SEQUENTIAL - each frame and prediction triggers separate call for sink,\n                in case of SinkMode.BATCH - list of frames and predictions will be provided to sink, always aligned\n                in the order of video sources - with None values in the place of vide_frames / predictions that\n                were skipped due to `batch_collection_timeout`.\n                `SinkMode.ADAPTIVE` is a middle ground (and default mode) - all old sources will work in that mode\n                against a single video input, as the pipeline will behave as if running in `SinkMode.SEQUENTIAL`.\n                To handle multiple videos - sink needs to accept `predictions: List[Optional[dict]]` and\n                `video_frame: List[Optional[VideoFrame]]`. It is also possible to process multiple videos using\n                old sinks - but then `SinkMode.SEQUENTIAL` is to be used, causing sink to be called on each\n                prediction element.\n            predictions_queue_size int: Size of buffer for predictions that are ready for dispatching\n                default value is taken from INFERENCE_PIPELINE_PREDICTIONS_QUEUE_SIZE env variable\n            decoding_buffer_size (int): size of video source decoding buffer\n                default value is taken from VIDEO_SOURCE_BUFFER_SIZE env variable\n\n        Other ENV variables involved in low-level configuration:\n        * INFERENCE_PIPELINE_PREDICTIONS_QUEUE_SIZE - size of buffer for predictions that are ready for dispatching\n        * INFERENCE_PIPELINE_RESTART_ATTEMPT_DELAY - delay for restarts on stream connection drop\n\n        Returns: Instance of InferencePipeline\n\n        Throws:\n            * SourceConnectionError if source cannot be connected at start, however it attempts to reconnect\n                always if connection to stream is lost.\n        \"\"\"\n        inference_config = ModelConfig.init(\n            class_agnostic_nms=class_agnostic_nms,\n            confidence=confidence,\n            iou_threshold=iou_threshold,\n            max_candidates=max_candidates,\n            max_detections=max_detections,\n        )\n        try:\n            from inference.core.interfaces.stream.model_handlers.yolo_world import (\n                build_yolo_world_inference_function,\n            )\n\n            on_video_frame = build_yolo_world_inference_function(\n                model_id=f\"yolo_world/{model_size}\",\n                classes=classes,\n                inference_config=inference_config,\n            )\n        except ImportError as error:\n            raise CannotInitialiseModelError(\n                f\"Could not initialise yolo_world/{model_size} due to lack of sufficient dependencies. \"\n                f\"Use pip install inference[yolo-world] to install missing dependencies and try again.\"\n            ) from error\n        return cls.init_with_custom_logic(\n            video_reference=video_reference,\n            on_video_frame=on_video_frame,\n            on_prediction=on_prediction,\n            on_pipeline_start=None,\n            on_pipeline_end=None,\n            max_fps=max_fps,\n            watchdog=watchdog,\n            status_update_handlers=status_update_handlers,\n            source_buffer_filling_strategy=source_buffer_filling_strategy,\n            source_buffer_consumption_strategy=source_buffer_consumption_strategy,\n            video_source_properties=video_source_properties,\n            batch_collection_timeout=batch_collection_timeout,\n            sink_mode=sink_mode,\n            predictions_queue_size=predictions_queue_size,\n            decoding_buffer_size=decoding_buffer_size,\n        )\n\n    @classmethod\n    @experimental(\n        reason=\"Usage of workflows with `InferencePipeline` is an experimental feature. Please report any issues \"\n        \"here: https://github.com/roboflow/inference/issues\"\n    )\n    def init_with_workflow(\n        cls,\n        video_reference: Union[str, int, List[Union[str, int]]],\n        workflow_specification: Optional[dict] = None,\n        workspace_name: Optional[str] = None,\n        workflow_id: Optional[str] = None,\n        api_key: Optional[str] = None,\n        image_input_name: str = \"image\",\n        workflows_parameters: Optional[Dict[str, Any]] = None,\n        on_prediction: SinkHandler = None,\n        max_fps: Optional[Union[float, int]] = None,\n        watchdog: Optional[PipelineWatchDog] = None,\n        status_update_handlers: Optional[List[Callable[[StatusUpdate], None]]] = None,\n        source_buffer_filling_strategy: Optional[BufferFillingStrategy] = None,\n        source_buffer_consumption_strategy: Optional[BufferConsumptionStrategy] = None,\n        video_source_properties: Optional[Dict[str, float]] = None,\n        workflow_init_parameters: Optional[Dict[str, Any]] = None,\n        workflows_thread_pool_workers: int = 4,\n        cancel_thread_pool_tasks_on_exit: bool = True,\n        video_metadata_input_name: str = \"video_metadata\",\n        batch_collection_timeout: Optional[float] = None,\n        profiling_directory: str = \"./inference_profiling\",\n        use_workflow_definition_cache: bool = True,\n        serialize_results: bool = False,\n        predictions_queue_size: int = PREDICTIONS_QUEUE_SIZE,\n        decoding_buffer_size: int = DEFAULT_BUFFER_SIZE,\n        model_manager: Optional[ModelManager] = None,\n        _is_preview: bool = False,\n        workflow_version_id: Optional[str] = None,\n    ) -> \"InferencePipeline\":\n        \"\"\"\n        This class creates the abstraction for making inferences from given workflow against video stream.\n        The way of how `InferencePipeline` works is displayed in `InferencePipeline.init(...)` initializer\n        method.\n\n        Args:\n            video_reference (Union[str, int, List[Union[str, int]]]): Reference of source to be used to make predictions\n                against. It can be video file path, stream URL and device (like camera) id\n                (we handle whatever cv2 handles). It can also be a list of references (since v0.13.0) - and then\n                it will trigger parallel processing of multiple sources. It has some implication on sinks. See:\n                `sink_mode` parameter comments.\n            workflow_specification (Optional[dict]): Valid specification of workflow. See [workflow docs](https://github.com/roboflow/inference/tree/main/inference/enterprise/workflows).\n                It can be provided optionally, but if not given, both `workspace_name` and `workflow_id`\n                must be provided.\n            workspace_name (Optional[str]): When using registered workflows - Roboflow workspace name needs to be given.\n            workflow_id (Optional[str]): When using registered workflows - Roboflow workflow id needs to be given.\n            api_key (Optional[str]): Roboflow API key - if not passed - will be looked in env under \"ROBOFLOW_API_KEY\"\n                and \"API_KEY\" variables. API key, passed in some form is required.\n            image_input_name (str): Name of input image defined in `workflow_specification` or Workflow definition saved\n                on the Roboflow Platform. `InferencePipeline` will be injecting video frames to workflow through that\n                parameter name.\n            workflows_parameters (Optional[Dict[str, Any]]): Dictionary with additional parameters that can be\n                defined within `workflow_specification`.\n            on_prediction (Callable[AnyPrediction, VideoFrame], None]): Function to be called\n                once prediction is ready - passing both decoded frame, their metadata and dict with workflow output.\n            max_fps (Optional[Union[float, int]]): Specific value passed as this parameter will be used to\n                dictate max FPS of each video source.\n                The implementation details of this option has been changed in release `v0.26.0`. Prior to the release\n                this value, when applied to video files caused the processing to wait `1 / max_fps` seconds before next\n                frame is processed - the new implementation drops the intermediate frames, which seems to be more\n                aligned with peoples expectations.\n                New behaviour is now enabled in experimental mode, by setting environmental variable flag\n                `ENABLE_FRAME_DROP_ON_VIDEO_FILE_RATE_LIMITING=True`. Please note that the new behaviour will\n                be the default one end of Q4 2024!\n            watchdog (Optional[PipelineWatchDog]): Implementation of class that allows profiling of\n                inference pipeline - if not given null implementation (doing nothing) will be used.\n            status_update_handlers (Optional[List[Callable[[StatusUpdate], None]]]): List of handlers to intercept\n                status updates of all elements of the pipeline. Should be used only if detailed inspection of\n                pipeline behaviour in time is needed. Please point out that handlers should be possible to be executed\n                fast - otherwise they will impair pipeline performance. All errors will be logged as warnings\n                without re-raising. Default: None.\n            source_buffer_filling_strategy (Optional[BufferFillingStrategy]): Parameter dictating strategy for\n                video stream decoding behaviour. By default - tweaked to the type of source given.\n                Please find detailed explanation in docs of [`VideoSource`](/reference/inference/core/interfaces/camera/video_source/#inference.core.interfaces.camera.video_source.VideoSource)\n            source_buffer_consumption_strategy (Optional[BufferConsumptionStrategy]): Parameter dictating strategy for\n                video stream frames consumption. By default - tweaked to the type of source given.\n                Please find detailed explanation in docs of [`VideoSource`](/reference/inference/core/interfaces/camera/video_source/#inference.core.interfaces.camera.video_source.VideoSource)\n            video_source_properties (Optional[dict[str, float]]): Optional source properties to set up the video source,\n                corresponding to cv2 VideoCapture properties cv2.CAP_PROP_*. If not given, defaults for the video source\n                will be used.\n                Example valid properties are: {\"frame_width\": 1920, \"frame_height\": 1080, \"fps\": 30.0}\n            workflow_init_parameters (Optional[Dict[str, Any]]): Additional init parameters to be used by\n                workflows Execution Engine to init steps of your workflow - may be required when running workflows\n                with custom plugins.\n            workflows_thread_pool_workers (int): Number of workers for workflows thread pool which is used\n                by workflows blocks to run background tasks.\n            cancel_thread_pool_tasks_on_exit (bool): Flag to decide if unstated background tasks should be\n                canceled at the end of InferencePipeline processing. By default, when video file ends or\n                pipeline is stopped, tasks that has not started will be cancelled.\n            video_metadata_input_name (str): Name of input for video metadata defined in `workflow_specification` or\n                Workflow definition saved  on the Roboflow Platform. `InferencePipeline` will be injecting video frames\n                metadata to workflows through that parameter name.\n            batch_collection_timeout (Optional[float]): Parameter of multiplex_videos(...) dictating how long process\n                to grab frames from multiple sources can wait for batch to be filled before yielding already collected\n                frames. Please set this value in PRODUCTION to avoid performance drops when specific sources shows\n                unstable latency. Visit `multiplex_videos(...)` for more information about multiplexing process.\n            profiling_directory (str): Directory where workflows profiler traces will be dumped. To enable profiling\n                export `ENABLE_WORKFLOWS_PROFILING=True` environmental variable. You may specify number of workflow\n                runs in a buffer with environmental variable `WORKFLOWS_PROFILER_BUFFER_SIZE=n` - making last `n`\n                frames to be present in buffer on processing end.\n            use_workflow_definition_cache (bool): Controls usage of cache for workflow definitions. Set this to False\n                when you frequently modify definition saved in Roboflow app and want to fetch the\n                newest version for the request. Only applies for Workflows definitions saved on Roboflow platform.\n            serialize_results (bool): Boolean flag to decide if ExecutionEngine run should serialize workflow\n                results for each frame. If that is set true, sinks will receive serialized workflow responses.\n            predictions_queue_size int: Size of buffer for predictions that are ready for dispatching\n                default value is taken from INFERENCE_PIPELINE_PREDICTIONS_QUEUE_SIZE env variable\n            decoding_buffer_size (int): size of video source decoding buffer\n                default value is taken from VIDEO_SOURCE_BUFFER_SIZE env variable\n            model_manager (Optional[ModelManager]): Model manager to be used by InferencePipeline, defaults to\n                BackgroundTaskActiveLearningManager with WithFixedSizeCache\n\n        Other ENV variables involved in low-level configuration:\n        * INFERENCE_PIPELINE_PREDICTIONS_QUEUE_SIZE - size of buffer for predictions that are ready for dispatching\n        * INFERENCE_PIPELINE_RESTART_ATTEMPT_DELAY - delay for restarts on stream connection drop\n\n        Returns: Instance of InferencePipeline\n\n        Throws:\n            * SourceConnectionError if source cannot be connected at start, however it attempts to reconnect\n                always if connection to stream is lost.\n            * ValueError if workflow specification not provided and registered workflow not pointed out\n            * NotImplementedError if workflow used against multiple videos which is not supported yet\n            * MissingApiKeyError - if API key is not provided in situation when retrieving workflow definition\n                from Roboflow API is needed\n        \"\"\"\n        if ENABLE_WORKFLOWS_PROFILING:\n            profiler = BaseWorkflowsProfiler.init(\n                max_runs_in_buffer=WORKFLOWS_PROFILER_BUFFER_SIZE\n            )\n        else:\n            profiler = NullWorkflowsProfiler.init()\n        if api_key is None:\n            api_key = API_KEY\n        named_workflow_specified = (workspace_name is not None) and (\n            workflow_id is not None\n        )\n        if not named_workflow_specified and not workflow_specification:\n            raise ValueError(\n                \"Either (`workspace_name`, `workflow_id`) or `workflow_specification` must be provided.\"\n            )\n        try:\n            from inference.core.interfaces.stream.model_handlers.workflows import (\n                WorkflowRunner,\n            )\n            from inference.core.roboflow_api import get_workflow_specification\n            from inference.core.workflows.execution_engine.core import ExecutionEngine\n\n            if workflow_specification is None:\n                if api_key is None:\n                    raise MissingApiKeyError(\n                        \"Roboflow API key needs to be provided either as parameter or via env variable \"\n                        \"ROBOFLOW_API_KEY. If you do not know how to get API key - visit \"\n                        \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to \"\n                        \"retrieve one.\"\n                    )\n                with profiler.profile_execution_phase(\n                    name=\"workflow_definition_fetching\",\n                    categories=[\"inference_package_operation\"],\n                ):\n                    workflow_specification = get_workflow_specification(\n                        api_key=api_key,\n                        workspace_id=workspace_name,\n                        workflow_id=workflow_id,\n                        workflow_version_id=workflow_version_id,\n                        use_cache=use_workflow_definition_cache,\n                    )\n            model_registry = RoboflowModelRegistry(ROBOFLOW_MODEL_TYPES)\n            if model_manager is None:\n                model_manager = BackgroundTaskActiveLearningManager(\n                    model_registry=model_registry, cache=cache\n                )\n                model_manager = WithFixedSizeCache(\n                    model_manager,\n                    max_size=MAX_ACTIVE_MODELS,\n                )\n            if workflow_init_parameters is None:\n                workflow_init_parameters = {}\n            thread_pool_executor = ThreadPoolExecutor(\n                max_workers=workflows_thread_pool_workers\n            )\n            workflow_init_parameters[\"workflows_core.model_manager\"] = model_manager\n            workflow_init_parameters[\"workflows_core.api_key\"] = api_key\n            workflow_init_parameters[\"workflows_core.thread_pool_executor\"] = (\n                thread_pool_executor\n            )\n            workflow_init_parameters.setdefault(\n                \"workflows_core.workflow_call_chain\", None\n            )\n            execution_engine = ExecutionEngine.init(\n                workflow_definition=workflow_specification,\n                init_parameters=workflow_init_parameters,\n                workflow_id=workflow_id,\n                profiler=profiler,\n            )\n            workflow_runner = WorkflowRunner()\n            on_video_frame = partial(\n                workflow_runner.run_workflow,\n                workflows_parameters=workflows_parameters,\n                execution_engine=execution_engine,\n                image_input_name=image_input_name,\n                video_metadata_input_name=video_metadata_input_name,\n                serialize_results=serialize_results,\n                _is_preview=_is_preview,\n            )\n        except ImportError as error:\n            raise CannotInitialiseModelError(\n                f\"Could not initialise workflow processing due to lack of dependencies required. \"\n                f\"Please provide an issue report under https://github.com/roboflow/inference/issues\"\n            ) from error\n        on_pipeline_end_closure = partial(\n            on_pipeline_end,\n            thread_pool_executor=thread_pool_executor,\n            cancel_thread_pool_tasks_on_exit=cancel_thread_pool_tasks_on_exit,\n            profiler=profiler,\n            profiling_directory=profiling_directory,\n        )\n        return cls.init_with_custom_logic(\n            video_reference=video_reference,\n            on_video_frame=on_video_frame,\n            on_prediction=on_prediction,\n            on_pipeline_start=None,\n            on_pipeline_end=on_pipeline_end_closure,\n            max_fps=max_fps,\n            watchdog=watchdog,\n            status_update_handlers=status_update_handlers,\n            source_buffer_filling_strategy=source_buffer_filling_strategy,\n            source_buffer_consumption_strategy=source_buffer_consumption_strategy,\n            video_source_properties=video_source_properties,\n            batch_collection_timeout=batch_collection_timeout,\n            predictions_queue_size=predictions_queue_size,\n            decoding_buffer_size=decoding_buffer_size,\n        )\n\n    @classmethod\n    def init_with_custom_logic(\n        cls,\n        video_reference: Union[VideoSourceIdentifier, List[VideoSourceIdentifier]],\n        on_video_frame: InferenceHandler,\n        on_prediction: SinkHandler = None,\n        on_pipeline_start: Optional[Callable[[], None]] = None,\n        on_pipeline_end: Optional[Callable[[], None]] = None,\n        max_fps: Optional[Union[float, int]] = None,\n        watchdog: Optional[PipelineWatchDog] = None,\n        status_update_handlers: Optional[List[Callable[[StatusUpdate], None]]] = None,\n        source_buffer_filling_strategy: Optional[BufferFillingStrategy] = None,\n        source_buffer_consumption_strategy: Optional[BufferConsumptionStrategy] = None,\n        video_source_properties: Optional[Dict[str, float]] = None,\n        batch_collection_timeout: Optional[float] = None,\n        sink_mode: SinkMode = SinkMode.ADAPTIVE,\n        predictions_queue_size: int = PREDICTIONS_QUEUE_SIZE,\n        decoding_buffer_size: int = DEFAULT_BUFFER_SIZE,\n    ) -> \"InferencePipeline\":\n        \"\"\"\n        This class creates the abstraction for making inferences from given workflow against video stream.\n        The way of how `InferencePipeline` works is displayed in `InferencePipeline.init(...)` initialiser\n        method.\n\n        Args:\n            video_reference (Union[str, int, List[Union[str, int]]]): Reference of source or sources to be used to make\n                predictions against. It can be video file path, stream URL and device (like camera) id\n                (we handle whatever cv2 handles). It can also be a list of references (since v0.9.18) - and then\n                it will trigger parallel processing of multiple sources. It has some implication on sinks. See:\n                `sink_mode` parameter comments.\n            on_video_frame (Callable[[VideoFrame], AnyPrediction]): function supposed to make prediction (or do another\n                kind of custom processing according to your will). Accept `VideoFrame` object and is supposed\n                to return dictionary with results of any kind.\n            on_prediction (Callable[AnyPrediction, VideoFrame], None]): Function to be called\n                once prediction is ready - passing both decoded frame, their metadata and dict with output from your\n                custom callable `on_video_frame(...)`. Logic here must be adjusted to the output of `on_video_frame`.\n            on_pipeline_start (Optional[Callable[[], None]]): Optional (parameter-free) function to be called\n                whenever pipeline starts\n            on_pipeline_end (Optional[Callable[[], None]]): Optional (parameter-free) function to be called\n                whenever pipeline ends\n            max_fps (Optional[Union[float, int]]): Specific value passed as this parameter will be used to\n                dictate max FPS of each video source.\n                The implementation details of this option has been changed in release `v0.26.0`. Prior to the release\n                this value, when applied to video files caused the processing to wait `1 / max_fps` seconds before next\n                frame is processed - the new implementation drops the intermediate frames, which seems to be more\n                aligned with peoples expectations.\n                New behaviour is now enabled in experimental mode, by setting environmental variable flag\n                `ENABLE_FRAME_DROP_ON_VIDEO_FILE_RATE_LIMITING=True`. Please note that the new behaviour will\n                be the default one end of Q4 2024!\n            watchdog (Optional[PipelineWatchDog]): Implementation of class that allows profiling of\n                inference pipeline - if not given null implementation (doing nothing) will be used.\n            status_update_handlers (Optional[List[Callable[[StatusUpdate], None]]]): List of handlers to intercept\n                status updates of all elements of the pipeline. Should be used only if detailed inspection of\n                pipeline behaviour in time is needed. Please point out that handlers should be possible to be executed\n                fast - otherwise they will impair pipeline performance. All errors will be logged as warnings\n                without re-raising. Default: None.\n            source_buffer_filling_strategy (Optional[BufferFillingStrategy]): Parameter dictating strategy for\n                video stream decoding behaviour. By default - tweaked to the type of source given.\n                Please find detailed explanation in docs of [`VideoSource`](/reference/inference/core/interfaces/camera/video_source/#inference.core.interfaces.camera.video_source.VideoSource)\n            source_buffer_consumption_strategy (Optional[BufferConsumptionStrategy]): Parameter dictating strategy for\n                video stream frames consumption. By default - tweaked to the type of source given.\n                Please find detailed explanation in docs of [`VideoSource`](/reference/inference/core/interfaces/camera/video_source/#inference.core.interfaces.camera.video_source.VideoSource)\n            video_source_properties (Optional[Union[Dict[str, float], List[Optional[Dict[str, float]]]]]):\n                Optional source properties to set up the video source, corresponding to cv2 VideoCapture properties\n                cv2.CAP_PROP_*. If not given, defaults for the video source will be used.\n                It is optional and if provided can be provided as single dict (applicable for all sources) or\n                as list of configs. Then the list must be of length of `video_reference` and may also contain None\n                values to denote that specific source should remain not configured.\n                Example valid properties are: {\"frame_width\": 1920, \"frame_height\": 1080, \"fps\": 30.0}\n            batch_collection_timeout (Optional[float]): Parameter of multiplex_videos(...) dictating how long process\n                to grab frames from multiple sources can wait for batch to be filled before yielding already collected\n                frames. Please set this value in PRODUCTION to avoid performance drops when specific sources shows\n                unstable latency. Visit `multiplex_videos(...)` for more information about multiplexing process.\n            sink_mode (SinkMode): Parameter that controls how video frames and predictions will be passed to sink\n                handler. With SinkMode.SEQUENTIAL - each frame and prediction triggers separate call for sink,\n                in case of SinkMode.BATCH - list of frames and predictions will be provided to sink, always aligned\n                in the order of video sources - with None values in the place of vide_frames / predictions that\n                were skipped due to `batch_collection_timeout`.\n                `SinkMode.ADAPTIVE` is a middle ground (and default mode) - all old sources will work in that mode\n                against a single video input, as the pipeline will behave as if running in `SinkMode.SEQUENTIAL`.\n                To handle multiple videos - sink needs to accept `predictions: List[Optional[dict]]` and\n                `video_frame: List[Optional[VideoFrame]]`. It is also possible to process multiple videos using\n                old sinks - but then `SinkMode.SEQUENTIAL` is to be used, causing sink to be called on each\n                prediction element.\n            predictions_queue_size int: Size of buffer for predictions that are ready for dispatching\n                default value is taken from INFERENCE_PIPELINE_PREDICTIONS_QUEUE_SIZE env variable\n            decoding_buffer_size (int): size of video source decoding buffer\n                default value is taken from VIDEO_SOURCE_BUFFER_SIZE env variable\n\n        Other ENV variables involved in low-level configuration:\n        * INFERENCE_PIPELINE_PREDICTIONS_QUEUE_SIZE - size of buffer for predictions that are ready for dispatching\n        * INFERENCE_PIPELINE_RESTART_ATTEMPT_DELAY - delay for restarts on stream connection drop\n\n        Returns: Instance of InferencePipeline\n\n        Throws:\n            * SourceConnectionError if source cannot be connected at start, however it attempts to reconnect\n                always if connection to stream is lost.\n        \"\"\"\n        if watchdog is None:\n            watchdog = NullPipelineWatchdog()\n        if status_update_handlers is None:\n            status_update_handlers = []\n        status_update_handlers.append(watchdog.on_status_update)\n        desired_source_fps = None\n        if ENABLE_FRAME_DROP_ON_VIDEO_FILE_RATE_LIMITING:\n            desired_source_fps = max_fps\n        video_sources = prepare_video_sources(\n            video_reference=video_reference,\n            video_source_properties=video_source_properties,\n            status_update_handlers=status_update_handlers,\n            source_buffer_filling_strategy=source_buffer_filling_strategy,\n            source_buffer_consumption_strategy=source_buffer_consumption_strategy,\n            desired_source_fps=desired_source_fps,\n            decoding_buffer_size=decoding_buffer_size,\n        )\n        watchdog.register_video_sources(video_sources=video_sources)\n        try:\n            predictions_queue_size = int(predictions_queue_size)\n        except ValueError:\n            predictions_queue_size = 512\n        predictions_queue = Queue(maxsize=predictions_queue_size)\n        return cls(\n            on_video_frame=on_video_frame,\n            video_sources=video_sources,\n            predictions_queue=predictions_queue,\n            watchdog=watchdog,\n            status_update_handlers=status_update_handlers,\n            on_prediction=on_prediction,\n            max_fps=max_fps,\n            on_pipeline_start=on_pipeline_start,\n            on_pipeline_end=on_pipeline_end,\n            batch_collection_timeout=batch_collection_timeout,\n            sink_mode=sink_mode,\n        )\n\n    def __init__(\n        self,\n        on_video_frame: InferenceHandler,\n        video_sources: List[VideoSource],\n        predictions_queue: Queue,\n        watchdog: PipelineWatchDog,\n        status_update_handlers: List[Callable[[StatusUpdate], None]],\n        on_prediction: SinkHandler = None,\n        on_pipeline_start: Optional[Callable[[], None]] = None,\n        on_pipeline_end: Optional[Callable[[], None]] = None,\n        max_fps: Optional[float] = None,\n        batch_collection_timeout: Optional[float] = None,\n        sink_mode: SinkMode = SinkMode.ADAPTIVE,\n    ):\n        self._on_video_frame = on_video_frame\n        self._video_sources = video_sources\n        self._on_prediction = on_prediction\n        self._max_fps = max_fps\n        self._predictions_queue = predictions_queue\n        self._watchdog = watchdog\n        self._command_handler_thread: Optional[Thread] = None\n        self._inference_thread: Optional[Thread] = None\n        self._dispatching_thread: Optional[Thread] = None\n        self._stop = False\n        self._camera_restart_ongoing = False\n        self._status_update_handlers = status_update_handlers\n        self._on_pipeline_start = on_pipeline_start\n        self._on_pipeline_end = on_pipeline_end\n        self._batch_collection_timeout = batch_collection_timeout\n        self._sink_mode = sink_mode\n\n    def start(self, use_main_thread: bool = True) -> None:\n        self._stop = False\n        self._inference_thread = Thread(target=self._execute_inference)\n        self._inference_thread.start()\n        if self._on_pipeline_start is not None:\n            self._on_pipeline_start()\n        if use_main_thread:\n            self._dispatch_inference_results()\n        else:\n            self._dispatching_thread = Thread(target=self._dispatch_inference_results)\n            self._dispatching_thread.start()\n\n    def terminate(self) -> None:\n        self._stop = True\n        for video_source in self._video_sources:\n            video_source.terminate(\n                wait_on_frames_consumption=False, purge_frames_buffer=True\n            )\n\n    def pause_stream(self, source_id: Optional[int] = None) -> None:\n        for video_source in self._video_sources:\n            if video_source.source_id == source_id or source_id is None:\n                video_source.pause()\n\n    def mute_stream(self, source_id: Optional[int] = None) -> None:\n        for video_source in self._video_sources:\n            if video_source.source_id == source_id or source_id is None:\n                video_source.mute()\n\n    def resume_stream(self, source_id: Optional[int] = None) -> None:\n        for video_source in self._video_sources:\n            if video_source.source_id == source_id or source_id is None:\n                video_source.resume()\n\n    def join(self) -> None:\n        if self._inference_thread is not None:\n            self._inference_thread.join()\n            self._inference_thread = None\n        if self._dispatching_thread is not None:\n            self._dispatching_thread.join()\n            self._dispatching_thread = None\n        if self._on_pipeline_end is not None:\n            self._on_pipeline_end()\n\n    def _execute_inference(self) -> None:\n        send_inference_pipeline_status_update(\n            severity=UpdateSeverity.INFO,\n            event_type=INFERENCE_THREAD_STARTED_EVENT,\n            status_update_handlers=self._status_update_handlers,\n        )\n        logger.info(f\"Inference thread started\")\n        try:\n            for video_frames in self._generate_frames():\n                self._watchdog.on_model_inference_started(\n                    frames=video_frames,\n                )\n                predictions = self._on_video_frame(video_frames)\n                self._watchdog.on_model_prediction_ready(\n                    frames=video_frames,\n                )\n                self._predictions_queue.put((predictions, video_frames))\n                send_inference_pipeline_status_update(\n                    severity=UpdateSeverity.DEBUG,\n                    event_type=INFERENCE_COMPLETED_EVENT,\n                    payload={\n                        \"frames_ids\": [f.frame_id for f in video_frames],\n                        \"frames_timestamps\": [f.frame_timestamp for f in video_frames],\n                        \"sources_id\": [f.source_id for f in video_frames],\n                    },\n                    status_update_handlers=self._status_update_handlers,\n                )\n\n        except Exception as error:\n            payload = {\n                \"error_type\": error.__class__.__name__,\n                \"error_message\": str(error),\n                \"error_context\": \"inference_thread\",\n            }\n            send_inference_pipeline_status_update(\n                severity=UpdateSeverity.ERROR,\n                event_type=INFERENCE_ERROR_EVENT,\n                payload=payload,\n                status_update_handlers=self._status_update_handlers,\n            )\n            logger.exception(f\"Encountered inference error: {error}\")\n        finally:\n            self._predictions_queue.put(None)\n            send_inference_pipeline_status_update(\n                severity=UpdateSeverity.INFO,\n                event_type=INFERENCE_THREAD_FINISHED_EVENT,\n                status_update_handlers=self._status_update_handlers,\n            )\n            logger.info(f\"Inference thread finished\")\n\n    def _dispatch_inference_results(self) -> None:\n        while True:\n            inference_results: Optional[\n                Tuple[List[AnyPrediction], List[VideoFrame]]\n            ] = self._predictions_queue.get()\n            if inference_results is None:\n                self._predictions_queue.task_done()\n                break\n            predictions, video_frames = inference_results\n            if self._on_prediction is not None:\n                self._handle_predictions_dispatching(\n                    predictions=predictions,\n                    video_frames=video_frames,\n                )\n            self._predictions_queue.task_done()\n\n    def _handle_predictions_dispatching(\n        self,\n        predictions: List[AnyPrediction],\n        video_frames: List[VideoFrame],\n    ) -> None:\n        if self._should_use_batch_sink():\n            self._use_batch_sink(predictions, video_frames)\n            return None\n        for frame_predictions, video_frame in zip(predictions, video_frames):\n            self._use_sink(frame_predictions, video_frame)\n\n    def _should_use_batch_sink(self) -> bool:\n        return self._sink_mode is SinkMode.BATCH or (\n            self._sink_mode is SinkMode.ADAPTIVE and len(self._video_sources) > 1\n        )\n\n    def _use_batch_sink(\n        self,\n        predictions: List[AnyPrediction],\n        video_frames: List[VideoFrame],\n    ) -> None:\n        # This function makes it possible to always call sinks with payloads aligned to order of\n        # video sources - marking empty frames as None\n        results_by_source_id = {\n            video_frame.source_id: (frame_predictions, video_frame)\n            for frame_predictions, video_frame in zip(predictions, video_frames)\n        }\n        source_id_aligned_sink_payload = [\n            results_by_source_id.get(video_source.source_id, (None, None))\n            for video_source in self._video_sources\n        ]\n        source_id_aligned_predictions = [e[0] for e in source_id_aligned_sink_payload]\n        source_id_aligned_frames = [e[1] for e in source_id_aligned_sink_payload]\n        self._use_sink(\n            predictions=source_id_aligned_predictions,\n            video_frames=source_id_aligned_frames,\n        )\n\n    def _use_sink(\n        self,\n        predictions: Union[AnyPrediction, List[Optional[AnyPrediction]]],\n        video_frames: Union[VideoFrame, List[Optional[VideoFrame]]],\n    ) -> None:\n        try:\n            self._on_prediction(predictions, video_frames)\n        except Exception as error:\n            payload = {\n                \"error_type\": error.__class__.__name__,\n                \"error_message\": str(error),\n                \"error_context\": \"inference_results_dispatching\",\n            }\n            send_inference_pipeline_status_update(\n                severity=UpdateSeverity.ERROR,\n                event_type=INFERENCE_RESULTS_DISPATCHING_ERROR_EVENT,\n                payload=payload,\n                status_update_handlers=self._status_update_handlers,\n            )\n            logger.exception(f\"Error in results dispatching - {error}\")\n\n    def _generate_frames(\n        self,\n    ) -> Generator[List[VideoFrame], None, None]:\n        for video_source in self._video_sources:\n            video_source.start()\n        max_fps = None\n        if not ENABLE_FRAME_DROP_ON_VIDEO_FILE_RATE_LIMITING:\n            max_fps = self._max_fps\n        yield from multiplex_videos(\n            videos=self._video_sources,\n            max_fps=max_fps,\n            batch_collection_timeout=self._batch_collection_timeout,\n            should_stop=lambda: self._stop,\n        )\n\n\ndef send_inference_pipeline_status_update(\n    severity: UpdateSeverity,\n    event_type: str,\n    status_update_handlers: List[Callable[[StatusUpdate], None]],\n    payload: Optional[dict] = None,\n    sub_context: Optional[str] = None,\n) -> None:\n    if payload is None:\n        payload = {}\n    context = INFERENCE_PIPELINE_CONTEXT\n    if sub_context is not None:\n        context = f\"{context}.{sub_context}\"\n    status_update = StatusUpdate(\n        timestamp=datetime.now(),\n        severity=severity,\n        event_type=event_type,\n        payload=payload,\n        context=context,\n    )\n    for handler in status_update_handlers:\n        try:\n            handler(status_update)\n        except Exception as error:\n            logger.warning(f\"Could not execute handler update. Cause: {error}\")\n",
    "patch": null
  },
  {
    "trace_id": "04e1c67d-0b27-450d-9cee-07390142345b",
    "function_name": "format_email_message",
    "file_path": "inference/core/workflows/core_steps/sinks/email_notification/v2.py",
    "speedup_x": 0.3528876109097496,
    "review_quality": "high",
    "pre_optimization_commit": "d919d77736809981dbfaa5d44a7d5aff8c339ded",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def format_email_message(\n    message: str,\n    message_parameters: Dict[str, Any],\n    message_parameters_operations: Dict[str, List[AllOperationsType]],\n) -> str:\n    \"\"\"Format email message by replacing parameter placeholders with actual values.\"\"\"\n    matching_parameters = PARAMETER_REGEX.findall(message)\n    parameters_to_get_values = {\n        p[1] for p in matching_parameters if p[1] in message_parameters\n    }\n\n    parameters_values = apply_operations_to_message_parameters(\n        message_parameters=message_parameters,\n        message_parameters_operations=message_parameters_operations,\n    )\n\n    parameter_to_placeholders = defaultdict(list)\n    for placeholder, parameter_name in matching_parameters:\n        if parameter_name not in parameters_to_get_values:\n            continue\n        parameter_to_placeholders[parameter_name].append(placeholder)\n    for parameter_name, placeholders in parameter_to_placeholders.items():\n        for placeholder in placeholders:\n            message = message.replace(\n                placeholder, str(parameters_values[parameter_name])\n            )\n    return message\n",
    "optimized_function_code": "import re\nfrom typing import Any, Dict, List\n\nfrom inference.core.workflows.core_steps.common.query_language.entities.operations import AllOperationsType\nfrom inference.core.workflows.core_steps.common.query_language.operations.core import build_operations_chain\n\nPARAMETER_REGEX = re.compile(r\"({{\\s*\\$parameters\\.(\\w+)\\s*}})\")\n\n\ndef apply_operations_to_message_parameters(\n    message_parameters: Dict[str, Any],\n    message_parameters_operations: Dict[str, List[AllOperationsType]],\n) -> Dict[str, Any]:\n    \"\"\"\n    Apply per-parameter operation chains to message parameter values.\n\n    For each parameter in message_parameters, if operations are defined in\n    message_parameters_operations for that parameter name, the operations are\n    applied in order (e.g. ToString, StringToUpperCase, LookupTable).\n    Parameters with no operations are returned unchanged.\n\n    Supports all value types, including WorkflowImageData: image operations\n    such as ExtractImageProperty, ConvertImageToBase64, and ConvertImageToJPEG\n    can be used to transform image parameters before they are serialized or\n    interpolated into the message.\n\n    Returns:\n        A dict with the same keys as message_parameters and values that are\n        either the original value (no operations) or the result of the\n        operations chain.\n    \"\"\"\n    parameters_values = {}\n    for parameter_name, parameter_value in message_parameters.items():\n\n        operations = message_parameters_operations.get(parameter_name)\n        if not operations:\n            parameters_values[parameter_name] = parameter_value\n            continue\n\n        operations_chain = build_operations_chain(operations=operations)\n        parameters_values[parameter_name] = operations_chain(\n            parameter_value, global_parameters={}\n        )\n\n    return parameters_values\n\n\ndef format_email_message(\n    message: str,\n    message_parameters: Dict[str, Any],\n    message_parameters_operations: Dict[str, List[AllOperationsType]],\n) -> str:\n    \"\"\"Format email message by replacing parameter placeholders with actual values.\"\"\"\n    matching_parameters = PARAMETER_REGEX.findall(message)\n    if not matching_parameters:\n        return message\n\n    parameters_values = apply_operations_to_message_parameters(\n        message_parameters=message_parameters,\n        message_parameters_operations=message_parameters_operations,\n    )\n\n    for placeholder, parameter_name in matching_parameters:\n        if parameter_name in message_parameters:\n            message = message.replace(\n                placeholder, str(parameters_values[parameter_name])\n            )\n    return message",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/sinks/email_notification/v2.py\nimport re\nfrom typing import Any, Dict, List\n\nfrom inference.core.workflows.core_steps.common.query_language.entities.operations import AllOperationsType\nfrom inference.core.workflows.core_steps.common.query_language.operations.core import build_operations_chain\n\nPARAMETER_REGEX = re.compile(r\"({{\\s*\\$parameters\\.(\\w+)\\s*}})\")\n\n\ndef apply_operations_to_message_parameters(\n    message_parameters: Dict[str, Any],\n    message_parameters_operations: Dict[str, List[AllOperationsType]],\n) -> Dict[str, Any]:\n    \"\"\"\n    Apply per-parameter operation chains to message parameter values.\n\n    For each parameter in message_parameters, if operations are defined in\n    message_parameters_operations for that parameter name, the operations are\n    applied in order (e.g. ToString, StringToUpperCase, LookupTable).\n    Parameters with no operations are returned unchanged.\n\n    Supports all value types, including WorkflowImageData: image operations\n    such as ExtractImageProperty, ConvertImageToBase64, and ConvertImageToJPEG\n    can be used to transform image parameters before they are serialized or\n    interpolated into the message.\n\n    Returns:\n        A dict with the same keys as message_parameters and values that are\n        either the original value (no operations) or the result of the\n        operations chain.\n    \"\"\"\n    parameters_values = {}\n    for parameter_name, parameter_value in message_parameters.items():\n\n        operations = message_parameters_operations.get(parameter_name)\n        if not operations:\n            parameters_values[parameter_name] = parameter_value\n            continue\n\n        operations_chain = build_operations_chain(operations=operations)\n        parameters_values[parameter_name] = operations_chain(\n            parameter_value, global_parameters={}\n        )\n\n    return parameters_values\n\n\ndef format_email_message(\n    message: str,\n    message_parameters: Dict[str, Any],\n    message_parameters_operations: Dict[str, List[AllOperationsType]],\n) -> str:\n    \"\"\"Format email message by replacing parameter placeholders with actual values.\"\"\"\n    matching_parameters = PARAMETER_REGEX.findall(message)\n    if not matching_parameters:\n        return message\n\n    parameters_values = apply_operations_to_message_parameters(\n        message_parameters=message_parameters,\n        message_parameters_operations=message_parameters_operations,\n    )\n\n    for placeholder, parameter_name in matching_parameters:\n        if parameter_name in message_parameters:\n            message = message.replace(\n                placeholder, str(parameters_values[parameter_name])\n            )\n    return message\n```",
    "optimized_function_only": "def format_email_message(\n    message: str,\n    message_parameters: Dict[str, Any],\n    message_parameters_operations: Dict[str, List[AllOperationsType]],\n) -> str:\n    \"\"\"Format email message by replacing parameter placeholders with actual values.\"\"\"\n    matching_parameters = PARAMETER_REGEX.findall(message)\n    if not matching_parameters:\n        return message\n\n    parameters_values = apply_operations_to_message_parameters(\n        message_parameters=message_parameters,\n        message_parameters_operations=message_parameters_operations,\n    )\n\n    for placeholder, parameter_name in matching_parameters:\n        if parameter_name in message_parameters:\n            message = message.replace(\n                placeholder, str(parameters_values[parameter_name])\n            )\n    return message",
    "original_file_content": "import logging\nimport re\nfrom collections import defaultdict\nfrom concurrent.futures import ThreadPoolExecutor\nfrom datetime import datetime\nfrom functools import partial\nfrom typing import Any, Dict, List, Literal, Optional, Tuple, Type, Union\n\nfrom fastapi import BackgroundTasks\nfrom pydantic import ConfigDict, Field, field_validator\n\nfrom inference.core.roboflow_api import post_to_roboflow_api\nfrom inference.core.utils.image_utils import encode_image_to_jpeg_bytes\nfrom inference.core.workflows.core_steps.common.query_language.entities.operations import (\n    AllOperationsType,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.core import (\n    build_operations_chain,\n)\nfrom inference.core.workflows.core_steps.sinks.email_notification.v1 import (\n    send_email_using_smtp_server,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    BOOLEAN_KIND,\n    BYTES_KIND,\n    IMAGE_KIND,\n    INTEGER_KIND,\n    LIST_OF_VALUES_KIND,\n    ROBOFLOW_MANAGED_KEY,\n    SECRET_KIND,\n    STRING_KIND,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nLONG_DESCRIPTION = \"\"\"\nThe **Email Notification** block allows users to send email notifications as part of a workflow.\n\n## How This Block Works\n\n### Email Provider Options\n\nThis block supports two email delivery methods via a dropdown selector:\n\n1. **Roboflow Managed API Key (Default)** - No SMTP configuration needed. Emails are sent through Roboflow's proxy service:\n   * **Simplified setup** - just provide subject, message, and recipient\n   * **Secure** - your workflow API key is used for authentication\n   * **No SMTP server required**\n\n2. **Custom SMTP** - Use your own SMTP server:\n   * Full control over email delivery\n   * Requires SMTP server configuration (host, port, credentials)\n   * Supports CC and BCC recipients\n\n### Customizable Email Content\n\n* **Subject:** Set the subject field to define the subject line of the email.\n\n* **Message:** Use the message field to write the body content of the email. **Message can be parametrised\nwith data generated during workflow run. See *Dynamic Parameters* section.**\n\n* **Recipients (To, CC, BCC)**: Define who will receive the email using `receiver_email`, \n`cc_receiver_email`, and `bcc_receiver_email` properties. You can input a single email or a list.\n\n### Dynamic Parameters\n\nContent of the message can be parametrised with Workflow execution outcomes. Take a look at the example\nmessage using dynamic parameters:\n\n```\nmessage = \"This is example notification. Predicted classes: {{ '{{' }} $parameters.predicted_classes {{ '}}' }}\"\n```\n\nMessage parameters are delivered by Workflows Execution Engine by setting proper data selectors in\n`message_parameters` field, for example:\n\n```\nmessage_parameters = {\n    \"predicted_classes\": \"$steps.model.predictions\"\n}\n```\n\nSelecting data is not the only option - data may be processed in the block. In the example below we wish to\nextract names of predicted classes. We can apply transformation **for each parameter** by setting\n`message_parameters_operations`:\n\n```\nmessage_parameters_operations = {\n    \"predictions\": [\n        {\"type\": \"DetectionsPropertyExtract\", \"property_name\": \"class_name\"}\n    ]\n}\n```\n\nAs a result, in the e-mail that will be sent, you can expect:\n\n```\nThis is example notification. Predicted classes: [\"class_a\", \"class_b\"].\n```\n\n### Using Custom SMTP Server\n\nTo use your own SMTP server, select \"Custom SMTP\" from the `email_provider` dropdown and configure \nthe following parameters:\n\n* `smtp_server` - hostname of the SMTP server to use\n\n* `sender_email` - e-mail account to be used as sender\n\n* `sender_email_password` - password for sender e-mail account\n\n* `smtp_port` - port of SMTP service - defaults to `465`\n\nBlock **enforces** SSL over SMTP.\n\nTypical scenario for using custom SMTP server involves sending e-mail through Google SMTP server.\nTake a look at [Google tutorial](https://support.google.com/a/answer/176600?hl=en) to configure the \nblock properly. \n\n!!! note \"GMAIL password will not work if 2-step verification is turned on\"\n    \n    GMAIL users choosing custom SMTP server as e-mail service provider must configure \n    [application password](https://support.google.com/accounts/answer/185833) to avoid\n    problems with 2-step verification protected account. Beware that **application\n    password must be kept protected** - we recommend sending the password in Workflow \n    input and providing it each time by the caller, avoiding storing it in Workflow \n    definition.\n    \n### Cooldown\n\nThe block accepts `cooldown_seconds` (which **defaults to `5` seconds**) to prevent unintended bursts of \nnotifications. Please adjust it according to your needs, setting `0` indicate no cooldown. \n\nDuring cooldown period, consecutive runs of the step will cause `throttling_status` output to be set `True`\nand no notification will be sent.\n\n!!! warning \"Cooldown limitations\"\n\n    Current implementation of cooldown is limited to video processing - using this block in context of a \n    Workflow that is run behind HTTP service (Roboflow Hosted API, Dedicated Deployment or self-hosted \n    `inference` server) will have no effect for processing HTTP requests.  \n\n### Attachments\n\nYou may specify attachment files to be sent with your e-mail. Attachments can be generated \nin runtime by dedicated blocks or from image outputs.\n\n**Supported attachment types:**\n- **CSV/Text files**: From blocks like [CSV Formatter](https://inference.roboflow.com/workflows/csv_formatter/)\n- **Images**: Any image output from visualization blocks (automatically converted to JPEG)\n- **Binary data**: Any bytes output from compatible blocks\n\nTo include attachments, provide the attachment filename as the key and reference the block output:\n\n```\nattachments = {\n    \"report.csv\": \"$steps.csv_formatter.csv_content\",\n    \"detection.jpg\": \"$steps.bounding_box_visualization.image\"\n}\n```\n\n**Note:** Image attachments are automatically converted to JPEG format. If the filename doesn't \ninclude a `.jpg` or `.jpeg` extension, it will be added automatically.\n\n### Async execution\n\nConfigure the `fire_and_forget` property. Set it to True if you want the email to be sent in the background, allowing the \nWorkflow to proceed without waiting on e-mail to be sent. In this case you will not be able to rely on \n`error_status` output which will always be set to `False`, so we **recommend setting the `fire_and_forget=False` for\ndebugging purposes**.\n\n### Disabling notifications based on runtime parameter\n\nSometimes it would be convenient to manually disable the e-mail notifier block. This is possible \nsetting `disable_sink` flag to hold reference to Workflow input. with such setup, caller would be\nable to disable the sink when needed sending agreed input parameter.\n\n## Common Use Cases\n\n- Use this block to [purpose based on block type]\n\n## Connecting to Other Blocks\n\nThe outputs from this block can be connected to other blocks in your workflow.\n\"\"\"\n\nPARAMETER_REGEX = re.compile(r\"({{\\s*\\$parameters\\.(\\w+)\\s*}})\")\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Email Notification\",\n            \"version\": \"v2\",\n            \"short_description\": \"Send notification via e-mail.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"sink\",\n            \"ui_manifest\": {\n                \"section\": \"notifications\",\n                \"icon\": \"far fa-envelope\",\n                \"blockPriority\": 0,\n                \"popular\": True,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/email_notification@v2\"]\n\n    email_provider: Literal[\"Roboflow Managed API Key\", \"Custom SMTP\"] = Field(\n        default=\"Roboflow Managed API Key\",\n        description=\"Choose email delivery method: use Roboflow's managed service or configure your own SMTP server.\",\n        examples=[\"Roboflow Managed API Key\", \"Custom SMTP\"],\n        json_schema_extra={\n            \"always_visible\": True,\n        },\n    )\n\n    subject: str = Field(\n        description=\"Subject of the message.\",\n        examples=[\"Workflow alert\"],\n        json_schema_extra={\n            \"hide_description\": True,\n            \"always_visible\": True,\n        },\n    )\n\n    receiver_email: Union[\n        str,\n        List[str],\n        Selector(kind=[STRING_KIND, LIST_OF_VALUES_KIND]),\n    ] = Field(\n        description=\"Destination e-mail address.\",\n        examples=[\"receiver@gmail.com\"],\n        json_schema_extra={\n            \"hide_description\": True,\n            \"always_visible\": True,\n        },\n    )\n\n    message: str = Field(\n        description=\"Content of the message to be send.\",\n        examples=[\n            \"During last 5 minutes detected {{ $parameters.num_instances }} instances\"\n        ],\n        json_schema_extra={\n            \"hide_description\": True,\n            \"multiline\": True,\n            \"always_visible\": True,\n        },\n    )\n\n    message_parameters: Dict[\n        str,\n        Union[Selector(), Selector(), str, int, float, bool],\n    ] = Field(\n        description=\"Data to be used inside the message.\",\n        examples=[\n            {\n                \"predictions\": \"$steps.model.predictions\",\n                \"reference\": \"$inputs.reference_class_names\",\n            }\n        ],\n        default_factory=dict,\n        json_schema_extra={\n            \"always_visible\": True,\n        },\n    )\n\n    message_parameters_operations: Dict[str, List[AllOperationsType]] = Field(\n        description=\"Preprocessing operations to be performed on message parameters.\",\n        examples=[\n            {\n                \"predictions\": [\n                    {\"type\": \"DetectionsPropertyExtract\", \"property_name\": \"class_name\"}\n                ]\n            }\n        ],\n        default_factory=dict,\n    )\n\n    # SMTP fields - hidden when using Roboflow Managed API Key\n    sender_email: Optional[Union[str, Selector(kind=[STRING_KIND])]] = Field(\n        default=None,\n        description=\"E-mail to be used to send the message.\",\n        examples=[\"sender@gmail.com\"],\n        json_schema_extra={\n            \"hide_description\": True,\n            \"relevant_for\": {\n                \"email_provider\": {\"values\": [\"Custom SMTP\"], \"required\": True},\n            },\n        },\n    )\n\n    smtp_server: Optional[Union[str, Selector(kind=[STRING_KIND])]] = Field(\n        default=None,\n        description=\"Custom SMTP server to be used.\",\n        examples=[\"$inputs.smtp_server\", \"smtp.google.com\"],\n        json_schema_extra={\n            \"relevant_for\": {\n                \"email_provider\": {\"values\": [\"Custom SMTP\"], \"required\": True},\n            },\n        },\n    )\n\n    sender_email_password: Optional[\n        Union[str, Selector(kind=[STRING_KIND, SECRET_KIND])]\n    ] = Field(\n        default=None,\n        description=\"Sender e-mail password be used when authenticating to SMTP server.\",\n        private=True,\n        examples=[\"$inputs.email_password\"],\n        json_schema_extra={\n            \"relevant_for\": {\n                \"email_provider\": {\"values\": [\"Custom SMTP\"], \"required\": True},\n            },\n        },\n    )\n\n    cc_receiver_email: Optional[\n        Union[\n            str,\n            List[str],\n            Selector(kind=[STRING_KIND, LIST_OF_VALUES_KIND]),\n        ]\n    ] = Field(\n        default=None,\n        description=\"CC e-mail address.\",\n        examples=[\"cc-receiver@gmail.com\"],\n        json_schema_extra={\n            \"hide_description\": True,\n            \"relevant_for\": {\n                \"email_provider\": {\"values\": [\"Custom SMTP\"], \"required\": True},\n            },\n        },\n    )\n\n    bcc_receiver_email: Optional[\n        Union[\n            str,\n            List[str],\n            Selector(kind=[STRING_KIND, LIST_OF_VALUES_KIND]),\n        ]\n    ] = Field(\n        default=None,\n        description=\"BCC e-mail address.\",\n        examples=[\"bcc-receiver@gmail.com\"],\n        json_schema_extra={\n            \"hide_description\": True,\n            \"relevant_for\": {\n                \"email_provider\": {\"values\": [\"Custom SMTP\"], \"required\": True},\n            },\n        },\n    )\n\n    smtp_port: int = Field(\n        default=465,\n        description=\"SMTP server port.\",\n        examples=[465],\n        json_schema_extra={\n            \"relevant_for\": {\n                \"email_provider\": {\"values\": [\"Custom SMTP\"], \"required\": True},\n            },\n        },\n    )\n\n    attachments: Dict[str, Selector(kind=[STRING_KIND, BYTES_KIND, IMAGE_KIND])] = (\n        Field(\n            description=\"Attachments\",\n            default_factory=dict,\n            examples=[{\"report.cvs\": \"$steps.csv_formatter.csv_content\"}],\n            json_schema_extra={\n                \"hide_description\": True,\n            },\n        )\n    )\n\n    fire_and_forget: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=True,\n        description=\"Boolean flag to run the block asynchronously (True) for faster workflows or  \"\n        \"synchronously (False) for debugging and error handling.\",\n        examples=[\"$inputs.fire_and_forget\", False],\n    )\n\n    disable_sink: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=False,\n        description=\"Boolean flag to disable block execution.\",\n        examples=[False, \"$inputs.disable_email_notifications\"],\n    )\n\n    cooldown_seconds: Union[int, Selector(kind=[INTEGER_KIND])] = Field(\n        default=5,\n        description=\"Number of seconds until a follow-up notification can be sent. \",\n        examples=[\"$inputs.cooldown_seconds\", 3],\n        json_schema_extra={\n            \"always_visible\": True,\n        },\n    )\n\n    @field_validator(\"receiver_email\")\n    @classmethod\n    def ensure_receiver_email_is_not_an_empty_list(cls, value: Any) -> dict:\n        if isinstance(value, list) and len(value) == 0:\n            raise ValueError(\n                \"E-mail notification must have at least one receiver defined.\"\n            )\n        return value\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"error_status\", kind=[BOOLEAN_KIND]),\n            OutputDefinition(name=\"throttling_status\", kind=[BOOLEAN_KIND]),\n            OutputDefinition(name=\"message\", kind=[STRING_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.4.0,<2.0.0\"\n\n\nclass EmailNotificationBlockV2(WorkflowBlock):\n\n    def __init__(\n        self,\n        background_tasks: Optional[BackgroundTasks],\n        thread_pool_executor: Optional[ThreadPoolExecutor],\n        api_key: Optional[str],\n    ):\n        self._background_tasks = background_tasks\n        self._thread_pool_executor = thread_pool_executor\n        self._api_key = api_key\n        self._last_notification_fired: Optional[datetime] = None\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"background_tasks\", \"thread_pool_executor\", \"api_key\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        subject: str,\n        message: str,\n        receiver_email: Union[str, List[str]],\n        email_provider: str,\n        sender_email: Optional[str],\n        cc_receiver_email: Optional[Union[str, List[str]]],\n        bcc_receiver_email: Optional[Union[str, List[str]]],\n        message_parameters: Dict[str, Any],\n        message_parameters_operations: Dict[str, List[AllOperationsType]],\n        attachments: Dict[str, str],\n        smtp_server: Optional[str],\n        sender_email_password: Optional[str],\n        smtp_port: int,\n        fire_and_forget: bool,\n        disable_sink: bool,\n        cooldown_seconds: int,\n    ) -> BlockResult:\n        if disable_sink:\n            return {\n                \"error_status\": False,\n                \"throttling_status\": False,\n                \"message\": \"Sink was disabled by parameter `disable_sink`\",\n            }\n        seconds_since_last_notification = cooldown_seconds\n        if self._last_notification_fired is not None:\n            seconds_since_last_notification = (\n                datetime.now() - self._last_notification_fired\n            ).total_seconds()\n        if seconds_since_last_notification < cooldown_seconds:\n            logging.info(f\"Activated `roboflow_core/email_notification@v2` cooldown.\")\n            return {\n                \"error_status\": False,\n                \"throttling_status\": True,\n                \"message\": \"Sink cooldown applies\",\n            }\n\n        receiver_email = (\n            receiver_email if isinstance(receiver_email, list) else [receiver_email]\n        )\n        if cc_receiver_email is not None:\n            cc_receiver_email = (\n                cc_receiver_email\n                if isinstance(cc_receiver_email, list)\n                else [cc_receiver_email]\n            )\n        if bcc_receiver_email is not None:\n            bcc_receiver_email = (\n                bcc_receiver_email\n                if isinstance(bcc_receiver_email, list)\n                else [bcc_receiver_email]\n            )\n\n        # Check if using Roboflow Managed API Key\n        use_managed_service = email_provider == \"Roboflow Managed API Key\"\n\n        if use_managed_service:\n            send_email_handler = partial(\n                send_email_via_roboflow_proxy,\n                roboflow_api_key=self._api_key,\n                receiver_email=receiver_email,\n                cc_receiver_email=cc_receiver_email,\n                bcc_receiver_email=bcc_receiver_email,\n                subject=subject,\n                message=message,\n                message_parameters=message_parameters,\n                message_parameters_operations=message_parameters_operations,\n                attachments=attachments,\n            )\n        else:\n            # Validate required SMTP fields\n            if not sender_email or not smtp_server or not sender_email_password:\n                return {\n                    \"error_status\": True,\n                    \"throttling_status\": False,\n                    \"message\": \"Custom SMTP requires sender_email, smtp_server, and sender_email_password\",\n                }\n\n            # Always format as HTML for SMTP to match Resend pathway behavior\n            formatted_message, inline_images = format_email_message_html_with_images(\n                message=message,\n                message_parameters=message_parameters,\n                message_parameters_operations=message_parameters_operations,\n            )\n            is_html = True\n\n            # Process attachments: convert images to bytes for SMTP\n            processed_attachments = {}\n            for filename, value in attachments.items():\n                if isinstance(value, WorkflowImageData):\n                    # Convert image to JPEG bytes\n                    numpy_image = value.numpy_image\n                    jpeg_bytes = encode_image_to_jpeg_bytes(numpy_image)\n                    # Ensure filename has .jpg extension\n                    if not filename.lower().endswith((\".jpg\", \".jpeg\")):\n                        filename = f\"{filename}.jpg\"\n                    processed_attachments[filename] = jpeg_bytes\n                elif isinstance(value, bytes):\n                    processed_attachments[filename] = value\n                elif isinstance(value, str):\n                    # String content (e.g., CSV)\n                    processed_attachments[filename] = value.encode(\"utf-8\")\n                else:\n                    # Fallback: convert to string then bytes\n                    processed_attachments[filename] = str(value).encode(\"utf-8\")\n\n            # Always use v2 SMTP function for HTML support (matches Resend behavior)\n            send_email_handler = partial(\n                send_email_using_smtp_server_v2,\n                sender_email=sender_email,\n                receiver_email=receiver_email,\n                cc_receiver_email=cc_receiver_email,\n                bcc_receiver_email=bcc_receiver_email,\n                subject=subject,\n                message=formatted_message,\n                attachments=processed_attachments,\n                smtp_server=smtp_server,\n                smtp_port=smtp_port,\n                sender_email_password=sender_email_password,\n                inline_images=inline_images,\n                is_html=is_html,\n            )\n\n        self._last_notification_fired = datetime.now()\n        if fire_and_forget and self._background_tasks:\n            self._background_tasks.add_task(send_email_handler)\n            return {\n                \"error_status\": False,\n                \"throttling_status\": False,\n                \"message\": \"Notification sent in the background task\",\n            }\n        if fire_and_forget and self._thread_pool_executor:\n            self._thread_pool_executor.submit(send_email_handler)\n            return {\n                \"error_status\": False,\n                \"throttling_status\": False,\n                \"message\": \"Notification sent in the background task\",\n            }\n        error_status, message = send_email_handler()\n        return {\n            \"error_status\": error_status,\n            \"throttling_status\": False,\n            \"message\": message,\n        }\n\n\ndef apply_operations_to_message_parameters(\n    message_parameters: Dict[str, Any],\n    message_parameters_operations: Dict[str, List[AllOperationsType]],\n) -> Dict[str, Any]:\n    \"\"\"\n    Apply per-parameter operation chains to message parameter values.\n\n    For each parameter in message_parameters, if operations are defined in\n    message_parameters_operations for that parameter name, the operations are\n    applied in order (e.g. ToString, StringToUpperCase, LookupTable).\n    Parameters with no operations are returned unchanged.\n\n    Supports all value types, including WorkflowImageData: image operations\n    such as ExtractImageProperty, ConvertImageToBase64, and ConvertImageToJPEG\n    can be used to transform image parameters before they are serialized or\n    interpolated into the message.\n\n    Returns:\n        A dict with the same keys as message_parameters and values that are\n        either the original value (no operations) or the result of the\n        operations chain.\n    \"\"\"\n    parameters_values = {}\n    for parameter_name in message_parameters:\n        parameter_value = message_parameters[parameter_name]\n\n        operations = message_parameters_operations.get(parameter_name)\n        if not operations:\n            parameters_values[parameter_name] = parameter_value\n            continue\n\n        operations_chain = build_operations_chain(operations=operations)\n        parameters_values[parameter_name] = operations_chain(\n            parameter_value, global_parameters={}\n        )\n\n    return parameters_values\n\n\ndef format_email_message(\n    message: str,\n    message_parameters: Dict[str, Any],\n    message_parameters_operations: Dict[str, List[AllOperationsType]],\n) -> str:\n    \"\"\"Format email message by replacing parameter placeholders with actual values.\"\"\"\n    matching_parameters = PARAMETER_REGEX.findall(message)\n    parameters_to_get_values = {\n        p[1] for p in matching_parameters if p[1] in message_parameters\n    }\n\n    parameters_values = apply_operations_to_message_parameters(\n        message_parameters=message_parameters,\n        message_parameters_operations=message_parameters_operations,\n    )\n\n    parameter_to_placeholders = defaultdict(list)\n    for placeholder, parameter_name in matching_parameters:\n        if parameter_name not in parameters_to_get_values:\n            continue\n        parameter_to_placeholders[parameter_name].append(placeholder)\n    for parameter_name, placeholders in parameter_to_placeholders.items():\n        for placeholder in placeholders:\n            message = message.replace(\n                placeholder, str(parameters_values[parameter_name])\n            )\n    return message\n\n\ndef format_email_message_html_with_images(\n    message: str,\n    message_parameters: Dict[str, Any],\n    message_parameters_operations: Dict[str, List[AllOperationsType]],\n) -> Tuple[str, Dict[str, bytes]]:\n    \"\"\"Format email message as HTML with inline images.\"\"\"\n    matching_parameters = PARAMETER_REGEX.findall(message)\n    parameters_to_get_values = {\n        p[1] for p in matching_parameters if p[1] in message_parameters\n    }\n\n    parameters_values = {}\n    image_attachments = {}\n\n    for parameter_name in parameters_to_get_values:\n        parameter_value = message_parameters[parameter_name]\n\n        # Apply operations if any\n        operations = message_parameters_operations.get(parameter_name)\n        if operations:\n            operations_chain = build_operations_chain(operations=operations)\n            parameter_value = operations_chain(parameter_value, global_parameters={})\n\n        if isinstance(parameter_value, WorkflowImageData):\n            # Convert to JPEG and create CID\n            jpeg_bytes = encode_image_to_jpeg_bytes(parameter_value.numpy_image)\n            cid = f\"image_{parameter_name}\"\n            image_attachments[cid] = jpeg_bytes\n            parameters_values[parameter_name] = (\n                f'<img src=\"cid:{cid}\" alt=\"{parameter_name}\" style=\"max-width: 600px; height: auto;\">'\n            )\n        else:\n            import html\n\n            parameters_values[parameter_name] = html.escape(str(parameter_value))\n\n    # Replace placeholders\n    parameter_to_placeholders = defaultdict(list)\n    for placeholder, parameter_name in matching_parameters:\n        if parameter_name in parameters_to_get_values:\n            parameter_to_placeholders[parameter_name].append(placeholder)\n\n    html_message = message\n    for parameter_name, placeholders in parameter_to_placeholders.items():\n        for placeholder in placeholders:\n            html_message = html_message.replace(\n                placeholder, str(parameters_values[parameter_name])\n            )\n\n    # Convert newlines to <br> tags for HTML\n    html_message = html_message.replace(\"\\n\", \"<br>\\n\")\n\n    return html_message, image_attachments\n\n\ndef serialize_image_data(value: Any) -> Any:\n    \"\"\"\n    Serialize WorkflowImageData objects to base64 strings for JSON transmission.\n    Returns the value unchanged if it's not a WorkflowImageData object.\n    \"\"\"\n    if isinstance(value, WorkflowImageData):\n        # Get the base64 representation of the image\n        base64_image = value.base64_image\n        if base64_image:\n            return base64_image\n        # If no base64 available, try to convert numpy array\n        numpy_image = value.numpy_image\n        if numpy_image is not None:\n            import cv2\n\n            _, buffer = cv2.imencode(\".jpg\", numpy_image)\n            import base64\n\n            return base64.b64encode(buffer).decode(\"utf-8\")\n    elif isinstance(value, dict):\n        return {k: serialize_image_data(v) for k, v in value.items()}\n    elif isinstance(value, list):\n        return [serialize_image_data(item) for item in value]\n    return value\n\n\ndef serialize_image_data_parameters(\n    message_parameters: Dict[str, Any]\n) -> Dict[str, Any]:\n    \"\"\"\n    Convert any WorkflowImageData objects in message_parameters to base64 strings\n    so they can be serialized to JSON for the API call.\n    \"\"\"\n    return {k: serialize_image_data(v) for k, v in message_parameters.items()}\n\n\ndef process_attachments(attachments: Dict[str, Any]) -> Dict[str, bytes]:\n    \"\"\"\n    Process attachments dict to convert WorkflowImageData to JPEG bytes.\n    Returns a dict with filename -> bytes mapping.\n    \"\"\"\n    processed = {}\n    for filename, value in attachments.items():\n        if isinstance(value, WorkflowImageData):\n            # Convert image to JPEG bytes\n            numpy_image = value.numpy_image\n            jpeg_bytes = encode_image_to_jpeg_bytes(numpy_image)\n            processed[filename] = jpeg_bytes\n        elif isinstance(value, bytes):\n            # Already bytes, use as-is\n            processed[filename] = value\n        elif isinstance(value, str):\n            # String data (e.g., CSV content)\n            processed[filename] = value.encode(\"utf-8\")\n        else:\n            # Fallback: convert to string then bytes\n            processed[filename] = str(value).encode(\"utf-8\")\n    return processed\n\n\ndef send_email_via_roboflow_proxy(\n    roboflow_api_key: str,\n    receiver_email: List[str],\n    cc_receiver_email: Optional[List[str]],\n    bcc_receiver_email: Optional[List[str]],\n    subject: str,\n    message: str,\n    message_parameters: Dict[str, Any],\n    message_parameters_operations: Dict[str, List[AllOperationsType]],\n    attachments: Dict[str, Any],\n) -> Tuple[bool, str]:\n    \"\"\"Send email through Roboflow's proxy service.\"\"\"\n    from inference.core.exceptions import (\n        RoboflowAPIForbiddenError,\n        RoboflowAPIUnsuccessfulRequestError,\n    )\n\n    # Custom error handler that preserves the API's error message\n    def handle_email_proxy_error(status_code: int, http_error: Exception) -> None:\n        \"\"\"Extract and preserve the actual error message from the API response.\"\"\"\n        try:\n            response = http_error.response\n            error_data = response.json()\n            # API returns 'details' field with the actual message, 'error' is generic\n            # Prioritize 'details' over 'error' for more specific messages\n            api_error_message = (\n                error_data.get(\"details\") or error_data.get(\"error\") or str(http_error)\n            )\n        except Exception:\n            api_error_message = str(http_error)\n\n        # Raise appropriate exception with the actual API error message\n        if status_code == 403:\n            raise RoboflowAPIForbiddenError(api_error_message) from http_error\n        elif status_code == 413:\n            raise RoboflowAPIUnsuccessfulRequestError(api_error_message) from http_error\n        elif status_code == 429:\n            raise RoboflowAPIUnsuccessfulRequestError(api_error_message) from http_error\n        else:\n            raise RoboflowAPIUnsuccessfulRequestError(api_error_message) from http_error\n\n    # Map status codes to our custom handler\n    custom_error_handlers = {\n        403: lambda e: handle_email_proxy_error(403, e),\n        413: lambda e: handle_email_proxy_error(413, e),\n        429: lambda e: handle_email_proxy_error(429, e),\n    }\n\n    try:\n        message_parameters_after_operations = apply_operations_to_message_parameters(\n            message_parameters=message_parameters,\n            message_parameters_operations=message_parameters_operations,\n        )\n        # Serialize any WorkflowImageData objects to base64 strings for JSON transmission\n        serialized_parameters = serialize_image_data_parameters(\n            message_parameters_after_operations\n        )\n\n        payload = {\n            \"receiver_email\": receiver_email,\n            \"subject\": subject,\n            \"message\": message,\n            \"message_parameters\": serialized_parameters,\n        }\n\n        if cc_receiver_email:\n            payload[\"cc_receiver_email\"] = cc_receiver_email\n        if bcc_receiver_email:\n            payload[\"bcc_receiver_email\"] = bcc_receiver_email\n        if attachments:\n            # Process attachments: convert images to JPEG bytes, then base64 encode\n            import base64\n\n            processed_attachments = {}\n            for filename, value in attachments.items():\n                if isinstance(value, WorkflowImageData):\n                    # Convert image to JPEG bytes\n                    numpy_image = value.numpy_image\n                    jpeg_bytes = encode_image_to_jpeg_bytes(numpy_image)\n                    # Ensure filename has .jpg extension\n                    if not filename.lower().endswith((\".jpg\", \".jpeg\")):\n                        filename = f\"{filename}.jpg\"\n                    # Base64 encode for JSON transmission\n                    processed_attachments[filename] = base64.b64encode(\n                        jpeg_bytes\n                    ).decode(\"utf-8\")\n                elif isinstance(value, bytes):\n                    # Already bytes, base64 encode\n                    processed_attachments[filename] = base64.b64encode(value).decode(\n                        \"utf-8\"\n                    )\n                elif isinstance(value, str):\n                    # String data (e.g., CSV content), base64 encode\n                    processed_attachments[filename] = base64.b64encode(\n                        value.encode(\"utf-8\")\n                    ).decode(\"utf-8\")\n                else:\n                    # Fallback: convert to string then bytes then base64\n                    processed_attachments[filename] = base64.b64encode(\n                        str(value).encode(\"utf-8\")\n                    ).decode(\"utf-8\")\n            payload[\"attachments\"] = processed_attachments\n\n        endpoint = \"apiproxy/email\"\n\n        response_data = post_to_roboflow_api(\n            endpoint=endpoint,\n            api_key=roboflow_api_key,\n            payload=payload,\n            http_errors_handlers=custom_error_handlers,\n        )\n\n        return False, \"Notification sent successfully via Roboflow proxy\"\n    except RoboflowAPIForbiddenError as error:\n        # Handle 403 errors (whitelist violations)\n        error_message = str(error)\n        logging.warning(\n            f\"Email rejected by proxy due to access restrictions: {error_message}\"\n        )\n\n        # Check if it's a workspace member restriction\n        # The API returns detailed error messages about non-workspace members\n        if \"non-workspace members\" in error_message.lower():\n            return True, (\n                \"To prevent spam, you can only send emails to members of your Roboflow Workspace via the Roboflow Managed API Key. \"\n                \"Add this email to your Workspace or switch to sending via your own SMTP server.\"\n            )\n        else:\n            return True, f\"Failed to send email: access forbidden. {error_message}\"\n    except RoboflowAPIUnsuccessfulRequestError as error:\n        # Handle rate limiting (429) and other API errors\n        error_message = str(error)\n        logging.warning(f\"Email proxy API error: {error_message}\")\n\n        # Check for payload too large (413)\n        if (\n            \"413\" in error_message\n            or \"payload too large\" in error_message.lower()\n            or \"too large\" in error_message.lower()\n        ):\n            return True, (\n                \"Failed to send email: attachment size exceeds the 5MB limit. \"\n                \"For image attachments, use the Image Preprocessing block to resize images before sending. \"\n                \"For other attachments (like CSV files), reduce the file size or send smaller data.\"\n            )\n        # Check if it's a rate limit error\n        elif \"rate limit\" in error_message.lower():\n            return True, (\n                \"Failed to send email: rate limit exceeded. \"\n                \"The workspace has exceeded its email sending limits. \"\n                \"Please wait before sending more emails or contact support to increase your limits.\"\n            )\n        elif \"credits exceeded\" in error_message.lower():\n            return True, (\n                \"Failed to send email: workspace credits exceeded. \"\n                \"Please add more credits to your workspace to continue sending emails.\"\n            )\n        else:\n            return True, f\"Failed to send email via proxy. {error_message}\"\n    except Exception as error:\n        logging.warning(\n            f\"Could not send e-mail via Roboflow proxy. Error: {str(error)}\"\n        )\n        return True, f\"Failed to send e-mail via proxy. Internal error details: {error}\"\n\n\ndef send_email_using_smtp_server_v2(\n    sender_email: str,\n    receiver_email: List[str],\n    cc_receiver_email: Optional[List[str]],\n    bcc_receiver_email: Optional[List[str]],\n    subject: str,\n    message: str,\n    attachments: Dict[str, bytes],\n    smtp_server: str,\n    smtp_port: int,\n    sender_email_password: str,\n    inline_images: Dict[str, bytes],\n    is_html: bool,\n) -> Tuple[bool, str]:\n    \"\"\"\n    V2-specific SMTP email sender with inline image support.\n    This function is used only by v2 block and does not modify v1 behavior.\n    \"\"\"\n    try:\n        _send_email_using_smtp_server_v2(\n            sender_email=sender_email,\n            receiver_email=receiver_email,\n            cc_receiver_email=cc_receiver_email,\n            bcc_receiver_email=bcc_receiver_email,\n            subject=subject,\n            message=message,\n            attachments=attachments,\n            smtp_server=smtp_server,\n            smtp_port=smtp_port,\n            sender_email_password=sender_email_password,\n            inline_images=inline_images,\n            is_html=is_html,\n        )\n        return False, \"Notification sent successfully\"\n    except Exception as error:\n        logging.warning(\n            f\"Could not send e-mail using custom SMTP server. Error: {str(error)}\"\n        )\n        return True, f\"Failed to send e-mail. Internal error details: {error}\"\n\n\ndef _send_email_using_smtp_server_v2(\n    sender_email: str,\n    receiver_email: List[str],\n    cc_receiver_email: Optional[List[str]],\n    bcc_receiver_email: Optional[List[str]],\n    subject: str,\n    message: str,\n    attachments: Dict[str, bytes],\n    smtp_server: str,\n    smtp_port: int,\n    sender_email_password: str,\n    inline_images: Dict[str, bytes],\n    is_html: bool,\n) -> None:\n    \"\"\"\n    Internal function to send email with inline images via SMTP.\n    V2-specific - does not modify v1 block behavior.\n    \"\"\"\n    import smtplib\n    import ssl\n    from contextlib import contextmanager\n    from email import encoders\n    from email.mime.base import MIMEBase\n    from email.mime.image import MIMEImage\n    from email.mime.multipart import MIMEMultipart\n    from email.mime.text import MIMEText\n    from typing import Generator\n\n    # Use multipart/related for inline images\n    e_mail_message = MIMEMultipart(\"related\")\n\n    e_mail_message[\"From\"] = sender_email\n    e_mail_message[\"To\"] = \",\".join(receiver_email)\n    if cc_receiver_email:\n        e_mail_message[\"Cc\"] = \",\".join(cc_receiver_email)\n    if bcc_receiver_email:\n        e_mail_message[\"Bcc\"] = \",\".join(bcc_receiver_email)\n    e_mail_message[\"Subject\"] = subject\n\n    # Attach message as HTML\n    message_type = \"html\" if is_html else \"plain\"\n    e_mail_message.attach(MIMEText(message, message_type))\n\n    # Attach inline images with Content-ID\n    for cid, image_bytes in inline_images.items():\n        image_part = MIMEImage(image_bytes)\n        image_part.add_header(\"Content-ID\", f\"<{cid}>\")\n        image_part.add_header(\"Content-Disposition\", \"inline\")\n        e_mail_message.attach(image_part)\n\n    # Attach regular attachments\n    for attachment_name, attachment_content in attachments.items():\n        part = MIMEBase(\"application\", \"octet-stream\")\n        binary_payload = attachment_content\n        if not isinstance(binary_payload, bytes):\n            binary_payload = binary_payload.encode(\"utf-8\")\n        part.set_payload(binary_payload)\n        encoders.encode_base64(part)\n        part.add_header(\n            \"Content-Disposition\",\n            f\"attachment; filename= {attachment_name}\",\n        )\n        e_mail_message.attach(part)\n\n    to_sent = e_mail_message.as_string()\n\n    # Establish SMTP connection\n    @contextmanager\n    def establish_smtp_connection(\n        smtp_server: str, smtp_port: int\n    ) -> Generator[smtplib.SMTP_SSL, None, None]:\n        context = ssl.create_default_context()\n        with smtplib.SMTP_SSL(smtp_server, smtp_port, context=context) as server:\n            yield server\n\n    with establish_smtp_connection(\n        smtp_server=smtp_server, smtp_port=smtp_port\n    ) as server:\n        server.login(sender_email, sender_email_password)\n        server.sendmail(sender_email, receiver_email, to_sent)\n",
    "patch": null
  },
  {
    "trace_id": "c4566e9b-f9f2-4554-b686-93700c77b3d3",
    "function_name": "apply_operations_to_message_parameters",
    "file_path": "inference/core/workflows/core_steps/sinks/email_notification/v2.py",
    "speedup_x": 0.14593291123508287,
    "review_quality": "medium",
    "pre_optimization_commit": "d919d77736809981dbfaa5d44a7d5aff8c339ded",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def apply_operations_to_message_parameters(\n    message_parameters: Dict[str, Any],\n    message_parameters_operations: Dict[str, List[AllOperationsType]],\n) -> Dict[str, Any]:\n    \"\"\"\n    Apply per-parameter operation chains to message parameter values.\n\n    For each parameter in message_parameters, if operations are defined in\n    message_parameters_operations for that parameter name, the operations are\n    applied in order (e.g. ToString, StringToUpperCase, LookupTable).\n    Parameters with no operations are returned unchanged.\n\n    Supports all value types, including WorkflowImageData: image operations\n    such as ExtractImageProperty, ConvertImageToBase64, and ConvertImageToJPEG\n    can be used to transform image parameters before they are serialized or\n    interpolated into the message.\n\n    Returns:\n        A dict with the same keys as message_parameters and values that are\n        either the original value (no operations) or the result of the\n        operations chain.\n    \"\"\"\n    parameters_values = {}\n    for parameter_name in message_parameters:\n        parameter_value = message_parameters[parameter_name]\n\n        operations = message_parameters_operations.get(parameter_name)\n        if not operations:\n            parameters_values[parameter_name] = parameter_value\n            continue\n\n        operations_chain = build_operations_chain(operations=operations)\n        parameters_values[parameter_name] = operations_chain(\n            parameter_value, global_parameters={}\n        )\n\n    return parameters_values\n",
    "optimized_function_code": "from functools import partial\nfrom typing import Any, Callable, Dict, List\n\nfrom inference.core.workflows.core_steps.common.query_language.entities.operations import \\\n    OperationDefinition\nfrom inference.core.workflows.core_steps.common.query_language.entities.types import (\n    T, V)\nfrom inference.core.workflows.core_steps.common.query_language.operations.booleans.base import \\\n    to_bool\nfrom inference.core.workflows.core_steps.common.query_language.operations.classification_results.base import \\\n    extract_classification_property\nfrom inference.core.workflows.core_steps.common.query_language.operations.detection.base import \\\n    extract_detection_property\nfrom inference.core.workflows.core_steps.common.query_language.operations.detections.base import (\n    detections_to_dictionary, extract_detections_property, offset_detections,\n    pick_detections_by_parent_class, rename_detections, select_detections,\n    shift_detections, sort_detections)\nfrom inference.core.workflows.core_steps.common.query_language.operations.dictionaries.base import \\\n    dictionary_to_json\nfrom inference.core.workflows.core_steps.common.query_language.operations.frame_metadata.base import \\\n    extract_frame_metadata\nfrom inference.core.workflows.core_steps.common.query_language.operations.generic.base import (\n    apply_lookup, generate_random_number)\nfrom inference.core.workflows.core_steps.common.query_language.operations.images.base import (\n    encode_image_to_base64, encode_image_to_jpeg, extract_image_property)\nfrom inference.core.workflows.core_steps.common.query_language.operations.numbers.base import (\n    divide, multiply, number_round, to_number)\nfrom inference.core.workflows.core_steps.common.query_language.operations.sequences.base import (\n    aggregate_numeric_sequence, aggregate_sequence,\n    get_sequence_elements_count, get_sequence_length, sequence_map)\nfrom inference.core.workflows.core_steps.common.query_language.operations.strings.base import (\n    string_matches, string_sub_sequence, string_to_lower, string_to_upper,\n    to_string)\nfrom inference.core.workflows.core_steps.common.query_language.operations.timestamps.base import \\\n    timestamp_to_iso_format\n\n# A small cache to avoid rebuilding identical operation chains many times.\n# Key is (id(operations), execution_context) to distinguish same list used in different contexts.\n_BUILT_OPERATIONS_CHAIN_CACHE: Dict[tuple[int, str], Callable] = {}\n\n\ndef identity(value: Any, **kwargs) -> Any:\n    return value\n\n\ndef build_operation(\n    operation_definition: OperationDefinition,\n    execution_context: str,\n) -> Callable[[T], V]:\n    if operation_definition.type in REGISTERED_SIMPLE_OPERATIONS:\n        return build_simple_operation(\n            operation_definition=operation_definition,\n            operation_function=REGISTERED_SIMPLE_OPERATIONS[operation_definition.type],\n            execution_context=execution_context,\n        )\n    if operation_definition.type in REGISTERED_COMPOUND_OPERATIONS_BUILDERS:\n        return REGISTERED_COMPOUND_OPERATIONS_BUILDERS[operation_definition.type](\n            operation_definition, execution_context\n        )\n    raise OperationTypeNotRecognisedError(\n        public_message=f\"Attempted to build operation with declared type: {operation_definition.type} \"\n        f\"which was not registered in Roboflow Query Language.\",\n        context=\"step_execution | roboflow_query_language_compilation\",\n    )\n\n\ndef chain(\n    value: T, global_parameters: Dict[str, Any], functions: List[Callable[[T], V]]\n) -> Callable[[T, Dict[str, Any]], V]:\n    for function in functions:\n        value = function(value, global_parameters=global_parameters)\n    return value\n\n\ndef build_operations_chain(\n    operations: List[OperationDefinition], execution_context: str = \"<root>\"\n) -> Callable[[T, Dict[str, Any]], V]:\n    if not operations:\n        return identity  # return identity function\n\n    cache_key = (id(operations), execution_context)\n    cached = _BUILT_OPERATIONS_CHAIN_CACHE.get(cache_key)\n    if cached is not None:\n        return cached\n\n    operations_functions: List[Callable[[T], V]] = []\n    local_build_operation = build_operation\n    local_execution_context = execution_context\n    append_fn = operations_functions.append\n\n    # Build functions list; minimize global lookups and repeated attribute access\n    for operation_id, operation_definition in enumerate(operations):\n        operation_context = f\"{local_execution_context}[{operation_id}]\"\n        operation_function = local_build_operation(\n            operation_definition=operation_definition, execution_context=operation_context\n        )\n        append_fn(operation_function)\n\n    result = partial(chain, functions=operations_functions)\n    _BUILT_OPERATIONS_CHAIN_CACHE[cache_key] = result\n    return result\n\n\n\n\nREGISTERED_SIMPLE_OPERATIONS = {\n    \"StringToLowerCase\": string_to_lower,\n    \"StringToUpperCase\": string_to_upper,\n    \"LookupTable\": apply_lookup,\n    \"ToNumber\": to_number,\n    \"NumberRound\": number_round,\n    \"SequenceMap\": sequence_map,\n    \"NumericSequenceAggregate\": aggregate_numeric_sequence,\n    \"ToString\": to_string,\n    \"ToBoolean\": to_bool,\n    \"StringSubSequence\": string_sub_sequence,\n    \"DetectionsPropertyExtract\": extract_detections_property,\n    \"SequenceAggregate\": aggregate_sequence,\n    \"ExtractDetectionProperty\": extract_detection_property,\n    \"DetectionsOffset\": offset_detections,\n    \"DetectionsShift\": shift_detections,\n    \"RandomNumber\": generate_random_number,\n    \"StringMatches\": string_matches,\n    \"SequenceLength\": get_sequence_length,\n    \"SequenceElementsCount\": get_sequence_elements_count,\n    \"ExtractImageProperty\": extract_image_property,\n    \"ExtractFrameMetadata\": extract_frame_metadata,\n    \"Multiply\": multiply,\n    \"Divide\": divide,\n    \"DetectionsSelection\": select_detections,\n    \"SortDetections\": sort_detections,\n    \"ClassificationPropertyExtract\": extract_classification_property,\n    \"DetectionsRename\": rename_detections,\n    \"ConvertImageToJPEG\": encode_image_to_jpeg,\n    \"ConvertImageToBase64\": encode_image_to_base64,\n    \"DetectionsToDictionary\": detections_to_dictionary,\n    \"ConvertDictionaryToJSON\": dictionary_to_json,\n    \"PickDetectionsByParentClass\": pick_detections_by_parent_class,\n    \"TimestampToISOFormat\": timestamp_to_iso_format,\n}\n\nREGISTERED_COMPOUND_OPERATIONS_BUILDERS = {\n    \"SequenceApply\": build_sequence_apply_operation,\n    \"DetectionsFilter\": build_detections_filter_operation,\n}",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/common/query_language/operations/core.py\nfrom functools import partial\nfrom typing import Any, Callable, Dict, List\n\nfrom inference.core.workflows.core_steps.common.query_language.entities.operations import \\\n    OperationDefinition\nfrom inference.core.workflows.core_steps.common.query_language.entities.types import (\n    T, V)\nfrom inference.core.workflows.core_steps.common.query_language.operations.booleans.base import \\\n    to_bool\nfrom inference.core.workflows.core_steps.common.query_language.operations.classification_results.base import \\\n    extract_classification_property\nfrom inference.core.workflows.core_steps.common.query_language.operations.detection.base import \\\n    extract_detection_property\nfrom inference.core.workflows.core_steps.common.query_language.operations.detections.base import (\n    detections_to_dictionary, extract_detections_property, offset_detections,\n    pick_detections_by_parent_class, rename_detections, select_detections,\n    shift_detections, sort_detections)\nfrom inference.core.workflows.core_steps.common.query_language.operations.dictionaries.base import \\\n    dictionary_to_json\nfrom inference.core.workflows.core_steps.common.query_language.operations.frame_metadata.base import \\\n    extract_frame_metadata\nfrom inference.core.workflows.core_steps.common.query_language.operations.generic.base import (\n    apply_lookup, generate_random_number)\nfrom inference.core.workflows.core_steps.common.query_language.operations.images.base import (\n    encode_image_to_base64, encode_image_to_jpeg, extract_image_property)\nfrom inference.core.workflows.core_steps.common.query_language.operations.numbers.base import (\n    divide, multiply, number_round, to_number)\nfrom inference.core.workflows.core_steps.common.query_language.operations.sequences.base import (\n    aggregate_numeric_sequence, aggregate_sequence,\n    get_sequence_elements_count, get_sequence_length, sequence_map)\nfrom inference.core.workflows.core_steps.common.query_language.operations.strings.base import (\n    string_matches, string_sub_sequence, string_to_lower, string_to_upper,\n    to_string)\nfrom inference.core.workflows.core_steps.common.query_language.operations.timestamps.base import \\\n    timestamp_to_iso_format\n\n# A small cache to avoid rebuilding identical operation chains many times.\n# Key is (id(operations), execution_context) to distinguish same list used in different contexts.\n_BUILT_OPERATIONS_CHAIN_CACHE: Dict[tuple[int, str], Callable] = {}\n\n\ndef identity(value: Any, **kwargs) -> Any:\n    return value\n\n\ndef build_operation(\n    operation_definition: OperationDefinition,\n    execution_context: str,\n) -> Callable[[T], V]:\n    if operation_definition.type in REGISTERED_SIMPLE_OPERATIONS:\n        return build_simple_operation(\n            operation_definition=operation_definition,\n            operation_function=REGISTERED_SIMPLE_OPERATIONS[operation_definition.type],\n            execution_context=execution_context,\n        )\n    if operation_definition.type in REGISTERED_COMPOUND_OPERATIONS_BUILDERS:\n        return REGISTERED_COMPOUND_OPERATIONS_BUILDERS[operation_definition.type](\n            operation_definition, execution_context\n        )\n    raise OperationTypeNotRecognisedError(\n        public_message=f\"Attempted to build operation with declared type: {operation_definition.type} \"\n        f\"which was not registered in Roboflow Query Language.\",\n        context=\"step_execution | roboflow_query_language_compilation\",\n    )\n\n\ndef chain(\n    value: T, global_parameters: Dict[str, Any], functions: List[Callable[[T], V]]\n) -> Callable[[T, Dict[str, Any]], V]:\n    for function in functions:\n        value = function(value, global_parameters=global_parameters)\n    return value\n\n\ndef build_operations_chain(\n    operations: List[OperationDefinition], execution_context: str = \"<root>\"\n) -> Callable[[T, Dict[str, Any]], V]:\n    if not operations:\n        return identity  # return identity function\n\n    cache_key = (id(operations), execution_context)\n    cached = _BUILT_OPERATIONS_CHAIN_CACHE.get(cache_key)\n    if cached is not None:\n        return cached\n\n    operations_functions: List[Callable[[T], V]] = []\n    local_build_operation = build_operation\n    local_execution_context = execution_context\n    append_fn = operations_functions.append\n\n    # Build functions list; minimize global lookups and repeated attribute access\n    for operation_id, operation_definition in enumerate(operations):\n        operation_context = f\"{local_execution_context}[{operation_id}]\"\n        operation_function = local_build_operation(\n            operation_definition=operation_definition, execution_context=operation_context\n        )\n        append_fn(operation_function)\n\n    result = partial(chain, functions=operations_functions)\n    _BUILT_OPERATIONS_CHAIN_CACHE[cache_key] = result\n    return result\n\n\n\n\nREGISTERED_SIMPLE_OPERATIONS = {\n    \"StringToLowerCase\": string_to_lower,\n    \"StringToUpperCase\": string_to_upper,\n    \"LookupTable\": apply_lookup,\n    \"ToNumber\": to_number,\n    \"NumberRound\": number_round,\n    \"SequenceMap\": sequence_map,\n    \"NumericSequenceAggregate\": aggregate_numeric_sequence,\n    \"ToString\": to_string,\n    \"ToBoolean\": to_bool,\n    \"StringSubSequence\": string_sub_sequence,\n    \"DetectionsPropertyExtract\": extract_detections_property,\n    \"SequenceAggregate\": aggregate_sequence,\n    \"ExtractDetectionProperty\": extract_detection_property,\n    \"DetectionsOffset\": offset_detections,\n    \"DetectionsShift\": shift_detections,\n    \"RandomNumber\": generate_random_number,\n    \"StringMatches\": string_matches,\n    \"SequenceLength\": get_sequence_length,\n    \"SequenceElementsCount\": get_sequence_elements_count,\n    \"ExtractImageProperty\": extract_image_property,\n    \"ExtractFrameMetadata\": extract_frame_metadata,\n    \"Multiply\": multiply,\n    \"Divide\": divide,\n    \"DetectionsSelection\": select_detections,\n    \"SortDetections\": sort_detections,\n    \"ClassificationPropertyExtract\": extract_classification_property,\n    \"DetectionsRename\": rename_detections,\n    \"ConvertImageToJPEG\": encode_image_to_jpeg,\n    \"ConvertImageToBase64\": encode_image_to_base64,\n    \"DetectionsToDictionary\": detections_to_dictionary,\n    \"ConvertDictionaryToJSON\": dictionary_to_json,\n    \"PickDetectionsByParentClass\": pick_detections_by_parent_class,\n    \"TimestampToISOFormat\": timestamp_to_iso_format,\n}\n\nREGISTERED_COMPOUND_OPERATIONS_BUILDERS = {\n    \"SequenceApply\": build_sequence_apply_operation,\n    \"DetectionsFilter\": build_detections_filter_operation,\n}\n```",
    "optimized_function_only": null,
    "original_file_content": "import logging\nimport re\nfrom collections import defaultdict\nfrom concurrent.futures import ThreadPoolExecutor\nfrom datetime import datetime\nfrom functools import partial\nfrom typing import Any, Dict, List, Literal, Optional, Tuple, Type, Union\n\nfrom fastapi import BackgroundTasks\nfrom pydantic import ConfigDict, Field, field_validator\n\nfrom inference.core.roboflow_api import post_to_roboflow_api\nfrom inference.core.utils.image_utils import encode_image_to_jpeg_bytes\nfrom inference.core.workflows.core_steps.common.query_language.entities.operations import (\n    AllOperationsType,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.core import (\n    build_operations_chain,\n)\nfrom inference.core.workflows.core_steps.sinks.email_notification.v1 import (\n    send_email_using_smtp_server,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    BOOLEAN_KIND,\n    BYTES_KIND,\n    IMAGE_KIND,\n    INTEGER_KIND,\n    LIST_OF_VALUES_KIND,\n    ROBOFLOW_MANAGED_KEY,\n    SECRET_KIND,\n    STRING_KIND,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nLONG_DESCRIPTION = \"\"\"\nThe **Email Notification** block allows users to send email notifications as part of a workflow.\n\n## How This Block Works\n\n### Email Provider Options\n\nThis block supports two email delivery methods via a dropdown selector:\n\n1. **Roboflow Managed API Key (Default)** - No SMTP configuration needed. Emails are sent through Roboflow's proxy service:\n   * **Simplified setup** - just provide subject, message, and recipient\n   * **Secure** - your workflow API key is used for authentication\n   * **No SMTP server required**\n\n2. **Custom SMTP** - Use your own SMTP server:\n   * Full control over email delivery\n   * Requires SMTP server configuration (host, port, credentials)\n   * Supports CC and BCC recipients\n\n### Customizable Email Content\n\n* **Subject:** Set the subject field to define the subject line of the email.\n\n* **Message:** Use the message field to write the body content of the email. **Message can be parametrised\nwith data generated during workflow run. See *Dynamic Parameters* section.**\n\n* **Recipients (To, CC, BCC)**: Define who will receive the email using `receiver_email`, \n`cc_receiver_email`, and `bcc_receiver_email` properties. You can input a single email or a list.\n\n### Dynamic Parameters\n\nContent of the message can be parametrised with Workflow execution outcomes. Take a look at the example\nmessage using dynamic parameters:\n\n```\nmessage = \"This is example notification. Predicted classes: {{ '{{' }} $parameters.predicted_classes {{ '}}' }}\"\n```\n\nMessage parameters are delivered by Workflows Execution Engine by setting proper data selectors in\n`message_parameters` field, for example:\n\n```\nmessage_parameters = {\n    \"predicted_classes\": \"$steps.model.predictions\"\n}\n```\n\nSelecting data is not the only option - data may be processed in the block. In the example below we wish to\nextract names of predicted classes. We can apply transformation **for each parameter** by setting\n`message_parameters_operations`:\n\n```\nmessage_parameters_operations = {\n    \"predictions\": [\n        {\"type\": \"DetectionsPropertyExtract\", \"property_name\": \"class_name\"}\n    ]\n}\n```\n\nAs a result, in the e-mail that will be sent, you can expect:\n\n```\nThis is example notification. Predicted classes: [\"class_a\", \"class_b\"].\n```\n\n### Using Custom SMTP Server\n\nTo use your own SMTP server, select \"Custom SMTP\" from the `email_provider` dropdown and configure \nthe following parameters:\n\n* `smtp_server` - hostname of the SMTP server to use\n\n* `sender_email` - e-mail account to be used as sender\n\n* `sender_email_password` - password for sender e-mail account\n\n* `smtp_port` - port of SMTP service - defaults to `465`\n\nBlock **enforces** SSL over SMTP.\n\nTypical scenario for using custom SMTP server involves sending e-mail through Google SMTP server.\nTake a look at [Google tutorial](https://support.google.com/a/answer/176600?hl=en) to configure the \nblock properly. \n\n!!! note \"GMAIL password will not work if 2-step verification is turned on\"\n    \n    GMAIL users choosing custom SMTP server as e-mail service provider must configure \n    [application password](https://support.google.com/accounts/answer/185833) to avoid\n    problems with 2-step verification protected account. Beware that **application\n    password must be kept protected** - we recommend sending the password in Workflow \n    input and providing it each time by the caller, avoiding storing it in Workflow \n    definition.\n    \n### Cooldown\n\nThe block accepts `cooldown_seconds` (which **defaults to `5` seconds**) to prevent unintended bursts of \nnotifications. Please adjust it according to your needs, setting `0` indicate no cooldown. \n\nDuring cooldown period, consecutive runs of the step will cause `throttling_status` output to be set `True`\nand no notification will be sent.\n\n!!! warning \"Cooldown limitations\"\n\n    Current implementation of cooldown is limited to video processing - using this block in context of a \n    Workflow that is run behind HTTP service (Roboflow Hosted API, Dedicated Deployment or self-hosted \n    `inference` server) will have no effect for processing HTTP requests.  \n\n### Attachments\n\nYou may specify attachment files to be sent with your e-mail. Attachments can be generated \nin runtime by dedicated blocks or from image outputs.\n\n**Supported attachment types:**\n- **CSV/Text files**: From blocks like [CSV Formatter](https://inference.roboflow.com/workflows/csv_formatter/)\n- **Images**: Any image output from visualization blocks (automatically converted to JPEG)\n- **Binary data**: Any bytes output from compatible blocks\n\nTo include attachments, provide the attachment filename as the key and reference the block output:\n\n```\nattachments = {\n    \"report.csv\": \"$steps.csv_formatter.csv_content\",\n    \"detection.jpg\": \"$steps.bounding_box_visualization.image\"\n}\n```\n\n**Note:** Image attachments are automatically converted to JPEG format. If the filename doesn't \ninclude a `.jpg` or `.jpeg` extension, it will be added automatically.\n\n### Async execution\n\nConfigure the `fire_and_forget` property. Set it to True if you want the email to be sent in the background, allowing the \nWorkflow to proceed without waiting on e-mail to be sent. In this case you will not be able to rely on \n`error_status` output which will always be set to `False`, so we **recommend setting the `fire_and_forget=False` for\ndebugging purposes**.\n\n### Disabling notifications based on runtime parameter\n\nSometimes it would be convenient to manually disable the e-mail notifier block. This is possible \nsetting `disable_sink` flag to hold reference to Workflow input. with such setup, caller would be\nable to disable the sink when needed sending agreed input parameter.\n\n## Common Use Cases\n\n- Use this block to [purpose based on block type]\n\n## Connecting to Other Blocks\n\nThe outputs from this block can be connected to other blocks in your workflow.\n\"\"\"\n\nPARAMETER_REGEX = re.compile(r\"({{\\s*\\$parameters\\.(\\w+)\\s*}})\")\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Email Notification\",\n            \"version\": \"v2\",\n            \"short_description\": \"Send notification via e-mail.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"sink\",\n            \"ui_manifest\": {\n                \"section\": \"notifications\",\n                \"icon\": \"far fa-envelope\",\n                \"blockPriority\": 0,\n                \"popular\": True,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/email_notification@v2\"]\n\n    email_provider: Literal[\"Roboflow Managed API Key\", \"Custom SMTP\"] = Field(\n        default=\"Roboflow Managed API Key\",\n        description=\"Choose email delivery method: use Roboflow's managed service or configure your own SMTP server.\",\n        examples=[\"Roboflow Managed API Key\", \"Custom SMTP\"],\n        json_schema_extra={\n            \"always_visible\": True,\n        },\n    )\n\n    subject: str = Field(\n        description=\"Subject of the message.\",\n        examples=[\"Workflow alert\"],\n        json_schema_extra={\n            \"hide_description\": True,\n            \"always_visible\": True,\n        },\n    )\n\n    receiver_email: Union[\n        str,\n        List[str],\n        Selector(kind=[STRING_KIND, LIST_OF_VALUES_KIND]),\n    ] = Field(\n        description=\"Destination e-mail address.\",\n        examples=[\"receiver@gmail.com\"],\n        json_schema_extra={\n            \"hide_description\": True,\n            \"always_visible\": True,\n        },\n    )\n\n    message: str = Field(\n        description=\"Content of the message to be send.\",\n        examples=[\n            \"During last 5 minutes detected {{ $parameters.num_instances }} instances\"\n        ],\n        json_schema_extra={\n            \"hide_description\": True,\n            \"multiline\": True,\n            \"always_visible\": True,\n        },\n    )\n\n    message_parameters: Dict[\n        str,\n        Union[Selector(), Selector(), str, int, float, bool],\n    ] = Field(\n        description=\"Data to be used inside the message.\",\n        examples=[\n            {\n                \"predictions\": \"$steps.model.predictions\",\n                \"reference\": \"$inputs.reference_class_names\",\n            }\n        ],\n        default_factory=dict,\n        json_schema_extra={\n            \"always_visible\": True,\n        },\n    )\n\n    message_parameters_operations: Dict[str, List[AllOperationsType]] = Field(\n        description=\"Preprocessing operations to be performed on message parameters.\",\n        examples=[\n            {\n                \"predictions\": [\n                    {\"type\": \"DetectionsPropertyExtract\", \"property_name\": \"class_name\"}\n                ]\n            }\n        ],\n        default_factory=dict,\n    )\n\n    # SMTP fields - hidden when using Roboflow Managed API Key\n    sender_email: Optional[Union[str, Selector(kind=[STRING_KIND])]] = Field(\n        default=None,\n        description=\"E-mail to be used to send the message.\",\n        examples=[\"sender@gmail.com\"],\n        json_schema_extra={\n            \"hide_description\": True,\n            \"relevant_for\": {\n                \"email_provider\": {\"values\": [\"Custom SMTP\"], \"required\": True},\n            },\n        },\n    )\n\n    smtp_server: Optional[Union[str, Selector(kind=[STRING_KIND])]] = Field(\n        default=None,\n        description=\"Custom SMTP server to be used.\",\n        examples=[\"$inputs.smtp_server\", \"smtp.google.com\"],\n        json_schema_extra={\n            \"relevant_for\": {\n                \"email_provider\": {\"values\": [\"Custom SMTP\"], \"required\": True},\n            },\n        },\n    )\n\n    sender_email_password: Optional[\n        Union[str, Selector(kind=[STRING_KIND, SECRET_KIND])]\n    ] = Field(\n        default=None,\n        description=\"Sender e-mail password be used when authenticating to SMTP server.\",\n        private=True,\n        examples=[\"$inputs.email_password\"],\n        json_schema_extra={\n            \"relevant_for\": {\n                \"email_provider\": {\"values\": [\"Custom SMTP\"], \"required\": True},\n            },\n        },\n    )\n\n    cc_receiver_email: Optional[\n        Union[\n            str,\n            List[str],\n            Selector(kind=[STRING_KIND, LIST_OF_VALUES_KIND]),\n        ]\n    ] = Field(\n        default=None,\n        description=\"CC e-mail address.\",\n        examples=[\"cc-receiver@gmail.com\"],\n        json_schema_extra={\n            \"hide_description\": True,\n            \"relevant_for\": {\n                \"email_provider\": {\"values\": [\"Custom SMTP\"], \"required\": True},\n            },\n        },\n    )\n\n    bcc_receiver_email: Optional[\n        Union[\n            str,\n            List[str],\n            Selector(kind=[STRING_KIND, LIST_OF_VALUES_KIND]),\n        ]\n    ] = Field(\n        default=None,\n        description=\"BCC e-mail address.\",\n        examples=[\"bcc-receiver@gmail.com\"],\n        json_schema_extra={\n            \"hide_description\": True,\n            \"relevant_for\": {\n                \"email_provider\": {\"values\": [\"Custom SMTP\"], \"required\": True},\n            },\n        },\n    )\n\n    smtp_port: int = Field(\n        default=465,\n        description=\"SMTP server port.\",\n        examples=[465],\n        json_schema_extra={\n            \"relevant_for\": {\n                \"email_provider\": {\"values\": [\"Custom SMTP\"], \"required\": True},\n            },\n        },\n    )\n\n    attachments: Dict[str, Selector(kind=[STRING_KIND, BYTES_KIND, IMAGE_KIND])] = (\n        Field(\n            description=\"Attachments\",\n            default_factory=dict,\n            examples=[{\"report.cvs\": \"$steps.csv_formatter.csv_content\"}],\n            json_schema_extra={\n                \"hide_description\": True,\n            },\n        )\n    )\n\n    fire_and_forget: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=True,\n        description=\"Boolean flag to run the block asynchronously (True) for faster workflows or  \"\n        \"synchronously (False) for debugging and error handling.\",\n        examples=[\"$inputs.fire_and_forget\", False],\n    )\n\n    disable_sink: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=False,\n        description=\"Boolean flag to disable block execution.\",\n        examples=[False, \"$inputs.disable_email_notifications\"],\n    )\n\n    cooldown_seconds: Union[int, Selector(kind=[INTEGER_KIND])] = Field(\n        default=5,\n        description=\"Number of seconds until a follow-up notification can be sent. \",\n        examples=[\"$inputs.cooldown_seconds\", 3],\n        json_schema_extra={\n            \"always_visible\": True,\n        },\n    )\n\n    @field_validator(\"receiver_email\")\n    @classmethod\n    def ensure_receiver_email_is_not_an_empty_list(cls, value: Any) -> dict:\n        if isinstance(value, list) and len(value) == 0:\n            raise ValueError(\n                \"E-mail notification must have at least one receiver defined.\"\n            )\n        return value\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"error_status\", kind=[BOOLEAN_KIND]),\n            OutputDefinition(name=\"throttling_status\", kind=[BOOLEAN_KIND]),\n            OutputDefinition(name=\"message\", kind=[STRING_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.4.0,<2.0.0\"\n\n\nclass EmailNotificationBlockV2(WorkflowBlock):\n\n    def __init__(\n        self,\n        background_tasks: Optional[BackgroundTasks],\n        thread_pool_executor: Optional[ThreadPoolExecutor],\n        api_key: Optional[str],\n    ):\n        self._background_tasks = background_tasks\n        self._thread_pool_executor = thread_pool_executor\n        self._api_key = api_key\n        self._last_notification_fired: Optional[datetime] = None\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"background_tasks\", \"thread_pool_executor\", \"api_key\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        subject: str,\n        message: str,\n        receiver_email: Union[str, List[str]],\n        email_provider: str,\n        sender_email: Optional[str],\n        cc_receiver_email: Optional[Union[str, List[str]]],\n        bcc_receiver_email: Optional[Union[str, List[str]]],\n        message_parameters: Dict[str, Any],\n        message_parameters_operations: Dict[str, List[AllOperationsType]],\n        attachments: Dict[str, str],\n        smtp_server: Optional[str],\n        sender_email_password: Optional[str],\n        smtp_port: int,\n        fire_and_forget: bool,\n        disable_sink: bool,\n        cooldown_seconds: int,\n    ) -> BlockResult:\n        if disable_sink:\n            return {\n                \"error_status\": False,\n                \"throttling_status\": False,\n                \"message\": \"Sink was disabled by parameter `disable_sink`\",\n            }\n        seconds_since_last_notification = cooldown_seconds\n        if self._last_notification_fired is not None:\n            seconds_since_last_notification = (\n                datetime.now() - self._last_notification_fired\n            ).total_seconds()\n        if seconds_since_last_notification < cooldown_seconds:\n            logging.info(f\"Activated `roboflow_core/email_notification@v2` cooldown.\")\n            return {\n                \"error_status\": False,\n                \"throttling_status\": True,\n                \"message\": \"Sink cooldown applies\",\n            }\n\n        receiver_email = (\n            receiver_email if isinstance(receiver_email, list) else [receiver_email]\n        )\n        if cc_receiver_email is not None:\n            cc_receiver_email = (\n                cc_receiver_email\n                if isinstance(cc_receiver_email, list)\n                else [cc_receiver_email]\n            )\n        if bcc_receiver_email is not None:\n            bcc_receiver_email = (\n                bcc_receiver_email\n                if isinstance(bcc_receiver_email, list)\n                else [bcc_receiver_email]\n            )\n\n        # Check if using Roboflow Managed API Key\n        use_managed_service = email_provider == \"Roboflow Managed API Key\"\n\n        if use_managed_service:\n            send_email_handler = partial(\n                send_email_via_roboflow_proxy,\n                roboflow_api_key=self._api_key,\n                receiver_email=receiver_email,\n                cc_receiver_email=cc_receiver_email,\n                bcc_receiver_email=bcc_receiver_email,\n                subject=subject,\n                message=message,\n                message_parameters=message_parameters,\n                message_parameters_operations=message_parameters_operations,\n                attachments=attachments,\n            )\n        else:\n            # Validate required SMTP fields\n            if not sender_email or not smtp_server or not sender_email_password:\n                return {\n                    \"error_status\": True,\n                    \"throttling_status\": False,\n                    \"message\": \"Custom SMTP requires sender_email, smtp_server, and sender_email_password\",\n                }\n\n            # Always format as HTML for SMTP to match Resend pathway behavior\n            formatted_message, inline_images = format_email_message_html_with_images(\n                message=message,\n                message_parameters=message_parameters,\n                message_parameters_operations=message_parameters_operations,\n            )\n            is_html = True\n\n            # Process attachments: convert images to bytes for SMTP\n            processed_attachments = {}\n            for filename, value in attachments.items():\n                if isinstance(value, WorkflowImageData):\n                    # Convert image to JPEG bytes\n                    numpy_image = value.numpy_image\n                    jpeg_bytes = encode_image_to_jpeg_bytes(numpy_image)\n                    # Ensure filename has .jpg extension\n                    if not filename.lower().endswith((\".jpg\", \".jpeg\")):\n                        filename = f\"{filename}.jpg\"\n                    processed_attachments[filename] = jpeg_bytes\n                elif isinstance(value, bytes):\n                    processed_attachments[filename] = value\n                elif isinstance(value, str):\n                    # String content (e.g., CSV)\n                    processed_attachments[filename] = value.encode(\"utf-8\")\n                else:\n                    # Fallback: convert to string then bytes\n                    processed_attachments[filename] = str(value).encode(\"utf-8\")\n\n            # Always use v2 SMTP function for HTML support (matches Resend behavior)\n            send_email_handler = partial(\n                send_email_using_smtp_server_v2,\n                sender_email=sender_email,\n                receiver_email=receiver_email,\n                cc_receiver_email=cc_receiver_email,\n                bcc_receiver_email=bcc_receiver_email,\n                subject=subject,\n                message=formatted_message,\n                attachments=processed_attachments,\n                smtp_server=smtp_server,\n                smtp_port=smtp_port,\n                sender_email_password=sender_email_password,\n                inline_images=inline_images,\n                is_html=is_html,\n            )\n\n        self._last_notification_fired = datetime.now()\n        if fire_and_forget and self._background_tasks:\n            self._background_tasks.add_task(send_email_handler)\n            return {\n                \"error_status\": False,\n                \"throttling_status\": False,\n                \"message\": \"Notification sent in the background task\",\n            }\n        if fire_and_forget and self._thread_pool_executor:\n            self._thread_pool_executor.submit(send_email_handler)\n            return {\n                \"error_status\": False,\n                \"throttling_status\": False,\n                \"message\": \"Notification sent in the background task\",\n            }\n        error_status, message = send_email_handler()\n        return {\n            \"error_status\": error_status,\n            \"throttling_status\": False,\n            \"message\": message,\n        }\n\n\ndef apply_operations_to_message_parameters(\n    message_parameters: Dict[str, Any],\n    message_parameters_operations: Dict[str, List[AllOperationsType]],\n) -> Dict[str, Any]:\n    \"\"\"\n    Apply per-parameter operation chains to message parameter values.\n\n    For each parameter in message_parameters, if operations are defined in\n    message_parameters_operations for that parameter name, the operations are\n    applied in order (e.g. ToString, StringToUpperCase, LookupTable).\n    Parameters with no operations are returned unchanged.\n\n    Supports all value types, including WorkflowImageData: image operations\n    such as ExtractImageProperty, ConvertImageToBase64, and ConvertImageToJPEG\n    can be used to transform image parameters before they are serialized or\n    interpolated into the message.\n\n    Returns:\n        A dict with the same keys as message_parameters and values that are\n        either the original value (no operations) or the result of the\n        operations chain.\n    \"\"\"\n    parameters_values = {}\n    for parameter_name in message_parameters:\n        parameter_value = message_parameters[parameter_name]\n\n        operations = message_parameters_operations.get(parameter_name)\n        if not operations:\n            parameters_values[parameter_name] = parameter_value\n            continue\n\n        operations_chain = build_operations_chain(operations=operations)\n        parameters_values[parameter_name] = operations_chain(\n            parameter_value, global_parameters={}\n        )\n\n    return parameters_values\n\n\ndef format_email_message(\n    message: str,\n    message_parameters: Dict[str, Any],\n    message_parameters_operations: Dict[str, List[AllOperationsType]],\n) -> str:\n    \"\"\"Format email message by replacing parameter placeholders with actual values.\"\"\"\n    matching_parameters = PARAMETER_REGEX.findall(message)\n    parameters_to_get_values = {\n        p[1] for p in matching_parameters if p[1] in message_parameters\n    }\n\n    parameters_values = apply_operations_to_message_parameters(\n        message_parameters=message_parameters,\n        message_parameters_operations=message_parameters_operations,\n    )\n\n    parameter_to_placeholders = defaultdict(list)\n    for placeholder, parameter_name in matching_parameters:\n        if parameter_name not in parameters_to_get_values:\n            continue\n        parameter_to_placeholders[parameter_name].append(placeholder)\n    for parameter_name, placeholders in parameter_to_placeholders.items():\n        for placeholder in placeholders:\n            message = message.replace(\n                placeholder, str(parameters_values[parameter_name])\n            )\n    return message\n\n\ndef format_email_message_html_with_images(\n    message: str,\n    message_parameters: Dict[str, Any],\n    message_parameters_operations: Dict[str, List[AllOperationsType]],\n) -> Tuple[str, Dict[str, bytes]]:\n    \"\"\"Format email message as HTML with inline images.\"\"\"\n    matching_parameters = PARAMETER_REGEX.findall(message)\n    parameters_to_get_values = {\n        p[1] for p in matching_parameters if p[1] in message_parameters\n    }\n\n    parameters_values = {}\n    image_attachments = {}\n\n    for parameter_name in parameters_to_get_values:\n        parameter_value = message_parameters[parameter_name]\n\n        # Apply operations if any\n        operations = message_parameters_operations.get(parameter_name)\n        if operations:\n            operations_chain = build_operations_chain(operations=operations)\n            parameter_value = operations_chain(parameter_value, global_parameters={})\n\n        if isinstance(parameter_value, WorkflowImageData):\n            # Convert to JPEG and create CID\n            jpeg_bytes = encode_image_to_jpeg_bytes(parameter_value.numpy_image)\n            cid = f\"image_{parameter_name}\"\n            image_attachments[cid] = jpeg_bytes\n            parameters_values[parameter_name] = (\n                f'<img src=\"cid:{cid}\" alt=\"{parameter_name}\" style=\"max-width: 600px; height: auto;\">'\n            )\n        else:\n            import html\n\n            parameters_values[parameter_name] = html.escape(str(parameter_value))\n\n    # Replace placeholders\n    parameter_to_placeholders = defaultdict(list)\n    for placeholder, parameter_name in matching_parameters:\n        if parameter_name in parameters_to_get_values:\n            parameter_to_placeholders[parameter_name].append(placeholder)\n\n    html_message = message\n    for parameter_name, placeholders in parameter_to_placeholders.items():\n        for placeholder in placeholders:\n            html_message = html_message.replace(\n                placeholder, str(parameters_values[parameter_name])\n            )\n\n    # Convert newlines to <br> tags for HTML\n    html_message = html_message.replace(\"\\n\", \"<br>\\n\")\n\n    return html_message, image_attachments\n\n\ndef serialize_image_data(value: Any) -> Any:\n    \"\"\"\n    Serialize WorkflowImageData objects to base64 strings for JSON transmission.\n    Returns the value unchanged if it's not a WorkflowImageData object.\n    \"\"\"\n    if isinstance(value, WorkflowImageData):\n        # Get the base64 representation of the image\n        base64_image = value.base64_image\n        if base64_image:\n            return base64_image\n        # If no base64 available, try to convert numpy array\n        numpy_image = value.numpy_image\n        if numpy_image is not None:\n            import cv2\n\n            _, buffer = cv2.imencode(\".jpg\", numpy_image)\n            import base64\n\n            return base64.b64encode(buffer).decode(\"utf-8\")\n    elif isinstance(value, dict):\n        return {k: serialize_image_data(v) for k, v in value.items()}\n    elif isinstance(value, list):\n        return [serialize_image_data(item) for item in value]\n    return value\n\n\ndef serialize_image_data_parameters(\n    message_parameters: Dict[str, Any]\n) -> Dict[str, Any]:\n    \"\"\"\n    Convert any WorkflowImageData objects in message_parameters to base64 strings\n    so they can be serialized to JSON for the API call.\n    \"\"\"\n    return {k: serialize_image_data(v) for k, v in message_parameters.items()}\n\n\ndef process_attachments(attachments: Dict[str, Any]) -> Dict[str, bytes]:\n    \"\"\"\n    Process attachments dict to convert WorkflowImageData to JPEG bytes.\n    Returns a dict with filename -> bytes mapping.\n    \"\"\"\n    processed = {}\n    for filename, value in attachments.items():\n        if isinstance(value, WorkflowImageData):\n            # Convert image to JPEG bytes\n            numpy_image = value.numpy_image\n            jpeg_bytes = encode_image_to_jpeg_bytes(numpy_image)\n            processed[filename] = jpeg_bytes\n        elif isinstance(value, bytes):\n            # Already bytes, use as-is\n            processed[filename] = value\n        elif isinstance(value, str):\n            # String data (e.g., CSV content)\n            processed[filename] = value.encode(\"utf-8\")\n        else:\n            # Fallback: convert to string then bytes\n            processed[filename] = str(value).encode(\"utf-8\")\n    return processed\n\n\ndef send_email_via_roboflow_proxy(\n    roboflow_api_key: str,\n    receiver_email: List[str],\n    cc_receiver_email: Optional[List[str]],\n    bcc_receiver_email: Optional[List[str]],\n    subject: str,\n    message: str,\n    message_parameters: Dict[str, Any],\n    message_parameters_operations: Dict[str, List[AllOperationsType]],\n    attachments: Dict[str, Any],\n) -> Tuple[bool, str]:\n    \"\"\"Send email through Roboflow's proxy service.\"\"\"\n    from inference.core.exceptions import (\n        RoboflowAPIForbiddenError,\n        RoboflowAPIUnsuccessfulRequestError,\n    )\n\n    # Custom error handler that preserves the API's error message\n    def handle_email_proxy_error(status_code: int, http_error: Exception) -> None:\n        \"\"\"Extract and preserve the actual error message from the API response.\"\"\"\n        try:\n            response = http_error.response\n            error_data = response.json()\n            # API returns 'details' field with the actual message, 'error' is generic\n            # Prioritize 'details' over 'error' for more specific messages\n            api_error_message = (\n                error_data.get(\"details\") or error_data.get(\"error\") or str(http_error)\n            )\n        except Exception:\n            api_error_message = str(http_error)\n\n        # Raise appropriate exception with the actual API error message\n        if status_code == 403:\n            raise RoboflowAPIForbiddenError(api_error_message) from http_error\n        elif status_code == 413:\n            raise RoboflowAPIUnsuccessfulRequestError(api_error_message) from http_error\n        elif status_code == 429:\n            raise RoboflowAPIUnsuccessfulRequestError(api_error_message) from http_error\n        else:\n            raise RoboflowAPIUnsuccessfulRequestError(api_error_message) from http_error\n\n    # Map status codes to our custom handler\n    custom_error_handlers = {\n        403: lambda e: handle_email_proxy_error(403, e),\n        413: lambda e: handle_email_proxy_error(413, e),\n        429: lambda e: handle_email_proxy_error(429, e),\n    }\n\n    try:\n        message_parameters_after_operations = apply_operations_to_message_parameters(\n            message_parameters=message_parameters,\n            message_parameters_operations=message_parameters_operations,\n        )\n        # Serialize any WorkflowImageData objects to base64 strings for JSON transmission\n        serialized_parameters = serialize_image_data_parameters(\n            message_parameters_after_operations\n        )\n\n        payload = {\n            \"receiver_email\": receiver_email,\n            \"subject\": subject,\n            \"message\": message,\n            \"message_parameters\": serialized_parameters,\n        }\n\n        if cc_receiver_email:\n            payload[\"cc_receiver_email\"] = cc_receiver_email\n        if bcc_receiver_email:\n            payload[\"bcc_receiver_email\"] = bcc_receiver_email\n        if attachments:\n            # Process attachments: convert images to JPEG bytes, then base64 encode\n            import base64\n\n            processed_attachments = {}\n            for filename, value in attachments.items():\n                if isinstance(value, WorkflowImageData):\n                    # Convert image to JPEG bytes\n                    numpy_image = value.numpy_image\n                    jpeg_bytes = encode_image_to_jpeg_bytes(numpy_image)\n                    # Ensure filename has .jpg extension\n                    if not filename.lower().endswith((\".jpg\", \".jpeg\")):\n                        filename = f\"{filename}.jpg\"\n                    # Base64 encode for JSON transmission\n                    processed_attachments[filename] = base64.b64encode(\n                        jpeg_bytes\n                    ).decode(\"utf-8\")\n                elif isinstance(value, bytes):\n                    # Already bytes, base64 encode\n                    processed_attachments[filename] = base64.b64encode(value).decode(\n                        \"utf-8\"\n                    )\n                elif isinstance(value, str):\n                    # String data (e.g., CSV content), base64 encode\n                    processed_attachments[filename] = base64.b64encode(\n                        value.encode(\"utf-8\")\n                    ).decode(\"utf-8\")\n                else:\n                    # Fallback: convert to string then bytes then base64\n                    processed_attachments[filename] = base64.b64encode(\n                        str(value).encode(\"utf-8\")\n                    ).decode(\"utf-8\")\n            payload[\"attachments\"] = processed_attachments\n\n        endpoint = \"apiproxy/email\"\n\n        response_data = post_to_roboflow_api(\n            endpoint=endpoint,\n            api_key=roboflow_api_key,\n            payload=payload,\n            http_errors_handlers=custom_error_handlers,\n        )\n\n        return False, \"Notification sent successfully via Roboflow proxy\"\n    except RoboflowAPIForbiddenError as error:\n        # Handle 403 errors (whitelist violations)\n        error_message = str(error)\n        logging.warning(\n            f\"Email rejected by proxy due to access restrictions: {error_message}\"\n        )\n\n        # Check if it's a workspace member restriction\n        # The API returns detailed error messages about non-workspace members\n        if \"non-workspace members\" in error_message.lower():\n            return True, (\n                \"To prevent spam, you can only send emails to members of your Roboflow Workspace via the Roboflow Managed API Key. \"\n                \"Add this email to your Workspace or switch to sending via your own SMTP server.\"\n            )\n        else:\n            return True, f\"Failed to send email: access forbidden. {error_message}\"\n    except RoboflowAPIUnsuccessfulRequestError as error:\n        # Handle rate limiting (429) and other API errors\n        error_message = str(error)\n        logging.warning(f\"Email proxy API error: {error_message}\")\n\n        # Check for payload too large (413)\n        if (\n            \"413\" in error_message\n            or \"payload too large\" in error_message.lower()\n            or \"too large\" in error_message.lower()\n        ):\n            return True, (\n                \"Failed to send email: attachment size exceeds the 5MB limit. \"\n                \"For image attachments, use the Image Preprocessing block to resize images before sending. \"\n                \"For other attachments (like CSV files), reduce the file size or send smaller data.\"\n            )\n        # Check if it's a rate limit error\n        elif \"rate limit\" in error_message.lower():\n            return True, (\n                \"Failed to send email: rate limit exceeded. \"\n                \"The workspace has exceeded its email sending limits. \"\n                \"Please wait before sending more emails or contact support to increase your limits.\"\n            )\n        elif \"credits exceeded\" in error_message.lower():\n            return True, (\n                \"Failed to send email: workspace credits exceeded. \"\n                \"Please add more credits to your workspace to continue sending emails.\"\n            )\n        else:\n            return True, f\"Failed to send email via proxy. {error_message}\"\n    except Exception as error:\n        logging.warning(\n            f\"Could not send e-mail via Roboflow proxy. Error: {str(error)}\"\n        )\n        return True, f\"Failed to send e-mail via proxy. Internal error details: {error}\"\n\n\ndef send_email_using_smtp_server_v2(\n    sender_email: str,\n    receiver_email: List[str],\n    cc_receiver_email: Optional[List[str]],\n    bcc_receiver_email: Optional[List[str]],\n    subject: str,\n    message: str,\n    attachments: Dict[str, bytes],\n    smtp_server: str,\n    smtp_port: int,\n    sender_email_password: str,\n    inline_images: Dict[str, bytes],\n    is_html: bool,\n) -> Tuple[bool, str]:\n    \"\"\"\n    V2-specific SMTP email sender with inline image support.\n    This function is used only by v2 block and does not modify v1 behavior.\n    \"\"\"\n    try:\n        _send_email_using_smtp_server_v2(\n            sender_email=sender_email,\n            receiver_email=receiver_email,\n            cc_receiver_email=cc_receiver_email,\n            bcc_receiver_email=bcc_receiver_email,\n            subject=subject,\n            message=message,\n            attachments=attachments,\n            smtp_server=smtp_server,\n            smtp_port=smtp_port,\n            sender_email_password=sender_email_password,\n            inline_images=inline_images,\n            is_html=is_html,\n        )\n        return False, \"Notification sent successfully\"\n    except Exception as error:\n        logging.warning(\n            f\"Could not send e-mail using custom SMTP server. Error: {str(error)}\"\n        )\n        return True, f\"Failed to send e-mail. Internal error details: {error}\"\n\n\ndef _send_email_using_smtp_server_v2(\n    sender_email: str,\n    receiver_email: List[str],\n    cc_receiver_email: Optional[List[str]],\n    bcc_receiver_email: Optional[List[str]],\n    subject: str,\n    message: str,\n    attachments: Dict[str, bytes],\n    smtp_server: str,\n    smtp_port: int,\n    sender_email_password: str,\n    inline_images: Dict[str, bytes],\n    is_html: bool,\n) -> None:\n    \"\"\"\n    Internal function to send email with inline images via SMTP.\n    V2-specific - does not modify v1 block behavior.\n    \"\"\"\n    import smtplib\n    import ssl\n    from contextlib import contextmanager\n    from email import encoders\n    from email.mime.base import MIMEBase\n    from email.mime.image import MIMEImage\n    from email.mime.multipart import MIMEMultipart\n    from email.mime.text import MIMEText\n    from typing import Generator\n\n    # Use multipart/related for inline images\n    e_mail_message = MIMEMultipart(\"related\")\n\n    e_mail_message[\"From\"] = sender_email\n    e_mail_message[\"To\"] = \",\".join(receiver_email)\n    if cc_receiver_email:\n        e_mail_message[\"Cc\"] = \",\".join(cc_receiver_email)\n    if bcc_receiver_email:\n        e_mail_message[\"Bcc\"] = \",\".join(bcc_receiver_email)\n    e_mail_message[\"Subject\"] = subject\n\n    # Attach message as HTML\n    message_type = \"html\" if is_html else \"plain\"\n    e_mail_message.attach(MIMEText(message, message_type))\n\n    # Attach inline images with Content-ID\n    for cid, image_bytes in inline_images.items():\n        image_part = MIMEImage(image_bytes)\n        image_part.add_header(\"Content-ID\", f\"<{cid}>\")\n        image_part.add_header(\"Content-Disposition\", \"inline\")\n        e_mail_message.attach(image_part)\n\n    # Attach regular attachments\n    for attachment_name, attachment_content in attachments.items():\n        part = MIMEBase(\"application\", \"octet-stream\")\n        binary_payload = attachment_content\n        if not isinstance(binary_payload, bytes):\n            binary_payload = binary_payload.encode(\"utf-8\")\n        part.set_payload(binary_payload)\n        encoders.encode_base64(part)\n        part.add_header(\n            \"Content-Disposition\",\n            f\"attachment; filename= {attachment_name}\",\n        )\n        e_mail_message.attach(part)\n\n    to_sent = e_mail_message.as_string()\n\n    # Establish SMTP connection\n    @contextmanager\n    def establish_smtp_connection(\n        smtp_server: str, smtp_port: int\n    ) -> Generator[smtplib.SMTP_SSL, None, None]:\n        context = ssl.create_default_context()\n        with smtplib.SMTP_SSL(smtp_server, smtp_port, context=context) as server:\n            yield server\n\n    with establish_smtp_connection(\n        smtp_server=smtp_server, smtp_port=smtp_port\n    ) as server:\n        server.login(sender_email, sender_email_password)\n        server.sendmail(sender_email, receiver_email, to_sent)\n",
    "patch": null
  },
  {
    "trace_id": "4fee4e4f-dd57-495d-8b80-f425862167f7",
    "function_name": "BlockManifest.describe_outputs",
    "file_path": "inference/core/workflows/core_steps/models/foundation/qwen3_5vl/v1.py",
    "speedup_x": 6.296928284819604,
    "review_quality": "high",
    "pre_optimization_commit": "c0249b396cecd814532f6b2a4c0abb4bd6c8c4f3",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(\n                name=\"parsed_output\",\n                kind=[DICTIONARY_KIND],\n                description=\"A parsed version of the output, provided as a dictionary containing the text.\",\n            ),\n        ]\n",
    "optimized_function_code": "##########################################################################\n# Qwen3.5-VL Workflow Block Manifest\n##########################################################################\nfrom inference.core.workflows.execution_engine.entities.base import OutputDefinition\nfrom inference.core.workflows.execution_engine.entities.types import DICTIONARY_KIND\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\nfrom typing import List\n\n_PARSED_OUTPUT_DEFINITION = OutputDefinition(\n    name=\"parsed_output\",\n    kind=[DICTIONARY_KIND],\n    description=\"A parsed version of the output, provided as a dictionary containing the text.\",\n)\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [_PARSED_OUTPUT_DEFINITION]",
    "optimized_raw_markdown": "```python:inference/core/workflows/execution_engine/entities/base.py\nfrom inference.core.workflows.execution_engine.entities.types import Kind, WILDCARD_KIND\nfrom pydantic import BaseModel, Field\nfrom typing import List\n\nclass OutputDefinition(BaseModel):\n    name: str\n    kind: List[Kind] = Field(default_factory=lambda: [WILDCARD_KIND])\n```\n```python:inference/core/workflows/core_steps/models/foundation/qwen3_5vl/v1.py\n##########################################################################\n# Qwen3.5-VL Workflow Block Manifest\n##########################################################################\nfrom inference.core.workflows.execution_engine.entities.base import OutputDefinition\nfrom inference.core.workflows.execution_engine.entities.types import DICTIONARY_KIND\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\nfrom typing import List\n\n_PARSED_OUTPUT_DEFINITION = OutputDefinition(\n    name=\"parsed_output\",\n    kind=[DICTIONARY_KIND],\n    description=\"A parsed version of the output, provided as a dictionary containing the text.\",\n)\n\nclass BlockManifest(WorkflowBlockManifest):\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [_PARSED_OUTPUT_DEFINITION]\n```",
    "optimized_function_only": "    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [_PARSED_OUTPUT_DEFINITION]",
    "original_file_content": "import json\nfrom typing import List, Literal, Optional, Type, Union\n\nimport supervision as sv\nfrom pydantic import ConfigDict, Field\n\nfrom inference.core.entities.requests.inference import LMMInferenceRequest\nfrom inference.core.env import (\n    HOSTED_CORE_MODEL_URL,\n    LOCAL_INFERENCE_API_URL,\n    WORKFLOWS_REMOTE_API_TARGET,\n)\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.entities import StepExecutionMode\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    DICTIONARY_KIND,\n    IMAGE_KIND,\n    LANGUAGE_MODEL_OUTPUT_KIND,\n    ROBOFLOW_MODEL_ID_KIND,\n    STRING_KIND,\n    ImageInputField,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\nfrom inference_sdk import InferenceHTTPClient\n\n\n##########################################################################\n# Qwen3.5-VL Workflow Block Manifest\n##########################################################################\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Qwen3.5-VL\",\n            \"version\": \"v1\",\n            \"short_description\": \"Run Qwen3.5-VL on an image.\",\n            \"long_description\": (\n                \"This workflow block runs Qwen3.5-VL\u2014a vision language model that accepts an image \"\n                \"and an optional text prompt\u2014and returns a text answer based on a conversation template.\"\n            ),\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"model\",\n            \"search_keywords\": [\n                \"Qwen3.5\",\n                \"qwen3.5-vl\",\n                \"vision language model\",\n                \"VLM\",\n                \"Alibaba\",\n            ],\n            \"is_vlm_block\": True,\n            \"ui_manifest\": {\n                \"section\": \"model\",\n                \"icon\": \"fal fa-atom\",\n                \"blockPriority\": 5.7,\n            },\n        },\n        protected_namespaces=(),\n    )\n    type: Literal[\"roboflow_core/qwen3_5vl@v1\"]\n\n    images: Selector(kind=[IMAGE_KIND]) = ImageInputField\n    prompt: Optional[str] = Field(\n        default=None,\n        description=\"Optional text prompt to provide additional context to Qwen3.5-VL. Otherwise it will just be a default one, which may affect the desired model behavior.\",\n        examples=[\"What is in this image?\"],\n    )\n    model_version: Union[Selector(kind=[ROBOFLOW_MODEL_ID_KIND]), str] = Field(\n        default=\"qwen3_5-0.8b\",\n        description=\"The Qwen3.5-VL model to be used for inference.\",\n        examples=[\"qwen3_5-0.8b\", \"qwen3_5-2b\"],\n    )\n\n    system_prompt: Optional[str] = Field(\n        default=None,\n        description=\"Optional system prompt to provide additional context to Qwen3.5-VL.\",\n        examples=[\"You are a helpful assistant.\"],\n    )\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(\n                name=\"parsed_output\",\n                kind=[DICTIONARY_KIND],\n                description=\"A parsed version of the output, provided as a dictionary containing the text.\",\n            ),\n        ]\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        # Only images can be passed in as a list/batch\n        return [\"images\"]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\n##########################################################################\n# Qwen3.5-VL Workflow Block\n##########################################################################\nclass Qwen35VLBlockV1(WorkflowBlock):\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"model_manager\", \"api_key\", \"step_execution_mode\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n        system_prompt: Optional[str],\n    ) -> BlockResult:\n        if self._step_execution_mode == StepExecutionMode.LOCAL:\n            return self.run_locally(\n                images=images,\n                model_version=model_version,\n                prompt=prompt,\n                system_prompt=system_prompt,\n            )\n        elif self._step_execution_mode == StepExecutionMode.REMOTE:\n            return self.run_remotely(\n                images=images,\n                model_version=model_version,\n                prompt=prompt,\n                system_prompt=system_prompt,\n            )\n        else:\n            raise ValueError(\n                f\"Unknown step execution mode: {self._step_execution_mode}\"\n            )\n\n    def run_remotely(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n        system_prompt: Optional[str],\n    ) -> BlockResult:\n        api_url = (\n            LOCAL_INFERENCE_API_URL\n            if WORKFLOWS_REMOTE_API_TARGET != \"hosted\"\n            else HOSTED_CORE_MODEL_URL\n        )\n        client = InferenceHTTPClient(\n            api_url=api_url,\n            api_key=self._api_key,\n        )\n        if WORKFLOWS_REMOTE_API_TARGET == \"hosted\":\n            client.select_api_v0()\n\n        prompt = prompt or \"Describe what's in this image.\"\n        system_prompt = (\n            system_prompt\n            or \"You are a Qwen3.5-VL model that can answer questions about any image.\"\n        )\n        combined_prompt = prompt + \"<system_prompt>\" + system_prompt\n\n        predictions = []\n        for image in images:\n            result = client.infer_lmm(\n                inference_input=image.base64_image,\n                model_id=model_version,\n                prompt=combined_prompt,\n                model_id_in_path=True,\n            )\n            response_text = result.get(\"response\", result)\n            predictions.append({\"parsed_output\": response_text})\n\n        return predictions\n\n    def run_locally(\n        self,\n        images: Batch[WorkflowImageData],\n        model_version: str,\n        prompt: Optional[str],\n        system_prompt: Optional[str],\n    ) -> BlockResult:\n        # Convert each image to the format required by the model.\n        inference_images = [\n            i.to_inference_format(numpy_preferred=False) for i in images\n        ]\n        # Use the provided prompt or default to a generic image description request.\n        prompt = prompt or \"Describe what's in this image.\"\n        system_prompt = (\n            system_prompt\n            or \"You are a Qwen3.5-VL model that can answer questions about any image.\"\n        )\n        prompts = [prompt + \"<system_prompt>\" + system_prompt] * len(inference_images)\n        # Register Qwen3.5-VL with the model manager.\n        self._model_manager.add_model(model_id=model_version, api_key=self._api_key)\n\n        predictions = []\n        for image, single_prompt in zip(inference_images, prompts):\n            # Build an LMMInferenceRequest with both prompt and image.\n            request = LMMInferenceRequest(\n                api_key=self._api_key,\n                model_id=model_version,\n                image=image,\n                source=\"workflow-execution\",\n                prompt=single_prompt,\n            )\n            # Run inference.\n            prediction = self._model_manager.infer_from_request_sync(\n                model_id=model_version, request=request\n            )\n            response_text = prediction.response\n            predictions.append(\n                {\n                    \"parsed_output\": response_text,\n                }\n            )\n        return predictions\n",
    "patch": null
  },
  {
    "trace_id": "715517b2-fe67-4727-a7c2-afb8244e8b22",
    "function_name": "_expand_metadata_to_records",
    "file_path": "inference/core/workflows/core_steps/sinks/roboflow/dataset_upload/v2.py",
    "speedup_x": 0.6202459015308277,
    "review_quality": "medium",
    "pre_optimization_commit": "HEAD",
    "resolution_method": "db_code_only",
    "source": "db_features",
    "original_function_code": "def _expand_metadata_to_records(\n    metadata: Optional[Union[Dict[str, Any], Batch]],\n    batch_size: int,\n) -> List[Optional[Dict[str, Any]]]:\n    \"\"\"Transpose metadata into a per-image list of dicts.\n\n    Handles three cases:\n    - None / empty: returns [None] * batch_size\n    - Batch[Dict]: engine already wrapped it, unwrap directly\n    - Dict with possible Batch values inside: transpose into per-element dicts\n    \"\"\"\n    if not metadata:\n        return [None] * batch_size\n    if isinstance(metadata, Batch):\n        return [m or None for m in metadata]\n    batch_entries = {k: v for k, v in metadata.items() if isinstance(v, Batch)}\n    non_batch_entries = {k: v for k, v in metadata.items() if not isinstance(v, Batch)}\n    if not batch_entries:\n        return [dict(metadata) for _ in range(batch_size)]\n    result = []\n    for i in range(batch_size):\n        entry = dict(non_batch_entries)\n        for k, batch_val in batch_entries.items():\n            entry[k] = batch_val[i]\n        result.append(entry)\n    return result",
    "optimized_function_code": "from typing import Any, Dict, List, Optional, Union\n\nfrom inference.core.workflows.execution_engine.entities.base import Batch\n\n\ndef _expand_metadata_to_records(\n    metadata: Optional[Union[Dict[str, Any], Batch]],\n    batch_size: int,\n) -> List[Optional[Dict[str, Any]]]:\n    \"\"\"Transpose metadata into a per-image list of dicts.\n\n    Handles three cases:\n    - None / empty: returns [None] * batch_size\n    - Batch[Dict]: engine already wrapped it, unwrap directly\n    - Dict with possible Batch values inside: transpose into per-element dicts\n    \"\"\"\n    if not metadata:\n        return [None] * batch_size\n    if isinstance(metadata, Batch):\n        return [m if m else None for m in metadata]\n    batch_entries = {}\n    non_batch_entries = {}\n    for k, v in metadata.items():\n        if isinstance(v, Batch):\n            batch_entries[k] = v\n        else:\n            non_batch_entries[k] = v\n    if not batch_entries:\n        return [dict(metadata)] * batch_size\n    result = []\n    for i in range(batch_size):\n        entry = {**non_batch_entries}\n        for k, batch_val in batch_entries.items():\n            entry[k] = batch_val[i]\n        result.append(entry)\n    return result",
    "optimized_raw_markdown": "```python:inference/core/workflows/execution_engine/entities/base.py\nfrom __future__ import annotations\n\nfrom typing import Generic, List, Optional, Tuple, TypeVar\n\nB = TypeVar(\"B\")\n\n\nclass Batch(Generic[B]):\n\n    def __init__(self, content: List[B], indices: Optional[List[Tuple[int, ...]]]):\n        self._content = content\n        self._indices = indices\n```\n```python:inference/core/workflows/core_steps/sinks/roboflow/dataset_upload/v2.py\nfrom typing import Any, Dict, List, Optional, Union\n\nfrom inference.core.workflows.execution_engine.entities.base import Batch\n\n\ndef _expand_metadata_to_records(\n    metadata: Optional[Union[Dict[str, Any], Batch]],\n    batch_size: int,\n) -> List[Optional[Dict[str, Any]]]:\n    \"\"\"Transpose metadata into a per-image list of dicts.\n\n    Handles three cases:\n    - None / empty: returns [None] * batch_size\n    - Batch[Dict]: engine already wrapped it, unwrap directly\n    - Dict with possible Batch values inside: transpose into per-element dicts\n    \"\"\"\n    if not metadata:\n        return [None] * batch_size\n    if isinstance(metadata, Batch):\n        return [m if m else None for m in metadata]\n    batch_entries = {}\n    non_batch_entries = {}\n    for k, v in metadata.items():\n        if isinstance(v, Batch):\n            batch_entries[k] = v\n        else:\n            non_batch_entries[k] = v\n    if not batch_entries:\n        return [dict(metadata)] * batch_size\n    result = []\n    for i in range(batch_size):\n        entry = {**non_batch_entries}\n        for k, batch_val in batch_entries.items():\n            entry[k] = batch_val[i]\n        result.append(entry)\n    return result\n```",
    "optimized_function_only": "def _expand_metadata_to_records(\n    metadata: Optional[Union[Dict[str, Any], Batch]],\n    batch_size: int,\n) -> List[Optional[Dict[str, Any]]]:\n    \"\"\"Transpose metadata into a per-image list of dicts.\n\n    Handles three cases:\n    - None / empty: returns [None] * batch_size\n    - Batch[Dict]: engine already wrapped it, unwrap directly\n    - Dict with possible Batch values inside: transpose into per-element dicts\n    \"\"\"\n    if not metadata:\n        return [None] * batch_size\n    if isinstance(metadata, Batch):\n        return [m if m else None for m in metadata]\n    batch_entries = {}\n    non_batch_entries = {}\n    for k, v in metadata.items():\n        if isinstance(v, Batch):\n            batch_entries[k] = v\n        else:\n            non_batch_entries[k] = v\n    if not batch_entries:\n        return [dict(metadata)] * batch_size\n    result = []\n    for i in range(batch_size):\n        entry = {**non_batch_entries}\n        for k, batch_val in batch_entries.items():\n            entry[k] = batch_val[i]\n        result.append(entry)\n    return result",
    "original_file_content": "from inference.core.workflows.execution_engine.entities.base import Batch\nfrom typing import Any, Dict, List, Optional, Union\n\ndef _expand_metadata_to_records(\n    metadata: Optional[Union[Dict[str, Any], Batch]],\n    batch_size: int,\n) -> List[Optional[Dict[str, Any]]]:\n    \"\"\"Transpose metadata into a per-image list of dicts.\n\n    Handles three cases:\n    - None / empty: returns [None] * batch_size\n    - Batch[Dict]: engine already wrapped it, unwrap directly\n    - Dict with possible Batch values inside: transpose into per-element dicts\n    \"\"\"\n    if not metadata:\n        return [None] * batch_size\n    if isinstance(metadata, Batch):\n        return [m or None for m in metadata]\n    batch_entries = {k: v for k, v in metadata.items() if isinstance(v, Batch)}\n    non_batch_entries = {k: v for k, v in metadata.items() if not isinstance(v, Batch)}\n    if not batch_entries:\n        return [dict(metadata) for _ in range(batch_size)]\n    result = []\n    for i in range(batch_size):\n        entry = dict(non_batch_entries)\n        for k, batch_val in batch_entries.items():\n            entry[k] = batch_val[i]\n        result.append(entry)\n    return result",
    "patch": null
  },
  {
    "trace_id": "5fe7743e-1bf7-449d-a7a4-b5a4f69ec73c",
    "function_name": "RoboflowDatasetUploadBlockV2.run",
    "file_path": "inference/core/workflows/core_steps/sinks/roboflow/dataset_upload/v2.py",
    "speedup_x": 8.139850927836438,
    "review_quality": "high",
    "pre_optimization_commit": "5172cfc4e59a6b29dd81a1c98238759ced9f16a0",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        predictions: Optional[Batch[Union[sv.Detections, dict]]],\n        target_project: str,\n        usage_quota_name: str,\n        data_percentage: float,\n        minutely_usage_limit: int,\n        persist_predictions: bool,\n        hourly_usage_limit: int,\n        daily_usage_limit: int,\n        max_image_size: Tuple[int, int],\n        compression_level: int,\n        registration_tags: List[str],\n        disable_sink: bool,\n        fire_and_forget: bool,\n        labeling_batch_prefix: str,\n        labeling_batches_recreation_frequency: BatchCreationFrequency,\n        image_name: Optional[Batch[Optional[str]]] = None,\n    ) -> BlockResult:\n        if self._api_key is None:\n            raise ValueError(\n                \"RoboflowDataCollector block cannot run without Roboflow API key. \"\n                \"If you do not know how to get API key - visit \"\n                \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to \"\n                \"retrieve one.\"\n            )\n        if disable_sink:\n            return [\n                {\n                    \"error_status\": False,\n                    \"message\": \"Sink was disabled by parameter `disable_sink`\",\n                }\n                for _ in range(len(images))\n            ]\n        result = []\n        predictions = [None] * len(images) if predictions is None else predictions\n        image_names = [None] * len(images) if image_name is None else image_name\n        for image, prediction, img_name in zip(images, predictions, image_names):\n            error_status, message = maybe_register_datapoint_at_roboflow(\n                image=image,\n                prediction=prediction,\n                target_project=target_project,\n                usage_quota_name=usage_quota_name,\n                data_percentage=data_percentage,\n                persist_predictions=persist_predictions,\n                minutely_usage_limit=minutely_usage_limit,\n                hourly_usage_limit=hourly_usage_limit,\n                daily_usage_limit=daily_usage_limit,\n                max_image_size=max_image_size,\n                compression_level=compression_level,\n                registration_tags=registration_tags,\n                fire_and_forget=fire_and_forget,\n                labeling_batch_prefix=labeling_batch_prefix,\n                new_labeling_batch_frequency=labeling_batches_recreation_frequency,\n                cache=self._cache,\n                background_tasks=self._background_tasks,\n                thread_pool_executor=self._thread_pool_executor,\n                api_key=self._api_key,\n                image_name=img_name,\n            )\n            result.append({\"error_status\": error_status, \"message\": message})\n        return result\n",
    "optimized_function_code": "from __future__ import annotations\n\nimport random\nfrom concurrent.futures import ThreadPoolExecutor\nfrom typing import List, Literal, Optional, Tuple, Union\n\nimport supervision as sv\nfrom fastapi import BackgroundTasks\nfrom inference.core.cache.base import BaseCache\nfrom inference.core.workflows.core_steps.sinks.roboflow.dataset_upload.v1 import \\\n    register_datapoint_at_roboflow\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch, WorkflowImageData)\nfrom inference.core.workflows.prototypes.block import (BlockResult,\n                                                       WorkflowBlock)\n\nBatchCreationFrequency = Literal[\"never\", \"daily\", \"weekly\", \"monthly\"]\n\n\nclass RoboflowDatasetUploadBlockV2(WorkflowBlock):\n\n    def __init__(\n        self,\n        cache: BaseCache,\n        api_key: Optional[str],\n        background_tasks: Optional[BackgroundTasks],\n        thread_pool_executor: Optional[ThreadPoolExecutor],\n    ):\n        self._cache = cache\n        self._api_key = api_key\n        self._background_tasks = background_tasks\n        self._thread_pool_executor = thread_pool_executor\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        predictions: Optional[Batch[Union[sv.Detections, dict]]],\n        target_project: str,\n        usage_quota_name: str,\n        data_percentage: float,\n        minutely_usage_limit: int,\n        persist_predictions: bool,\n        hourly_usage_limit: int,\n        daily_usage_limit: int,\n        max_image_size: Tuple[int, int],\n        compression_level: int,\n        registration_tags: List[str],\n        disable_sink: bool,\n        fire_and_forget: bool,\n        labeling_batch_prefix: str,\n        labeling_batches_recreation_frequency: BatchCreationFrequency,\n        image_name: Optional[Batch[Optional[str]]] = None,\n    ) -> BlockResult:\n        if self._api_key is None:\n            raise ValueError(\n                \"RoboflowDataCollector block cannot run without Roboflow API key. \"\n                \"If you do not know how to get API key - visit \"\n                \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to \"\n                \"retrieve one.\"\n            )\n        if disable_sink:\n            return [\n                {\n                    \"error_status\": False,\n                    \"message\": \"Sink was disabled by parameter `disable_sink`\",\n                }\n                for _ in range(len(images))\n            ]\n        result = []\n        predictions = [None] * len(images) if predictions is None else predictions\n        image_names = [None] * len(images) if image_name is None else image_name\n\n        # Fast-paths and local aliases for hot loop\n        normalized_probability = data_percentage / 100\n        register_func = register_datapoint_at_roboflow\n        append_result = result.append\n        rand = random.random\n\n        # If no sampling, skip all quickly\n        if normalized_probability <= 0.0:\n            for _ in images:\n                append_result({\"error_status\": False, \"message\": \"Registration skipped due to sampling settings\"})\n            return result\n\n        # If full sampling, register all quickly\n        if normalized_probability >= 1.0:\n            for image, prediction, img_name in zip(images, predictions, image_names):\n                error_status, message = register_func(\n                    image=image,\n                    prediction=prediction,\n                    target_project=target_project,\n                    usage_quota_name=usage_quota_name,\n                    persist_predictions=persist_predictions,\n                    minutely_usage_limit=minutely_usage_limit,\n                    hourly_usage_limit=hourly_usage_limit,\n                    daily_usage_limit=daily_usage_limit,\n                    max_image_size=max_image_size,\n                    compression_level=compression_level,\n                    registration_tags=registration_tags,\n                    fire_and_forget=fire_and_forget,\n                    labeling_batch_prefix=labeling_batch_prefix,\n                    new_labeling_batch_frequency=labeling_batches_recreation_frequency,\n                    cache=self._cache,\n                    background_tasks=self._background_tasks,\n                    thread_pool_executor=self._thread_pool_executor,\n                    api_key=self._api_key,\n                    image_name=img_name,\n                )\n                append_result({\"error_status\": error_status, \"message\": message})\n            return result\n\n        # General case: sample once per image and only call register when selected\n        prob = normalized_probability\n        for image, prediction, img_name in zip(images, predictions, image_names):\n            if rand() < prob:\n                error_status, message = register_func(\n                    image=image,\n                    prediction=prediction,\n                    target_project=target_project,\n                    usage_quota_name=usage_quota_name,\n                    persist_predictions=persist_predictions,\n                    minutely_usage_limit=minutely_usage_limit,\n                    hourly_usage_limit=hourly_usage_limit,\n                    daily_usage_limit=daily_usage_limit,\n                    max_image_size=max_image_size,\n                    compression_level=compression_level,\n                    registration_tags=registration_tags,\n                    fire_and_forget=fire_and_forget,\n                    labeling_batch_prefix=labeling_batch_prefix,\n                    new_labeling_batch_frequency=labeling_batches_recreation_frequency,\n                    cache=self._cache,\n                    background_tasks=self._background_tasks,\n                    thread_pool_executor=self._thread_pool_executor,\n                    api_key=self._api_key,\n                    image_name=img_name,\n                )\n            else:\n                error_status, message = False, \"Registration skipped due to sampling settings\"\n            append_result({\"error_status\": error_status, \"message\": message})\n        return result\n\n\ndef maybe_register_datapoint_at_roboflow(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    usage_quota_name: str,\n    data_percentage: float,\n    persist_predictions: bool,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    fire_and_forget: bool,\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    background_tasks: Optional[BackgroundTasks],\n    thread_pool_executor: Optional[ThreadPoolExecutor],\n    api_key: str,\n    image_name: Optional[str] = None,\n) -> Tuple[bool, str]:\n    normalised_probability = data_percentage / 100\n    if random.random() < normalised_probability:\n        return register_datapoint_at_roboflow(\n            image=image,\n            prediction=prediction,\n            target_project=target_project,\n            usage_quota_name=usage_quota_name,\n            persist_predictions=persist_predictions,\n            minutely_usage_limit=minutely_usage_limit,\n            hourly_usage_limit=hourly_usage_limit,\n            daily_usage_limit=daily_usage_limit,\n            max_image_size=max_image_size,\n            compression_level=compression_level,\n            registration_tags=registration_tags,\n            fire_and_forget=fire_and_forget,\n            labeling_batch_prefix=labeling_batch_prefix,\n            new_labeling_batch_frequency=new_labeling_batch_frequency,\n            cache=cache,\n            background_tasks=background_tasks,\n            thread_pool_executor=thread_pool_executor,\n            api_key=api_key,\n            image_name=image_name,\n        )\n    return False, \"Registration skipped due to sampling settings\"",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/sinks/roboflow/dataset_upload/v2.py\nfrom __future__ import annotations\n\nimport random\nfrom concurrent.futures import ThreadPoolExecutor\nfrom typing import List, Literal, Optional, Tuple, Union\n\nimport supervision as sv\nfrom fastapi import BackgroundTasks\nfrom inference.core.cache.base import BaseCache\nfrom inference.core.workflows.core_steps.sinks.roboflow.dataset_upload.v1 import \\\n    register_datapoint_at_roboflow\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch, WorkflowImageData)\nfrom inference.core.workflows.prototypes.block import (BlockResult,\n                                                       WorkflowBlock)\n\nBatchCreationFrequency = Literal[\"never\", \"daily\", \"weekly\", \"monthly\"]\n\n\nclass RoboflowDatasetUploadBlockV2(WorkflowBlock):\n\n    def __init__(\n        self,\n        cache: BaseCache,\n        api_key: Optional[str],\n        background_tasks: Optional[BackgroundTasks],\n        thread_pool_executor: Optional[ThreadPoolExecutor],\n    ):\n        self._cache = cache\n        self._api_key = api_key\n        self._background_tasks = background_tasks\n        self._thread_pool_executor = thread_pool_executor\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        predictions: Optional[Batch[Union[sv.Detections, dict]]],\n        target_project: str,\n        usage_quota_name: str,\n        data_percentage: float,\n        minutely_usage_limit: int,\n        persist_predictions: bool,\n        hourly_usage_limit: int,\n        daily_usage_limit: int,\n        max_image_size: Tuple[int, int],\n        compression_level: int,\n        registration_tags: List[str],\n        disable_sink: bool,\n        fire_and_forget: bool,\n        labeling_batch_prefix: str,\n        labeling_batches_recreation_frequency: BatchCreationFrequency,\n        image_name: Optional[Batch[Optional[str]]] = None,\n    ) -> BlockResult:\n        if self._api_key is None:\n            raise ValueError(\n                \"RoboflowDataCollector block cannot run without Roboflow API key. \"\n                \"If you do not know how to get API key - visit \"\n                \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to \"\n                \"retrieve one.\"\n            )\n        if disable_sink:\n            return [\n                {\n                    \"error_status\": False,\n                    \"message\": \"Sink was disabled by parameter `disable_sink`\",\n                }\n                for _ in range(len(images))\n            ]\n        result = []\n        predictions = [None] * len(images) if predictions is None else predictions\n        image_names = [None] * len(images) if image_name is None else image_name\n\n        # Fast-paths and local aliases for hot loop\n        normalized_probability = data_percentage / 100\n        register_func = register_datapoint_at_roboflow\n        append_result = result.append\n        rand = random.random\n\n        # If no sampling, skip all quickly\n        if normalized_probability <= 0.0:\n            for _ in images:\n                append_result({\"error_status\": False, \"message\": \"Registration skipped due to sampling settings\"})\n            return result\n\n        # If full sampling, register all quickly\n        if normalized_probability >= 1.0:\n            for image, prediction, img_name in zip(images, predictions, image_names):\n                error_status, message = register_func(\n                    image=image,\n                    prediction=prediction,\n                    target_project=target_project,\n                    usage_quota_name=usage_quota_name,\n                    persist_predictions=persist_predictions,\n                    minutely_usage_limit=minutely_usage_limit,\n                    hourly_usage_limit=hourly_usage_limit,\n                    daily_usage_limit=daily_usage_limit,\n                    max_image_size=max_image_size,\n                    compression_level=compression_level,\n                    registration_tags=registration_tags,\n                    fire_and_forget=fire_and_forget,\n                    labeling_batch_prefix=labeling_batch_prefix,\n                    new_labeling_batch_frequency=labeling_batches_recreation_frequency,\n                    cache=self._cache,\n                    background_tasks=self._background_tasks,\n                    thread_pool_executor=self._thread_pool_executor,\n                    api_key=self._api_key,\n                    image_name=img_name,\n                )\n                append_result({\"error_status\": error_status, \"message\": message})\n            return result\n\n        # General case: sample once per image and only call register when selected\n        prob = normalized_probability\n        for image, prediction, img_name in zip(images, predictions, image_names):\n            if rand() < prob:\n                error_status, message = register_func(\n                    image=image,\n                    prediction=prediction,\n                    target_project=target_project,\n                    usage_quota_name=usage_quota_name,\n                    persist_predictions=persist_predictions,\n                    minutely_usage_limit=minutely_usage_limit,\n                    hourly_usage_limit=hourly_usage_limit,\n                    daily_usage_limit=daily_usage_limit,\n                    max_image_size=max_image_size,\n                    compression_level=compression_level,\n                    registration_tags=registration_tags,\n                    fire_and_forget=fire_and_forget,\n                    labeling_batch_prefix=labeling_batch_prefix,\n                    new_labeling_batch_frequency=labeling_batches_recreation_frequency,\n                    cache=self._cache,\n                    background_tasks=self._background_tasks,\n                    thread_pool_executor=self._thread_pool_executor,\n                    api_key=self._api_key,\n                    image_name=img_name,\n                )\n            else:\n                error_status, message = False, \"Registration skipped due to sampling settings\"\n            append_result({\"error_status\": error_status, \"message\": message})\n        return result\n\n\ndef maybe_register_datapoint_at_roboflow(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    usage_quota_name: str,\n    data_percentage: float,\n    persist_predictions: bool,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    fire_and_forget: bool,\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    background_tasks: Optional[BackgroundTasks],\n    thread_pool_executor: Optional[ThreadPoolExecutor],\n    api_key: str,\n    image_name: Optional[str] = None,\n) -> Tuple[bool, str]:\n    normalised_probability = data_percentage / 100\n    if random.random() < normalised_probability:\n        return register_datapoint_at_roboflow(\n            image=image,\n            prediction=prediction,\n            target_project=target_project,\n            usage_quota_name=usage_quota_name,\n            persist_predictions=persist_predictions,\n            minutely_usage_limit=minutely_usage_limit,\n            hourly_usage_limit=hourly_usage_limit,\n            daily_usage_limit=daily_usage_limit,\n            max_image_size=max_image_size,\n            compression_level=compression_level,\n            registration_tags=registration_tags,\n            fire_and_forget=fire_and_forget,\n            labeling_batch_prefix=labeling_batch_prefix,\n            new_labeling_batch_frequency=new_labeling_batch_frequency,\n            cache=cache,\n            background_tasks=background_tasks,\n            thread_pool_executor=thread_pool_executor,\n            api_key=api_key,\n            image_name=image_name,\n        )\n    return False, \"Registration skipped due to sampling settings\"\n```",
    "optimized_function_only": "    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        predictions: Optional[Batch[Union[sv.Detections, dict]]],\n        target_project: str,\n        usage_quota_name: str,\n        data_percentage: float,\n        minutely_usage_limit: int,\n        persist_predictions: bool,\n        hourly_usage_limit: int,\n        daily_usage_limit: int,\n        max_image_size: Tuple[int, int],\n        compression_level: int,\n        registration_tags: List[str],\n        disable_sink: bool,\n        fire_and_forget: bool,\n        labeling_batch_prefix: str,\n        labeling_batches_recreation_frequency: BatchCreationFrequency,\n        image_name: Optional[Batch[Optional[str]]] = None,\n    ) -> BlockResult:\n        if self._api_key is None:\n            raise ValueError(\n                \"RoboflowDataCollector block cannot run without Roboflow API key. \"\n                \"If you do not know how to get API key - visit \"\n                \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to \"\n                \"retrieve one.\"\n            )\n        if disable_sink:\n            return [\n                {\n                    \"error_status\": False,\n                    \"message\": \"Sink was disabled by parameter `disable_sink`\",\n                }\n                for _ in range(len(images))\n            ]\n        result = []\n        predictions = [None] * len(images) if predictions is None else predictions\n        image_names = [None] * len(images) if image_name is None else image_name\n\n        # Fast-paths and local aliases for hot loop\n        normalized_probability = data_percentage / 100\n        register_func = register_datapoint_at_roboflow\n        append_result = result.append\n        rand = random.random\n\n        # If no sampling, skip all quickly\n        if normalized_probability <= 0.0:\n            for _ in images:\n                append_result({\"error_status\": False, \"message\": \"Registration skipped due to sampling settings\"})\n            return result\n\n        # If full sampling, register all quickly\n        if normalized_probability >= 1.0:\n            for image, prediction, img_name in zip(images, predictions, image_names):\n                error_status, message = register_func(\n                    image=image,\n                    prediction=prediction,\n                    target_project=target_project,\n                    usage_quota_name=usage_quota_name,\n                    persist_predictions=persist_predictions,\n                    minutely_usage_limit=minutely_usage_limit,\n                    hourly_usage_limit=hourly_usage_limit,\n                    daily_usage_limit=daily_usage_limit,\n                    max_image_size=max_image_size,\n                    compression_level=compression_level,\n                    registration_tags=registration_tags,\n                    fire_and_forget=fire_and_forget,\n                    labeling_batch_prefix=labeling_batch_prefix,\n                    new_labeling_batch_frequency=labeling_batches_recreation_frequency,\n                    cache=self._cache,\n                    background_tasks=self._background_tasks,\n                    thread_pool_executor=self._thread_pool_executor,\n                    api_key=self._api_key,\n                    image_name=img_name,\n                )\n                append_result({\"error_status\": error_status, \"message\": message})\n            return result\n\n        # General case: sample once per image and only call register when selected\n        prob = normalized_probability\n        for image, prediction, img_name in zip(images, predictions, image_names):\n            if rand() < prob:\n                error_status, message = register_func(\n                    image=image,\n                    prediction=prediction,\n                    target_project=target_project,\n                    usage_quota_name=usage_quota_name,\n                    persist_predictions=persist_predictions,\n                    minutely_usage_limit=minutely_usage_limit,\n                    hourly_usage_limit=hourly_usage_limit,\n                    daily_usage_limit=daily_usage_limit,\n                    max_image_size=max_image_size,\n                    compression_level=compression_level,\n                    registration_tags=registration_tags,\n                    fire_and_forget=fire_and_forget,\n                    labeling_batch_prefix=labeling_batch_prefix,\n                    new_labeling_batch_frequency=labeling_batches_recreation_frequency,\n                    cache=self._cache,\n                    background_tasks=self._background_tasks,\n                    thread_pool_executor=self._thread_pool_executor,\n                    api_key=self._api_key,\n                    image_name=img_name,\n                )\n            else:\n                error_status, message = False, \"Registration skipped due to sampling settings\"\n            append_result({\"error_status\": error_status, \"message\": message})\n        return result\n",
    "original_file_content": "import random\nfrom concurrent.futures import ThreadPoolExecutor\nfrom typing import List, Literal, Optional, Tuple, Type, Union\n\nimport supervision as sv\nfrom fastapi import BackgroundTasks\nfrom pydantic import AliasChoices, ConfigDict, Field\nfrom typing_extensions import Annotated\n\nfrom inference.core.cache.base import BaseCache\nfrom inference.core.workflows.core_steps.sinks.roboflow.dataset_upload.v1 import (\n    register_datapoint_at_roboflow,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    BOOLEAN_KIND,\n    CLASSIFICATION_PREDICTION_KIND,\n    FLOAT_KIND,\n    IMAGE_KIND,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    KEYPOINT_DETECTION_PREDICTION_KIND,\n    LIST_OF_VALUES_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    ROBOFLOW_PROJECT_KIND,\n    STRING_KIND,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nFloatZeroToHundred = Annotated[float, Field(ge=0.0, le=100.0)]\n\nSHORT_DESCRIPTION = \"Save images and predictions to your Roboflow Dataset.\"\n\nLONG_DESCRIPTION = \"\"\"\nUpload images and model predictions to a Roboflow dataset for active learning, model improvement, and data collection, with configurable usage quotas, probabilistic sampling, batch organization, image compression, and optional annotation persistence.\n\n## How This Block Works\n\nThis block uploads workflow images and predictions to your Roboflow dataset for storage, labeling, and model training. The block:\n\n1. Takes images and optional model predictions (object detection, instance segmentation, keypoint detection, or classification) as input\n2. Validates the Roboflow API key is available (required for uploading)\n3. Applies probabilistic sampling based on `data_percentage` setting, randomly selecting a percentage of inputs to upload (e.g., 50% uploads half the data, 100% uploads everything)\n4. Checks usage quotas (minutely, hourly, daily limits) to ensure uploads stay within configured rate limits for active learning strategies\n5. Prepares images by resizing if they exceed maximum size (maintaining aspect ratio) and compressing to specified quality level\n6. Generates labeling batch names based on the prefix and batch creation frequency (never, daily, weekly, or monthly), organizing uploaded data into batches\n7. Optionally persists model predictions as annotations if `persist_predictions` is enabled, allowing predictions to serve as pre-labels for review and correction\n8. Attaches registration tags to images for organization and filtering in the Roboflow platform\n9. Registers the image (and annotations if enabled) to the specified Roboflow project via the Roboflow API\n10. Executes synchronously or asynchronously based on `fire_and_forget` setting, allowing non-blocking uploads for faster workflow execution\n11. Returns error status and messages indicating upload success, failure, or sampling skip\n\nThe block supports active learning workflows by implementing usage quotas that prevent excessive data collection, helping focus on collecting valuable training data within rate limits. The probabilistic sampling feature (new in v2) allows you to randomly sample a percentage of data for upload, enabling cost-effective data collection strategies where you want to collect representative samples rather than all data. Images are organized into labeling batches that can be automatically recreated on a schedule (daily, weekly, monthly), making it easier to manage and review collected data over time. The block can operate in fire-and-forget mode for asynchronous execution, allowing workflows to continue processing without waiting for uploads to complete, or synchronously for debugging and error handling.\n\n## Version Differences (v2 vs v1)\n\n**New Features in v2:**\n\n- **Probabilistic Data Sampling**: Added `data_percentage` parameter (0-100%) that enables random sampling of data for upload. This allows you to upload only a percentage of workflow inputs (e.g., 25% samples one in four images), reducing storage and annotation costs while still collecting representative data. When sampling skips an upload, the block returns a message indicating the skip.\n\n- **Improved Default Settings**: \n  - `max_image_size` default increased from (512, 512) to (1920, 1080) for higher resolution data collection\n  - `compression_level` default increased from 75 to 95 for better image quality preservation\n\n**Behavior Changes:**\n\n- By default, `data_percentage` is set to 100, so v2 behaves identically to v1 unless sampling is explicitly configured\n- The block now uses probabilistic sampling before quota checking and image preparation, allowing efficient filtering before resource-intensive operations\n\n## Requirements\n\n**API Key Required**: This block requires a valid Roboflow API key to upload data. The API key must be configured in your environment or workflow configuration. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve an API key.\n\n## Common Use Cases\n\n- **Active Learning Data Collection**: Collect images and predictions from production environments where models struggle or are uncertain (e.g., low-confidence detections, edge cases), enabling iterative model improvement by gathering challenging examples for retraining\n- **Probabilistic Data Sampling**: Use `data_percentage` to randomly sample a subset of data for upload (e.g., upload 20% of all detections, 50% of low-confidence cases), enabling cost-effective data collection strategies that reduce storage and annotation overhead while maintaining dataset diversity\n- **Production Data Logging**: Continuously upload production inference data to Roboflow datasets for monitoring, analysis, and future model training, creating a growing dataset from real-world deployments\n- **Pre-Labeled Data Collection**: Upload images with model predictions as pre-labels (when `persist_predictions` is enabled), accelerating annotation workflows by providing initial labels that can be reviewed and corrected rather than starting from scratch\n- **Stratified Data Sampling**: Combine probabilistic sampling with rate limiting and quotas to selectively collect data based on specific criteria (e.g., sample 30% of detections that pass filters), ensuring diverse and balanced dataset collection without overwhelming storage or annotation resources\n- **Batch-Based Labeling Workflows**: Organize uploaded data into batches with automatic recreation schedules (daily, weekly, monthly), making it easier to manage labeling tasks, track progress, and organize data collection efforts over time\n\n## Connecting to Other Blocks\n\nThis block receives data from workflow steps and uploads it to Roboflow:\n\n- **After detection or analysis blocks** (e.g., Object Detection Model, Instance Segmentation Model, Classification Model, Keypoint Detection Model) to upload images along with their predictions, enabling active learning by collecting inference data with model outputs for annotation and retraining\n- **After filtering or analytics blocks** (e.g., Detections Filter, Continue If, Overlap Filter) to selectively upload only specific types of data (e.g., low-confidence detections, overlapping objects, specific classes), focusing data collection on valuable edge cases or interesting scenarios\n- **After rate limiter blocks** (e.g., Rate Limiter) to throttle upload frequency and stay within usage quotas, ensuring controlled data collection that respects rate limits and prevents excessive storage usage\n- **Image inputs or preprocessing blocks** to upload raw images or processed images (e.g., crops, transformed images) without predictions, enabling collection of image data for future labeling or analysis\n- **Conditional workflows** using flow control blocks (e.g., Continue If) to upload data only when certain conditions are met (e.g., upload only when detection count exceeds threshold, upload only errors or failures), enabling selective data collection based on workflow state\n- **Batch processing workflows** where multiple images or predictions are generated, allowing bulk upload of workflow outputs to Roboflow datasets with probabilistic sampling for organized and cost-effective data collection\n\"\"\"\n\nWORKSPACE_NAME_CACHE_EXPIRE = 900  # 15 min\nTIMESTAMP_FORMAT = \"%Y_%m_%d\"\nDUPLICATED_STATUS = \"Duplicated image\"\nBatchCreationFrequency = Literal[\"never\", \"daily\", \"weekly\", \"monthly\"]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Roboflow Dataset Upload\",\n            \"version\": \"v2\",\n            \"short_description\": SHORT_DESCRIPTION,\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"sink\",\n            \"ui_manifest\": {\n                \"section\": \"data_storage\",\n                \"icon\": \"fal fa-upload\",\n                \"blockPriority\": 0,\n                \"popular\": True,\n                \"requires_rf_key\": True,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/roboflow_dataset_upload@v2\"]\n    images: Selector(kind=[IMAGE_KIND]) = Field(\n        title=\"Image\",\n        description=\"Image(s) to upload to the Roboflow dataset. Can be a single image or batch of images from workflow inputs or processing steps. Images are randomly sampled based on data_percentage, resized if they exceed max_image_size, and compressed before uploading. Supports batch processing.\",\n        examples=[\"$inputs.image\", \"$steps.cropping.crops\"],\n        validation_alias=AliasChoices(\"images\", \"image\"),\n    )\n    target_project: Union[Selector(kind=[ROBOFLOW_PROJECT_KIND]), str] = Field(\n        description=\"Roboflow project identifier where uploaded images and annotations will be saved. Must be a valid project in your Roboflow workspace. The project name can be specified directly or referenced from workflow inputs.\",\n        examples=[\"my_dataset\", \"$inputs.target_al_dataset\"],\n    )\n    predictions: Optional[\n        Selector(\n            kind=[\n                OBJECT_DETECTION_PREDICTION_KIND,\n                INSTANCE_SEGMENTATION_PREDICTION_KIND,\n                KEYPOINT_DETECTION_PREDICTION_KIND,\n                CLASSIFICATION_PREDICTION_KIND,\n            ]\n        )\n    ] = Field(\n        default=None,\n        description=\"Optional model predictions to upload alongside images. Predictions are saved as annotations (pre-labels) in the Roboflow dataset when persist_predictions is enabled, allowing predictions to serve as starting points for annotation review and correction. Supports object detection, instance segmentation, keypoint detection, and classification predictions. If None, only images are uploaded.\",\n        examples=[\"$steps.object_detection_model.predictions\"],\n        json_schema_extra={\"always_visible\": True},\n    )\n    data_percentage: Union[FloatZeroToHundred, Selector(kind=[FLOAT_KIND])] = Field(\n        default=100,\n        description=\"Percentage of input data (0.0 to 100.0) to randomly sample for upload. This enables probabilistic data collection where only a subset of inputs are uploaded, reducing storage and annotation costs. For example, 25.0 uploads approximately 25% of images (one in four on average), 50.0 uploads half, and 100.0 uploads everything (no sampling). Random sampling occurs before quota checking and image processing, making it efficient for large-scale data collection workflows.\",\n        examples=[100, 25, 50, \"$inputs.sampling_rate\"],\n    )\n    minutely_usage_limit: int = Field(\n        default=10,\n        description=\"Maximum number of image uploads allowed per minute for this quota. Part of the usage quota system that enforces rate limits for active learning data collection. Uploads exceeding this limit are skipped to prevent excessive data collection. Works together with hourly_usage_limit and daily_usage_limit to provide multi-level rate limiting. Note: This quota is checked after probabilistic sampling via data_percentage.\",\n        examples=[10, 60],\n    )\n    hourly_usage_limit: int = Field(\n        default=100,\n        description=\"Maximum number of image uploads allowed per hour for this quota. Part of the usage quota system that enforces rate limits for active learning data collection. Uploads exceeding this limit are skipped to prevent excessive data collection. Works together with minutely_usage_limit and daily_usage_limit to provide multi-level rate limiting. Note: This quota is checked after probabilistic sampling via data_percentage.\",\n        examples=[10, 60],\n    )\n    daily_usage_limit: int = Field(\n        default=1000,\n        description=\"Maximum number of image uploads allowed per day for this quota. Part of the usage quota system that enforces rate limits for active learning data collection. Uploads exceeding this limit are skipped to prevent excessive data collection. Works together with minutely_usage_limit and hourly_usage_limit to provide multi-level rate limiting. Note: This quota is checked after probabilistic sampling via data_percentage.\",\n        examples=[10, 60],\n    )\n    usage_quota_name: str = Field(\n        description=\"Unique identifier for tracking usage quotas (minutely, hourly, daily limits). Used internally to manage rate limiting across multiple upload operations. Each unique quota name maintains separate counters, allowing different upload strategies or data collection workflows to have independent rate limits.\",\n        examples=[\"quota-for-data-sampling-1\"],\n        json_schema_extra={\"hidden\": True},\n    )\n    max_image_size: Tuple[int, int] = Field(\n        default=(1920, 1080),\n        description=\"Maximum dimensions (width, height) for uploaded images. Images exceeding these dimensions are automatically resized while preserving aspect ratio before uploading. Default is (1920, 1080) for higher resolution data collection. Use smaller sizes (e.g., (512, 512)) for efficient storage and faster uploads, or keep the default for preserving image quality.\",\n        examples=[(1920, 1080), (512, 512)],\n    )\n    compression_level: int = Field(\n        default=95,\n        gt=0,\n        le=100,\n        description=\"JPEG compression quality level for uploaded images, ranging from 1 (highest compression, smallest file size, lower quality) to 100 (no compression, largest file size, highest quality). Default is 95 for better image quality preservation. Higher values preserve more image quality but increase storage and bandwidth usage. Typical values range from 70-95 for balanced quality and size.\",\n        examples=[95, 75],\n    )\n    registration_tags: Union[\n        List[Union[Selector(kind=[STRING_KIND]), str]],\n        Selector(kind=[LIST_OF_VALUES_KIND]),\n    ] = Field(\n        default_factory=list,\n        description=\"List of tags to attach to uploaded images for organization and filtering in Roboflow. Tags can be static strings (e.g., 'location-florida', 'camera-1') or dynamic values from workflow inputs. Tags help organize collected data, filter images in Roboflow, and add metadata for dataset management. Can be an empty list if no tags are needed.\",\n        examples=[\n            [\"location-florida\", \"factory-name\", \"$inputs.dynamic_tag\"],\n            \"$inputs.tags\",\n        ],\n    )\n    persist_predictions: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=True,\n        description=\"If True, model predictions are saved as annotations (pre-labels) in the Roboflow dataset alongside images. This enables predictions to serve as starting points for annotation, allowing reviewers to correct or approve labels rather than creating them from scratch. If False, only images are uploaded without annotations. Enabling this accelerates annotation workflows by providing initial labels.\",\n        examples=[True, False, \"$inputs.persist_predictions\"],\n    )\n    disable_sink: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=False,\n        description=\"If True, the block execution is disabled and no uploads occur. This allows temporarily disabling data collection without removing the block from workflows, useful for testing, debugging, or conditional data collection. When disabled, returns a message indicating the sink was disabled. Default is False (uploads enabled).\",\n        examples=[True, \"$inputs.disable_active_learning\"],\n    )\n    fire_and_forget: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=True,\n        description=\"If True, uploads execute asynchronously (fire-and-forget mode), allowing the workflow to continue immediately without waiting for upload completion. This improves workflow performance but prevents error handling. If False, uploads execute synchronously, blocking workflow execution until completion and allowing proper error handling and status reporting. Use async mode (True) for production workflows where speed is prioritized, and sync mode (False) for debugging or when error handling is critical.\",\n    )\n    labeling_batch_prefix: Union[str, Selector(kind=[STRING_KIND])] = Field(\n        default=\"workflows_data_collector\",\n        description=\"Prefix used to generate labeling batch names for organizing uploaded images in Roboflow. Combined with the batch recreation frequency and timestamps to create batch names like 'workflows_data_collector_2024_01_15'. Batches help organize collected data for labeling, making it easier to manage and review uploaded images in groups. Can be customized to match your organization scheme.\",\n        examples=[\"my_labeling_batch_name\"],\n    )\n    labeling_batches_recreation_frequency: BatchCreationFrequency = Field(\n        default=\"never\",\n        description=\"Frequency at which new labeling batches are automatically created for uploaded images. Options: 'never' (all images go to the same batch), 'daily' (new batch each day), 'weekly' (new batch each week), 'monthly' (new batch each month). Batch timestamps are appended to the labeling_batch_prefix to create unique batch names. Automatically organizing uploads into time-based batches simplifies dataset management and makes it easier to track and review collected data over time.\",\n        examples=[\"never\", \"daily\"],\n    )\n    image_name: Optional[Union[str, Selector(kind=[STRING_KIND])]] = Field(\n        default=None,\n        description=\"Optional custom name for the uploaded image. This is useful when you want to preserve the original filename or use a meaningful identifier (e.g., serial number, timestamp) for the image in the Roboflow dataset. The name should not include file extension. If not provided, a UUID will be generated automatically.\",\n        examples=[\"serial_12345\", \"camera1_frame_001\", \"$inputs.filename\"],\n    )\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return [\"images\", \"predictions\", \"image_name\"]\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"error_status\", kind=[BOOLEAN_KIND]),\n            OutputDefinition(name=\"message\", kind=[STRING_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass RoboflowDatasetUploadBlockV2(WorkflowBlock):\n\n    def __init__(\n        self,\n        cache: BaseCache,\n        api_key: Optional[str],\n        background_tasks: Optional[BackgroundTasks],\n        thread_pool_executor: Optional[ThreadPoolExecutor],\n    ):\n        self._cache = cache\n        self._api_key = api_key\n        self._background_tasks = background_tasks\n        self._thread_pool_executor = thread_pool_executor\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"cache\", \"api_key\", \"background_tasks\", \"thread_pool_executor\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        predictions: Optional[Batch[Union[sv.Detections, dict]]],\n        target_project: str,\n        usage_quota_name: str,\n        data_percentage: float,\n        minutely_usage_limit: int,\n        persist_predictions: bool,\n        hourly_usage_limit: int,\n        daily_usage_limit: int,\n        max_image_size: Tuple[int, int],\n        compression_level: int,\n        registration_tags: List[str],\n        disable_sink: bool,\n        fire_and_forget: bool,\n        labeling_batch_prefix: str,\n        labeling_batches_recreation_frequency: BatchCreationFrequency,\n        image_name: Optional[Batch[Optional[str]]] = None,\n    ) -> BlockResult:\n        if self._api_key is None:\n            raise ValueError(\n                \"RoboflowDataCollector block cannot run without Roboflow API key. \"\n                \"If you do not know how to get API key - visit \"\n                \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to \"\n                \"retrieve one.\"\n            )\n        if disable_sink:\n            return [\n                {\n                    \"error_status\": False,\n                    \"message\": \"Sink was disabled by parameter `disable_sink`\",\n                }\n                for _ in range(len(images))\n            ]\n        result = []\n        predictions = [None] * len(images) if predictions is None else predictions\n        image_names = [None] * len(images) if image_name is None else image_name\n        for image, prediction, img_name in zip(images, predictions, image_names):\n            error_status, message = maybe_register_datapoint_at_roboflow(\n                image=image,\n                prediction=prediction,\n                target_project=target_project,\n                usage_quota_name=usage_quota_name,\n                data_percentage=data_percentage,\n                persist_predictions=persist_predictions,\n                minutely_usage_limit=minutely_usage_limit,\n                hourly_usage_limit=hourly_usage_limit,\n                daily_usage_limit=daily_usage_limit,\n                max_image_size=max_image_size,\n                compression_level=compression_level,\n                registration_tags=registration_tags,\n                fire_and_forget=fire_and_forget,\n                labeling_batch_prefix=labeling_batch_prefix,\n                new_labeling_batch_frequency=labeling_batches_recreation_frequency,\n                cache=self._cache,\n                background_tasks=self._background_tasks,\n                thread_pool_executor=self._thread_pool_executor,\n                api_key=self._api_key,\n                image_name=img_name,\n            )\n            result.append({\"error_status\": error_status, \"message\": message})\n        return result\n\n\ndef maybe_register_datapoint_at_roboflow(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    usage_quota_name: str,\n    data_percentage: float,\n    persist_predictions: bool,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    fire_and_forget: bool,\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    background_tasks: Optional[BackgroundTasks],\n    thread_pool_executor: Optional[ThreadPoolExecutor],\n    api_key: str,\n    image_name: Optional[str] = None,\n) -> Tuple[bool, str]:\n    normalised_probability = data_percentage / 100\n    if random.random() < normalised_probability:\n        return register_datapoint_at_roboflow(\n            image=image,\n            prediction=prediction,\n            target_project=target_project,\n            usage_quota_name=usage_quota_name,\n            persist_predictions=persist_predictions,\n            minutely_usage_limit=minutely_usage_limit,\n            hourly_usage_limit=hourly_usage_limit,\n            daily_usage_limit=daily_usage_limit,\n            max_image_size=max_image_size,\n            compression_level=compression_level,\n            registration_tags=registration_tags,\n            fire_and_forget=fire_and_forget,\n            labeling_batch_prefix=labeling_batch_prefix,\n            new_labeling_batch_frequency=new_labeling_batch_frequency,\n            cache=cache,\n            background_tasks=background_tasks,\n            thread_pool_executor=thread_pool_executor,\n            api_key=api_key,\n            image_name=image_name,\n        )\n    return False, \"Registration skipped due to sampling settings\"\n",
    "patch": null
  },
  {
    "trace_id": "9e33c841-f999-4a4f-a649-5f2a9190863e",
    "function_name": "is_prediction_registration_forbidden",
    "file_path": "inference/core/workflows/core_steps/sinks/roboflow/dataset_upload/v1.py",
    "speedup_x": 0.4361530609115484,
    "review_quality": "high",
    "pre_optimization_commit": "c20359386c628a08bde69f5f3f780cedd782c50c",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def is_prediction_registration_forbidden(\n    prediction: Optional[Union[sv.Detections, dict]],\n) -> bool:\n    if prediction is None:\n        return True\n    if isinstance(prediction, sv.Detections) and len(prediction) == 0:\n        return True\n    if isinstance(prediction, dict) and (\n        \"top\" not in prediction and \"predicted_classes\" not in prediction\n    ):\n        return True\n    return False\n",
    "optimized_function_code": "from typing import Optional, Union\n\nimport supervision as sv\n\n\ndef is_prediction_registration_forbidden(\n    prediction: Optional[Union[sv.Detections, dict]],\n) -> bool:\n    if prediction is None:\n        return True\n    \n    # Fast path: check if it's a dict first (most common case based on profiling)\n    pred_type = type(prediction)\n    if pred_type is dict:\n        return \"top\" not in prediction and \"predicted_classes\" not in prediction\n    \n    # Check sv.Detections case\n    if isinstance(prediction, sv.Detections):\n        return len(prediction) == 0\n    \n    return False",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/sinks/roboflow/dataset_upload/v1.py\nfrom typing import Optional, Union\n\nimport supervision as sv\n\n\ndef is_prediction_registration_forbidden(\n    prediction: Optional[Union[sv.Detections, dict]],\n) -> bool:\n    if prediction is None:\n        return True\n    \n    # Fast path: check if it's a dict first (most common case based on profiling)\n    pred_type = type(prediction)\n    if pred_type is dict:\n        return \"top\" not in prediction and \"predicted_classes\" not in prediction\n    \n    # Check sv.Detections case\n    if isinstance(prediction, sv.Detections):\n        return len(prediction) == 0\n    \n    return False\n```",
    "optimized_function_only": "def is_prediction_registration_forbidden(\n    prediction: Optional[Union[sv.Detections, dict]],\n) -> bool:\n    if prediction is None:\n        return True\n    \n    # Fast path: check if it's a dict first (most common case based on profiling)\n    pred_type = type(prediction)\n    if pred_type is dict:\n        return \"top\" not in prediction and \"predicted_classes\" not in prediction\n    \n    # Check sv.Detections case\n    if isinstance(prediction, sv.Detections):\n        return len(prediction) == 0\n    \n    return False",
    "original_file_content": "\"\"\"\n*****************************************************************\n*                           WARNING!                            *\n*****************************************************************\nThis module contains the utility functions used by\nRoboflowDatasetUploadBlockV2.\n\nWe do not recommend making multiple blocks dependent on the same code,\nbut the change between v1 and v2 was basically the default value of\nsome parameter - hence we decided not to replicate the code.\n\nIf you need to modify this module beware that you may introduce\nchange to RoboflowDatasetUploadBlockV2! If that happens,\nprobably that's the time to disentangle those blocks and copy the\ncode.\n\"\"\"\n\nimport hashlib\nimport json\nimport logging\nfrom collections import OrderedDict\nfrom concurrent.futures import ThreadPoolExecutor\nfrom datetime import datetime, timedelta\nfrom functools import partial\nfrom typing import Any, Dict, List, Literal, Optional, Tuple, Type, Union\nfrom uuid import uuid4\n\nimport supervision as sv\nfrom fastapi import BackgroundTasks\nfrom pydantic import AliasChoices, ConfigDict, Field\n\nfrom inference.core.active_learning.cache_operations import (\n    return_strategy_credit,\n    use_credit_of_matching_strategy,\n)\nfrom inference.core.active_learning.core import prepare_image_to_registration\nfrom inference.core.active_learning.entities import (\n    ImageDimensions,\n    StrategyLimit,\n    StrategyLimitType,\n)\nfrom inference.core.cache.base import BaseCache\nfrom inference.core.roboflow_api import (\n    annotate_image_at_roboflow,\n    get_roboflow_workspace,\n    register_image_at_roboflow,\n)\nfrom inference.core.workflows.core_steps.common.serializers import (\n    serialise_sv_detections,\n)\nfrom inference.core.workflows.core_steps.common.utils import scale_sv_detections\nfrom inference.core.workflows.execution_engine.constants import INFERENCE_ID_KEY\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    BOOLEAN_KIND,\n    CLASSIFICATION_PREDICTION_KIND,\n    IMAGE_KIND,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    KEYPOINT_DETECTION_PREDICTION_KIND,\n    LIST_OF_VALUES_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    ROBOFLOW_PROJECT_KIND,\n    STRING_KIND,\n    ImageInputField,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    AirGappedAvailability,\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nSHORT_DESCRIPTION = \"Save images and predictions to your Roboflow Dataset.\"\n\nLONG_DESCRIPTION = \"\"\"\nUpload images and model predictions to a Roboflow dataset for active learning, model improvement, and data collection, with configurable usage quotas, batch organization, image compression, and optional annotation persistence.\n\n## How This Block Works\n\nThis block uploads workflow images and predictions to your Roboflow dataset for storage, labeling, and model training. The block:\n\n1. Takes images and optional model predictions (object detection, instance segmentation, keypoint detection, or classification) as input\n2. Validates the Roboflow API key is available (required for uploading)\n3. Checks usage quotas (minutely, hourly, daily limits) to ensure uploads stay within configured rate limits for active learning strategies\n4. Prepares images by resizing if they exceed maximum size (maintaining aspect ratio) and compressing to specified quality level\n5. Generates labeling batch names based on the prefix and batch creation frequency (never, daily, weekly, or monthly), organizing uploaded data into batches\n6. Optionally persists model predictions as annotations if `persist_predictions` is enabled, allowing predictions to serve as pre-labels for review and correction\n7. Attaches registration tags to images for organization and filtering in the Roboflow platform\n8. Registers the image (and annotations if enabled) to the specified Roboflow project via the Roboflow API\n9. Executes synchronously or asynchronously based on `fire_and_forget` setting, allowing non-blocking uploads for faster workflow execution\n10. Returns error status and messages indicating upload success or failure\n\nThe block supports active learning workflows by implementing usage quotas that prevent excessive data collection, helping focus on collecting valuable training data within rate limits. Images are organized into labeling batches that can be automatically recreated on a schedule (daily, weekly, monthly), making it easier to manage and review collected data over time. The block can operate in fire-and-forget mode for asynchronous execution, allowing workflows to continue processing without waiting for uploads to complete, or synchronously for debugging and error handling.\n\n## Requirements\n\n**API Key Required**: This block requires a valid Roboflow API key to upload data. The API key must be configured in your environment or workflow configuration. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve an API key.\n\n## Common Use Cases\n\n- **Active Learning Data Collection**: Collect images and predictions from production environments where models struggle or are uncertain (e.g., low-confidence detections, edge cases), enabling iterative model improvement by gathering challenging examples for retraining\n- **Production Data Logging**: Continuously upload production inference data to Roboflow datasets for monitoring, analysis, and future model training, creating a growing dataset from real-world deployments\n- **Pre-Labeled Data Collection**: Upload images with model predictions as pre-labels (when `persist_predictions` is enabled), accelerating annotation workflows by providing initial labels that can be reviewed and corrected rather than starting from scratch\n- **Stratified Data Sampling**: Use rate limiting and quotas to selectively collect data based on specific criteria (e.g., combine with Rate Limiter or Continue If blocks), ensuring diverse and balanced dataset collection without overwhelming storage or annotation resources\n- **Batch-Based Labeling Workflows**: Organize uploaded data into batches with automatic recreation schedules (daily, weekly, monthly), making it easier to manage labeling tasks, track progress, and organize data collection efforts over time\n- **Tagged Data Organization**: Attach metadata tags to uploaded images (e.g., location, camera ID, time period, model version), enabling filtering and organization of collected data in Roboflow for better dataset management and analysis\n\n## Connecting to Other Blocks\n\nThis block receives data from workflow steps and uploads it to Roboflow:\n\n- **After detection or analysis blocks** (e.g., Object Detection Model, Instance Segmentation Model, Classification Model, Keypoint Detection Model) to upload images along with their predictions, enabling active learning by collecting inference data with model outputs for annotation and retraining\n- **After filtering or analytics blocks** (e.g., Detections Filter, Continue If, Overlap Filter) to selectively upload only specific types of data (e.g., low-confidence detections, overlapping objects, specific classes), focusing data collection on valuable edge cases or interesting scenarios\n- **After rate limiter blocks** (e.g., Rate Limiter) to throttle upload frequency and stay within usage quotas, ensuring controlled data collection that respects rate limits and prevents excessive storage usage\n- **Image inputs or preprocessing blocks** to upload raw images or processed images (e.g., crops, transformed images) without predictions, enabling collection of image data for future labeling or analysis\n- **Conditional workflows** using flow control blocks (e.g., Continue If) to upload data only when certain conditions are met (e.g., upload only when detection count exceeds threshold, upload only errors or failures), enabling selective data collection based on workflow state\n- **Batch processing workflows** where multiple images or predictions are generated, allowing bulk upload of workflow outputs to Roboflow datasets for organized data collection and management\n\"\"\"\n\nWORKSPACE_NAME_CACHE_EXPIRE = 900  # 15 min\nTIMESTAMP_FORMAT = \"%Y_%m_%d\"\nDUPLICATED_STATUS = \"Duplicated image\"\nBatchCreationFrequency = Literal[\"never\", \"daily\", \"weekly\", \"monthly\"]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Roboflow Dataset Upload\",\n            \"version\": \"v1\",\n            \"short_description\": SHORT_DESCRIPTION,\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"sink\",\n            \"ui_manifest\": {\n                \"section\": \"data_storage\",\n                \"icon\": \"fal fa-upload\",\n                \"blockPriority\": 0,\n                \"popular\": True,\n                \"requires_rf_key\": True,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/roboflow_dataset_upload@v1\", \"RoboflowDatasetUpload\"]\n    images: Selector(kind=[IMAGE_KIND]) = Field(\n        title=\"Input Image\",\n        description=\"Image(s) to upload to the Roboflow dataset. Can be a single image or batch of images from workflow inputs or processing steps. Images are resized if they exceed max_image_size and compressed before uploading. Supports batch processing.\",\n        examples=[\"$inputs.image\", \"$steps.cropping.crops\"],\n        validation_alias=AliasChoices(\"image\", \"images\"),\n    )\n    predictions: Optional[\n        Selector(\n            kind=[\n                OBJECT_DETECTION_PREDICTION_KIND,\n                INSTANCE_SEGMENTATION_PREDICTION_KIND,\n                KEYPOINT_DETECTION_PREDICTION_KIND,\n                CLASSIFICATION_PREDICTION_KIND,\n            ]\n        )\n    ] = Field(\n        default=None,\n        description=\"Optional model predictions to upload alongside images. Predictions are saved as annotations (pre-labels) in the Roboflow dataset when persist_predictions is enabled, allowing predictions to serve as starting points for annotation review and correction. Supports object detection, instance segmentation, keypoint detection, and classification predictions. If None, only images are uploaded.\",\n        examples=[\"$steps.object_detection_model.predictions\"],\n    )\n    target_project: Union[Selector(kind=[ROBOFLOW_PROJECT_KIND]), str] = Field(\n        description=\"Roboflow project identifier where uploaded images and annotations will be saved. Must be a valid project in your Roboflow workspace. The project name can be specified directly or referenced from workflow inputs.\",\n        examples=[\"my_project\", \"$inputs.target_project\"],\n    )\n    minutely_usage_limit: int = Field(\n        default=10,\n        description=\"Maximum number of image uploads allowed per minute for this quota. Part of the usage quota system that enforces rate limits for active learning data collection. Uploads exceeding this limit are skipped to prevent excessive data collection. Works together with hourly_usage_limit and daily_usage_limit to provide multi-level rate limiting.\",\n        examples=[10, 60],\n    )\n    hourly_usage_limit: int = Field(\n        default=100,\n        description=\"Maximum number of image uploads allowed per hour for this quota. Part of the usage quota system that enforces rate limits for active learning data collection. Uploads exceeding this limit are skipped to prevent excessive data collection. Works together with minutely_usage_limit and daily_usage_limit to provide multi-level rate limiting.\",\n        examples=[10, 60],\n    )\n    daily_usage_limit: int = Field(\n        default=1000,\n        description=\"Maximum number of image uploads allowed per day for this quota. Part of the usage quota system that enforces rate limits for active learning data collection. Uploads exceeding this limit are skipped to prevent excessive data collection. Works together with minutely_usage_limit and hourly_usage_limit to provide multi-level rate limiting.\",\n        examples=[10, 60],\n    )\n    usage_quota_name: str = Field(\n        description=\"Unique identifier for tracking usage quotas (minutely, hourly, daily limits). Used internally to manage rate limiting across multiple upload operations. Each unique quota name maintains separate counters, allowing different upload strategies or data collection workflows to have independent rate limits.\",\n        examples=[\"quota-for-data-sampling-1\"],\n        json_schema_extra={\"hidden\": True},\n    )\n    max_image_size: Tuple[int, int] = Field(\n        default=(512, 512),\n        description=\"Maximum dimensions (width, height) for uploaded images. Images exceeding these dimensions are automatically resized while preserving aspect ratio before uploading. Smaller sizes reduce storage and bandwidth but may lose image quality. Use larger sizes (e.g., (1920, 1080)) for high-resolution data collection, or smaller sizes (e.g., (512, 512)) for efficient storage and faster uploads.\",\n        examples=[(512, 512), (1920, 1080)],\n    )\n    compression_level: int = Field(\n        default=75,\n        gt=0,\n        le=100,\n        description=\"JPEG compression quality level for uploaded images, ranging from 1 (highest compression, smallest file size, lower quality) to 100 (no compression, largest file size, highest quality). Higher values preserve more image quality but increase storage and bandwidth usage. Typical values range from 70-90 for balanced quality and size. Default of 75 provides good quality with reasonable file sizes.\",\n        examples=[75],\n    )\n    registration_tags: Union[\n        List[Union[Selector(kind=[STRING_KIND]), str]],\n        Selector(kind=[LIST_OF_VALUES_KIND]),\n    ] = Field(\n        default_factory=list,\n        description=\"List of tags to attach to uploaded images for organization and filtering in Roboflow. Tags can be static strings (e.g., 'location-florida', 'camera-1') or dynamic values from workflow inputs. Tags help organize collected data, filter images in Roboflow, and add metadata for dataset management. Can be an empty list if no tags are needed.\",\n        examples=[\n            [\"location-florida\", \"factory-name\", \"$inputs.dynamic_tag\"],\n            \"$inputs.tags\",\n        ],\n    )\n    persist_predictions: bool = Field(\n        default=True,\n        description=\"If True, model predictions are saved as annotations (pre-labels) in the Roboflow dataset alongside images. This enables predictions to serve as starting points for annotation, allowing reviewers to correct or approve labels rather than creating them from scratch. If False, only images are uploaded without annotations. Enabling this accelerates annotation workflows by providing initial labels.\",\n        examples=[True, False],\n    )\n    disable_sink: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=False,\n        description=\"If True, the block execution is disabled and no uploads occur. This allows temporarily disabling data collection without removing the block from workflows, useful for testing, debugging, or conditional data collection. When disabled, returns a message indicating the sink was disabled. Default is False (uploads enabled).\",\n        examples=[True, \"$inputs.disable_active_learning\"],\n    )\n    fire_and_forget: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=True,\n        description=\"If True, uploads execute asynchronously (fire-and-forget mode), allowing the workflow to continue immediately without waiting for upload completion. This improves workflow performance but prevents error handling. If False, uploads execute synchronously, blocking workflow execution until completion and allowing proper error handling and status reporting. Use async mode (True) for production workflows where speed is prioritized, and sync mode (False) for debugging or when error handling is critical.\",\n        examples=[True],\n    )\n    labeling_batch_prefix: Union[str, Selector(kind=[STRING_KIND])] = Field(\n        default=\"workflows_data_collector\",\n        description=\"Prefix used to generate labeling batch names for organizing uploaded images in Roboflow. Combined with the batch recreation frequency and timestamps to create batch names like 'workflows_data_collector_2024_01_15'. Batches help organize collected data for labeling, making it easier to manage and review uploaded images in groups. Can be customized to match your organization scheme.\",\n        examples=[\"my_labeling_batch_name\"],\n    )\n    labeling_batches_recreation_frequency: BatchCreationFrequency = Field(\n        default=\"never\",\n        description=\"Frequency at which new labeling batches are automatically created for uploaded images. Options: 'never' (all images go to the same batch), 'daily' (new batch each day), 'weekly' (new batch each week), 'monthly' (new batch each month). Batch timestamps are appended to the labeling_batch_prefix to create unique batch names. Automatically organizing uploads into time-based batches simplifies dataset management and makes it easier to track and review collected data over time.\",\n        examples=[\"never\", \"daily\"],\n    )\n    image_name: Optional[Union[str, Selector(kind=[STRING_KIND])]] = Field(\n        default=None,\n        description=\"Optional custom name for the uploaded image. If provided, this name will be used instead of an auto-generated UUID. This is useful when you want to preserve the original filename or use a meaningful identifier (e.g., serial number, timestamp) for the image in the Roboflow dataset. The name should not include file extension. If not provided, a UUID will be generated automatically.\",\n        examples=[\"serial_12345\", \"camera1_frame_001\", \"$inputs.filename\"],\n    )\n\n    @classmethod\n    def get_air_gapped_availability(cls) -> AirGappedAvailability:\n        return AirGappedAvailability(available=False, reason=\"requires_internet\")\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return [\"images\", \"predictions\", \"image_name\"]\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"error_status\", kind=[BOOLEAN_KIND]),\n            OutputDefinition(name=\"message\", kind=[STRING_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass RoboflowDatasetUploadBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        cache: BaseCache,\n        api_key: Optional[str],\n        background_tasks: Optional[BackgroundTasks],\n        thread_pool_executor: Optional[ThreadPoolExecutor],\n    ):\n        self._cache = cache\n        self._api_key = api_key\n        self._background_tasks = background_tasks\n        self._thread_pool_executor = thread_pool_executor\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"cache\", \"api_key\", \"background_tasks\", \"thread_pool_executor\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        predictions: Optional[Batch[Union[sv.Detections, dict]]],\n        target_project: str,\n        usage_quota_name: str,\n        minutely_usage_limit: int,\n        persist_predictions: bool,\n        hourly_usage_limit: int,\n        daily_usage_limit: int,\n        max_image_size: Tuple[int, int],\n        compression_level: int,\n        registration_tags: List[str],\n        disable_sink: bool,\n        fire_and_forget: bool,\n        labeling_batch_prefix: str,\n        labeling_batches_recreation_frequency: BatchCreationFrequency,\n        image_name: Optional[Batch[Optional[str]]] = None,\n    ) -> BlockResult:\n        if self._api_key is None:\n            raise ValueError(\n                \"RoboflowDataCollector block cannot run without Roboflow API key. \"\n                \"If you do not know how to get API key - visit \"\n                \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to \"\n                \"retrieve one.\"\n            )\n        if disable_sink:\n            return [\n                {\n                    \"error_status\": False,\n                    \"message\": \"Sink was disabled by parameter `disable_sink`\",\n                }\n                for _ in range(len(images))\n            ]\n        result = []\n        predictions = [None] * len(images) if predictions is None else predictions\n        image_names = [None] * len(images) if image_name is None else image_name\n        for image, prediction, img_name in zip(images, predictions, image_names):\n            error_status, message = register_datapoint_at_roboflow(\n                image=image,\n                prediction=prediction,\n                target_project=target_project,\n                usage_quota_name=usage_quota_name,\n                persist_predictions=persist_predictions,\n                minutely_usage_limit=minutely_usage_limit,\n                hourly_usage_limit=hourly_usage_limit,\n                daily_usage_limit=daily_usage_limit,\n                max_image_size=max_image_size,\n                compression_level=compression_level,\n                registration_tags=registration_tags,\n                fire_and_forget=fire_and_forget,\n                labeling_batch_prefix=labeling_batch_prefix,\n                new_labeling_batch_frequency=labeling_batches_recreation_frequency,\n                cache=self._cache,\n                background_tasks=self._background_tasks,\n                thread_pool_executor=self._thread_pool_executor,\n                api_key=self._api_key,\n                image_name=img_name,\n            )\n            result.append({\"error_status\": error_status, \"message\": message})\n        return result\n\n\ndef register_datapoint_at_roboflow(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    usage_quota_name: str,\n    persist_predictions: bool,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    fire_and_forget: bool,\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    background_tasks: Optional[BackgroundTasks],\n    thread_pool_executor: Optional[ThreadPoolExecutor],\n    api_key: str,\n    image_name: Optional[str] = None,\n    metadata: Optional[Dict[str, Any]] = None,\n) -> Tuple[bool, str]:\n    registration_task = partial(\n        execute_registration,\n        image=image,\n        prediction=prediction,\n        target_project=target_project,\n        usage_quota_name=usage_quota_name,\n        persist_predictions=persist_predictions,\n        minutely_usage_limit=minutely_usage_limit,\n        hourly_usage_limit=hourly_usage_limit,\n        daily_usage_limit=daily_usage_limit,\n        max_image_size=max_image_size,\n        compression_level=compression_level,\n        registration_tags=registration_tags,\n        labeling_batch_prefix=labeling_batch_prefix,\n        new_labeling_batch_frequency=new_labeling_batch_frequency,\n        cache=cache,\n        api_key=api_key,\n        image_name=image_name,\n        metadata=metadata,\n    )\n    if fire_and_forget and background_tasks:\n        background_tasks.add_task(registration_task)\n        return False, \"Element registration happens in the background task\"\n    if fire_and_forget and thread_pool_executor:\n        thread_pool_executor.submit(registration_task)\n        return False, \"Element registration happens in the background task\"\n    return registration_task()\n\n\ndef execute_registration(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    persist_predictions: bool,\n    usage_quota_name: str,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    api_key: str,\n    image_name: Optional[str] = None,\n    metadata: Optional[Dict[str, Any]] = None,\n) -> Tuple[bool, str]:\n    matching_strategies_limits = OrderedDict(\n        {\n            usage_quota_name: [\n                StrategyLimit(\n                    limit_type=StrategyLimitType.MINUTELY, value=minutely_usage_limit\n                ),\n                StrategyLimit(\n                    limit_type=StrategyLimitType.HOURLY, value=hourly_usage_limit\n                ),\n                StrategyLimit(\n                    limit_type=StrategyLimitType.DAILY, value=daily_usage_limit\n                ),\n            ]\n        }\n    )\n    workspace_name = get_workspace_name(api_key=api_key, cache=cache)\n    strategy_with_spare_credit = use_credit_of_matching_strategy(\n        cache=cache,\n        workspace=workspace_name,\n        project=target_project,\n        matching_strategies_limits=matching_strategies_limits,\n    )\n    if strategy_with_spare_credit is None:\n        return False, \"Registration skipped due to usage quota exceeded\"\n    credit_to_be_returned = False\n    try:\n        local_image_id = image_name if image_name else str(uuid4())\n        encoded_image, scaling_factor = prepare_image_to_registration(\n            image=image.numpy_image,\n            desired_size=ImageDimensions(\n                width=max_image_size[0], height=max_image_size[1]\n            ),\n            jpeg_compression_level=compression_level,\n        )\n        batch_name = generate_batch_name(\n            labeling_batch_prefix=labeling_batch_prefix,\n            new_labeling_batch_frequency=new_labeling_batch_frequency,\n        )\n        if isinstance(prediction, sv.Detections):\n            prediction = scale_sv_detections(\n                detections=prediction, scale=scaling_factor\n            )\n        status = register_datapoint(\n            target_project=target_project,\n            encoded_image=encoded_image,\n            local_image_id=local_image_id,\n            prediction=prediction if persist_predictions else None,\n            api_key=api_key,\n            batch_name=batch_name,\n            tags=registration_tags,\n            metadata=metadata,\n        )\n        if status == DUPLICATED_STATUS:\n            credit_to_be_returned = True\n        return False, status\n    except Exception as error:\n        credit_to_be_returned = True\n        logging.exception(\"Failed to register datapoint on the Roboflow platform\")\n        return (\n            True,\n            f\"Error while registration. Error type: {type(error)}. Details: {error}\",\n        )\n    finally:\n        if credit_to_be_returned:\n            return_strategy_credit(\n                cache=cache,\n                workspace=workspace_name,\n                project=target_project,\n                strategy_name=strategy_with_spare_credit,\n            )\n\n\ndef get_workspace_name(\n    api_key: str,\n    cache: BaseCache,\n) -> str:\n    api_key_hash = hashlib.md5(api_key.encode(\"utf-8\")).hexdigest()\n    cache_key = f\"workflows:api_key_to_workspace:{api_key_hash}\"\n    cached_workspace_name = cache.get(cache_key)\n    if cached_workspace_name:\n        return cached_workspace_name\n    workspace_name_from_api = get_roboflow_workspace(api_key=api_key)\n    cache.set(\n        key=cache_key, value=workspace_name_from_api, expire=WORKSPACE_NAME_CACHE_EXPIRE\n    )\n    return workspace_name_from_api\n\n\ndef generate_batch_name(\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n) -> str:\n    if new_labeling_batch_frequency == \"never\":\n        return labeling_batch_prefix\n    timestamp_generator = RECREATION_INTERVAL2TIMESTAMP_GENERATOR[\n        new_labeling_batch_frequency\n    ]\n    timestamp = timestamp_generator()\n    return f\"{labeling_batch_prefix}_{timestamp}\"\n\n\ndef generate_today_timestamp() -> str:\n    return datetime.today().strftime(TIMESTAMP_FORMAT)\n\n\ndef generate_start_timestamp_for_this_week() -> str:\n    today = datetime.today()\n    return (today - timedelta(days=today.weekday())).strftime(TIMESTAMP_FORMAT)\n\n\ndef generate_start_timestamp_for_this_month() -> str:\n    return datetime.today().replace(day=1).strftime(TIMESTAMP_FORMAT)\n\n\nRECREATION_INTERVAL2TIMESTAMP_GENERATOR = {\n    \"daily\": generate_today_timestamp,\n    \"weekly\": generate_start_timestamp_for_this_week,\n    \"monthly\": generate_start_timestamp_for_this_month,\n}\n\n\ndef register_datapoint(\n    target_project: str,\n    encoded_image: bytes,\n    local_image_id: str,\n    prediction: Optional[Union[sv.Detections, dict]],\n    api_key: str,\n    batch_name: str,\n    tags: List[str],\n    metadata: Optional[Dict[str, Any]] = None,\n) -> str:\n    inference_id = None\n    if isinstance(prediction, dict):\n        inference_id = prediction.get(INFERENCE_ID_KEY)\n    if isinstance(prediction, sv.Detections) and len(prediction) > 0:\n        # TODO: Lack of inference ID for empty prediction -\n        #  dependent on https://github.com/roboflow/inference/issues/567\n        inference_id_array = prediction.data.get(INFERENCE_ID_KEY)\n        if inference_id_array is not None:\n            inference_id_list = inference_id_array.tolist()\n            inference_id = inference_id_list[0]\n    roboflow_image_id = safe_register_image_at_roboflow(\n        target_project=target_project,\n        encoded_image=encoded_image,\n        local_image_id=local_image_id,\n        api_key=api_key,\n        batch_name=batch_name,\n        tags=tags,\n        inference_id=inference_id,\n        metadata=metadata,\n    )\n    if roboflow_image_id is None:\n        return DUPLICATED_STATUS\n    if is_prediction_registration_forbidden(prediction=prediction):\n        return \"Successfully registered image\"\n    encoded_prediction, prediction_format = encode_prediction(prediction=prediction)\n    _ = annotate_image_at_roboflow(\n        api_key=api_key,\n        dataset_id=target_project,\n        local_image_id=local_image_id,\n        roboflow_image_id=roboflow_image_id,\n        annotation_content=encoded_prediction,\n        annotation_file_type=prediction_format,\n        is_prediction=True,\n    )\n    return \"Successfully registered image and annotation\"\n\n\ndef safe_register_image_at_roboflow(\n    target_project: str,\n    encoded_image: bytes,\n    local_image_id: str,\n    api_key: str,\n    batch_name: str,\n    tags: List[str],\n    inference_id: Optional[str],\n    metadata: Optional[Dict[str, Any]] = None,\n) -> Optional[str]:\n    registration_response = register_image_at_roboflow(\n        api_key=api_key,\n        dataset_id=target_project,\n        local_image_id=local_image_id,\n        image_bytes=encoded_image,\n        batch_name=batch_name,\n        tags=tags,\n        inference_id=inference_id,\n        metadata=metadata,\n    )\n    image_duplicated = registration_response.get(\"duplicate\", False)\n    if image_duplicated:\n        logging.warning(f\"Image duplication detected: {registration_response}.\")\n        return None\n    return registration_response[\"id\"]\n\n\ndef is_prediction_registration_forbidden(\n    prediction: Optional[Union[sv.Detections, dict]],\n) -> bool:\n    if prediction is None:\n        return True\n    if isinstance(prediction, sv.Detections) and len(prediction) == 0:\n        return True\n    if isinstance(prediction, dict) and (\n        \"top\" not in prediction and \"predicted_classes\" not in prediction\n    ):\n        return True\n    return False\n\n\ndef encode_prediction(\n    prediction: Union[sv.Detections, dict],\n) -> Tuple[str, str]:\n    if isinstance(prediction, dict):\n        if \"predicted_classes\" in prediction:\n            return \",\".join(prediction[\"predicted_classes\"]), \"txt\"\n        return prediction[\"top\"], \"txt\"\n    detections_in_inference_format = serialise_sv_detections(detections=prediction)\n    return json.dumps(detections_in_inference_format), \"json\"\n",
    "patch": null
  },
  {
    "trace_id": "9f6b0ac0-c6e6-4208-a68e-476e7b8baf7f",
    "function_name": "_transpose_metadata_batches",
    "file_path": "inference/core/workflows/core_steps/sinks/roboflow/dataset_upload/v2.py",
    "speedup_x": 0.36256670386915957,
    "review_quality": "high",
    "pre_optimization_commit": "HEAD",
    "resolution_method": "db_code_only",
    "source": "db_features",
    "original_function_code": "def _transpose_metadata_batches(\n    metadata: Optional[Union[Dict[str, Any], Batch]],\n    batch_size: int,\n) -> List[Optional[Dict[str, Any]]]:\n    \"\"\"Transpose metadata into a per-image list of dicts.\n\n    Handles three cases:\n    - None / empty: returns [None] * batch_size\n    - Batch[Dict]: engine already wrapped it, unwrap directly\n    - Dict with possible Batch values inside: transpose into per-element dicts\n    \"\"\"\n    if not metadata:\n        return [None] * batch_size\n    if isinstance(metadata, Batch):\n        return [m or None for m in metadata]\n    batch_entries = {k: v for k, v in metadata.items() if isinstance(v, Batch)}\n    non_batch_entries = {k: v for k, v in metadata.items() if not isinstance(v, Batch)}\n    if not batch_entries:\n        return [dict(metadata) for _ in range(batch_size)]\n    result = []\n    for i in range(batch_size):\n        entry = dict(non_batch_entries)\n        for k, batch_val in batch_entries.items():\n            entry[k] = batch_val[i]\n        result.append(entry)\n    return result",
    "optimized_function_code": "from typing import Any, Dict, List, Optional, Union\n\nfrom inference.core.workflows.execution_engine.entities.base import Batch\n\n\ndef _transpose_metadata_batches(\n    metadata: Optional[Union[Dict[str, Any], Batch]],\n    batch_size: int,\n) -> List[Optional[Dict[str, Any]]]:\n    \"\"\"Transpose metadata into a per-image list of dicts.\n\n    Handles three cases:\n    - None / empty: returns [None] * batch_size\n    - Batch[Dict]: engine already wrapped it, unwrap directly\n    - Dict with possible Batch values inside: transpose into per-element dicts\n    \"\"\"\n    if not metadata:\n        return [None] * batch_size\n    if isinstance(metadata, Batch):\n        return [m or None for m in metadata]\n\n    # Partition metadata into batch-backed entries and static entries in one pass.\n    batch_entries: Dict[str, Batch] = {}\n    non_batch_entries: Dict[str, Any] = {}\n    for k, v in metadata.items():\n        if isinstance(v, Batch):\n            batch_entries[k] = v\n        else:\n            non_batch_entries[k] = v\n\n    if not batch_entries:\n        template = dict(metadata)\n        return [template.copy() for _ in range(batch_size)]\n\n    # Prepare result by copying non-batch entries once per slot.\n    result: List[Dict[str, Any]] = [non_batch_entries.copy() for _ in range(batch_size)]\n\n    # For each batch-backed key, materialize its values once and assign into result.\n    for k, batch_val in batch_entries.items():\n        vals = list(batch_val)  # materialize to native list for faster indexed access\n        # Preserve original IndexError behavior if vals is too short.\n        for i in range(batch_size):\n            result[i][k] = vals[i]\n\n    return result",
    "optimized_raw_markdown": "```python:inference/core/workflows/execution_engine/entities/base.py\nfrom __future__ import annotations\n\nfrom typing import Generic, Iterator, List, Optional, Tuple, TypeVar\n\nB = TypeVar(\"B\")\n\n\nclass Batch(Generic[B]):\n\n    __slots__ = (\"_content\", \"_indices\")\n\n    def __init__(self, content: List[B], indices: Optional[List[Tuple[int, ...]]]):\n        self._content = content\n        self._indices = indices\n\n    def __getitem__(self, index: int) -> B:\n        return self._content[index]\n\n    def __len__(self) -> int:\n        return len(self._content)\n\n    def __iter__(self) -> Iterator[B]:\n        # Return the underlying iterator directly to avoid generator overhead.\n        return iter(self._content)\n```\n```python:inference/core/workflows/core_steps/sinks/roboflow/dataset_upload/v2.py\nfrom typing import Any, Dict, List, Optional, Union\n\nfrom inference.core.workflows.execution_engine.entities.base import Batch\n\n\ndef _transpose_metadata_batches(\n    metadata: Optional[Union[Dict[str, Any], Batch]],\n    batch_size: int,\n) -> List[Optional[Dict[str, Any]]]:\n    \"\"\"Transpose metadata into a per-image list of dicts.\n\n    Handles three cases:\n    - None / empty: returns [None] * batch_size\n    - Batch[Dict]: engine already wrapped it, unwrap directly\n    - Dict with possible Batch values inside: transpose into per-element dicts\n    \"\"\"\n    if not metadata:\n        return [None] * batch_size\n    if isinstance(metadata, Batch):\n        return [m or None for m in metadata]\n\n    # Partition metadata into batch-backed entries and static entries in one pass.\n    batch_entries: Dict[str, Batch] = {}\n    non_batch_entries: Dict[str, Any] = {}\n    for k, v in metadata.items():\n        if isinstance(v, Batch):\n            batch_entries[k] = v\n        else:\n            non_batch_entries[k] = v\n\n    if not batch_entries:\n        template = dict(metadata)\n        return [template.copy() for _ in range(batch_size)]\n\n    # Prepare result by copying non-batch entries once per slot.\n    result: List[Dict[str, Any]] = [non_batch_entries.copy() for _ in range(batch_size)]\n\n    # For each batch-backed key, materialize its values once and assign into result.\n    for k, batch_val in batch_entries.items():\n        vals = list(batch_val)  # materialize to native list for faster indexed access\n        # Preserve original IndexError behavior if vals is too short.\n        for i in range(batch_size):\n            result[i][k] = vals[i]\n\n    return result\n```",
    "optimized_function_only": "def _transpose_metadata_batches(\n    metadata: Optional[Union[Dict[str, Any], Batch]],\n    batch_size: int,\n) -> List[Optional[Dict[str, Any]]]:\n    \"\"\"Transpose metadata into a per-image list of dicts.\n\n    Handles three cases:\n    - None / empty: returns [None] * batch_size\n    - Batch[Dict]: engine already wrapped it, unwrap directly\n    - Dict with possible Batch values inside: transpose into per-element dicts\n    \"\"\"\n    if not metadata:\n        return [None] * batch_size\n    if isinstance(metadata, Batch):\n        return [m or None for m in metadata]\n\n    # Partition metadata into batch-backed entries and static entries in one pass.\n    batch_entries: Dict[str, Batch] = {}\n    non_batch_entries: Dict[str, Any] = {}\n    for k, v in metadata.items():\n        if isinstance(v, Batch):\n            batch_entries[k] = v\n        else:\n            non_batch_entries[k] = v\n\n    if not batch_entries:\n        template = dict(metadata)\n        return [template.copy() for _ in range(batch_size)]\n\n    # Prepare result by copying non-batch entries once per slot.\n    result: List[Dict[str, Any]] = [non_batch_entries.copy() for _ in range(batch_size)]\n\n    # For each batch-backed key, materialize its values once and assign into result.\n    for k, batch_val in batch_entries.items():\n        vals = list(batch_val)  # materialize to native list for faster indexed access\n        # Preserve original IndexError behavior if vals is too short.\n        for i in range(batch_size):\n            result[i][k] = vals[i]\n\n    return result",
    "original_file_content": "from inference.core.workflows.execution_engine.entities.base import Batch\nfrom typing import Any, Dict, List, Optional, Union\n\ndef _transpose_metadata_batches(\n    metadata: Optional[Union[Dict[str, Any], Batch]],\n    batch_size: int,\n) -> List[Optional[Dict[str, Any]]]:\n    \"\"\"Transpose metadata into a per-image list of dicts.\n\n    Handles three cases:\n    - None / empty: returns [None] * batch_size\n    - Batch[Dict]: engine already wrapped it, unwrap directly\n    - Dict with possible Batch values inside: transpose into per-element dicts\n    \"\"\"\n    if not metadata:\n        return [None] * batch_size\n    if isinstance(metadata, Batch):\n        return [m or None for m in metadata]\n    batch_entries = {k: v for k, v in metadata.items() if isinstance(v, Batch)}\n    non_batch_entries = {k: v for k, v in metadata.items() if not isinstance(v, Batch)}\n    if not batch_entries:\n        return [dict(metadata) for _ in range(batch_size)]\n    result = []\n    for i in range(batch_size):\n        entry = dict(non_batch_entries)\n        for k, batch_val in batch_entries.items():\n            entry[k] = batch_val[i]\n        result.append(entry)\n    return result",
    "patch": null
  },
  {
    "trace_id": "25f9cdf8-8c8a-420c-9f00-41719197f01a",
    "function_name": "register_datapoint_at_roboflow",
    "file_path": "inference/core/workflows/core_steps/sinks/roboflow/dataset_upload/v1.py",
    "speedup_x": 0.3215856229329653,
    "review_quality": "high",
    "pre_optimization_commit": "c20359386c628a08bde69f5f3f780cedd782c50c",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def register_datapoint_at_roboflow(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    usage_quota_name: str,\n    persist_predictions: bool,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    fire_and_forget: bool,\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    background_tasks: Optional[BackgroundTasks],\n    thread_pool_executor: Optional[ThreadPoolExecutor],\n    api_key: str,\n    image_name: Optional[str] = None,\n    metadata: Optional[Dict[str, Any]] = None,\n) -> Tuple[bool, str]:\n    registration_task = partial(\n        execute_registration,\n        image=image,\n        prediction=prediction,\n        target_project=target_project,\n        usage_quota_name=usage_quota_name,\n        persist_predictions=persist_predictions,\n        minutely_usage_limit=minutely_usage_limit,\n        hourly_usage_limit=hourly_usage_limit,\n        daily_usage_limit=daily_usage_limit,\n        max_image_size=max_image_size,\n        compression_level=compression_level,\n        registration_tags=registration_tags,\n        labeling_batch_prefix=labeling_batch_prefix,\n        new_labeling_batch_frequency=new_labeling_batch_frequency,\n        cache=cache,\n        api_key=api_key,\n        image_name=image_name,\n        metadata=metadata,\n    )\n    if fire_and_forget and background_tasks:\n        background_tasks.add_task(registration_task)\n        return False, \"Element registration happens in the background task\"\n    if fire_and_forget and thread_pool_executor:\n        thread_pool_executor.submit(registration_task)\n        return False, \"Element registration happens in the background task\"\n    return registration_task()\n",
    "optimized_function_code": "import logging\nimport supervision as sv\nfrom collections import OrderedDict\nfrom concurrent.futures import ThreadPoolExecutor\nfrom fastapi import BackgroundTasks\nfrom inference.core.active_learning.cache_operations import return_strategy_credit, use_credit_of_matching_strategy\nfrom inference.core.active_learning.core import prepare_image_to_registration\nfrom inference.core.active_learning.entities import ImageDimensions, StrategyLimit, StrategyLimitType\nfrom inference.core.cache.base import BaseCache\nfrom inference.core.workflows.core_steps.common.utils import scale_sv_detections\nfrom inference.core.workflows.execution_engine.entities.base import WorkflowImageData\nfrom typing import Any, Dict, List, Literal, Optional, Tuple, Union\nfrom uuid import uuid4\n\nWORKSPACE_NAME_CACHE_EXPIRE = 900  # 15 min\nTIMESTAMP_FORMAT = \"%Y_%m_%d\"\nDUPLICATED_STATUS = \"Duplicated image\"\nBatchCreationFrequency = Literal[\"never\", \"daily\", \"weekly\", \"monthly\"]\n\n\ndef register_datapoint_at_roboflow(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    usage_quota_name: str,\n    persist_predictions: bool,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    fire_and_forget: bool,\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    background_tasks: Optional[BackgroundTasks],\n    thread_pool_executor: Optional[ThreadPoolExecutor],\n    api_key: str,\n    image_name: Optional[str] = None,\n    metadata: Optional[Dict[str, Any]] = None,\n) -> Tuple[bool, str]:\n    if fire_and_forget and background_tasks:\n        background_tasks.add_task(\n            execute_registration,\n            image,\n            prediction,\n            target_project,\n            persist_predictions,\n            usage_quota_name,\n            minutely_usage_limit,\n            hourly_usage_limit,\n            daily_usage_limit,\n            max_image_size,\n            compression_level,\n            registration_tags,\n            labeling_batch_prefix,\n            new_labeling_batch_frequency,\n            cache,\n            api_key,\n            image_name,\n            metadata,\n        )\n        return False, \"Element registration happens in the background task\"\n    if fire_and_forget and thread_pool_executor:\n        thread_pool_executor.submit(\n            execute_registration,\n            image,\n            prediction,\n            target_project,\n            persist_predictions,\n            usage_quota_name,\n            minutely_usage_limit,\n            hourly_usage_limit,\n            daily_usage_limit,\n            max_image_size,\n            compression_level,\n            registration_tags,\n            labeling_batch_prefix,\n            new_labeling_batch_frequency,\n            cache,\n            api_key,\n            image_name,\n            metadata,\n        )\n        return False, \"Element registration happens in the background task\"\n    return execute_registration(\n        image,\n        prediction,\n        target_project,\n        persist_predictions,\n        usage_quota_name,\n        minutely_usage_limit,\n        hourly_usage_limit,\n        daily_usage_limit,\n        max_image_size,\n        compression_level,\n        registration_tags,\n        labeling_batch_prefix,\n        new_labeling_batch_frequency,\n        cache,\n        api_key,\n        image_name,\n        metadata,\n    )\n\n\ndef execute_registration(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    persist_predictions: bool,\n    usage_quota_name: str,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    api_key: str,\n    image_name: Optional[str] = None,\n    metadata: Optional[Dict[str, Any]] = None,\n) -> Tuple[bool, str]:\n    matching_strategies_limits = OrderedDict(\n        {\n            usage_quota_name: [\n                StrategyLimit(\n                    limit_type=StrategyLimitType.MINUTELY, value=minutely_usage_limit\n                ),\n                StrategyLimit(\n                    limit_type=StrategyLimitType.HOURLY, value=hourly_usage_limit\n                ),\n                StrategyLimit(\n                    limit_type=StrategyLimitType.DAILY, value=daily_usage_limit\n                ),\n            ]\n        }\n    )\n    workspace_name = get_workspace_name(api_key=api_key, cache=cache)\n    strategy_with_spare_credit = use_credit_of_matching_strategy(\n        cache=cache,\n        workspace=workspace_name,\n        project=target_project,\n        matching_strategies_limits=matching_strategies_limits,\n    )\n    if strategy_with_spare_credit is None:\n        return False, \"Registration skipped due to usage quota exceeded\"\n    credit_to_be_returned = False\n    try:\n        local_image_id = image_name if image_name else str(uuid4())\n        encoded_image, scaling_factor = prepare_image_to_registration(\n            image=image.numpy_image,\n            desired_size=ImageDimensions(\n                width=max_image_size[0], height=max_image_size[1]\n            ),\n            jpeg_compression_level=compression_level,\n        )\n        batch_name = generate_batch_name(\n            labeling_batch_prefix=labeling_batch_prefix,\n            new_labeling_batch_frequency=new_labeling_batch_frequency,\n        )\n        if isinstance(prediction, sv.Detections):\n            prediction = scale_sv_detections(\n                detections=prediction, scale=scaling_factor\n            )\n        status = register_datapoint(\n            target_project=target_project,\n            encoded_image=encoded_image,\n            local_image_id=local_image_id,\n            prediction=prediction if persist_predictions else None,\n            api_key=api_key,\n            batch_name=batch_name,\n            tags=registration_tags,\n            metadata=metadata,\n        )\n        if status == DUPLICATED_STATUS:\n            credit_to_be_returned = True\n        return False, status\n    except Exception as error:\n        credit_to_be_returned = True\n        logging.exception(\"Failed to register datapoint on the Roboflow platform\")\n        return (\n            True,\n            f\"Error while registration. Error type: {type(error)}. Details: {error}\",\n        )\n    finally:\n        if credit_to_be_returned:\n            return_strategy_credit(\n                cache=cache,\n                workspace=workspace_name,\n                project=target_project,\n                strategy_name=strategy_with_spare_credit,\n            )\n\n\nRECREATION_INTERVAL2TIMESTAMP_GENERATOR = {\n    \"daily\": generate_today_timestamp,\n    \"weekly\": generate_start_timestamp_for_this_week,\n    \"monthly\": generate_start_timestamp_for_this_month,\n}",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/sinks/roboflow/dataset_upload/v1.py\nimport logging\nimport supervision as sv\nfrom collections import OrderedDict\nfrom concurrent.futures import ThreadPoolExecutor\nfrom fastapi import BackgroundTasks\nfrom inference.core.active_learning.cache_operations import return_strategy_credit, use_credit_of_matching_strategy\nfrom inference.core.active_learning.core import prepare_image_to_registration\nfrom inference.core.active_learning.entities import ImageDimensions, StrategyLimit, StrategyLimitType\nfrom inference.core.cache.base import BaseCache\nfrom inference.core.workflows.core_steps.common.utils import scale_sv_detections\nfrom inference.core.workflows.execution_engine.entities.base import WorkflowImageData\nfrom typing import Any, Dict, List, Literal, Optional, Tuple, Union\nfrom uuid import uuid4\n\nWORKSPACE_NAME_CACHE_EXPIRE = 900  # 15 min\nTIMESTAMP_FORMAT = \"%Y_%m_%d\"\nDUPLICATED_STATUS = \"Duplicated image\"\nBatchCreationFrequency = Literal[\"never\", \"daily\", \"weekly\", \"monthly\"]\n\n\ndef register_datapoint_at_roboflow(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    usage_quota_name: str,\n    persist_predictions: bool,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    fire_and_forget: bool,\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    background_tasks: Optional[BackgroundTasks],\n    thread_pool_executor: Optional[ThreadPoolExecutor],\n    api_key: str,\n    image_name: Optional[str] = None,\n    metadata: Optional[Dict[str, Any]] = None,\n) -> Tuple[bool, str]:\n    if fire_and_forget and background_tasks:\n        background_tasks.add_task(\n            execute_registration,\n            image,\n            prediction,\n            target_project,\n            persist_predictions,\n            usage_quota_name,\n            minutely_usage_limit,\n            hourly_usage_limit,\n            daily_usage_limit,\n            max_image_size,\n            compression_level,\n            registration_tags,\n            labeling_batch_prefix,\n            new_labeling_batch_frequency,\n            cache,\n            api_key,\n            image_name,\n            metadata,\n        )\n        return False, \"Element registration happens in the background task\"\n    if fire_and_forget and thread_pool_executor:\n        thread_pool_executor.submit(\n            execute_registration,\n            image,\n            prediction,\n            target_project,\n            persist_predictions,\n            usage_quota_name,\n            minutely_usage_limit,\n            hourly_usage_limit,\n            daily_usage_limit,\n            max_image_size,\n            compression_level,\n            registration_tags,\n            labeling_batch_prefix,\n            new_labeling_batch_frequency,\n            cache,\n            api_key,\n            image_name,\n            metadata,\n        )\n        return False, \"Element registration happens in the background task\"\n    return execute_registration(\n        image,\n        prediction,\n        target_project,\n        persist_predictions,\n        usage_quota_name,\n        minutely_usage_limit,\n        hourly_usage_limit,\n        daily_usage_limit,\n        max_image_size,\n        compression_level,\n        registration_tags,\n        labeling_batch_prefix,\n        new_labeling_batch_frequency,\n        cache,\n        api_key,\n        image_name,\n        metadata,\n    )\n\n\ndef execute_registration(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    persist_predictions: bool,\n    usage_quota_name: str,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    api_key: str,\n    image_name: Optional[str] = None,\n    metadata: Optional[Dict[str, Any]] = None,\n) -> Tuple[bool, str]:\n    matching_strategies_limits = OrderedDict(\n        {\n            usage_quota_name: [\n                StrategyLimit(\n                    limit_type=StrategyLimitType.MINUTELY, value=minutely_usage_limit\n                ),\n                StrategyLimit(\n                    limit_type=StrategyLimitType.HOURLY, value=hourly_usage_limit\n                ),\n                StrategyLimit(\n                    limit_type=StrategyLimitType.DAILY, value=daily_usage_limit\n                ),\n            ]\n        }\n    )\n    workspace_name = get_workspace_name(api_key=api_key, cache=cache)\n    strategy_with_spare_credit = use_credit_of_matching_strategy(\n        cache=cache,\n        workspace=workspace_name,\n        project=target_project,\n        matching_strategies_limits=matching_strategies_limits,\n    )\n    if strategy_with_spare_credit is None:\n        return False, \"Registration skipped due to usage quota exceeded\"\n    credit_to_be_returned = False\n    try:\n        local_image_id = image_name if image_name else str(uuid4())\n        encoded_image, scaling_factor = prepare_image_to_registration(\n            image=image.numpy_image,\n            desired_size=ImageDimensions(\n                width=max_image_size[0], height=max_image_size[1]\n            ),\n            jpeg_compression_level=compression_level,\n        )\n        batch_name = generate_batch_name(\n            labeling_batch_prefix=labeling_batch_prefix,\n            new_labeling_batch_frequency=new_labeling_batch_frequency,\n        )\n        if isinstance(prediction, sv.Detections):\n            prediction = scale_sv_detections(\n                detections=prediction, scale=scaling_factor\n            )\n        status = register_datapoint(\n            target_project=target_project,\n            encoded_image=encoded_image,\n            local_image_id=local_image_id,\n            prediction=prediction if persist_predictions else None,\n            api_key=api_key,\n            batch_name=batch_name,\n            tags=registration_tags,\n            metadata=metadata,\n        )\n        if status == DUPLICATED_STATUS:\n            credit_to_be_returned = True\n        return False, status\n    except Exception as error:\n        credit_to_be_returned = True\n        logging.exception(\"Failed to register datapoint on the Roboflow platform\")\n        return (\n            True,\n            f\"Error while registration. Error type: {type(error)}. Details: {error}\",\n        )\n    finally:\n        if credit_to_be_returned:\n            return_strategy_credit(\n                cache=cache,\n                workspace=workspace_name,\n                project=target_project,\n                strategy_name=strategy_with_spare_credit,\n            )\n\n\nRECREATION_INTERVAL2TIMESTAMP_GENERATOR = {\n    \"daily\": generate_today_timestamp,\n    \"weekly\": generate_start_timestamp_for_this_week,\n    \"monthly\": generate_start_timestamp_for_this_month,\n}\n```",
    "optimized_function_only": "def register_datapoint_at_roboflow(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    usage_quota_name: str,\n    persist_predictions: bool,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    fire_and_forget: bool,\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    background_tasks: Optional[BackgroundTasks],\n    thread_pool_executor: Optional[ThreadPoolExecutor],\n    api_key: str,\n    image_name: Optional[str] = None,\n    metadata: Optional[Dict[str, Any]] = None,\n) -> Tuple[bool, str]:\n    if fire_and_forget and background_tasks:\n        background_tasks.add_task(\n            execute_registration,\n            image,\n            prediction,\n            target_project,\n            persist_predictions,\n            usage_quota_name,\n            minutely_usage_limit,\n            hourly_usage_limit,\n            daily_usage_limit,\n            max_image_size,\n            compression_level,\n            registration_tags,\n            labeling_batch_prefix,\n            new_labeling_batch_frequency,\n            cache,\n            api_key,\n            image_name,\n            metadata,\n        )\n        return False, \"Element registration happens in the background task\"\n    if fire_and_forget and thread_pool_executor:\n        thread_pool_executor.submit(\n            execute_registration,\n            image,\n            prediction,\n            target_project,\n            persist_predictions,\n            usage_quota_name,\n            minutely_usage_limit,\n            hourly_usage_limit,\n            daily_usage_limit,\n            max_image_size,\n            compression_level,\n            registration_tags,\n            labeling_batch_prefix,\n            new_labeling_batch_frequency,\n            cache,\n            api_key,\n            image_name,\n            metadata,\n        )\n        return False, \"Element registration happens in the background task\"\n    return execute_registration(\n        image,\n        prediction,\n        target_project,\n        persist_predictions,\n        usage_quota_name,\n        minutely_usage_limit,\n        hourly_usage_limit,\n        daily_usage_limit,\n        max_image_size,\n        compression_level,\n        registration_tags,\n        labeling_batch_prefix,\n        new_labeling_batch_frequency,\n        cache,\n        api_key,\n        image_name,\n        metadata,\n    )\n",
    "original_file_content": "\"\"\"\n*****************************************************************\n*                           WARNING!                            *\n*****************************************************************\nThis module contains the utility functions used by\nRoboflowDatasetUploadBlockV2.\n\nWe do not recommend making multiple blocks dependent on the same code,\nbut the change between v1 and v2 was basically the default value of\nsome parameter - hence we decided not to replicate the code.\n\nIf you need to modify this module beware that you may introduce\nchange to RoboflowDatasetUploadBlockV2! If that happens,\nprobably that's the time to disentangle those blocks and copy the\ncode.\n\"\"\"\n\nimport hashlib\nimport json\nimport logging\nfrom collections import OrderedDict\nfrom concurrent.futures import ThreadPoolExecutor\nfrom datetime import datetime, timedelta\nfrom functools import partial\nfrom typing import Any, Dict, List, Literal, Optional, Tuple, Type, Union\nfrom uuid import uuid4\n\nimport supervision as sv\nfrom fastapi import BackgroundTasks\nfrom pydantic import AliasChoices, ConfigDict, Field\n\nfrom inference.core.active_learning.cache_operations import (\n    return_strategy_credit,\n    use_credit_of_matching_strategy,\n)\nfrom inference.core.active_learning.core import prepare_image_to_registration\nfrom inference.core.active_learning.entities import (\n    ImageDimensions,\n    StrategyLimit,\n    StrategyLimitType,\n)\nfrom inference.core.cache.base import BaseCache\nfrom inference.core.roboflow_api import (\n    annotate_image_at_roboflow,\n    get_roboflow_workspace,\n    register_image_at_roboflow,\n)\nfrom inference.core.workflows.core_steps.common.serializers import (\n    serialise_sv_detections,\n)\nfrom inference.core.workflows.core_steps.common.utils import scale_sv_detections\nfrom inference.core.workflows.execution_engine.constants import INFERENCE_ID_KEY\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    BOOLEAN_KIND,\n    CLASSIFICATION_PREDICTION_KIND,\n    IMAGE_KIND,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    KEYPOINT_DETECTION_PREDICTION_KIND,\n    LIST_OF_VALUES_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    ROBOFLOW_PROJECT_KIND,\n    STRING_KIND,\n    ImageInputField,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    AirGappedAvailability,\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nSHORT_DESCRIPTION = \"Save images and predictions to your Roboflow Dataset.\"\n\nLONG_DESCRIPTION = \"\"\"\nUpload images and model predictions to a Roboflow dataset for active learning, model improvement, and data collection, with configurable usage quotas, batch organization, image compression, and optional annotation persistence.\n\n## How This Block Works\n\nThis block uploads workflow images and predictions to your Roboflow dataset for storage, labeling, and model training. The block:\n\n1. Takes images and optional model predictions (object detection, instance segmentation, keypoint detection, or classification) as input\n2. Validates the Roboflow API key is available (required for uploading)\n3. Checks usage quotas (minutely, hourly, daily limits) to ensure uploads stay within configured rate limits for active learning strategies\n4. Prepares images by resizing if they exceed maximum size (maintaining aspect ratio) and compressing to specified quality level\n5. Generates labeling batch names based on the prefix and batch creation frequency (never, daily, weekly, or monthly), organizing uploaded data into batches\n6. Optionally persists model predictions as annotations if `persist_predictions` is enabled, allowing predictions to serve as pre-labels for review and correction\n7. Attaches registration tags to images for organization and filtering in the Roboflow platform\n8. Registers the image (and annotations if enabled) to the specified Roboflow project via the Roboflow API\n9. Executes synchronously or asynchronously based on `fire_and_forget` setting, allowing non-blocking uploads for faster workflow execution\n10. Returns error status and messages indicating upload success or failure\n\nThe block supports active learning workflows by implementing usage quotas that prevent excessive data collection, helping focus on collecting valuable training data within rate limits. Images are organized into labeling batches that can be automatically recreated on a schedule (daily, weekly, monthly), making it easier to manage and review collected data over time. The block can operate in fire-and-forget mode for asynchronous execution, allowing workflows to continue processing without waiting for uploads to complete, or synchronously for debugging and error handling.\n\n## Requirements\n\n**API Key Required**: This block requires a valid Roboflow API key to upload data. The API key must be configured in your environment or workflow configuration. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve an API key.\n\n## Common Use Cases\n\n- **Active Learning Data Collection**: Collect images and predictions from production environments where models struggle or are uncertain (e.g., low-confidence detections, edge cases), enabling iterative model improvement by gathering challenging examples for retraining\n- **Production Data Logging**: Continuously upload production inference data to Roboflow datasets for monitoring, analysis, and future model training, creating a growing dataset from real-world deployments\n- **Pre-Labeled Data Collection**: Upload images with model predictions as pre-labels (when `persist_predictions` is enabled), accelerating annotation workflows by providing initial labels that can be reviewed and corrected rather than starting from scratch\n- **Stratified Data Sampling**: Use rate limiting and quotas to selectively collect data based on specific criteria (e.g., combine with Rate Limiter or Continue If blocks), ensuring diverse and balanced dataset collection without overwhelming storage or annotation resources\n- **Batch-Based Labeling Workflows**: Organize uploaded data into batches with automatic recreation schedules (daily, weekly, monthly), making it easier to manage labeling tasks, track progress, and organize data collection efforts over time\n- **Tagged Data Organization**: Attach metadata tags to uploaded images (e.g., location, camera ID, time period, model version), enabling filtering and organization of collected data in Roboflow for better dataset management and analysis\n\n## Connecting to Other Blocks\n\nThis block receives data from workflow steps and uploads it to Roboflow:\n\n- **After detection or analysis blocks** (e.g., Object Detection Model, Instance Segmentation Model, Classification Model, Keypoint Detection Model) to upload images along with their predictions, enabling active learning by collecting inference data with model outputs for annotation and retraining\n- **After filtering or analytics blocks** (e.g., Detections Filter, Continue If, Overlap Filter) to selectively upload only specific types of data (e.g., low-confidence detections, overlapping objects, specific classes), focusing data collection on valuable edge cases or interesting scenarios\n- **After rate limiter blocks** (e.g., Rate Limiter) to throttle upload frequency and stay within usage quotas, ensuring controlled data collection that respects rate limits and prevents excessive storage usage\n- **Image inputs or preprocessing blocks** to upload raw images or processed images (e.g., crops, transformed images) without predictions, enabling collection of image data for future labeling or analysis\n- **Conditional workflows** using flow control blocks (e.g., Continue If) to upload data only when certain conditions are met (e.g., upload only when detection count exceeds threshold, upload only errors or failures), enabling selective data collection based on workflow state\n- **Batch processing workflows** where multiple images or predictions are generated, allowing bulk upload of workflow outputs to Roboflow datasets for organized data collection and management\n\"\"\"\n\nWORKSPACE_NAME_CACHE_EXPIRE = 900  # 15 min\nTIMESTAMP_FORMAT = \"%Y_%m_%d\"\nDUPLICATED_STATUS = \"Duplicated image\"\nBatchCreationFrequency = Literal[\"never\", \"daily\", \"weekly\", \"monthly\"]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Roboflow Dataset Upload\",\n            \"version\": \"v1\",\n            \"short_description\": SHORT_DESCRIPTION,\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"sink\",\n            \"ui_manifest\": {\n                \"section\": \"data_storage\",\n                \"icon\": \"fal fa-upload\",\n                \"blockPriority\": 0,\n                \"popular\": True,\n                \"requires_rf_key\": True,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/roboflow_dataset_upload@v1\", \"RoboflowDatasetUpload\"]\n    images: Selector(kind=[IMAGE_KIND]) = Field(\n        title=\"Input Image\",\n        description=\"Image(s) to upload to the Roboflow dataset. Can be a single image or batch of images from workflow inputs or processing steps. Images are resized if they exceed max_image_size and compressed before uploading. Supports batch processing.\",\n        examples=[\"$inputs.image\", \"$steps.cropping.crops\"],\n        validation_alias=AliasChoices(\"image\", \"images\"),\n    )\n    predictions: Optional[\n        Selector(\n            kind=[\n                OBJECT_DETECTION_PREDICTION_KIND,\n                INSTANCE_SEGMENTATION_PREDICTION_KIND,\n                KEYPOINT_DETECTION_PREDICTION_KIND,\n                CLASSIFICATION_PREDICTION_KIND,\n            ]\n        )\n    ] = Field(\n        default=None,\n        description=\"Optional model predictions to upload alongside images. Predictions are saved as annotations (pre-labels) in the Roboflow dataset when persist_predictions is enabled, allowing predictions to serve as starting points for annotation review and correction. Supports object detection, instance segmentation, keypoint detection, and classification predictions. If None, only images are uploaded.\",\n        examples=[\"$steps.object_detection_model.predictions\"],\n    )\n    target_project: Union[Selector(kind=[ROBOFLOW_PROJECT_KIND]), str] = Field(\n        description=\"Roboflow project identifier where uploaded images and annotations will be saved. Must be a valid project in your Roboflow workspace. The project name can be specified directly or referenced from workflow inputs.\",\n        examples=[\"my_project\", \"$inputs.target_project\"],\n    )\n    minutely_usage_limit: int = Field(\n        default=10,\n        description=\"Maximum number of image uploads allowed per minute for this quota. Part of the usage quota system that enforces rate limits for active learning data collection. Uploads exceeding this limit are skipped to prevent excessive data collection. Works together with hourly_usage_limit and daily_usage_limit to provide multi-level rate limiting.\",\n        examples=[10, 60],\n    )\n    hourly_usage_limit: int = Field(\n        default=100,\n        description=\"Maximum number of image uploads allowed per hour for this quota. Part of the usage quota system that enforces rate limits for active learning data collection. Uploads exceeding this limit are skipped to prevent excessive data collection. Works together with minutely_usage_limit and daily_usage_limit to provide multi-level rate limiting.\",\n        examples=[10, 60],\n    )\n    daily_usage_limit: int = Field(\n        default=1000,\n        description=\"Maximum number of image uploads allowed per day for this quota. Part of the usage quota system that enforces rate limits for active learning data collection. Uploads exceeding this limit are skipped to prevent excessive data collection. Works together with minutely_usage_limit and hourly_usage_limit to provide multi-level rate limiting.\",\n        examples=[10, 60],\n    )\n    usage_quota_name: str = Field(\n        description=\"Unique identifier for tracking usage quotas (minutely, hourly, daily limits). Used internally to manage rate limiting across multiple upload operations. Each unique quota name maintains separate counters, allowing different upload strategies or data collection workflows to have independent rate limits.\",\n        examples=[\"quota-for-data-sampling-1\"],\n        json_schema_extra={\"hidden\": True},\n    )\n    max_image_size: Tuple[int, int] = Field(\n        default=(512, 512),\n        description=\"Maximum dimensions (width, height) for uploaded images. Images exceeding these dimensions are automatically resized while preserving aspect ratio before uploading. Smaller sizes reduce storage and bandwidth but may lose image quality. Use larger sizes (e.g., (1920, 1080)) for high-resolution data collection, or smaller sizes (e.g., (512, 512)) for efficient storage and faster uploads.\",\n        examples=[(512, 512), (1920, 1080)],\n    )\n    compression_level: int = Field(\n        default=75,\n        gt=0,\n        le=100,\n        description=\"JPEG compression quality level for uploaded images, ranging from 1 (highest compression, smallest file size, lower quality) to 100 (no compression, largest file size, highest quality). Higher values preserve more image quality but increase storage and bandwidth usage. Typical values range from 70-90 for balanced quality and size. Default of 75 provides good quality with reasonable file sizes.\",\n        examples=[75],\n    )\n    registration_tags: Union[\n        List[Union[Selector(kind=[STRING_KIND]), str]],\n        Selector(kind=[LIST_OF_VALUES_KIND]),\n    ] = Field(\n        default_factory=list,\n        description=\"List of tags to attach to uploaded images for organization and filtering in Roboflow. Tags can be static strings (e.g., 'location-florida', 'camera-1') or dynamic values from workflow inputs. Tags help organize collected data, filter images in Roboflow, and add metadata for dataset management. Can be an empty list if no tags are needed.\",\n        examples=[\n            [\"location-florida\", \"factory-name\", \"$inputs.dynamic_tag\"],\n            \"$inputs.tags\",\n        ],\n    )\n    persist_predictions: bool = Field(\n        default=True,\n        description=\"If True, model predictions are saved as annotations (pre-labels) in the Roboflow dataset alongside images. This enables predictions to serve as starting points for annotation, allowing reviewers to correct or approve labels rather than creating them from scratch. If False, only images are uploaded without annotations. Enabling this accelerates annotation workflows by providing initial labels.\",\n        examples=[True, False],\n    )\n    disable_sink: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=False,\n        description=\"If True, the block execution is disabled and no uploads occur. This allows temporarily disabling data collection without removing the block from workflows, useful for testing, debugging, or conditional data collection. When disabled, returns a message indicating the sink was disabled. Default is False (uploads enabled).\",\n        examples=[True, \"$inputs.disable_active_learning\"],\n    )\n    fire_and_forget: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=True,\n        description=\"If True, uploads execute asynchronously (fire-and-forget mode), allowing the workflow to continue immediately without waiting for upload completion. This improves workflow performance but prevents error handling. If False, uploads execute synchronously, blocking workflow execution until completion and allowing proper error handling and status reporting. Use async mode (True) for production workflows where speed is prioritized, and sync mode (False) for debugging or when error handling is critical.\",\n        examples=[True],\n    )\n    labeling_batch_prefix: Union[str, Selector(kind=[STRING_KIND])] = Field(\n        default=\"workflows_data_collector\",\n        description=\"Prefix used to generate labeling batch names for organizing uploaded images in Roboflow. Combined with the batch recreation frequency and timestamps to create batch names like 'workflows_data_collector_2024_01_15'. Batches help organize collected data for labeling, making it easier to manage and review uploaded images in groups. Can be customized to match your organization scheme.\",\n        examples=[\"my_labeling_batch_name\"],\n    )\n    labeling_batches_recreation_frequency: BatchCreationFrequency = Field(\n        default=\"never\",\n        description=\"Frequency at which new labeling batches are automatically created for uploaded images. Options: 'never' (all images go to the same batch), 'daily' (new batch each day), 'weekly' (new batch each week), 'monthly' (new batch each month). Batch timestamps are appended to the labeling_batch_prefix to create unique batch names. Automatically organizing uploads into time-based batches simplifies dataset management and makes it easier to track and review collected data over time.\",\n        examples=[\"never\", \"daily\"],\n    )\n    image_name: Optional[Union[str, Selector(kind=[STRING_KIND])]] = Field(\n        default=None,\n        description=\"Optional custom name for the uploaded image. If provided, this name will be used instead of an auto-generated UUID. This is useful when you want to preserve the original filename or use a meaningful identifier (e.g., serial number, timestamp) for the image in the Roboflow dataset. The name should not include file extension. If not provided, a UUID will be generated automatically.\",\n        examples=[\"serial_12345\", \"camera1_frame_001\", \"$inputs.filename\"],\n    )\n\n    @classmethod\n    def get_air_gapped_availability(cls) -> AirGappedAvailability:\n        return AirGappedAvailability(available=False, reason=\"requires_internet\")\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return [\"images\", \"predictions\", \"image_name\"]\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"error_status\", kind=[BOOLEAN_KIND]),\n            OutputDefinition(name=\"message\", kind=[STRING_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass RoboflowDatasetUploadBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        cache: BaseCache,\n        api_key: Optional[str],\n        background_tasks: Optional[BackgroundTasks],\n        thread_pool_executor: Optional[ThreadPoolExecutor],\n    ):\n        self._cache = cache\n        self._api_key = api_key\n        self._background_tasks = background_tasks\n        self._thread_pool_executor = thread_pool_executor\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"cache\", \"api_key\", \"background_tasks\", \"thread_pool_executor\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        predictions: Optional[Batch[Union[sv.Detections, dict]]],\n        target_project: str,\n        usage_quota_name: str,\n        minutely_usage_limit: int,\n        persist_predictions: bool,\n        hourly_usage_limit: int,\n        daily_usage_limit: int,\n        max_image_size: Tuple[int, int],\n        compression_level: int,\n        registration_tags: List[str],\n        disable_sink: bool,\n        fire_and_forget: bool,\n        labeling_batch_prefix: str,\n        labeling_batches_recreation_frequency: BatchCreationFrequency,\n        image_name: Optional[Batch[Optional[str]]] = None,\n    ) -> BlockResult:\n        if self._api_key is None:\n            raise ValueError(\n                \"RoboflowDataCollector block cannot run without Roboflow API key. \"\n                \"If you do not know how to get API key - visit \"\n                \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to \"\n                \"retrieve one.\"\n            )\n        if disable_sink:\n            return [\n                {\n                    \"error_status\": False,\n                    \"message\": \"Sink was disabled by parameter `disable_sink`\",\n                }\n                for _ in range(len(images))\n            ]\n        result = []\n        predictions = [None] * len(images) if predictions is None else predictions\n        image_names = [None] * len(images) if image_name is None else image_name\n        for image, prediction, img_name in zip(images, predictions, image_names):\n            error_status, message = register_datapoint_at_roboflow(\n                image=image,\n                prediction=prediction,\n                target_project=target_project,\n                usage_quota_name=usage_quota_name,\n                persist_predictions=persist_predictions,\n                minutely_usage_limit=minutely_usage_limit,\n                hourly_usage_limit=hourly_usage_limit,\n                daily_usage_limit=daily_usage_limit,\n                max_image_size=max_image_size,\n                compression_level=compression_level,\n                registration_tags=registration_tags,\n                fire_and_forget=fire_and_forget,\n                labeling_batch_prefix=labeling_batch_prefix,\n                new_labeling_batch_frequency=labeling_batches_recreation_frequency,\n                cache=self._cache,\n                background_tasks=self._background_tasks,\n                thread_pool_executor=self._thread_pool_executor,\n                api_key=self._api_key,\n                image_name=img_name,\n            )\n            result.append({\"error_status\": error_status, \"message\": message})\n        return result\n\n\ndef register_datapoint_at_roboflow(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    usage_quota_name: str,\n    persist_predictions: bool,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    fire_and_forget: bool,\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    background_tasks: Optional[BackgroundTasks],\n    thread_pool_executor: Optional[ThreadPoolExecutor],\n    api_key: str,\n    image_name: Optional[str] = None,\n    metadata: Optional[Dict[str, Any]] = None,\n) -> Tuple[bool, str]:\n    registration_task = partial(\n        execute_registration,\n        image=image,\n        prediction=prediction,\n        target_project=target_project,\n        usage_quota_name=usage_quota_name,\n        persist_predictions=persist_predictions,\n        minutely_usage_limit=minutely_usage_limit,\n        hourly_usage_limit=hourly_usage_limit,\n        daily_usage_limit=daily_usage_limit,\n        max_image_size=max_image_size,\n        compression_level=compression_level,\n        registration_tags=registration_tags,\n        labeling_batch_prefix=labeling_batch_prefix,\n        new_labeling_batch_frequency=new_labeling_batch_frequency,\n        cache=cache,\n        api_key=api_key,\n        image_name=image_name,\n        metadata=metadata,\n    )\n    if fire_and_forget and background_tasks:\n        background_tasks.add_task(registration_task)\n        return False, \"Element registration happens in the background task\"\n    if fire_and_forget and thread_pool_executor:\n        thread_pool_executor.submit(registration_task)\n        return False, \"Element registration happens in the background task\"\n    return registration_task()\n\n\ndef execute_registration(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    persist_predictions: bool,\n    usage_quota_name: str,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    api_key: str,\n    image_name: Optional[str] = None,\n    metadata: Optional[Dict[str, Any]] = None,\n) -> Tuple[bool, str]:\n    matching_strategies_limits = OrderedDict(\n        {\n            usage_quota_name: [\n                StrategyLimit(\n                    limit_type=StrategyLimitType.MINUTELY, value=minutely_usage_limit\n                ),\n                StrategyLimit(\n                    limit_type=StrategyLimitType.HOURLY, value=hourly_usage_limit\n                ),\n                StrategyLimit(\n                    limit_type=StrategyLimitType.DAILY, value=daily_usage_limit\n                ),\n            ]\n        }\n    )\n    workspace_name = get_workspace_name(api_key=api_key, cache=cache)\n    strategy_with_spare_credit = use_credit_of_matching_strategy(\n        cache=cache,\n        workspace=workspace_name,\n        project=target_project,\n        matching_strategies_limits=matching_strategies_limits,\n    )\n    if strategy_with_spare_credit is None:\n        return False, \"Registration skipped due to usage quota exceeded\"\n    credit_to_be_returned = False\n    try:\n        local_image_id = image_name if image_name else str(uuid4())\n        encoded_image, scaling_factor = prepare_image_to_registration(\n            image=image.numpy_image,\n            desired_size=ImageDimensions(\n                width=max_image_size[0], height=max_image_size[1]\n            ),\n            jpeg_compression_level=compression_level,\n        )\n        batch_name = generate_batch_name(\n            labeling_batch_prefix=labeling_batch_prefix,\n            new_labeling_batch_frequency=new_labeling_batch_frequency,\n        )\n        if isinstance(prediction, sv.Detections):\n            prediction = scale_sv_detections(\n                detections=prediction, scale=scaling_factor\n            )\n        status = register_datapoint(\n            target_project=target_project,\n            encoded_image=encoded_image,\n            local_image_id=local_image_id,\n            prediction=prediction if persist_predictions else None,\n            api_key=api_key,\n            batch_name=batch_name,\n            tags=registration_tags,\n            metadata=metadata,\n        )\n        if status == DUPLICATED_STATUS:\n            credit_to_be_returned = True\n        return False, status\n    except Exception as error:\n        credit_to_be_returned = True\n        logging.exception(\"Failed to register datapoint on the Roboflow platform\")\n        return (\n            True,\n            f\"Error while registration. Error type: {type(error)}. Details: {error}\",\n        )\n    finally:\n        if credit_to_be_returned:\n            return_strategy_credit(\n                cache=cache,\n                workspace=workspace_name,\n                project=target_project,\n                strategy_name=strategy_with_spare_credit,\n            )\n\n\ndef get_workspace_name(\n    api_key: str,\n    cache: BaseCache,\n) -> str:\n    api_key_hash = hashlib.md5(api_key.encode(\"utf-8\")).hexdigest()\n    cache_key = f\"workflows:api_key_to_workspace:{api_key_hash}\"\n    cached_workspace_name = cache.get(cache_key)\n    if cached_workspace_name:\n        return cached_workspace_name\n    workspace_name_from_api = get_roboflow_workspace(api_key=api_key)\n    cache.set(\n        key=cache_key, value=workspace_name_from_api, expire=WORKSPACE_NAME_CACHE_EXPIRE\n    )\n    return workspace_name_from_api\n\n\ndef generate_batch_name(\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n) -> str:\n    if new_labeling_batch_frequency == \"never\":\n        return labeling_batch_prefix\n    timestamp_generator = RECREATION_INTERVAL2TIMESTAMP_GENERATOR[\n        new_labeling_batch_frequency\n    ]\n    timestamp = timestamp_generator()\n    return f\"{labeling_batch_prefix}_{timestamp}\"\n\n\ndef generate_today_timestamp() -> str:\n    return datetime.today().strftime(TIMESTAMP_FORMAT)\n\n\ndef generate_start_timestamp_for_this_week() -> str:\n    today = datetime.today()\n    return (today - timedelta(days=today.weekday())).strftime(TIMESTAMP_FORMAT)\n\n\ndef generate_start_timestamp_for_this_month() -> str:\n    return datetime.today().replace(day=1).strftime(TIMESTAMP_FORMAT)\n\n\nRECREATION_INTERVAL2TIMESTAMP_GENERATOR = {\n    \"daily\": generate_today_timestamp,\n    \"weekly\": generate_start_timestamp_for_this_week,\n    \"monthly\": generate_start_timestamp_for_this_month,\n}\n\n\ndef register_datapoint(\n    target_project: str,\n    encoded_image: bytes,\n    local_image_id: str,\n    prediction: Optional[Union[sv.Detections, dict]],\n    api_key: str,\n    batch_name: str,\n    tags: List[str],\n    metadata: Optional[Dict[str, Any]] = None,\n) -> str:\n    inference_id = None\n    if isinstance(prediction, dict):\n        inference_id = prediction.get(INFERENCE_ID_KEY)\n    if isinstance(prediction, sv.Detections) and len(prediction) > 0:\n        # TODO: Lack of inference ID for empty prediction -\n        #  dependent on https://github.com/roboflow/inference/issues/567\n        inference_id_array = prediction.data.get(INFERENCE_ID_KEY)\n        if inference_id_array is not None:\n            inference_id_list = inference_id_array.tolist()\n            inference_id = inference_id_list[0]\n    roboflow_image_id = safe_register_image_at_roboflow(\n        target_project=target_project,\n        encoded_image=encoded_image,\n        local_image_id=local_image_id,\n        api_key=api_key,\n        batch_name=batch_name,\n        tags=tags,\n        inference_id=inference_id,\n        metadata=metadata,\n    )\n    if roboflow_image_id is None:\n        return DUPLICATED_STATUS\n    if is_prediction_registration_forbidden(prediction=prediction):\n        return \"Successfully registered image\"\n    encoded_prediction, prediction_format = encode_prediction(prediction=prediction)\n    _ = annotate_image_at_roboflow(\n        api_key=api_key,\n        dataset_id=target_project,\n        local_image_id=local_image_id,\n        roboflow_image_id=roboflow_image_id,\n        annotation_content=encoded_prediction,\n        annotation_file_type=prediction_format,\n        is_prediction=True,\n    )\n    return \"Successfully registered image and annotation\"\n\n\ndef safe_register_image_at_roboflow(\n    target_project: str,\n    encoded_image: bytes,\n    local_image_id: str,\n    api_key: str,\n    batch_name: str,\n    tags: List[str],\n    inference_id: Optional[str],\n    metadata: Optional[Dict[str, Any]] = None,\n) -> Optional[str]:\n    registration_response = register_image_at_roboflow(\n        api_key=api_key,\n        dataset_id=target_project,\n        local_image_id=local_image_id,\n        image_bytes=encoded_image,\n        batch_name=batch_name,\n        tags=tags,\n        inference_id=inference_id,\n        metadata=metadata,\n    )\n    image_duplicated = registration_response.get(\"duplicate\", False)\n    if image_duplicated:\n        logging.warning(f\"Image duplication detected: {registration_response}.\")\n        return None\n    return registration_response[\"id\"]\n\n\ndef is_prediction_registration_forbidden(\n    prediction: Optional[Union[sv.Detections, dict]],\n) -> bool:\n    if prediction is None:\n        return True\n    if isinstance(prediction, sv.Detections) and len(prediction) == 0:\n        return True\n    if isinstance(prediction, dict) and (\n        \"top\" not in prediction and \"predicted_classes\" not in prediction\n    ):\n        return True\n    return False\n\n\ndef encode_prediction(\n    prediction: Union[sv.Detections, dict],\n) -> Tuple[str, str]:\n    if isinstance(prediction, dict):\n        if \"predicted_classes\" in prediction:\n            return \",\".join(prediction[\"predicted_classes\"]), \"txt\"\n        return prediction[\"top\"], \"txt\"\n    detections_in_inference_format = serialise_sv_detections(detections=prediction)\n    return json.dumps(detections_in_inference_format), \"json\"\n",
    "patch": null
  },
  {
    "trace_id": "6caa6891-5647-4204-99a8-5ba317e13864",
    "function_name": "prepare_parameters",
    "file_path": "inference/core/workflows/execution_engine/v1/executor/execution_data_manager/step_input_assembler.py",
    "speedup_x": 0.11641916089256196,
    "review_quality": "high",
    "pre_optimization_commit": "HEAD",
    "resolution_method": "db_code_only",
    "source": "db_features",
    "original_function_code": "def prepare_parameters(\n    step_node: StepNode,\n    dynamic_batches_manager: DynamicBatchesManager,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> BatchModeSIMDStepInput:\n    step_requests_batch_input = step_node.step_manifest.accepts_batch_input()\n    result = {}\n    indices_for_parameter = {}\n    guard_of_indices_wrapping = GuardForIndicesWrapping()\n    compound_inputs = set()\n    contains_empty_scalar_step_output_selector = False\n    for parameter_name, parameter_specs in step_node.input_data.items():\n        if parameter_specs.is_compound_input():\n            (\n                result[parameter_name],\n                indices_for_parameter[parameter_name],\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_compound_parameter_value(\n                parameter=parameter_specs,\n                step_execution_dimensionality=step_node.step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=step_node.auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n            compound_inputs.add(parameter_name)\n            if isinstance(result[parameter_name], dict):\n                result[parameter_name] = _transpose_dict_of_batches_if_needed(\n                    result[parameter_name],\n                )\n        else:\n            (\n                result[parameter_name],\n                indices_for_parameter[parameter_name],\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=parameter_specs,\n                step_execution_dimensionality=step_node.step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=step_node.auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n        contains_empty_scalar_step_output_selector = (\n            contains_empty_scalar_step_output_selector\n            or value_contains_empty_scalar_step_output_selector\n        )\n    batch_parameters_indices = [\n        i for i in indices_for_parameter.values() if i is not None\n    ]\n    ensure_compound_input_indices_match(indices=batch_parameters_indices)\n    if not batch_parameters_indices:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"For step: {step_node.name} which is assessed by Workflows Compiler as \"\n            f\"SIMD step Execution Engine cannot detect batch inputs. \"\n            f\"This is most likely a bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    indices = batch_parameters_indices[0]\n    if not step_node.step_manifest.accepts_empty_values():\n        if contains_empty_scalar_step_output_selector:\n            return BatchModeSIMDStepInput(\n                indices=[],\n                parameters={},\n            )\n        empty_indices = get_empty_batch_elements_indices(value=result)\n        if empty_indices:\n            indices = [e for e in indices if e not in empty_indices]\n            result = remove_indices(value=result, indices=empty_indices)\n    return BatchModeSIMDStepInput(\n        indices=indices,\n        parameters=result,\n    )\n",
    "optimized_function_code": "from dataclasses import dataclass\nfrom typing import Any, Dict, List, Optional, Set, Tuple, TypeVar, Union\n\nfrom inference.core.workflows.errors import (AssumptionError,\n                                             ExecutionEngineRuntimeError)\nfrom inference.core.workflows.execution_engine.entities.base import Batch\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import (\n    AutoBatchCastingConfig, CompoundStepInputDefinition,\n    DynamicStepInputDefinition, StaticStepInputDefinition, StepInputDefinition,\n    StepNode)\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import \\\n    get_last_chunk_of_selector\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.dynamic_batches_manager import (\n    DynamicBatchesManager, DynamicBatchIndex)\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.execution_cache import \\\n    ExecutionCache\n\nT = TypeVar(\"T\")\n\n\n@dataclass(frozen=True)\nclass BatchModeSIMDStepInput:\n    indices: List[DynamicBatchIndex]\n    parameters: Dict[str, Any]\n\n\nclass GuardForIndicesWrapping:\n\n    def __init__(self):\n        self._registered_wrapping: Optional[List[DynamicBatchIndex]] = None\n\n\ndef prepare_parameters(\n    step_node: StepNode,\n    dynamic_batches_manager: DynamicBatchesManager,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> BatchModeSIMDStepInput:\n    step_requests_batch_input = step_node.step_manifest.accepts_batch_input()\n    result = {}\n    indices_for_parameter = {}\n    guard_of_indices_wrapping = GuardForIndicesWrapping()\n    compound_inputs = set()\n    contains_empty_scalar_step_output_selector = False\n    step_execution_dimensionality = step_node.step_execution_dimensionality\n    auto_batch_casting_lineage_supports = step_node.auto_batch_casting_lineage_supports\n    input_data = step_node.input_data\n    \n    for parameter_name, parameter_specs in input_data.items():\n        if parameter_specs.is_compound_input():\n            (\n                result[parameter_name],\n                indices_for_parameter[parameter_name],\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_compound_parameter_value(\n                parameter=parameter_specs,\n                step_execution_dimensionality=step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n            compound_inputs.add(parameter_name)\n            if isinstance(result[parameter_name], dict):\n                result[parameter_name] = _transpose_dict_of_batches_if_needed(\n                    result[parameter_name],\n                )\n        else:\n            (\n                result[parameter_name],\n                indices_for_parameter[parameter_name],\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=parameter_specs,\n                step_execution_dimensionality=step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n        contains_empty_scalar_step_output_selector = (\n            contains_empty_scalar_step_output_selector\n            or value_contains_empty_scalar_step_output_selector\n        )\n    batch_parameters_indices = [\n        i for i in indices_for_parameter.values() if i is not None\n    ]\n    ensure_compound_input_indices_match(indices=batch_parameters_indices)\n    if not batch_parameters_indices:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"For step: {step_node.name} which is assessed by Workflows Compiler as \"\n            f\"SIMD step Execution Engine cannot detect batch inputs. \"\n            f\"This is most likely a bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    indices = batch_parameters_indices[0]\n    if not step_node.step_manifest.accepts_empty_values():\n        if contains_empty_scalar_step_output_selector:\n            return BatchModeSIMDStepInput(\n                indices=[],\n                parameters={},\n            )\n        empty_indices = get_empty_batch_elements_indices(value=result)\n        if empty_indices:\n            indices = [e for e in indices if e not in empty_indices]\n            result = remove_indices(value=result, indices=empty_indices)\n    return BatchModeSIMDStepInput(\n        indices=indices,\n        parameters=result,\n    )\n\n\ndef _transpose_dict_of_batches_if_needed(\n    value: Dict[str, Any],\n) -> Union[Dict[str, Any], Batch]:\n    \"\"\"Transpose a dict-of-Batches into a Batch-of-dicts.\n\n    Compound dict inputs are resolved as {\"key1\": Batch([...]), \"key2\": Batch([...])}.\n    Batch-mode blocks expect Batch[Dict] instead. This function detects dicts containing\n    Batch values and transposes them so each batch element is a complete dict.\n    If no Batch values are present, returns the dict unchanged.\n    \"\"\"\n    batch_entries = {k: v for k, v in value.items() if isinstance(v, Batch)}\n    if not batch_entries:\n        return value\n    non_batch_entries = {k: v for k, v in value.items() if not isinstance(v, Batch)}\n    first_batch = next(iter(batch_entries.values()))\n    indices = first_batch.indices\n    length = len(first_batch)\n    content = []\n    \n    batch_keys = list(batch_entries.keys())\n    batch_values = [batch_entries[k] for k in batch_keys]\n    \n    for i in range(length):\n        entry = {k: batch_values[j]._content[i] for j, k in enumerate(batch_keys)}\n        entry.update(non_batch_entries)\n        content.append(entry)\n    return Batch(content=content, indices=indices)\n\n\ndef get_compound_parameter_value(\n    parameter: CompoundStepInputDefinition,\n    step_execution_dimensionality: int,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n    dynamic_batches_manager: DynamicBatchesManager,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n    auto_batch_casting_lineage_supports: Dict[str, AutoBatchCastingConfig],\n    step_requests_batch_input: bool,\n) -> Tuple[Union[list, Dict[str, Any]], Optional[List[DynamicBatchIndex]], bool]:\n    contains_empty_scalar_step_output_selector = False\n    batch_indices = []\n    represents_list = parameter.represents_list_of_inputs()\n    \n    if represents_list:\n        result = []\n        for nested_element in parameter.iterate_through_definitions():\n            (\n                non_compound_parameter_value,\n                non_compound_indices,\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=nested_element,\n                step_execution_dimensionality=step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n            result.append(non_compound_parameter_value)\n            contains_empty_scalar_step_output_selector = (\n                contains_empty_scalar_step_output_selector\n                or value_contains_empty_scalar_step_output_selector\n            )\n            if non_compound_indices is not None:\n                batch_indices.append(non_compound_indices)\n    else:\n        result = {}\n        for nested_element in parameter.iterate_through_definitions():\n            (\n                non_compound_parameter_value,\n                non_compound_indices,\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=nested_element,\n                step_execution_dimensionality=step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n            result[nested_element.parameter_specification.nested_element_key] = (\n                non_compound_parameter_value\n            )\n            contains_empty_scalar_step_output_selector = (\n                contains_empty_scalar_step_output_selector\n                or value_contains_empty_scalar_step_output_selector\n            )\n            if non_compound_indices is not None:\n                batch_indices.append(non_compound_indices)\n    ensure_compound_input_indices_match(indices=batch_indices)\n    result_indices = None\n    if len(batch_indices) > 0:\n        result_indices = batch_indices[0]\n    return result, result_indices, contains_empty_scalar_step_output_selector\n\n\ndef get_non_compound_parameter_value(\n    parameter: StepInputDefinition,\n    step_execution_dimensionality: int,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n    dynamic_batches_manager: DynamicBatchesManager,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n    auto_batch_casting_lineage_supports: Dict[str, AutoBatchCastingConfig],\n    step_requests_batch_input: bool,\n) -> Tuple[Any, Optional[List[DynamicBatchIndex]], bool]:\n    is_batch_oriented = parameter.is_batch_oriented()\n    \n    if not is_batch_oriented:\n        parameter_name_spec = parameter.parameter_specification.parameter_name\n        requested_as_batch = parameter_name_spec in auto_batch_casting_lineage_supports\n        \n        if parameter.points_to_input():\n            input_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n            parameter_name = get_last_chunk_of_selector(\n                selector=input_parameter.selector\n            )\n            if not requested_as_batch:\n                return runtime_parameters[parameter_name], None, False\n            else:\n                return apply_auto_batch_casting(\n                    parameter_name=parameter_name,\n                    value=runtime_parameters[parameter_name],\n                    auto_batch_casting_config=auto_batch_casting_lineage_supports[\n                        parameter_name_spec\n                    ],\n                    contains_empty_scalar_step_output_selector=False,\n                    dynamic_batches_manager=dynamic_batches_manager,\n                    step_execution_dimensionality=step_execution_dimensionality,\n                    guard_of_indices_wrapping=guard_of_indices_wrapping,\n                    step_requests_batch_input=step_requests_batch_input,\n                    masks=masks,\n                    scalars_discarded=False,\n                )\n        elif parameter.points_to_step_output():\n            input_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n            value = execution_cache.get_non_batch_output(\n                selector=input_parameter.selector\n            )\n            if not requested_as_batch:\n                return value, None, value is None\n            else:\n                return apply_auto_batch_casting(\n                    parameter_name=parameter_name_spec,\n                    value=value,\n                    auto_batch_casting_config=auto_batch_casting_lineage_supports[\n                        parameter_name_spec\n                    ],\n                    contains_empty_scalar_step_output_selector=value is None,\n                    dynamic_batches_manager=dynamic_batches_manager,\n                    step_execution_dimensionality=step_execution_dimensionality,\n                    guard_of_indices_wrapping=guard_of_indices_wrapping,\n                    step_requests_batch_input=step_requests_batch_input,\n                    masks=masks,\n                    scalars_discarded=scalars_discarded,\n                )\n        else:\n            static_input: StaticStepInputDefinition = parameter  # type: ignore\n            if not requested_as_batch or static_input.value is None:\n                # when we have Optional[Selector()] in manifest - we must retain\n                # ability to inject None into the run(...) parameters - as\n                # if we treat that as actual batch and broadcast Batch[None],\n                # we would behave exactly as condition execution does -\n                # and the logic executing after this, will filter-out empty\n                # elements - so on None, we behave \"the old way\" regardless of the fact that ABC\n                # was requested\n                return static_input.value, None, False\n            else:\n                return apply_auto_batch_casting(\n                    parameter_name=parameter_name_spec,\n                    value=static_input.value,\n                    auto_batch_casting_config=auto_batch_casting_lineage_supports[\n                        parameter_name_spec\n                    ],\n                    contains_empty_scalar_step_output_selector=False,\n                    dynamic_batches_manager=dynamic_batches_manager,\n                    step_execution_dimensionality=step_execution_dimensionality,\n                    guard_of_indices_wrapping=guard_of_indices_wrapping,\n                    step_requests_batch_input=step_requests_batch_input,\n                    masks=masks,\n                    scalars_discarded=False,\n                )\n    dynamic_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n    parameter_dimensionality = dynamic_parameter.get_dimensionality()\n    data_lineage = dynamic_parameter.data_lineage\n    lineage_indices = dynamic_batches_manager.get_indices_for_data_lineage(\n        lineage=data_lineage,\n    )\n    mask_for_dimension = masks[parameter_dimensionality]\n    if dynamic_parameter.points_to_input():\n        input_name = get_last_chunk_of_selector(selector=dynamic_parameter.selector)\n        batch_input = _flatten_batch_oriented_inputs(\n            runtime_parameters[input_name],\n            dimensionality=parameter_dimensionality,\n        )\n        if mask_for_dimension is not None:\n            if len(lineage_indices) != len(batch_input):\n                raise ExecutionEngineRuntimeError(\n                    public_message=f\"Detected a situation when input parameter: \"\n                    f\"{input_name}\"\n                    f\"size is mismatched compared to mask requested for that input. \"\n                    f\"Input length: {len(batch_input)}, mask size: {len(lineage_indices)}. \"\n                    f\"This is most likely a bug. \"\n                    f\"Contact Roboflow team through github issues \"\n                    f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                    f\"the problem - including workflow definition you use.\",\n                    context=\"workflow_execution | step_input_assembling\",\n                )\n            batch_input = [\n                input_element if element_index in mask_for_dimension else None\n                for element_index, input_element in zip(lineage_indices, batch_input)\n            ]\n    else:\n        batch_input = execution_cache.get_batch_output(\n            selector=dynamic_parameter.selector,\n            batch_elements_indices=lineage_indices,\n            mask=mask_for_dimension,\n        )\n    if step_execution_dimensionality == parameter_dimensionality:\n        return Batch(batch_input, lineage_indices), lineage_indices, False\n    if step_execution_dimensionality > parameter_dimensionality:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter.parameter_specification.parameter_name}\"\n            f\"has a dimensionality {parameter_dimensionality} larger \"\n            f\"than step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if abs(parameter_dimensionality - step_execution_dimensionality) > 1:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter.parameter_specification.parameter_name}\"\n            f\"has a dimensionality {parameter_dimensionality} differing more than one level \"\n            f\"from step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if step_execution_dimensionality == 0 and not step_requests_batch_input:\n        return Batch(batch_input, lineage_indices), lineage_indices, False\n    upper_lineage = data_lineage[:-1]\n    if len(upper_lineage) == 0:\n        if not step_requests_batch_input:\n            raise AssumptionError(\n                public_message=f\"Parameter: {parameter.parameter_specification.parameter_name} \"\n                f\"requires dimensionality wrapping, but registered lineage support is incompatible \"\n                f\"which should be detected by the compiler. This is most likely a bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n        upper_level_indices = [()]\n    else:\n        upper_level_indices = dynamic_batches_manager.get_indices_for_data_lineage(\n            lineage=upper_lineage,\n        )\n    result = reduce_batch_dimensionality(\n        indices=lineage_indices,\n        upper_level_index=upper_level_indices,\n        data=batch_input,\n        guard_of_indices_wrapping=guard_of_indices_wrapping,\n    )\n    return result, result.indices, False\n\n\ndef ensure_compound_input_indices_match(indices: List[List[DynamicBatchIndex]]) -> None:\n    if len(indices) < 2:\n        return None\n    reference_set = set(indices[0])\n    for index in indices[1:]:\n        other_set = set(index)\n        if reference_set != other_set:\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Detected a situation when step input parameters cannot be created \"\n                f\"due to missmatch in batch element indices. This is most likely a bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n\n\ndef get_empty_batch_elements_indices(value: Any) -> Set[DynamicBatchIndex]:\n    result = set()\n    if isinstance(value, dict):\n        for v in value.values():\n            value_result = get_empty_batch_elements_indices(v)\n            result = result.union(value_result)\n    elif isinstance(value, list):\n        for v in value:\n            value_result = get_empty_batch_elements_indices(v)\n            result = result.union(value_result)\n    elif isinstance(value, Batch):\n        batch_content = value._content\n        batch_indices = value._indices\n        for i, value_element in enumerate(batch_content):\n            if isinstance(value_element, Batch):\n                value_result = get_empty_batch_elements_indices(value=value_element)\n                result = result.union(value_result)\n            elif value_element is None:\n                result.add(batch_indices[i])\n    return result\n\n\ndef remove_indices(value: Any, indices: Set[DynamicBatchIndex]) -> Any:\n    if isinstance(value, dict):\n        return {k: remove_indices(value=v, indices=indices) for k, v in value.items()}\n    if isinstance(value, list):\n        return [remove_indices(value=v, indices=indices) for v in value]\n    if isinstance(value, Batch):\n        return value.remove_by_indices(indices_to_remove=indices)\n    return value",
    "optimized_raw_markdown": "```python:inference/core/workflows/prototypes/block.py\nfrom abc import ABC\nfrom pydantic import BaseModel\n\nclass WorkflowBlockManifest(BaseModel, ABC):\n\n    @classmethod\n    def accepts_batch_input(cls) -> bool:\n        return (\n            len(cls.get_parameters_accepting_batches()) > 0\n            or len(cls.get_parameters_accepting_batches_and_scalars()) > 0\n        )\n\n    @classmethod\n    def accepts_empty_values(cls) -> bool:\n        return False\n```\n```python:inference/core/workflows/execution_engine/v1/executor/execution_data_manager/step_input_assembler.py\nfrom dataclasses import dataclass\nfrom typing import Any, Dict, List, Optional, Set, Tuple, TypeVar, Union\n\nfrom inference.core.workflows.errors import (AssumptionError,\n                                             ExecutionEngineRuntimeError)\nfrom inference.core.workflows.execution_engine.entities.base import Batch\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import (\n    AutoBatchCastingConfig, CompoundStepInputDefinition,\n    DynamicStepInputDefinition, StaticStepInputDefinition, StepInputDefinition,\n    StepNode)\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import \\\n    get_last_chunk_of_selector\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.dynamic_batches_manager import (\n    DynamicBatchesManager, DynamicBatchIndex)\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.execution_cache import \\\n    ExecutionCache\n\nT = TypeVar(\"T\")\n\n\n@dataclass(frozen=True)\nclass BatchModeSIMDStepInput:\n    indices: List[DynamicBatchIndex]\n    parameters: Dict[str, Any]\n\n\nclass GuardForIndicesWrapping:\n\n    def __init__(self):\n        self._registered_wrapping: Optional[List[DynamicBatchIndex]] = None\n\n\ndef prepare_parameters(\n    step_node: StepNode,\n    dynamic_batches_manager: DynamicBatchesManager,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> BatchModeSIMDStepInput:\n    step_requests_batch_input = step_node.step_manifest.accepts_batch_input()\n    result = {}\n    indices_for_parameter = {}\n    guard_of_indices_wrapping = GuardForIndicesWrapping()\n    compound_inputs = set()\n    contains_empty_scalar_step_output_selector = False\n    step_execution_dimensionality = step_node.step_execution_dimensionality\n    auto_batch_casting_lineage_supports = step_node.auto_batch_casting_lineage_supports\n    input_data = step_node.input_data\n    \n    for parameter_name, parameter_specs in input_data.items():\n        if parameter_specs.is_compound_input():\n            (\n                result[parameter_name],\n                indices_for_parameter[parameter_name],\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_compound_parameter_value(\n                parameter=parameter_specs,\n                step_execution_dimensionality=step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n            compound_inputs.add(parameter_name)\n            if isinstance(result[parameter_name], dict):\n                result[parameter_name] = _transpose_dict_of_batches_if_needed(\n                    result[parameter_name],\n                )\n        else:\n            (\n                result[parameter_name],\n                indices_for_parameter[parameter_name],\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=parameter_specs,\n                step_execution_dimensionality=step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n        contains_empty_scalar_step_output_selector = (\n            contains_empty_scalar_step_output_selector\n            or value_contains_empty_scalar_step_output_selector\n        )\n    batch_parameters_indices = [\n        i for i in indices_for_parameter.values() if i is not None\n    ]\n    ensure_compound_input_indices_match(indices=batch_parameters_indices)\n    if not batch_parameters_indices:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"For step: {step_node.name} which is assessed by Workflows Compiler as \"\n            f\"SIMD step Execution Engine cannot detect batch inputs. \"\n            f\"This is most likely a bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    indices = batch_parameters_indices[0]\n    if not step_node.step_manifest.accepts_empty_values():\n        if contains_empty_scalar_step_output_selector:\n            return BatchModeSIMDStepInput(\n                indices=[],\n                parameters={},\n            )\n        empty_indices = get_empty_batch_elements_indices(value=result)\n        if empty_indices:\n            indices = [e for e in indices if e not in empty_indices]\n            result = remove_indices(value=result, indices=empty_indices)\n    return BatchModeSIMDStepInput(\n        indices=indices,\n        parameters=result,\n    )\n\n\ndef _transpose_dict_of_batches_if_needed(\n    value: Dict[str, Any],\n) -> Union[Dict[str, Any], Batch]:\n    \"\"\"Transpose a dict-of-Batches into a Batch-of-dicts.\n\n    Compound dict inputs are resolved as {\"key1\": Batch([...]), \"key2\": Batch([...])}.\n    Batch-mode blocks expect Batch[Dict] instead. This function detects dicts containing\n    Batch values and transposes them so each batch element is a complete dict.\n    If no Batch values are present, returns the dict unchanged.\n    \"\"\"\n    batch_entries = {k: v for k, v in value.items() if isinstance(v, Batch)}\n    if not batch_entries:\n        return value\n    non_batch_entries = {k: v for k, v in value.items() if not isinstance(v, Batch)}\n    first_batch = next(iter(batch_entries.values()))\n    indices = first_batch.indices\n    length = len(first_batch)\n    content = []\n    \n    batch_keys = list(batch_entries.keys())\n    batch_values = [batch_entries[k] for k in batch_keys]\n    \n    for i in range(length):\n        entry = {k: batch_values[j]._content[i] for j, k in enumerate(batch_keys)}\n        entry.update(non_batch_entries)\n        content.append(entry)\n    return Batch(content=content, indices=indices)\n\n\ndef get_compound_parameter_value(\n    parameter: CompoundStepInputDefinition,\n    step_execution_dimensionality: int,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n    dynamic_batches_manager: DynamicBatchesManager,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n    auto_batch_casting_lineage_supports: Dict[str, AutoBatchCastingConfig],\n    step_requests_batch_input: bool,\n) -> Tuple[Union[list, Dict[str, Any]], Optional[List[DynamicBatchIndex]], bool]:\n    contains_empty_scalar_step_output_selector = False\n    batch_indices = []\n    represents_list = parameter.represents_list_of_inputs()\n    \n    if represents_list:\n        result = []\n        for nested_element in parameter.iterate_through_definitions():\n            (\n                non_compound_parameter_value,\n                non_compound_indices,\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=nested_element,\n                step_execution_dimensionality=step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n            result.append(non_compound_parameter_value)\n            contains_empty_scalar_step_output_selector = (\n                contains_empty_scalar_step_output_selector\n                or value_contains_empty_scalar_step_output_selector\n            )\n            if non_compound_indices is not None:\n                batch_indices.append(non_compound_indices)\n    else:\n        result = {}\n        for nested_element in parameter.iterate_through_definitions():\n            (\n                non_compound_parameter_value,\n                non_compound_indices,\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=nested_element,\n                step_execution_dimensionality=step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n            result[nested_element.parameter_specification.nested_element_key] = (\n                non_compound_parameter_value\n            )\n            contains_empty_scalar_step_output_selector = (\n                contains_empty_scalar_step_output_selector\n                or value_contains_empty_scalar_step_output_selector\n            )\n            if non_compound_indices is not None:\n                batch_indices.append(non_compound_indices)\n    ensure_compound_input_indices_match(indices=batch_indices)\n    result_indices = None\n    if len(batch_indices) > 0:\n        result_indices = batch_indices[0]\n    return result, result_indices, contains_empty_scalar_step_output_selector\n\n\ndef get_non_compound_parameter_value(\n    parameter: StepInputDefinition,\n    step_execution_dimensionality: int,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n    dynamic_batches_manager: DynamicBatchesManager,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n    auto_batch_casting_lineage_supports: Dict[str, AutoBatchCastingConfig],\n    step_requests_batch_input: bool,\n) -> Tuple[Any, Optional[List[DynamicBatchIndex]], bool]:\n    is_batch_oriented = parameter.is_batch_oriented()\n    \n    if not is_batch_oriented:\n        parameter_name_spec = parameter.parameter_specification.parameter_name\n        requested_as_batch = parameter_name_spec in auto_batch_casting_lineage_supports\n        \n        if parameter.points_to_input():\n            input_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n            parameter_name = get_last_chunk_of_selector(\n                selector=input_parameter.selector\n            )\n            if not requested_as_batch:\n                return runtime_parameters[parameter_name], None, False\n            else:\n                return apply_auto_batch_casting(\n                    parameter_name=parameter_name,\n                    value=runtime_parameters[parameter_name],\n                    auto_batch_casting_config=auto_batch_casting_lineage_supports[\n                        parameter_name_spec\n                    ],\n                    contains_empty_scalar_step_output_selector=False,\n                    dynamic_batches_manager=dynamic_batches_manager,\n                    step_execution_dimensionality=step_execution_dimensionality,\n                    guard_of_indices_wrapping=guard_of_indices_wrapping,\n                    step_requests_batch_input=step_requests_batch_input,\n                    masks=masks,\n                    scalars_discarded=False,\n                )\n        elif parameter.points_to_step_output():\n            input_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n            value = execution_cache.get_non_batch_output(\n                selector=input_parameter.selector\n            )\n            if not requested_as_batch:\n                return value, None, value is None\n            else:\n                return apply_auto_batch_casting(\n                    parameter_name=parameter_name_spec,\n                    value=value,\n                    auto_batch_casting_config=auto_batch_casting_lineage_supports[\n                        parameter_name_spec\n                    ],\n                    contains_empty_scalar_step_output_selector=value is None,\n                    dynamic_batches_manager=dynamic_batches_manager,\n                    step_execution_dimensionality=step_execution_dimensionality,\n                    guard_of_indices_wrapping=guard_of_indices_wrapping,\n                    step_requests_batch_input=step_requests_batch_input,\n                    masks=masks,\n                    scalars_discarded=scalars_discarded,\n                )\n        else:\n            static_input: StaticStepInputDefinition = parameter  # type: ignore\n            if not requested_as_batch or static_input.value is None:\n                # when we have Optional[Selector()] in manifest - we must retain\n                # ability to inject None into the run(...) parameters - as\n                # if we treat that as actual batch and broadcast Batch[None],\n                # we would behave exactly as condition execution does -\n                # and the logic executing after this, will filter-out empty\n                # elements - so on None, we behave \"the old way\" regardless of the fact that ABC\n                # was requested\n                return static_input.value, None, False\n            else:\n                return apply_auto_batch_casting(\n                    parameter_name=parameter_name_spec,\n                    value=static_input.value,\n                    auto_batch_casting_config=auto_batch_casting_lineage_supports[\n                        parameter_name_spec\n                    ],\n                    contains_empty_scalar_step_output_selector=False,\n                    dynamic_batches_manager=dynamic_batches_manager,\n                    step_execution_dimensionality=step_execution_dimensionality,\n                    guard_of_indices_wrapping=guard_of_indices_wrapping,\n                    step_requests_batch_input=step_requests_batch_input,\n                    masks=masks,\n                    scalars_discarded=False,\n                )\n    dynamic_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n    parameter_dimensionality = dynamic_parameter.get_dimensionality()\n    data_lineage = dynamic_parameter.data_lineage\n    lineage_indices = dynamic_batches_manager.get_indices_for_data_lineage(\n        lineage=data_lineage,\n    )\n    mask_for_dimension = masks[parameter_dimensionality]\n    if dynamic_parameter.points_to_input():\n        input_name = get_last_chunk_of_selector(selector=dynamic_parameter.selector)\n        batch_input = _flatten_batch_oriented_inputs(\n            runtime_parameters[input_name],\n            dimensionality=parameter_dimensionality,\n        )\n        if mask_for_dimension is not None:\n            if len(lineage_indices) != len(batch_input):\n                raise ExecutionEngineRuntimeError(\n                    public_message=f\"Detected a situation when input parameter: \"\n                    f\"{input_name}\"\n                    f\"size is mismatched compared to mask requested for that input. \"\n                    f\"Input length: {len(batch_input)}, mask size: {len(lineage_indices)}. \"\n                    f\"This is most likely a bug. \"\n                    f\"Contact Roboflow team through github issues \"\n                    f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                    f\"the problem - including workflow definition you use.\",\n                    context=\"workflow_execution | step_input_assembling\",\n                )\n            batch_input = [\n                input_element if element_index in mask_for_dimension else None\n                for element_index, input_element in zip(lineage_indices, batch_input)\n            ]\n    else:\n        batch_input = execution_cache.get_batch_output(\n            selector=dynamic_parameter.selector,\n            batch_elements_indices=lineage_indices,\n            mask=mask_for_dimension,\n        )\n    if step_execution_dimensionality == parameter_dimensionality:\n        return Batch(batch_input, lineage_indices), lineage_indices, False\n    if step_execution_dimensionality > parameter_dimensionality:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter.parameter_specification.parameter_name}\"\n            f\"has a dimensionality {parameter_dimensionality} larger \"\n            f\"than step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if abs(parameter_dimensionality - step_execution_dimensionality) > 1:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter.parameter_specification.parameter_name}\"\n            f\"has a dimensionality {parameter_dimensionality} differing more than one level \"\n            f\"from step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if step_execution_dimensionality == 0 and not step_requests_batch_input:\n        return Batch(batch_input, lineage_indices), lineage_indices, False\n    upper_lineage = data_lineage[:-1]\n    if len(upper_lineage) == 0:\n        if not step_requests_batch_input:\n            raise AssumptionError(\n                public_message=f\"Parameter: {parameter.parameter_specification.parameter_name} \"\n                f\"requires dimensionality wrapping, but registered lineage support is incompatible \"\n                f\"which should be detected by the compiler. This is most likely a bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n        upper_level_indices = [()]\n    else:\n        upper_level_indices = dynamic_batches_manager.get_indices_for_data_lineage(\n            lineage=upper_lineage,\n        )\n    result = reduce_batch_dimensionality(\n        indices=lineage_indices,\n        upper_level_index=upper_level_indices,\n        data=batch_input,\n        guard_of_indices_wrapping=guard_of_indices_wrapping,\n    )\n    return result, result.indices, False\n\n\ndef ensure_compound_input_indices_match(indices: List[List[DynamicBatchIndex]]) -> None:\n    if len(indices) < 2:\n        return None\n    reference_set = set(indices[0])\n    for index in indices[1:]:\n        other_set = set(index)\n        if reference_set != other_set:\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Detected a situation when step input parameters cannot be created \"\n                f\"due to missmatch in batch element indices. This is most likely a bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n\n\ndef get_empty_batch_elements_indices(value: Any) -> Set[DynamicBatchIndex]:\n    result = set()\n    if isinstance(value, dict):\n        for v in value.values():\n            value_result = get_empty_batch_elements_indices(v)\n            result = result.union(value_result)\n    elif isinstance(value, list):\n        for v in value:\n            value_result = get_empty_batch_elements_indices(v)\n            result = result.union(value_result)\n    elif isinstance(value, Batch):\n        batch_content = value._content\n        batch_indices = value._indices\n        for i, value_element in enumerate(batch_content):\n            if isinstance(value_element, Batch):\n                value_result = get_empty_batch_elements_indices(value=value_element)\n                result = result.union(value_result)\n            elif value_element is None:\n                result.add(batch_indices[i])\n    return result\n\n\ndef remove_indices(value: Any, indices: Set[DynamicBatchIndex]) -> Any:\n    if isinstance(value, dict):\n        return {k: remove_indices(value=v, indices=indices) for k, v in value.items()}\n    if isinstance(value, list):\n        return [remove_indices(value=v, indices=indices) for v in value]\n    if isinstance(value, Batch):\n        return value.remove_by_indices(indices_to_remove=indices)\n    return value\n```\n```python:inference/core/workflows/execution_engine/v1/compiler/entities.py\nfrom abc import abstractmethod\nfrom dataclasses import dataclass\nfrom enum import Enum\nfrom typing import Optional\n\nclass NodeInputCategory(Enum):\n    NON_BATCH_INPUT_PARAMETER = \"NON_BATCH_INPUT_PARAMETER\"\n    BATCH_INPUT_PARAMETER = \"BATCH_INPUT_PARAMETER\"\n    NON_BATCH_STEP_OUTPUT = \"NON_BATCH_STEP_OUTPUT\"\n    BATCH_STEP_OUTPUT = \"BATCH_STEP_OUTPUT\"\n    STATIC_VALUE = \"STATIC_VALUE\"\n\n\n@dataclass(frozen=True)\nclass ParameterSpecification:\n    parameter_name: str\n    nested_element_key: Optional[str] = None\n    nested_element_index: Optional[int] = None\n\n\n@dataclass(frozen=True)\nclass StepInputDefinition:\n    parameter_specification: ParameterSpecification\n    category: NodeInputCategory\n\n    def points_to_input(self) -> bool:\n        return self.category in INPUTS_REFERENCES\n\n    def points_to_step_output(self) -> bool:\n        return self.category in STEPS_OUTPUTS_REFERENCES\n\n    def is_static_value(self) -> bool:\n        return self.category is NodeInputCategory.STATIC_VALUE\n\n    @abstractmethod\n    def is_batch_oriented(self) -> bool:\n        pass\n\n    @abstractmethod\n    def get_dimensionality(self) -> int:\n        pass\n\n    @classmethod\n    def is_compound_input(cls) -> bool:\n        return False\n\n\n@dataclass(frozen=True)\nclass CompoundStepInputDefinition:\n\n    @classmethod\n    def is_compound_input(cls) -> bool:\n        return True\n```",
    "optimized_function_only": "def prepare_parameters(\n    step_node: StepNode,\n    dynamic_batches_manager: DynamicBatchesManager,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> BatchModeSIMDStepInput:\n    step_requests_batch_input = step_node.step_manifest.accepts_batch_input()\n    result = {}\n    indices_for_parameter = {}\n    guard_of_indices_wrapping = GuardForIndicesWrapping()\n    compound_inputs = set()\n    contains_empty_scalar_step_output_selector = False\n    step_execution_dimensionality = step_node.step_execution_dimensionality\n    auto_batch_casting_lineage_supports = step_node.auto_batch_casting_lineage_supports\n    input_data = step_node.input_data\n    \n    for parameter_name, parameter_specs in input_data.items():\n        if parameter_specs.is_compound_input():\n            (\n                result[parameter_name],\n                indices_for_parameter[parameter_name],\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_compound_parameter_value(\n                parameter=parameter_specs,\n                step_execution_dimensionality=step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n            compound_inputs.add(parameter_name)\n            if isinstance(result[parameter_name], dict):\n                result[parameter_name] = _transpose_dict_of_batches_if_needed(\n                    result[parameter_name],\n                )\n        else:\n            (\n                result[parameter_name],\n                indices_for_parameter[parameter_name],\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=parameter_specs,\n                step_execution_dimensionality=step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n        contains_empty_scalar_step_output_selector = (\n            contains_empty_scalar_step_output_selector\n            or value_contains_empty_scalar_step_output_selector\n        )\n    batch_parameters_indices = [\n        i for i in indices_for_parameter.values() if i is not None\n    ]\n    ensure_compound_input_indices_match(indices=batch_parameters_indices)\n    if not batch_parameters_indices:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"For step: {step_node.name} which is assessed by Workflows Compiler as \"\n            f\"SIMD step Execution Engine cannot detect batch inputs. \"\n            f\"This is most likely a bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    indices = batch_parameters_indices[0]\n    if not step_node.step_manifest.accepts_empty_values():\n        if contains_empty_scalar_step_output_selector:\n            return BatchModeSIMDStepInput(\n                indices=[],\n                parameters={},\n            )\n        empty_indices = get_empty_batch_elements_indices(value=result)\n        if empty_indices:\n            indices = [e for e in indices if e not in empty_indices]\n            result = remove_indices(value=result, indices=empty_indices)\n    return BatchModeSIMDStepInput(\n        indices=indices,\n        parameters=result,\n    )\n",
    "original_file_content": "from dataclasses import dataclass\nfrom inference.core.workflows.errors import AssumptionError, ExecutionEngineRuntimeError\nfrom inference.core.workflows.execution_engine.entities.base import Batch\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import AutoBatchCastingConfig, CompoundStepInputDefinition, DynamicStepInputDefinition, StaticStepInputDefinition, StepInputDefinition, StepNode\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import get_last_chunk_of_selector\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.dynamic_batches_manager import DynamicBatchIndex, DynamicBatchesManager\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.execution_cache import ExecutionCache\nfrom typing import Any, Dict, List, Optional, Set, Tuple, TypeVar, Union\n\nT = TypeVar(\"T\")\n\n\n@dataclass(frozen=True)\nclass BatchModeSIMDStepInput:\n    indices: List[DynamicBatchIndex]\n    parameters: Dict[str, Any]\n\n\nclass GuardForIndicesWrapping:\n\n    def __init__(self):\n        self._registered_wrapping: Optional[List[DynamicBatchIndex]] = None\n\n\ndef prepare_parameters(\n    step_node: StepNode,\n    dynamic_batches_manager: DynamicBatchesManager,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> BatchModeSIMDStepInput:\n    step_requests_batch_input = step_node.step_manifest.accepts_batch_input()\n    result = {}\n    indices_for_parameter = {}\n    guard_of_indices_wrapping = GuardForIndicesWrapping()\n    compound_inputs = set()\n    contains_empty_scalar_step_output_selector = False\n    for parameter_name, parameter_specs in step_node.input_data.items():\n        if parameter_specs.is_compound_input():\n            (\n                result[parameter_name],\n                indices_for_parameter[parameter_name],\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_compound_parameter_value(\n                parameter=parameter_specs,\n                step_execution_dimensionality=step_node.step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=step_node.auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n            compound_inputs.add(parameter_name)\n            if isinstance(result[parameter_name], dict):\n                result[parameter_name] = _transpose_dict_of_batches_if_needed(\n                    result[parameter_name],\n                )\n        else:\n            (\n                result[parameter_name],\n                indices_for_parameter[parameter_name],\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=parameter_specs,\n                step_execution_dimensionality=step_node.step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=step_node.auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n        contains_empty_scalar_step_output_selector = (\n            contains_empty_scalar_step_output_selector\n            or value_contains_empty_scalar_step_output_selector\n        )\n    batch_parameters_indices = [\n        i for i in indices_for_parameter.values() if i is not None\n    ]\n    ensure_compound_input_indices_match(indices=batch_parameters_indices)\n    if not batch_parameters_indices:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"For step: {step_node.name} which is assessed by Workflows Compiler as \"\n            f\"SIMD step Execution Engine cannot detect batch inputs. \"\n            f\"This is most likely a bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    indices = batch_parameters_indices[0]\n    if not step_node.step_manifest.accepts_empty_values():\n        if contains_empty_scalar_step_output_selector:\n            return BatchModeSIMDStepInput(\n                indices=[],\n                parameters={},\n            )\n        empty_indices = get_empty_batch_elements_indices(value=result)\n        if empty_indices:\n            indices = [e for e in indices if e not in empty_indices]\n            result = remove_indices(value=result, indices=empty_indices)\n    return BatchModeSIMDStepInput(\n        indices=indices,\n        parameters=result,\n    )\n\n\ndef _transpose_dict_of_batches_if_needed(\n    value: Dict[str, Any],\n) -> Union[Dict[str, Any], Batch]:\n    \"\"\"Transpose a dict-of-Batches into a Batch-of-dicts.\n\n    Compound dict inputs are resolved as {\"key1\": Batch([...]), \"key2\": Batch([...])}.\n    Batch-mode blocks expect Batch[Dict] instead. This function detects dicts containing\n    Batch values and transposes them so each batch element is a complete dict.\n    If no Batch values are present, returns the dict unchanged.\n    \"\"\"\n    batch_entries = {k: v for k, v in value.items() if isinstance(v, Batch)}\n    if not batch_entries:\n        return value\n    non_batch_entries = {k: v for k, v in value.items() if not isinstance(v, Batch)}\n    first_batch = next(iter(batch_entries.values()))\n    indices = first_batch.indices\n    length = len(first_batch)\n    content = []\n    for i in range(length):\n        entry = {}\n        for k, batch_val in batch_entries.items():\n            entry[k] = batch_val[i]\n        entry.update(non_batch_entries)\n        content.append(entry)\n    return Batch(content=content, indices=indices)\n\n\ndef get_compound_parameter_value(\n    parameter: CompoundStepInputDefinition,\n    step_execution_dimensionality: int,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n    dynamic_batches_manager: DynamicBatchesManager,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n    auto_batch_casting_lineage_supports: Dict[str, AutoBatchCastingConfig],\n    step_requests_batch_input: bool,\n) -> Tuple[Union[list, Dict[str, Any]], Optional[List[DynamicBatchIndex]], bool]:\n    contains_empty_scalar_step_output_selector = False\n    batch_indices = []\n    if parameter.represents_list_of_inputs():\n        result = []\n        for nested_element in parameter.iterate_through_definitions():\n            (\n                non_compound_parameter_value,\n                non_compound_indices,\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=nested_element,\n                step_execution_dimensionality=step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n            result.append(non_compound_parameter_value)\n            contains_empty_scalar_step_output_selector = (\n                contains_empty_scalar_step_output_selector\n                or value_contains_empty_scalar_step_output_selector\n            )\n            if non_compound_indices is not None:\n                batch_indices.append(non_compound_indices)\n    else:\n        result = {}\n        for nested_element in parameter.iterate_through_definitions():\n            (\n                non_compound_parameter_value,\n                non_compound_indices,\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=nested_element,\n                step_execution_dimensionality=step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n            result[nested_element.parameter_specification.nested_element_key] = (\n                non_compound_parameter_value\n            )\n            contains_empty_scalar_step_output_selector = (\n                contains_empty_scalar_step_output_selector\n                or value_contains_empty_scalar_step_output_selector\n            )\n            if non_compound_indices is not None:\n                batch_indices.append(non_compound_indices)\n    ensure_compound_input_indices_match(indices=batch_indices)\n    result_indices = None\n    if len(batch_indices) > 0:\n        result_indices = batch_indices[0]\n    return result, result_indices, contains_empty_scalar_step_output_selector\n\n\ndef get_non_compound_parameter_value(\n    parameter: StepInputDefinition,\n    step_execution_dimensionality: int,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n    dynamic_batches_manager: DynamicBatchesManager,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n    auto_batch_casting_lineage_supports: Dict[str, AutoBatchCastingConfig],\n    step_requests_batch_input: bool,\n) -> Tuple[Any, Optional[List[DynamicBatchIndex]], bool]:\n    if not parameter.is_batch_oriented():\n        requested_as_batch = (\n            parameter.parameter_specification.parameter_name\n            in auto_batch_casting_lineage_supports\n        )\n        if parameter.points_to_input():\n            input_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n            parameter_name = get_last_chunk_of_selector(\n                selector=input_parameter.selector\n            )\n            if not requested_as_batch:\n                return runtime_parameters[parameter_name], None, False\n            else:\n                return apply_auto_batch_casting(\n                    parameter_name=parameter_name,\n                    value=runtime_parameters[parameter_name],\n                    auto_batch_casting_config=auto_batch_casting_lineage_supports[\n                        parameter.parameter_specification.parameter_name\n                    ],\n                    contains_empty_scalar_step_output_selector=False,\n                    dynamic_batches_manager=dynamic_batches_manager,\n                    step_execution_dimensionality=step_execution_dimensionality,\n                    guard_of_indices_wrapping=guard_of_indices_wrapping,\n                    step_requests_batch_input=step_requests_batch_input,\n                    masks=masks,\n                    scalars_discarded=False,\n                )\n        elif parameter.points_to_step_output():\n            input_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n            value = execution_cache.get_non_batch_output(\n                selector=input_parameter.selector\n            )\n            if not requested_as_batch:\n                return value, None, value is None\n            else:\n                return apply_auto_batch_casting(\n                    parameter_name=parameter.parameter_specification.parameter_name,\n                    value=value,\n                    auto_batch_casting_config=auto_batch_casting_lineage_supports[\n                        parameter.parameter_specification.parameter_name\n                    ],\n                    contains_empty_scalar_step_output_selector=value is None,\n                    dynamic_batches_manager=dynamic_batches_manager,\n                    step_execution_dimensionality=step_execution_dimensionality,\n                    guard_of_indices_wrapping=guard_of_indices_wrapping,\n                    step_requests_batch_input=step_requests_batch_input,\n                    masks=masks,\n                    scalars_discarded=scalars_discarded,\n                )\n        else:\n            static_input: StaticStepInputDefinition = parameter  # type: ignore\n            if not requested_as_batch or static_input.value is None:\n                # when we have Optional[Selector()] in manifest - we must retain\n                # ability to inject None into the run(...) parameters - as\n                # if we treat that as actual batch and broadcast Batch[None],\n                # we would behave exactly as condition execution does -\n                # and the logic executing after this, will filter-out empty\n                # elements - so on None, we behave \"the old way\" regardless of the fact that ABC\n                # was requested\n                return static_input.value, None, False\n            else:\n                return apply_auto_batch_casting(\n                    parameter_name=parameter.parameter_specification.parameter_name,\n                    value=static_input.value,\n                    auto_batch_casting_config=auto_batch_casting_lineage_supports[\n                        parameter.parameter_specification.parameter_name\n                    ],\n                    contains_empty_scalar_step_output_selector=False,\n                    dynamic_batches_manager=dynamic_batches_manager,\n                    step_execution_dimensionality=step_execution_dimensionality,\n                    guard_of_indices_wrapping=guard_of_indices_wrapping,\n                    step_requests_batch_input=step_requests_batch_input,\n                    masks=masks,\n                    scalars_discarded=False,\n                )\n    dynamic_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n    parameter_dimensionality = dynamic_parameter.get_dimensionality()\n    lineage_indices = dynamic_batches_manager.get_indices_for_data_lineage(\n        lineage=dynamic_parameter.data_lineage,\n    )\n    mask_for_dimension = masks[parameter_dimensionality]\n    if dynamic_parameter.points_to_input():\n        input_name = get_last_chunk_of_selector(selector=dynamic_parameter.selector)\n        batch_input = _flatten_batch_oriented_inputs(\n            runtime_parameters[input_name],\n            dimensionality=parameter_dimensionality,\n        )\n        if mask_for_dimension is not None:\n            if len(lineage_indices) != len(batch_input):\n                raise ExecutionEngineRuntimeError(\n                    public_message=f\"Detected a situation when input parameter: \"\n                    f\"{input_name}\"\n                    f\"size is mismatched compared to mask requested for that input. \"\n                    f\"Input length: {len(batch_input)}, mask size: {len(lineage_indices)}. \"\n                    f\"This is most likely a bug. \"\n                    f\"Contact Roboflow team through github issues \"\n                    f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                    f\"the problem - including workflow definition you use.\",\n                    context=\"workflow_execution | step_input_assembling\",\n                )\n            batch_input = [\n                input_element if element_index in mask_for_dimension else None\n                for element_index, input_element in zip(lineage_indices, batch_input)\n            ]\n    else:\n        batch_input = execution_cache.get_batch_output(\n            selector=dynamic_parameter.selector,\n            batch_elements_indices=lineage_indices,\n            mask=mask_for_dimension,\n        )\n    if step_execution_dimensionality == parameter_dimensionality:\n        return Batch(batch_input, lineage_indices), lineage_indices, False\n    if step_execution_dimensionality > parameter_dimensionality:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter.parameter_specification.parameter_name}\"\n            f\"has a dimensionality {parameter_dimensionality} larger \"\n            f\"than step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if abs(parameter_dimensionality - step_execution_dimensionality) > 1:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter.parameter_specification.parameter_name}\"\n            f\"has a dimensionality {parameter_dimensionality} differing more than one level \"\n            f\"from step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if step_execution_dimensionality == 0 and not step_requests_batch_input:\n        return Batch(batch_input, lineage_indices), lineage_indices, False\n    upper_lineage = dynamic_parameter.data_lineage[:-1]\n    if len(upper_lineage) == 0:\n        if not step_requests_batch_input:\n            raise AssumptionError(\n                public_message=f\"Parameter: {parameter.parameter_specification.parameter_name} \"\n                f\"requires dimensionality wrapping, but registered lineage support is incompatible \"\n                f\"which should be detected by the compiler. This is most likely a bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n        upper_level_indices = [()]\n    else:\n        upper_level_indices = dynamic_batches_manager.get_indices_for_data_lineage(\n            lineage=dynamic_parameter.data_lineage[:-1],\n        )\n    result = reduce_batch_dimensionality(\n        indices=lineage_indices,\n        upper_level_index=upper_level_indices,\n        data=batch_input,\n        guard_of_indices_wrapping=guard_of_indices_wrapping,\n    )\n    return result, result.indices, False\n\n\ndef ensure_compound_input_indices_match(indices: List[List[DynamicBatchIndex]]) -> None:\n    if len(indices) < 2:\n        return None\n    reference_set = set(indices[0])\n    for index in indices[1:]:\n        other_set = set(index)\n        if reference_set != other_set:\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Detected a situation when step input parameters cannot be created \"\n                f\"due to missmatch in batch element indices. This is most likely a bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n\n\ndef get_empty_batch_elements_indices(value: Any) -> Set[DynamicBatchIndex]:\n    result = set()\n    if isinstance(value, dict):\n        for v in value.values():\n            value_result = get_empty_batch_elements_indices(v)\n            result = result.union(value_result)\n    if isinstance(value, list):\n        for v in value:\n            value_result = get_empty_batch_elements_indices(v)\n            result = result.union(value_result)\n    if isinstance(value, Batch):\n        for index, value_element in value.iter_with_indices():\n            if isinstance(value_element, Batch):\n                value_result = get_empty_batch_elements_indices(value=value_element)\n                result = result.union(value_result)\n            elif value_element is None:\n                result.add(index)\n    return result\n\n\ndef remove_indices(value: Any, indices: Set[DynamicBatchIndex]) -> Any:\n    if isinstance(value, dict):\n        return {k: remove_indices(value=v, indices=indices) for k, v in value.items()}\n    if isinstance(value, list):\n        return [remove_indices(value=v, indices=indices) for v in value]\n    if isinstance(value, Batch):\n        return value.remove_by_indices(indices_to_remove=indices)\n    return value",
    "patch": null
  },
  {
    "trace_id": "506de95f-ee69-4567-9fee-cf2f1bba8f2d",
    "function_name": "_generate_grid_colors",
    "file_path": "inference/core/interfaces/camera/test_pattern_producer.py",
    "speedup_x": 217.2971048177145,
    "review_quality": "high",
    "pre_optimization_commit": "be557aac76928908f189d4366f62bf9b5433ef2f",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def _generate_grid_colors(seed: int) -> np.ndarray:\n    rng = np.random.RandomState(seed)\n    return rng.randint(40, 220, size=(GRID_ROWS, GRID_COLS, 3), dtype=np.uint8)\n",
    "optimized_function_code": "from typing import Dict\n\nimport numpy as np\n\nGRID_COLS = 16\nGRID_ROWS = 9\n\n\n\n# Module-level cache mapping seed -> read-only numpy array of generated colors.\n_CACHE: Dict[int, np.ndarray] = {}\n\n\ndef _generate_grid_colors(seed: int) -> np.ndarray:\n    rng = None\n    # Fast path: return a copy of a cached array if available.\n    cached = _CACHE.get(seed)\n    if cached is not None:\n        return cached.copy()\n\n    # Slow path: create RandomState once for this seed, generate array, cache it as read-only,\n    # and return a copy to preserve the original behavior of returning a new array each call.\n    rng = np.random.RandomState(seed)\n    arr = rng.randint(40, 220, size=(GRID_ROWS, GRID_COLS, 3), dtype=np.uint8)\n    arr.setflags(write=False)\n    _CACHE[seed] = arr\n    return arr.copy()",
    "optimized_raw_markdown": "```python:inference/core/interfaces/camera/test_pattern_producer.py\nfrom typing import Dict\n\nimport numpy as np\n\nGRID_COLS = 16\nGRID_ROWS = 9\n\n\n\n# Module-level cache mapping seed -> read-only numpy array of generated colors.\n_CACHE: Dict[int, np.ndarray] = {}\n\n\ndef _generate_grid_colors(seed: int) -> np.ndarray:\n    rng = None\n    # Fast path: return a copy of a cached array if available.\n    cached = _CACHE.get(seed)\n    if cached is not None:\n        return cached.copy()\n\n    # Slow path: create RandomState once for this seed, generate array, cache it as read-only,\n    # and return a copy to preserve the original behavior of returning a new array each call.\n    rng = np.random.RandomState(seed)\n    arr = rng.randint(40, 220, size=(GRID_ROWS, GRID_COLS, 3), dtype=np.uint8)\n    arr.setflags(write=False)\n    _CACHE[seed] = arr\n    return arr.copy()\n```",
    "optimized_function_only": "def _generate_grid_colors(seed: int) -> np.ndarray:\n    rng = None\n    # Fast path: return a copy of a cached array if available.\n    cached = _CACHE.get(seed)\n    if cached is not None:\n        return cached.copy()\n\n    # Slow path: create RandomState once for this seed, generate array, cache it as read-only,\n    # and return a copy to preserve the original behavior of returning a new array each call.\n    rng = np.random.RandomState(seed)\n    arr = rng.randint(40, 220, size=(GRID_ROWS, GRID_COLS, 3), dtype=np.uint8)\n    arr.setflags(write=False)\n    _CACHE[seed] = arr\n    return arr.copy()",
    "original_file_content": "import threading\nimport time\nfrom datetime import datetime\nfrom typing import Dict, Optional, Tuple\n\nimport cv2\nimport numpy as np\n\nfrom inference.core.interfaces.camera.entities import (\n    SourceProperties,\n    VideoFrameProducer,\n)\n\nWIDTH = 1920\nHEIGHT = 1080\nFPS = 10\nGRID_COLS = 16\nGRID_ROWS = 9\nBORDER_PX = 5\nCOLOR_SHUFFLE_INTERVAL = 5.0\n\n\ndef _generate_grid_colors(seed: int) -> np.ndarray:\n    rng = np.random.RandomState(seed)\n    return rng.randint(40, 220, size=(GRID_ROWS, GRID_COLS, 3), dtype=np.uint8)\n\n\ndef _draw_color_grid(frame: np.ndarray, colors: np.ndarray) -> None:\n    cell_w = WIDTH // GRID_COLS\n    cell_h = HEIGHT // GRID_ROWS\n    for row in range(GRID_ROWS):\n        for col in range(GRID_COLS):\n            x1 = col * cell_w + BORDER_PX\n            y1 = row * cell_h + BORDER_PX\n            x2 = (col + 1) * cell_w - BORDER_PX\n            y2 = (row + 1) * cell_h - BORDER_PX\n            color = tuple(int(c) for c in colors[row, col])\n            cv2.rectangle(frame, (x1, y1), (x2, y2), color, -1)\n\n\ndef _draw_outlined_text(\n    frame: np.ndarray,\n    text: str,\n    center_x: int,\n    center_y: int,\n    font_scale: float,\n    thickness: int,\n    outline: int,\n) -> None:\n    font = cv2.FONT_HERSHEY_DUPLEX\n    (tw, th), _ = cv2.getTextSize(text, font, font_scale, thickness)\n    x = center_x - tw // 2\n    y = center_y + th // 2\n    cv2.putText(\n        frame,\n        text,\n        (x, y),\n        font,\n        font_scale,\n        (0, 0, 0),\n        thickness + outline,\n        cv2.LINE_AA,\n    )\n    cv2.putText(\n        frame, text, (x, y), font, font_scale, (255, 255, 255), thickness, cv2.LINE_AA\n    )\n\n\ndef _draw_fixed_width_time(\n    frame: np.ndarray,\n    time_str: str,\n    center_x: int,\n    center_y: int,\n    font_scale: float,\n    thickness: int,\n    outline: int,\n) -> None:\n    font = cv2.FONT_HERSHEY_DUPLEX\n    (char_w, _), _ = cv2.getTextSize(\"0\", font, font_scale, thickness)\n    slot_w = int(char_w * 1.15)\n    total_w = slot_w * len(time_str)\n    start_x = center_x - total_w // 2\n\n    for i, ch in enumerate(time_str):\n        cx = start_x + i * slot_w + slot_w // 2\n        if ch == \":\":\n            _draw_outlined_text(frame, ch, cx, center_y, font_scale, thickness, outline)\n        else:\n            _draw_outlined_text(frame, ch, cx, center_y, font_scale, thickness, outline)\n\n\ndef generate_frame(now: Optional[datetime] = None) -> np.ndarray:\n    if now is None:\n        now = datetime.now()\n    frame = np.zeros((HEIGHT, WIDTH, 3), dtype=np.uint8)\n\n    color_seed = int(time.time() / COLOR_SHUFFLE_INTERVAL)\n    colors = _generate_grid_colors(color_seed)\n    _draw_color_grid(frame, colors)\n\n    time_str = now.strftime(\"%H:%M:%S\")\n    date_str = now.strftime(\"%Y-%m-%d\")\n\n    time_scale = 4.0\n    date_scale = 1.5\n    time_thickness = 6\n    date_thickness = 2\n    outline = 20\n\n    cx = WIDTH // 2\n    time_cy = HEIGHT // 2 - int(HEIGHT * 0.04)\n    _draw_fixed_width_time(\n        frame, time_str, cx, time_cy, time_scale, time_thickness, outline\n    )\n\n    font = cv2.FONT_HERSHEY_DUPLEX\n    (_, time_h), _ = cv2.getTextSize(\"0\", font, time_scale, time_thickness)\n    date_cy = time_cy + time_h + int(HEIGHT * 0.06)\n    _draw_outlined_text(\n        frame, date_str, cx, date_cy, date_scale, date_thickness, outline\n    )\n\n    return frame\n\n\nclass _SharedGenerator:\n    def __init__(self):\n        self._lock = threading.Lock()\n        self._frame: Optional[np.ndarray] = None\n        self._running = False\n        self._thread: Optional[threading.Thread] = None\n        self._ref_count = 0\n\n    def acquire(self) -> None:\n        with self._lock:\n            self._ref_count += 1\n            if not self._running:\n                self._running = True\n                self._thread = threading.Thread(target=self._loop, daemon=True)\n                self._thread.start()\n\n    def release(self) -> None:\n        with self._lock:\n            self._ref_count = max(0, self._ref_count - 1)\n            if self._ref_count == 0:\n                self._running = False\n\n    @property\n    def frame(self) -> Optional[np.ndarray]:\n        return self._frame\n\n    def _loop(self) -> None:\n        interval = 1.0 / FPS\n        while self._running:\n            self._frame = generate_frame()\n            time.sleep(interval)\n        self._frame = None\n\n\n_shared = _SharedGenerator()\n\n\nclass TestPatternStreamProducer(VideoFrameProducer):\n\n    def __init__(self):\n        self._opened = False\n\n    def grab(self) -> bool:\n        return self._opened and _shared.frame is not None\n\n    def retrieve(self) -> Tuple[bool, Optional[np.ndarray]]:\n        f = _shared.frame\n        if f is None:\n            return False, None\n        return True, f.copy()\n\n    def release(self) -> None:\n        if self._opened:\n            _shared.release()\n            self._opened = False\n\n    def isOpened(self) -> bool:\n        if not self._opened:\n            _shared.acquire()\n            self._opened = True\n            for _ in range(50):\n                if _shared.frame is not None:\n                    break\n                time.sleep(0.05)\n        return self._opened\n\n    def discover_source_properties(self) -> SourceProperties:\n        return SourceProperties(\n            width=WIDTH,\n            height=HEIGHT,\n            total_frames=-1,\n            is_file=False,\n            fps=float(FPS),\n            is_reconnectable=True,\n        )\n\n    def initialize_source_properties(self, properties: Dict[str, float]) -> None:\n        pass\n\n\nif __name__ == \"__main__\":\n    frame = generate_frame()\n    out_path = \"test_pattern_preview.png\"\n    cv2.imwrite(out_path, frame)\n    print(f\"Saved preview frame to {out_path} ({frame.shape[1]}x{frame.shape[0]})\")\n",
    "patch": null
  },
  {
    "trace_id": "48c10dfe-3820-41a5-8261-5a2e9833d3a2",
    "function_name": "RoboflowSemanticSegmentationModelBlockV1._convert_to_sv_detections",
    "file_path": "inference/core/workflows/core_steps/models/roboflow/semantic_segmentation/v1.py",
    "speedup_x": 1.2223439061498738,
    "review_quality": "high",
    "pre_optimization_commit": "HEAD",
    "resolution_method": "db_code_only",
    "source": "db_features",
    "original_function_code": "    def _convert_to_sv_detections(predictions_dict: Dict) -> sv.Detections:\n        seg_mask_b64 = predictions_dict.get(\"segmentation_mask\", \"\")\n        conf_mask_b64 = predictions_dict.get(\"confidence_mask\", \"\")\n        class_map: Dict[str, str] = predictions_dict.get(\"class_map\", {})\n\n        mask_bytes = base64.b64decode(seg_mask_b64)\n        nparr = np.frombuffer(mask_bytes, np.uint8)\n        mask_array = cv2.imdecode(nparr, cv2.IMREAD_GRAYSCALE)\n\n        if mask_array is None:\n            return sv.Detections.empty()\n\n        unique_class_ids = [cid for cid in np.unique(mask_array).tolist() if cid != 0]\n        if not unique_class_ids:\n            return sv.Detections.empty()\n\n        conf_array = None\n        if conf_mask_b64:\n            conf_bytes = base64.b64decode(conf_mask_b64)\n            conf_nparr = np.frombuffer(conf_bytes, np.uint8)\n            conf_array = cv2.imdecode(conf_nparr, cv2.IMREAD_GRAYSCALE)\n\n        xyxy_list, masks_list, class_id_list, class_name_list, confidence_list = (\n            [],\n            [],\n            [],\n            [],\n            [],\n        )\n        for class_id in unique_class_ids:\n            binary_mask = mask_array == class_id\n            rows = np.where(np.any(binary_mask, axis=1))[0]\n            cols = np.where(np.any(binary_mask, axis=0))[0]\n            xyxy_list.append([cols[0], rows[0], cols[-1], rows[-1]])\n            masks_list.append(binary_mask)\n            class_id_list.append(class_id)\n            class_name_list.append(class_map.get(str(class_id), str(class_id)))\n            if conf_array is not None:\n                confidence_list.append(float(conf_array[binary_mask].mean()) / 255.0)\n            else:\n                confidence_list.append(1.0)\n\n        detection_ids = np.array([str(uuid4()) for _ in class_id_list])\n        result = sv.Detections(\n            xyxy=np.array(xyxy_list, dtype=np.float64),\n            mask=np.array(masks_list, dtype=bool),\n            class_id=np.array(class_id_list),\n            confidence=np.array(confidence_list, dtype=np.float32),\n            data={\n                \"class_name\": np.array(class_name_list),\n                DETECTION_ID_KEY: detection_ids,\n            },\n        )\n\n        if conf_array is not None:\n            result[\"confidence_mask\"] = conf_array\n\n        return result",
    "optimized_function_code": "import base64\nimport cv2\nimport numpy as np\nimport supervision as sv\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.entities import StepExecutionMode\nfrom inference.core.workflows.execution_engine.constants import DETECTION_ID_KEY\nfrom inference.core.workflows.prototypes.block import WorkflowBlock\nfrom typing import Dict, Optional\nfrom uuid import uuid4\n\n\nclass RoboflowSemanticSegmentationModelBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    @staticmethod\n    def _convert_to_sv_detections(predictions_dict: Dict) -> sv.Detections:\n        seg_mask_b64 = predictions_dict.get(\"segmentation_mask\", \"\")\n        conf_mask_b64 = predictions_dict.get(\"confidence_mask\", \"\")\n        class_map: Dict[str, str] = predictions_dict.get(\"class_map\", {})\n\n        mask_bytes = base64.b64decode(seg_mask_b64)\n        nparr = np.frombuffer(mask_bytes, np.uint8)\n        mask_array = cv2.imdecode(nparr, cv2.IMREAD_GRAYSCALE)\n\n        if mask_array is None:\n            return sv.Detections.empty()\n\n        unique_class_ids = [cid for cid in np.unique(mask_array).tolist() if cid != 0]\n        if not unique_class_ids:\n            return sv.Detections.empty()\n\n        conf_array = None\n        if conf_mask_b64:\n            conf_bytes = base64.b64decode(conf_mask_b64)\n            conf_nparr = np.frombuffer(conf_bytes, np.uint8)\n            conf_array = cv2.imdecode(conf_nparr, cv2.IMREAD_GRAYSCALE)\n\n        xyxy_list, masks_list, class_id_list, class_name_list, confidence_list = (\n            [],\n            [],\n            [],\n            [],\n            [],\n        )\n\n        for class_id in unique_class_ids:\n            mask_uint8 = (mask_array == class_id).astype(np.uint8)\n\n            # Compute bounding box using OpenCV (C-level) instead of Python-level row/col scans\n            x, y, w, h = cv2.boundingRect(mask_uint8)\n            # boundingRect gives width/height; original code used inclusive indices\n            xyxy_list.append([x, y, x + w - 1, y + h - 1])\n\n            # Store boolean mask (preserve original dtype expectation)\n            masks_list.append(mask_uint8.astype(bool))\n\n            class_id_list.append(class_id)\n            class_name_list.append(class_map.get(str(class_id), str(class_id)))\n            if conf_array is not None:\n                # Use cv2.mean with mask to compute masked mean in C (faster than indexing)\n                mean_val = float(cv2.mean(conf_array, mask=mask_uint8)[0])\n                confidence_list.append(mean_val / 255.0)\n            else:\n                confidence_list.append(1.0)\n\n        detection_ids = np.array([str(uuid4()) for _ in class_id_list])\n        result = sv.Detections(\n            xyxy=np.array(xyxy_list, dtype=np.float64),\n            mask=np.array(masks_list, dtype=bool),\n            class_id=np.array(class_id_list),\n            confidence=np.array(confidence_list, dtype=np.float32),\n            data={\n                \"class_name\": np.array(class_name_list),\n                DETECTION_ID_KEY: detection_ids,\n            },\n        )\n\n        if conf_array is not None:\n            result[\"confidence_mask\"] = conf_array\n\n        return result",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/models/roboflow/semantic_segmentation/v1.py\nimport base64\nimport cv2\nimport numpy as np\nimport supervision as sv\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.entities import StepExecutionMode\nfrom inference.core.workflows.execution_engine.constants import DETECTION_ID_KEY\nfrom inference.core.workflows.prototypes.block import WorkflowBlock\nfrom typing import Dict, Optional\nfrom uuid import uuid4\n\n\nclass RoboflowSemanticSegmentationModelBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    @staticmethod\n    def _convert_to_sv_detections(predictions_dict: Dict) -> sv.Detections:\n        seg_mask_b64 = predictions_dict.get(\"segmentation_mask\", \"\")\n        conf_mask_b64 = predictions_dict.get(\"confidence_mask\", \"\")\n        class_map: Dict[str, str] = predictions_dict.get(\"class_map\", {})\n\n        mask_bytes = base64.b64decode(seg_mask_b64)\n        nparr = np.frombuffer(mask_bytes, np.uint8)\n        mask_array = cv2.imdecode(nparr, cv2.IMREAD_GRAYSCALE)\n\n        if mask_array is None:\n            return sv.Detections.empty()\n\n        unique_class_ids = [cid for cid in np.unique(mask_array).tolist() if cid != 0]\n        if not unique_class_ids:\n            return sv.Detections.empty()\n\n        conf_array = None\n        if conf_mask_b64:\n            conf_bytes = base64.b64decode(conf_mask_b64)\n            conf_nparr = np.frombuffer(conf_bytes, np.uint8)\n            conf_array = cv2.imdecode(conf_nparr, cv2.IMREAD_GRAYSCALE)\n\n        xyxy_list, masks_list, class_id_list, class_name_list, confidence_list = (\n            [],\n            [],\n            [],\n            [],\n            [],\n        )\n\n        for class_id in unique_class_ids:\n            mask_uint8 = (mask_array == class_id).astype(np.uint8)\n\n            # Compute bounding box using OpenCV (C-level) instead of Python-level row/col scans\n            x, y, w, h = cv2.boundingRect(mask_uint8)\n            # boundingRect gives width/height; original code used inclusive indices\n            xyxy_list.append([x, y, x + w - 1, y + h - 1])\n\n            # Store boolean mask (preserve original dtype expectation)\n            masks_list.append(mask_uint8.astype(bool))\n\n            class_id_list.append(class_id)\n            class_name_list.append(class_map.get(str(class_id), str(class_id)))\n            if conf_array is not None:\n                # Use cv2.mean with mask to compute masked mean in C (faster than indexing)\n                mean_val = float(cv2.mean(conf_array, mask=mask_uint8)[0])\n                confidence_list.append(mean_val / 255.0)\n            else:\n                confidence_list.append(1.0)\n\n        detection_ids = np.array([str(uuid4()) for _ in class_id_list])\n        result = sv.Detections(\n            xyxy=np.array(xyxy_list, dtype=np.float64),\n            mask=np.array(masks_list, dtype=bool),\n            class_id=np.array(class_id_list),\n            confidence=np.array(confidence_list, dtype=np.float32),\n            data={\n                \"class_name\": np.array(class_name_list),\n                DETECTION_ID_KEY: detection_ids,\n            },\n        )\n\n        if conf_array is not None:\n            result[\"confidence_mask\"] = conf_array\n\n        return result\n```",
    "optimized_function_only": "    def _convert_to_sv_detections(predictions_dict: Dict) -> sv.Detections:\n        seg_mask_b64 = predictions_dict.get(\"segmentation_mask\", \"\")\n        conf_mask_b64 = predictions_dict.get(\"confidence_mask\", \"\")\n        class_map: Dict[str, str] = predictions_dict.get(\"class_map\", {})\n\n        mask_bytes = base64.b64decode(seg_mask_b64)\n        nparr = np.frombuffer(mask_bytes, np.uint8)\n        mask_array = cv2.imdecode(nparr, cv2.IMREAD_GRAYSCALE)\n\n        if mask_array is None:\n            return sv.Detections.empty()\n\n        unique_class_ids = [cid for cid in np.unique(mask_array).tolist() if cid != 0]\n        if not unique_class_ids:\n            return sv.Detections.empty()\n\n        conf_array = None\n        if conf_mask_b64:\n            conf_bytes = base64.b64decode(conf_mask_b64)\n            conf_nparr = np.frombuffer(conf_bytes, np.uint8)\n            conf_array = cv2.imdecode(conf_nparr, cv2.IMREAD_GRAYSCALE)\n\n        xyxy_list, masks_list, class_id_list, class_name_list, confidence_list = (\n            [],\n            [],\n            [],\n            [],\n            [],\n        )\n\n        for class_id in unique_class_ids:\n            mask_uint8 = (mask_array == class_id).astype(np.uint8)\n\n            # Compute bounding box using OpenCV (C-level) instead of Python-level row/col scans\n            x, y, w, h = cv2.boundingRect(mask_uint8)\n            # boundingRect gives width/height; original code used inclusive indices\n            xyxy_list.append([x, y, x + w - 1, y + h - 1])\n\n            # Store boolean mask (preserve original dtype expectation)\n            masks_list.append(mask_uint8.astype(bool))\n\n            class_id_list.append(class_id)\n            class_name_list.append(class_map.get(str(class_id), str(class_id)))\n            if conf_array is not None:\n                # Use cv2.mean with mask to compute masked mean in C (faster than indexing)\n                mean_val = float(cv2.mean(conf_array, mask=mask_uint8)[0])\n                confidence_list.append(mean_val / 255.0)\n            else:\n                confidence_list.append(1.0)\n\n        detection_ids = np.array([str(uuid4()) for _ in class_id_list])\n        result = sv.Detections(\n            xyxy=np.array(xyxy_list, dtype=np.float64),\n            mask=np.array(masks_list, dtype=bool),\n            class_id=np.array(class_id_list),\n            confidence=np.array(confidence_list, dtype=np.float32),\n            data={\n                \"class_name\": np.array(class_name_list),\n                DETECTION_ID_KEY: detection_ids,\n            },\n        )\n\n        if conf_array is not None:\n            result[\"confidence_mask\"] = conf_array\n\n        return result",
    "original_file_content": "import base64\nimport cv2\nimport numpy as np\nimport supervision as sv\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.workflows.core_steps.common.entities import StepExecutionMode\nfrom inference.core.workflows.execution_engine.constants import DETECTION_ID_KEY\nfrom inference.core.workflows.prototypes.block import WorkflowBlock\nfrom typing import Dict, Optional\nfrom uuid import uuid4\n\nclass RoboflowSemanticSegmentationModelBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n        step_execution_mode: StepExecutionMode,\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n        self._step_execution_mode = step_execution_mode\n\n    @staticmethod\n    def _convert_to_sv_detections(predictions_dict: Dict) -> sv.Detections:\n        seg_mask_b64 = predictions_dict.get(\"segmentation_mask\", \"\")\n        conf_mask_b64 = predictions_dict.get(\"confidence_mask\", \"\")\n        class_map: Dict[str, str] = predictions_dict.get(\"class_map\", {})\n\n        mask_bytes = base64.b64decode(seg_mask_b64)\n        nparr = np.frombuffer(mask_bytes, np.uint8)\n        mask_array = cv2.imdecode(nparr, cv2.IMREAD_GRAYSCALE)\n\n        if mask_array is None:\n            return sv.Detections.empty()\n\n        unique_class_ids = [cid for cid in np.unique(mask_array).tolist() if cid != 0]\n        if not unique_class_ids:\n            return sv.Detections.empty()\n\n        conf_array = None\n        if conf_mask_b64:\n            conf_bytes = base64.b64decode(conf_mask_b64)\n            conf_nparr = np.frombuffer(conf_bytes, np.uint8)\n            conf_array = cv2.imdecode(conf_nparr, cv2.IMREAD_GRAYSCALE)\n\n        xyxy_list, masks_list, class_id_list, class_name_list, confidence_list = (\n            [],\n            [],\n            [],\n            [],\n            [],\n        )\n        for class_id in unique_class_ids:\n            binary_mask = mask_array == class_id\n            rows = np.where(np.any(binary_mask, axis=1))[0]\n            cols = np.where(np.any(binary_mask, axis=0))[0]\n            xyxy_list.append([cols[0], rows[0], cols[-1], rows[-1]])\n            masks_list.append(binary_mask)\n            class_id_list.append(class_id)\n            class_name_list.append(class_map.get(str(class_id), str(class_id)))\n            if conf_array is not None:\n                confidence_list.append(float(conf_array[binary_mask].mean()) / 255.0)\n            else:\n                confidence_list.append(1.0)\n\n        detection_ids = np.array([str(uuid4()) for _ in class_id_list])\n        result = sv.Detections(\n            xyxy=np.array(xyxy_list, dtype=np.float64),\n            mask=np.array(masks_list, dtype=bool),\n            class_id=np.array(class_id_list),\n            confidence=np.array(confidence_list, dtype=np.float32),\n            data={\n                \"class_name\": np.array(class_name_list),\n                DETECTION_ID_KEY: detection_ids,\n            },\n        )\n\n        if conf_array is not None:\n            result[\"confidence_mask\"] = conf_array\n\n        return result",
    "patch": null
  },
  {
    "trace_id": "199ed8b8-635a-4ac9-8ca7-832cb6a65dd6",
    "function_name": "WithFixedSizeCache.add_model",
    "file_path": "inference/core/managers/decorators/fixed_size_cache.py",
    "speedup_x": 0.16769860050011387,
    "review_quality": "high",
    "pre_optimization_commit": "c692969e494714fbbb6ba8563429b32dd54fb8a5",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def add_model(\n        self,\n        model_id: str,\n        api_key: str,\n        model_id_alias: Optional[str] = None,\n        endpoint_type: ModelEndpointType = ModelEndpointType.ORT,\n        countinference: Optional[bool] = None,\n        service_secret: Optional[str] = None,\n    ) -> None:\n        \"\"\"Adds a model to the manager and evicts the least recently used if the cache is full.\n\n        Args:\n            model_id (str): The identifier of the model.\n            model (Model): The model instance.\n            endpoint_type (ModelEndpointType, optional): The endpoint type to use for the model.\n        \"\"\"\n        if MODELS_CACHE_AUTH_ENABLED:\n            if not _check_if_api_key_has_access_to_model(\n                api_key=api_key,\n                model_id=model_id,\n                endpoint_type=endpoint_type,\n                countinference=countinference,\n                service_secret=service_secret,\n            ):\n                raise RoboflowAPINotAuthorizedError(\n                    f\"API key {api_key} does not have access to model {model_id}\"\n                )\n\n        queue_id = self._resolve_queue_id(\n            model_id=model_id, model_id_alias=model_id_alias\n        )\n        if queue_id in self:\n            logger.debug(\n                f\"Detected {queue_id} in WithFixedSizeCache models queue -> marking as most recently used.\"\n            )\n            self._refresh_model_position_in_a_queue(model_id=queue_id)\n            return None\n\n        logger.debug(f\"Current capacity of ModelManager: {len(self)}/{self.max_size}\")\n        with acquire_with_timeout(\n            lock=self._queue_lock, timeout=HOT_MODELS_QUEUE_LOCK_ACQUIRE_TIMEOUT\n        ) as acquired:\n            if not acquired:\n                raise ModelManagerLockAcquisitionError(\n                    \"Could not acquire lock on Model Manager state to add model from active models queue.\"\n                )\n            while self._key_queue and (\n                len(self) >= self.max_size\n                or (MEMORY_FREE_THRESHOLD and self.memory_pressure_detected())\n            ):\n                # To prevent flapping around the threshold, remove up to 3 models to make some space.\n                evicted_count = 0\n                skipped_pinned = []\n                for _ in range(3):\n                    if not self._key_queue:\n                        logger.error(\n                            \"Tried to remove model from cache even though key queue is already empty!\"\n                            \"(max_size: %s, len(self): %s, MEMORY_FREE_THRESHOLD: %s)\",\n                            self.max_size,\n                            len(self),\n                            MEMORY_FREE_THRESHOLD,\n                        )\n                        break\n                    to_remove_model_id = self._key_queue.popleft()\n                    if to_remove_model_id in self._pinned_models:\n                        skipped_pinned.append(to_remove_model_id)\n                        continue\n                    super().remove(\n                        to_remove_model_id, delete_from_disk=DISK_CACHE_CLEANUP\n                    )  # LRU model overflow cleanup may or maynot need the weights removed from disk\n                    logger.debug(f\"Model {to_remove_model_id} successfully unloaded.\")\n                    evicted_count += 1\n                # Put pinned models back at the front of the queue\n                for mid in reversed(skipped_pinned):\n                    self._key_queue.appendleft(mid)\n                if evicted_count == 0:\n                    logger.warning(\n                        \"Cannot free model cache space \u2014 all remaining models are pinned (preloaded). \"\n                        \"Proceeding with cache exceeding max_size.\"\n                    )\n                    break\n                gc.collect()\n            logger.debug(f\"Marking new model {queue_id} as most recently used.\")\n            self._key_queue.append(queue_id)\n        try:\n            return super().add_model(\n                model_id,\n                api_key,\n                model_id_alias=model_id_alias,\n                endpoint_type=endpoint_type,\n                countinference=countinference,\n                service_secret=service_secret,\n            )\n        except Exception as error:\n            logger.debug(\n                f\"Could not initialise model {queue_id}. Removing from WithFixedSizeCache models queue.\"\n            )\n            with acquire_with_timeout(\n                lock=self._queue_lock, timeout=HOT_MODELS_QUEUE_LOCK_ACQUIRE_TIMEOUT\n            ) as acquired:\n                if not acquired:\n                    raise ModelManagerLockAcquisitionError(\n                        \"Could not acquire lock on Model Manager state to remove model from active models queue.\"\n                    )\n                self._safe_remove_model_from_queue(queue_id)\n            raise error\n",
    "optimized_function_code": "from typing import Optional\n\nfrom cachetools.func import ttl_cache\nfrom inference.core.devices.utils import GLOBAL_DEVICE_ID\nfrom inference.core.env import (MODELS_CACHE_AUTH_CACHE_MAX_SIZE,\n                                MODELS_CACHE_AUTH_CACHE_TTL)\nfrom inference.core.exceptions import RoboflowAPINotAuthorizedError\nfrom inference.core.roboflow_api import (ModelEndpointType,\n                                         get_roboflow_instant_model_data,\n                                         get_roboflow_model_data)\nfrom inference.core.utils.roboflow import get_model_id_chunks\nfrom inference.models.aliases import resolve_roboflow_model_alias\n\n\n@ttl_cache(ttl=MODELS_CACHE_AUTH_CACHE_TTL, maxsize=MODELS_CACHE_AUTH_CACHE_MAX_SIZE)\ndef _check_if_api_key_has_access_to_model_cached(\n    api_key: str,\n    resolved_model_id: str,\n    endpoint_type: ModelEndpointType = ModelEndpointType.ORT,\n    countinference: Optional[bool] = None,\n    service_secret: Optional[str] = None,\n) -> bool:\n    _, version_id = get_model_id_chunks(model_id=resolved_model_id)\n    try:\n        if version_id is not None:\n            get_roboflow_model_data(\n                api_key=api_key,\n                model_id=resolved_model_id,\n                endpoint_type=endpoint_type,\n                device_id=GLOBAL_DEVICE_ID,\n                countinference=countinference,\n                service_secret=service_secret,\n            )\n        else:\n            get_roboflow_instant_model_data(\n                api_key=api_key,\n                model_id=resolved_model_id,\n                countinference=countinference,\n                service_secret=service_secret,\n            )\n    except RoboflowAPINotAuthorizedError:\n        return False\n    return True\n\n\ndef _check_if_api_key_has_access_to_model(\n    api_key: str,\n    model_id: str,\n    endpoint_type: ModelEndpointType = ModelEndpointType.ORT,\n    countinference: Optional[bool] = None,\n    service_secret: Optional[str] = None,\n) -> bool:\n    # Resolve aliases before consulting the cache so different aliases that\n    # point to the same model will hit the same cache entry.\n    resolved_model_id = resolve_roboflow_model_alias(model_id=model_id)\n    return _check_if_api_key_has_access_to_model_cached(\n        api_key=api_key,\n        resolved_model_id=resolved_model_id,\n        endpoint_type=endpoint_type,\n        countinference=countinference,\n        service_secret=service_secret,\n    )",
    "optimized_raw_markdown": "```python:inference/core/registries/roboflow.py\nfrom typing import Optional\n\nfrom cachetools.func import ttl_cache\nfrom inference.core.devices.utils import GLOBAL_DEVICE_ID\nfrom inference.core.env import (MODELS_CACHE_AUTH_CACHE_MAX_SIZE,\n                                MODELS_CACHE_AUTH_CACHE_TTL)\nfrom inference.core.exceptions import RoboflowAPINotAuthorizedError\nfrom inference.core.roboflow_api import (ModelEndpointType,\n                                         get_roboflow_instant_model_data,\n                                         get_roboflow_model_data)\nfrom inference.core.utils.roboflow import get_model_id_chunks\nfrom inference.models.aliases import resolve_roboflow_model_alias\n\n\n@ttl_cache(ttl=MODELS_CACHE_AUTH_CACHE_TTL, maxsize=MODELS_CACHE_AUTH_CACHE_MAX_SIZE)\ndef _check_if_api_key_has_access_to_model_cached(\n    api_key: str,\n    resolved_model_id: str,\n    endpoint_type: ModelEndpointType = ModelEndpointType.ORT,\n    countinference: Optional[bool] = None,\n    service_secret: Optional[str] = None,\n) -> bool:\n    _, version_id = get_model_id_chunks(model_id=resolved_model_id)\n    try:\n        if version_id is not None:\n            get_roboflow_model_data(\n                api_key=api_key,\n                model_id=resolved_model_id,\n                endpoint_type=endpoint_type,\n                device_id=GLOBAL_DEVICE_ID,\n                countinference=countinference,\n                service_secret=service_secret,\n            )\n        else:\n            get_roboflow_instant_model_data(\n                api_key=api_key,\n                model_id=resolved_model_id,\n                countinference=countinference,\n                service_secret=service_secret,\n            )\n    except RoboflowAPINotAuthorizedError:\n        return False\n    return True\n\n\ndef _check_if_api_key_has_access_to_model(\n    api_key: str,\n    model_id: str,\n    endpoint_type: ModelEndpointType = ModelEndpointType.ORT,\n    countinference: Optional[bool] = None,\n    service_secret: Optional[str] = None,\n) -> bool:\n    # Resolve aliases before consulting the cache so different aliases that\n    # point to the same model will hit the same cache entry.\n    resolved_model_id = resolve_roboflow_model_alias(model_id=model_id)\n    return _check_if_api_key_has_access_to_model_cached(\n        api_key=api_key,\n        resolved_model_id=resolved_model_id,\n        endpoint_type=endpoint_type,\n        countinference=countinference,\n        service_secret=service_secret,\n    )\n```",
    "optimized_function_only": null,
    "original_file_content": "import gc\nfrom collections import deque\nfrom threading import Lock\nfrom typing import List, Optional\n\nfrom inference.core import logger\nfrom inference.core.entities.requests.inference import InferenceRequest\nfrom inference.core.entities.responses.inference import InferenceResponse\nfrom inference.core.env import (\n    DISK_CACHE_CLEANUP,\n    HOT_MODELS_QUEUE_LOCK_ACQUIRE_TIMEOUT,\n    MEMORY_FREE_THRESHOLD,\n    MODELS_CACHE_AUTH_ENABLED,\n    USE_INFERENCE_MODELS,\n)\nfrom inference.core.exceptions import (\n    ModelManagerLockAcquisitionError,\n    RoboflowAPINotAuthorizedError,\n)\nfrom inference.core.managers.base import Model, ModelManager, acquire_with_timeout\nfrom inference.core.managers.decorators.base import ModelManagerDecorator\nfrom inference.core.managers.entities import ModelDescription\nfrom inference.core.registries.roboflow import (\n    ModelEndpointType,\n    _check_if_api_key_has_access_to_model,\n)\n\n\nclass WithFixedSizeCache(ModelManagerDecorator):\n    def __init__(self, model_manager: ModelManager, max_size: int = 8):\n        \"\"\"Cache decorator, models will be evicted based on the last utilization (`.infer` call). Internally, a [double-ended queue](https://docs.python.org/3/library/collections.html#collections.deque) is used to keep track of model utilization.\n\n        Args:\n            model_manager (ModelManager): Instance of a ModelManager.\n            max_size (int, optional): Max number of models at the same time. Defaults to 8.\n        \"\"\"\n        super().__init__(model_manager)\n        self.max_size = max_size\n        self._key_queue = deque(self.model_manager.keys())\n        self._queue_lock = Lock()\n        self._pinned_models: set = set()\n\n    def pin_model(self, model_id: str) -> None:\n        \"\"\"Mark a model as pinned so it won't be evicted by the LRU cache.\n\n        Pinned models (typically preloaded models) are protected from eviction\n        when the cache is full or under memory pressure.\n        \"\"\"\n        self._pinned_models.add(model_id)\n        logger.debug(f\"Model '{model_id}' pinned \u2014 will not be evicted from cache.\")\n\n    def add_model(\n        self,\n        model_id: str,\n        api_key: str,\n        model_id_alias: Optional[str] = None,\n        endpoint_type: ModelEndpointType = ModelEndpointType.ORT,\n        countinference: Optional[bool] = None,\n        service_secret: Optional[str] = None,\n    ) -> None:\n        \"\"\"Adds a model to the manager and evicts the least recently used if the cache is full.\n\n        Args:\n            model_id (str): The identifier of the model.\n            model (Model): The model instance.\n            endpoint_type (ModelEndpointType, optional): The endpoint type to use for the model.\n        \"\"\"\n        if MODELS_CACHE_AUTH_ENABLED:\n            if not _check_if_api_key_has_access_to_model(\n                api_key=api_key,\n                model_id=model_id,\n                endpoint_type=endpoint_type,\n                countinference=countinference,\n                service_secret=service_secret,\n            ):\n                raise RoboflowAPINotAuthorizedError(\n                    f\"API key {api_key} does not have access to model {model_id}\"\n                )\n\n        queue_id = self._resolve_queue_id(\n            model_id=model_id, model_id_alias=model_id_alias\n        )\n        if queue_id in self:\n            logger.debug(\n                f\"Detected {queue_id} in WithFixedSizeCache models queue -> marking as most recently used.\"\n            )\n            self._refresh_model_position_in_a_queue(model_id=queue_id)\n            return None\n\n        logger.debug(f\"Current capacity of ModelManager: {len(self)}/{self.max_size}\")\n        with acquire_with_timeout(\n            lock=self._queue_lock, timeout=HOT_MODELS_QUEUE_LOCK_ACQUIRE_TIMEOUT\n        ) as acquired:\n            if not acquired:\n                raise ModelManagerLockAcquisitionError(\n                    \"Could not acquire lock on Model Manager state to add model from active models queue.\"\n                )\n            while self._key_queue and (\n                len(self) >= self.max_size\n                or (MEMORY_FREE_THRESHOLD and self.memory_pressure_detected())\n            ):\n                # To prevent flapping around the threshold, remove up to 3 models to make some space.\n                evicted_count = 0\n                skipped_pinned = []\n                for _ in range(3):\n                    if not self._key_queue:\n                        logger.error(\n                            \"Tried to remove model from cache even though key queue is already empty!\"\n                            \"(max_size: %s, len(self): %s, MEMORY_FREE_THRESHOLD: %s)\",\n                            self.max_size,\n                            len(self),\n                            MEMORY_FREE_THRESHOLD,\n                        )\n                        break\n                    to_remove_model_id = self._key_queue.popleft()\n                    if to_remove_model_id in self._pinned_models:\n                        skipped_pinned.append(to_remove_model_id)\n                        continue\n                    super().remove(\n                        to_remove_model_id, delete_from_disk=DISK_CACHE_CLEANUP\n                    )  # LRU model overflow cleanup may or maynot need the weights removed from disk\n                    logger.debug(f\"Model {to_remove_model_id} successfully unloaded.\")\n                    evicted_count += 1\n                # Put pinned models back at the front of the queue\n                for mid in reversed(skipped_pinned):\n                    self._key_queue.appendleft(mid)\n                if evicted_count == 0:\n                    logger.warning(\n                        \"Cannot free model cache space \u2014 all remaining models are pinned (preloaded). \"\n                        \"Proceeding with cache exceeding max_size.\"\n                    )\n                    break\n                gc.collect()\n            logger.debug(f\"Marking new model {queue_id} as most recently used.\")\n            self._key_queue.append(queue_id)\n        try:\n            return super().add_model(\n                model_id,\n                api_key,\n                model_id_alias=model_id_alias,\n                endpoint_type=endpoint_type,\n                countinference=countinference,\n                service_secret=service_secret,\n            )\n        except Exception as error:\n            logger.debug(\n                f\"Could not initialise model {queue_id}. Removing from WithFixedSizeCache models queue.\"\n            )\n            with acquire_with_timeout(\n                lock=self._queue_lock, timeout=HOT_MODELS_QUEUE_LOCK_ACQUIRE_TIMEOUT\n            ) as acquired:\n                if not acquired:\n                    raise ModelManagerLockAcquisitionError(\n                        \"Could not acquire lock on Model Manager state to remove model from active models queue.\"\n                    )\n                self._safe_remove_model_from_queue(queue_id)\n            raise error\n\n    def clear(self) -> None:\n        \"\"\"Removes all models from the manager.\"\"\"\n        for model_id in list(self.keys()):\n            self.remove(model_id)\n\n    def remove(self, model_id: str, delete_from_disk: bool = True) -> Model:\n        with acquire_with_timeout(\n            lock=self._queue_lock, timeout=HOT_MODELS_QUEUE_LOCK_ACQUIRE_TIMEOUT\n        ) as acquired:\n            if not acquired:\n                raise ModelManagerLockAcquisitionError(\n                    \"Could not acquire lock on Model Manager state to remove model from active models queue.\"\n                )\n            self._safe_remove_model_from_queue(model_id=model_id)\n        return super().remove(model_id, delete_from_disk=delete_from_disk)\n\n    async def infer_from_request(\n        self, model_id: str, request: InferenceRequest, **kwargs\n    ) -> InferenceResponse:\n        \"\"\"Processes a complete inference request and updates the cache.\n\n        Args:\n            model_id (str): The identifier of the model.\n            request (InferenceRequest): The request to process.\n\n        Returns:\n            InferenceResponse: The response from the inference.\n        \"\"\"\n        self._refresh_model_position_in_a_queue(model_id=model_id)\n        return await super().infer_from_request(model_id, request, **kwargs)\n\n    def infer_from_request_sync(\n        self, model_id: str, request: InferenceRequest, **kwargs\n    ) -> InferenceResponse:\n        \"\"\"Processes a complete inference request and updates the cache.\n\n        Args:\n            model_id (str): The identifier of the model.\n            request (InferenceRequest): The request to process.\n\n        Returns:\n            InferenceResponse: The response from the inference.\n        \"\"\"\n        self._refresh_model_position_in_a_queue(model_id=model_id)\n        return super().infer_from_request_sync(model_id, request, **kwargs)\n\n    def infer_only(self, model_id: str, request, img_in, img_dims, batch_size=None):\n        \"\"\"Performs only the inference part of a request and updates the cache.\n\n        Args:\n            model_id (str): The identifier of the model.\n            request: The request to process.\n            img_in: Input image.\n            img_dims: Image dimensions.\n            batch_size (int, optional): Batch size.\n\n        Returns:\n            Response from the inference-only operation.\n        \"\"\"\n        self._refresh_model_position_in_a_queue(model_id=model_id)\n        return super().infer_only(model_id, request, img_in, img_dims, batch_size)\n\n    def preprocess(self, model_id: str, request):\n        \"\"\"Processes the preprocessing part of a request and updates the cache.\n\n        Args:\n            model_id (str): The identifier of the model.\n            request (InferenceRequest): The request to preprocess.\n        \"\"\"\n        self._refresh_model_position_in_a_queue(model_id=model_id)\n        return super().preprocess(model_id, request)\n\n    def describe_models(self) -> List[ModelDescription]:\n        return self.model_manager.describe_models()\n\n    def _resolve_queue_id(\n        self, model_id: str, model_id_alias: Optional[str] = None\n    ) -> str:\n        return model_id if model_id_alias is None else model_id_alias\n\n    def _refresh_model_position_in_a_queue(self, model_id: str) -> None:\n        with acquire_with_timeout(\n            lock=self._queue_lock, timeout=HOT_MODELS_QUEUE_LOCK_ACQUIRE_TIMEOUT\n        ) as acquired:\n            if not acquired:\n                raise ModelManagerLockAcquisitionError(\n                    \"Could not acquire lock on Model Manager state to refresh model position in active models queue.\"\n                )\n            self._safe_remove_model_from_queue(model_id=model_id)\n            self._key_queue.append(model_id)\n\n    def _safe_remove_model_from_queue(self, model_id: str) -> None:\n        try:\n            while model_id in self._key_queue:\n                self._key_queue.remove(model_id)\n        except ValueError:\n            logger.warning(\n                f\"Could not successfully purge model {model_id} from  WithFixedSizeCache models queue - \"\n                f\"model id not found.\"\n            )\n\n    def memory_pressure_detected(self) -> bool:\n        return_boolean = False\n        try:\n            import torch\n\n            if torch.cuda.is_available():\n                free_memory, total_memory = torch.cuda.mem_get_info()\n                return_boolean = (\n                    float(free_memory / total_memory) < MEMORY_FREE_THRESHOLD\n                )\n                if return_boolean and USE_INFERENCE_MODELS:\n                    # we only enable this under condition that USE_INFERENCE_MODELS is True\n                    # and we are about to remove a model\n                    # just to make sure we are not flapping around the threshold for no reason\n                    torch.cuda.empty_cache()\n                    free_memory, total_memory = torch.cuda.mem_get_info()\n                    return_boolean = (\n                        float(free_memory / total_memory) < MEMORY_FREE_THRESHOLD\n                    )\n                logger.debug(\n                    f\"Free memory: {free_memory}, Total memory: {total_memory}, threshold: {MEMORY_FREE_THRESHOLD}, return_boolean: {return_boolean}\"\n                )\n            # TODO: Add memory calculation for other non-CUDA devices\n        except Exception as e:\n            logger.error(\n                f\"Failed to check CUDA memory pressure: {e}, returning {return_boolean}\"\n            )\n        return return_boolean\n",
    "patch": null
  },
  {
    "trace_id": "9e589f18-7ce6-4275-a299-dc89858ea3af",
    "function_name": "_is_flash_attn_usable",
    "file_path": "inference/models/qwen3vl/qwen3vl.py",
    "speedup_x": 140.4063954333915,
    "review_quality": "high",
    "pre_optimization_commit": "HEAD",
    "resolution_method": "db_code_only",
    "source": "db_features",
    "original_function_code": "def _is_flash_attn_usable() -> bool:\n    \"\"\"Check if flash attention 2 is both installed and supported by the GPU.\"\"\"\n    if not is_flash_attn_2_available():\n        return False\n    try:\n        if not torch.cuda.is_available():\n            return False\n        major, _ = torch.cuda.get_device_capability()\n        return major >= 8\n    except Exception:\n        return False",
    "optimized_function_code": "import functools\n\nimport torch\nfrom transformers.utils import is_flash_attn_2_available\n\n\n@functools.cache\ndef _is_flash_attn_usable() -> bool:\n    \"\"\"Check if flash attention 2 is both installed and supported by the GPU.\"\"\"\n    try:\n        if not torch.cuda.is_available():\n            return False\n        if not is_flash_attn_2_available():\n            return False\n        major, _ = torch.cuda.get_device_capability()\n        return major >= 8\n    except Exception:\n        return False",
    "optimized_raw_markdown": "```python:inference/models/qwen3vl/qwen3vl.py\nimport functools\n\nimport torch\nfrom transformers.utils import is_flash_attn_2_available\n\n\n@functools.cache\ndef _is_flash_attn_usable() -> bool:\n    \"\"\"Check if flash attention 2 is both installed and supported by the GPU.\"\"\"\n    try:\n        if not torch.cuda.is_available():\n            return False\n        if not is_flash_attn_2_available():\n            return False\n        major, _ = torch.cuda.get_device_capability()\n        return major >= 8\n    except Exception:\n        return False\n```",
    "optimized_function_only": "def _is_flash_attn_usable() -> bool:\n    \"\"\"Check if flash attention 2 is both installed and supported by the GPU.\"\"\"\n    try:\n        if not torch.cuda.is_available():\n            return False\n        if not is_flash_attn_2_available():\n            return False\n        major, _ = torch.cuda.get_device_capability()\n        return major >= 8\n    except Exception:\n        return False",
    "original_file_content": "import torch\nfrom transformers.utils import is_flash_attn_2_available\n\ndef _is_flash_attn_usable() -> bool:\n    \"\"\"Check if flash attention 2 is both installed and supported by the GPU.\"\"\"\n    if not is_flash_attn_2_available():\n        return False\n    try:\n        if not torch.cuda.is_available():\n            return False\n        major, _ = torch.cuda.get_device_capability()\n        return major >= 8\n    except Exception:\n        return False",
    "patch": null
  },
  {
    "trace_id": "15ee30f1-6e60-4e47-905b-e5f56d9cab93",
    "function_name": "UsageCollector._compute_execution_duration",
    "file_path": "inference/usage_tracking/collector.py",
    "speedup_x": 0.5527596230230375,
    "review_quality": "high",
    "pre_optimization_commit": "f52188ff2e0ddbba9a1e15dd0b1f69b6dabf9fdc",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def _compute_execution_duration(t1: float, t2: float) -> float:\n        raw = t2 - t1\n        if not GCP_SERVERLESS:\n            return raw\n        if apply_duration_minimum is not None:\n            try:\n                if apply_duration_minimum.get():\n                    return max(raw, 0.1)\n                return raw\n            except LookupError:\n                pass\n        return max(raw, 0.1)\n",
    "optimized_function_code": "import asyncio\nimport atexit\nimport time\nfrom collections import defaultdict\nfrom queue import Queue\nfrom threading import Event, Lock, Thread\nfrom typing import Any, DefaultDict, Dict, Tuple, TypeVar\nfrom uuid import uuid4\n\nfrom inference.core.env import GCP_SERVERLESS, LAMBDA, REDIS_HOST\nfrom inference.core.logger import logger\nfrom inference.usage_tracking.config import (TelemetrySettings,\n                                             get_telemetry_settings)\nfrom inference.usage_tracking.payload_helpers import (APIKey, APIKeyHash,\n                                                      APIKeyUsage,\n                                                      ResourceCategory,\n                                                      ResourceID, UsagePayload)\nfrom inference.usage_tracking.plan_details import PlanDetails\nfrom inference.usage_tracking.redis_queue import RedisQueue\nfrom inference.usage_tracking.sqlite_queue import SQLiteQueue\nfrom typing_extensions import ParamSpec\n\ntry:\n    from inference_sdk.config import apply_duration_minimum\nexcept ImportError:\n    apply_duration_minimum = None\n\nT = TypeVar(\"T\")\nP = ParamSpec(\"P\")\n\n\nclass UsageCollector:\n\n    _lock = Lock()\n\n    def __init__(self):\n        with UsageCollector._lock:\n            if self._queue:\n                return\n\n        # Async lock only for async protection, should not be shared between threads\n        self._async_lock = None\n        try:\n            self._async_lock = asyncio.Lock()\n        except Exception as exc:\n            logger.debug(\"Failed to create async lock %s\", exc)\n\n        self._exec_session_id = f\"{time.time_ns()}_{uuid4().hex[:4]}\"\n\n        self._settings: TelemetrySettings = get_telemetry_settings()\n        self._usage: APIKeyUsage = self.empty_usage_dict(\n            exec_session_id=self._exec_session_id\n        )\n\n        self._hashed_api_keys: Dict[APIKey, APIKeyHash] = {}\n        self._api_keys_hashing_enabled = True\n\n        self._plan_details = PlanDetails(\n            api_plan_endpoint_url=self._settings.api_plan_endpoint_url,\n            webrtc_plans_endpoint_url=self._settings.webrtc_plans_endpoint_url,\n            sqlite_cache_enabled=False,\n            api_plan_cache_ttl_seconds=self._settings.api_plan_cache_ttl_seconds,\n        )\n        if (LAMBDA or GCP_SERVERLESS) and REDIS_HOST:\n            logger.debug(\"Persistence through RedisQueue\")\n            self._queue: \"Queue[UsagePayload]\" = RedisQueue()\n            self._api_keys_hashing_enabled = False\n        elif (LAMBDA or GCP_SERVERLESS) or not self._settings.use_persistent_queue:\n            logger.debug(\"No persistence\")\n            self._queue: \"Queue[UsagePayload]\" = Queue(\n                maxsize=self._settings.queue_size\n            )\n            self._api_keys_hashing_enabled = False\n        else:\n            try:\n                self._queue = SQLiteQueue()\n                logger.debug(\"Persistence through SQLiteQueue\")\n            except Exception as exc:\n                logger.debug(\"Unable to create instance of SQLiteQueue, %s\", exc)\n                logger.debug(\"No persistence\")\n                self._queue: \"Queue[UsagePayload]\" = Queue(\n                    maxsize=self._settings.queue_size\n                )\n                self._api_keys_hashing_enabled = False\n            try:\n                self._plan_details = PlanDetails(\n                    api_plan_endpoint_url=self._settings.api_plan_endpoint_url,\n                    webrtc_plans_endpoint_url=self._settings.webrtc_plans_endpoint_url,\n                    api_plan_cache_ttl_seconds=self._settings.api_plan_cache_ttl_seconds,\n                )\n                logger.debug(\"Cached plan details\")\n            except Exception as exc:\n                logger.debug(\"Unable to create instance of SQLiteQueue, %s\", exc)\n        self._queue_lock = Lock()\n\n        self._system_info_lock = Lock()\n        self._system_info: Dict[str, Any] = {}\n        self._resource_details_lock = Lock()\n        self._resource_details: DefaultDict[\n            APIKey, Dict[Tuple[ResourceCategory, ResourceID], Dict[str, Any]]\n        ] = defaultdict(dict)\n\n        self._terminate_collector_thread = Event()\n        self._collector_thread = Thread(target=self._usage_collector, daemon=True)\n        self._collector_thread.start()\n\n        self._terminate_sender_thread = Event()\n        self._sender_thread = Thread(target=self._usage_sender, daemon=True)\n        self._sender_thread.start()\n\n        atexit.register(self._cleanup)\n\n    @staticmethod\n    def _compute_execution_duration(t1: float, t2: float) -> float:\n        raw = t2 - t1\n        if not GCP_SERVERLESS:\n            return raw\n\n        # Localize globals to reduce attribute lookups on hot path\n        adm = apply_duration_minimum\n        MIN_DUR = 0.1\n        if adm is not None:\n            try:\n                # Only catch LookupError exactly as original code did\n                if adm.get():\n                    return raw if raw >= MIN_DUR else MIN_DUR\n                return raw\n            except LookupError:\n                pass\n\n        # Default when apply_duration_minimum is None or LookupError occurred\n        return raw if raw >= MIN_DUR else MIN_DUR",
    "optimized_raw_markdown": "```python:inference/usage_tracking/collector.py\nimport asyncio\nimport atexit\nimport time\nfrom collections import defaultdict\nfrom queue import Queue\nfrom threading import Event, Lock, Thread\nfrom typing import Any, DefaultDict, Dict, Tuple, TypeVar\nfrom uuid import uuid4\n\nfrom inference.core.env import GCP_SERVERLESS, LAMBDA, REDIS_HOST\nfrom inference.core.logger import logger\nfrom inference.usage_tracking.config import (TelemetrySettings,\n                                             get_telemetry_settings)\nfrom inference.usage_tracking.payload_helpers import (APIKey, APIKeyHash,\n                                                      APIKeyUsage,\n                                                      ResourceCategory,\n                                                      ResourceID, UsagePayload)\nfrom inference.usage_tracking.plan_details import PlanDetails\nfrom inference.usage_tracking.redis_queue import RedisQueue\nfrom inference.usage_tracking.sqlite_queue import SQLiteQueue\nfrom typing_extensions import ParamSpec\n\ntry:\n    from inference_sdk.config import apply_duration_minimum\nexcept ImportError:\n    apply_duration_minimum = None\n\nT = TypeVar(\"T\")\nP = ParamSpec(\"P\")\n\n\nclass UsageCollector:\n\n    _lock = Lock()\n\n    def __init__(self):\n        with UsageCollector._lock:\n            if self._queue:\n                return\n\n        # Async lock only for async protection, should not be shared between threads\n        self._async_lock = None\n        try:\n            self._async_lock = asyncio.Lock()\n        except Exception as exc:\n            logger.debug(\"Failed to create async lock %s\", exc)\n\n        self._exec_session_id = f\"{time.time_ns()}_{uuid4().hex[:4]}\"\n\n        self._settings: TelemetrySettings = get_telemetry_settings()\n        self._usage: APIKeyUsage = self.empty_usage_dict(\n            exec_session_id=self._exec_session_id\n        )\n\n        self._hashed_api_keys: Dict[APIKey, APIKeyHash] = {}\n        self._api_keys_hashing_enabled = True\n\n        self._plan_details = PlanDetails(\n            api_plan_endpoint_url=self._settings.api_plan_endpoint_url,\n            webrtc_plans_endpoint_url=self._settings.webrtc_plans_endpoint_url,\n            sqlite_cache_enabled=False,\n            api_plan_cache_ttl_seconds=self._settings.api_plan_cache_ttl_seconds,\n        )\n        if (LAMBDA or GCP_SERVERLESS) and REDIS_HOST:\n            logger.debug(\"Persistence through RedisQueue\")\n            self._queue: \"Queue[UsagePayload]\" = RedisQueue()\n            self._api_keys_hashing_enabled = False\n        elif (LAMBDA or GCP_SERVERLESS) or not self._settings.use_persistent_queue:\n            logger.debug(\"No persistence\")\n            self._queue: \"Queue[UsagePayload]\" = Queue(\n                maxsize=self._settings.queue_size\n            )\n            self._api_keys_hashing_enabled = False\n        else:\n            try:\n                self._queue = SQLiteQueue()\n                logger.debug(\"Persistence through SQLiteQueue\")\n            except Exception as exc:\n                logger.debug(\"Unable to create instance of SQLiteQueue, %s\", exc)\n                logger.debug(\"No persistence\")\n                self._queue: \"Queue[UsagePayload]\" = Queue(\n                    maxsize=self._settings.queue_size\n                )\n                self._api_keys_hashing_enabled = False\n            try:\n                self._plan_details = PlanDetails(\n                    api_plan_endpoint_url=self._settings.api_plan_endpoint_url,\n                    webrtc_plans_endpoint_url=self._settings.webrtc_plans_endpoint_url,\n                    api_plan_cache_ttl_seconds=self._settings.api_plan_cache_ttl_seconds,\n                )\n                logger.debug(\"Cached plan details\")\n            except Exception as exc:\n                logger.debug(\"Unable to create instance of SQLiteQueue, %s\", exc)\n        self._queue_lock = Lock()\n\n        self._system_info_lock = Lock()\n        self._system_info: Dict[str, Any] = {}\n        self._resource_details_lock = Lock()\n        self._resource_details: DefaultDict[\n            APIKey, Dict[Tuple[ResourceCategory, ResourceID], Dict[str, Any]]\n        ] = defaultdict(dict)\n\n        self._terminate_collector_thread = Event()\n        self._collector_thread = Thread(target=self._usage_collector, daemon=True)\n        self._collector_thread.start()\n\n        self._terminate_sender_thread = Event()\n        self._sender_thread = Thread(target=self._usage_sender, daemon=True)\n        self._sender_thread.start()\n\n        atexit.register(self._cleanup)\n\n    @staticmethod\n    def _compute_execution_duration(t1: float, t2: float) -> float:\n        raw = t2 - t1\n        if not GCP_SERVERLESS:\n            return raw\n\n        # Localize globals to reduce attribute lookups on hot path\n        adm = apply_duration_minimum\n        MIN_DUR = 0.1\n        if adm is not None:\n            try:\n                # Only catch LookupError exactly as original code did\n                if adm.get():\n                    return raw if raw >= MIN_DUR else MIN_DUR\n                return raw\n            except LookupError:\n                pass\n\n        # Default when apply_duration_minimum is None or LookupError occurred\n        return raw if raw >= MIN_DUR else MIN_DUR\n```",
    "optimized_function_only": "    def _compute_execution_duration(t1: float, t2: float) -> float:\n        raw = t2 - t1\n        if not GCP_SERVERLESS:\n            return raw\n\n        # Localize globals to reduce attribute lookups on hot path\n        adm = apply_duration_minimum\n        MIN_DUR = 0.1\n        if adm is not None:\n            try:\n                # Only catch LookupError exactly as original code did\n                if adm.get():\n                    return raw if raw >= MIN_DUR else MIN_DUR\n                return raw\n            except LookupError:\n                pass\n\n        # Default when apply_duration_minimum is None or LookupError occurred\n        return raw if raw >= MIN_DUR else MIN_DUR",
    "original_file_content": "import asyncio\nimport atexit\nimport json\nimport mimetypes\nimport numbers\nimport socket\nimport sys\nimport time\nfrom collections import defaultdict\nfrom functools import wraps\nfrom queue import Queue\nfrom threading import Event, Lock, Thread\nfrom typing import (\n    Any,\n    Callable,\n    DefaultDict,\n    Dict,\n    List,\n    Literal,\n    Optional,\n    Tuple,\n    TypeVar,\n)\nfrom uuid import uuid4\n\nfrom typing_extensions import ParamSpec\n\nfrom inference.core.env import (\n    API_KEY,\n    DEDICATED_DEPLOYMENT_ID,\n    DEVICE_ID,\n    GCP_SERVERLESS,\n    LAMBDA,\n    REDIS_HOST,\n    ROBOFLOW_INTERNAL_SERVICE_NAME,\n    ROBOFLOW_INTERNAL_SERVICE_SECRET,\n)\nfrom inference.core.logger import logger\nfrom inference.core.roboflow_api import build_roboflow_api_headers\nfrom inference.core.version import __version__ as inference_version\n\ntry:\n    from inference_sdk.config import apply_duration_minimum, execution_id\nexcept ImportError:\n    apply_duration_minimum = None\n    execution_id = None\n\nfrom .config import TelemetrySettings, get_telemetry_settings\nfrom .decorator_helpers import (\n    get_model_id_from_kwargs,\n    get_model_resource_details_from_kwargs,\n    get_request_api_key_from_kwargs,\n    get_request_resource_details_from_kwargs,\n    get_request_resource_id_from_kwargs,\n    get_workflow_api_key_from_kwargs,\n    get_workflow_resource_details_from_kwargs,\n)\nfrom .payload_helpers import (\n    APIKey,\n    APIKeyHash,\n    APIKeyUsage,\n    ResourceCategory,\n    ResourceID,\n    SystemDetails,\n    UsagePayload,\n    send_usage_payload,\n    sha256_hash,\n    zip_usage_payloads,\n)\nfrom .plan_details import PlanDetails\nfrom .redis_queue import RedisQueue\nfrom .sqlite_queue import SQLiteQueue\nfrom .utils import collect_func_params\n\nT = TypeVar(\"T\")\nP = ParamSpec(\"P\")\n\n\nclass UsageCollector:\n    _lock = Lock()\n\n    def __new__(cls, *args, **kwargs):\n        with UsageCollector._lock:\n            if not hasattr(cls, \"_instance\"):\n                cls._instance = super().__new__(cls)\n                cls._instance._queue = None\n        return cls._instance\n\n    def __init__(self):\n        with UsageCollector._lock:\n            if self._queue:\n                return\n\n        # Async lock only for async protection, should not be shared between threads\n        self._async_lock = None\n        try:\n            self._async_lock = asyncio.Lock()\n        except Exception as exc:\n            logger.debug(\"Failed to create async lock %s\", exc)\n\n        self._exec_session_id = f\"{time.time_ns()}_{uuid4().hex[:4]}\"\n\n        self._settings: TelemetrySettings = get_telemetry_settings()\n        self._usage: APIKeyUsage = self.empty_usage_dict(\n            exec_session_id=self._exec_session_id\n        )\n\n        self._hashed_api_keys: Dict[APIKey, APIKeyHash] = {}\n        self._api_keys_hashing_enabled = True\n\n        self._plan_details = PlanDetails(\n            api_plan_endpoint_url=self._settings.api_plan_endpoint_url,\n            webrtc_plans_endpoint_url=self._settings.webrtc_plans_endpoint_url,\n            sqlite_cache_enabled=False,\n            api_plan_cache_ttl_seconds=self._settings.api_plan_cache_ttl_seconds,\n        )\n        if (LAMBDA or GCP_SERVERLESS) and REDIS_HOST:\n            logger.debug(\"Persistence through RedisQueue\")\n            self._queue: \"Queue[UsagePayload]\" = RedisQueue()\n            self._api_keys_hashing_enabled = False\n        elif (LAMBDA or GCP_SERVERLESS) or not self._settings.use_persistent_queue:\n            logger.debug(\"No persistence\")\n            self._queue: \"Queue[UsagePayload]\" = Queue(\n                maxsize=self._settings.queue_size\n            )\n            self._api_keys_hashing_enabled = False\n        else:\n            try:\n                self._queue = SQLiteQueue()\n                logger.debug(\"Persistence through SQLiteQueue\")\n            except Exception as exc:\n                logger.debug(\"Unable to create instance of SQLiteQueue, %s\", exc)\n                logger.debug(\"No persistence\")\n                self._queue: \"Queue[UsagePayload]\" = Queue(\n                    maxsize=self._settings.queue_size\n                )\n                self._api_keys_hashing_enabled = False\n            try:\n                self._plan_details = PlanDetails(\n                    api_plan_endpoint_url=self._settings.api_plan_endpoint_url,\n                    webrtc_plans_endpoint_url=self._settings.webrtc_plans_endpoint_url,\n                    api_plan_cache_ttl_seconds=self._settings.api_plan_cache_ttl_seconds,\n                )\n                logger.debug(\"Cached plan details\")\n            except Exception as exc:\n                logger.debug(\"Unable to create instance of SQLiteQueue, %s\", exc)\n        self._queue_lock = Lock()\n\n        self._system_info_lock = Lock()\n        self._system_info: Dict[str, Any] = {}\n        self._resource_details_lock = Lock()\n        self._resource_details: DefaultDict[\n            APIKey, Dict[Tuple[ResourceCategory, ResourceID], Dict[str, Any]]\n        ] = defaultdict(dict)\n\n        self._terminate_collector_thread = Event()\n        self._collector_thread = Thread(target=self._usage_collector, daemon=True)\n        self._collector_thread.start()\n\n        self._terminate_sender_thread = Event()\n        self._sender_thread = Thread(target=self._usage_sender, daemon=True)\n        self._sender_thread.start()\n\n        atexit.register(self._cleanup)\n\n    @staticmethod\n    def empty_usage_dict(exec_session_id: str) -> APIKeyUsage:\n        usage_dict = {\n            \"timestamp_start\": None,\n            \"timestamp_stop\": None,\n            \"exec_session_id\": exec_session_id,\n            \"hostname\": \"\",\n            \"ip_address_hash\": \"\",\n            \"processed_frames\": 0,\n            \"fps\": 0,\n            \"source_duration\": 0,\n            \"category\": \"\",\n            \"resource_id\": \"\",\n            \"resource_details\": \"{}\",\n            \"hosted\": bool(LAMBDA)\n            or bool(DEDICATED_DEPLOYMENT_ID)\n            or bool(GCP_SERVERLESS)\n            or bool(ROBOFLOW_INTERNAL_SERVICE_SECRET),\n            \"api_key_hash\": \"\",\n            \"is_gpu_available\": False,\n            \"python_version\": sys.version.split()[0],\n            \"inference_version\": inference_version,\n            \"enterprise\": False,\n            \"execution_duration\": 0,\n        }\n        if ROBOFLOW_INTERNAL_SERVICE_SECRET:\n            usage_dict[\"roboflow_internal_secret\"] = ROBOFLOW_INTERNAL_SERVICE_SECRET\n        if ROBOFLOW_INTERNAL_SERVICE_NAME:\n            usage_dict[\"roboflow_service_name\"] = ROBOFLOW_INTERNAL_SERVICE_NAME\n\n        return defaultdict(  # api_key_hash\n            lambda: defaultdict(lambda: {**usage_dict})  # category:resource_id\n        )\n\n    def _dump_usage_queue_no_lock(self) -> List[APIKeyUsage]:\n        usage_payloads: List[APIKeyUsage] = []\n        while self._queue:\n            if self._queue.empty():\n                break\n            payload = self._queue.get_nowait()\n            if not payload:\n                continue\n            if not isinstance(payload, list):\n                payload = [payload]\n            usage_payloads.extend(payload)\n        return usage_payloads\n\n    def _dump_usage_queue_with_lock(self) -> List[APIKeyUsage]:\n        with self._queue_lock:\n            usage_payloads = self._dump_usage_queue_no_lock()\n        return usage_payloads\n\n    def _calculate_api_key_hash(self, api_key: APIKey) -> APIKeyHash:\n        api_key_hash = \"\"\n        if not api_key:\n            api_key = API_KEY\n        if api_key:\n            api_key_hash = self._hashed_api_keys.get(api_key)\n            if not api_key_hash:\n                if self._api_keys_hashing_enabled:\n                    api_key_hash = sha256_hash(api_key, length=-1)\n                else:\n                    api_key_hash = api_key\n            self._hashed_api_keys[api_key] = api_key_hash\n        return api_key_hash\n\n    @staticmethod\n    def _calculate_resource_hash(resource_details: Dict[str, Any]) -> str:\n        return sha256_hash(json.dumps(resource_details, sort_keys=True))\n\n    def _enqueue_payload(self, payload: UsagePayload):\n        logger.debug(\"Enqueuing usage payload\")\n        if not payload:\n            return\n        with self._queue_lock:\n            if not self._queue.full():\n                self._queue.put(payload)\n            else:\n                usage_payloads = self._dump_usage_queue_no_lock()\n                usage_payloads.append(payload)\n                merged_usage_payloads = zip_usage_payloads(\n                    usage_payloads=usage_payloads,\n                )\n                for usage_payload in merged_usage_payloads:\n                    self._queue.put(usage_payload)\n\n    def record_resource_details(\n        self,\n        category: str,\n        resource_details: Dict[str, Any],\n        resource_id: str = \"\",\n        api_key: str = \"\",\n    ):\n        if not category:\n            raise ValueError(\"Category is compulsory when recording resource details.\")\n        if not resource_details or not isinstance(resource_details, dict):\n            logger.debug(\n                \"Tried to record non-dict resource details, '%s'\", resource_details\n            )\n            return\n\n        if not resource_id:\n            resource_id = UsageCollector._calculate_resource_hash(\n                resource_details=resource_details\n            )\n\n        with self._resource_details_lock:\n            api_key_resource_details = self._resource_details[api_key]\n            api_key_resource_details[(category, resource_id)] = resource_details\n\n    @staticmethod\n    def system_info(\n        ip_address: Optional[str] = None,\n        hostname: Optional[str] = None,\n        dedicated_deployment_id: Optional[str] = None,\n    ) -> SystemDetails:\n        if not dedicated_deployment_id:\n            dedicated_deployment_id = DEDICATED_DEPLOYMENT_ID\n        if not hostname:\n            try:\n                hostname = socket.gethostname()\n            except Exception as exc:\n                logger.warning(\"Could not obtain hostname, %s\", exc)\n                hostname = \"\"\n        if dedicated_deployment_id:\n            hostname = f\"{dedicated_deployment_id}:{hostname}\"\n        else:\n            hostname = sha256_hash(hostname)\n\n        if not ip_address:\n            try:\n                ip_address: str = socket.gethostbyname(socket.gethostname())\n            except Exception as exc:\n                logger.warning(\"Could not obtain IP address, %s\", exc)\n                s = None\n                try:\n                    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)\n                    s.connect((\"8.8.8.8\", 80))\n                    ip_address = s.getsockname()[0]\n                except:\n                    ip_address: str = socket.gethostbyname(\"localhost\")\n\n                if s:\n                    s.close()\n        ip_address_hash_hex = sha256_hash(ip_address)\n\n        return {\n            \"hostname\": hostname,\n            \"ip_address_hash\": ip_address_hash_hex,\n            \"is_gpu_available\": False,  # TODO\n        }\n\n    def record_system_info(\n        self,\n        ip_address: Optional[str] = None,\n    ):\n        if self._system_info:\n            return\n        with self._system_info_lock:\n            self._system_info = self.system_info(\n                ip_address=ip_address,\n            )\n        logger.debug(\"Usage (system info): %s\", self._system_info)\n\n    @staticmethod\n    def _guess_source_type(source: str) -> str:\n        mime_type, _ = mimetypes.guess_type(source)\n        stream_schemes = [\"rtsp\", \"rtmp\"]\n        source_type = None\n        if mime_type and mime_type.startswith(\"video\"):\n            source_type = \"video\"\n        elif mime_type and mime_type.startswith(\"image\"):\n            source_type = \"image\"\n        elif mime_type:\n            logger.debug(\"Unhandled mime type\")\n            source_type = mime_type.split(\"/\")[0]\n        elif not mime_type and str.isnumeric(source):\n            source_type = \"camera\"\n        elif not mime_type and any(\n            source.lower().startswith(s) for s in stream_schemes\n        ):\n            source_type = \"stream\"\n        return source_type\n\n    def _update_usage_payload(\n        self,\n        source: str,\n        category: str,\n        frames: int = 1,\n        api_key: APIKey = \"\",\n        resource_details: Optional[Dict[str, Any]] = None,\n        resource_id: str = \"\",\n        inference_test_run: bool = False,\n        fps: float = 0,\n        execution_duration: float = 0,\n        roboflow_service_name: Optional[str] = None,\n        roboflow_internal_secret: Optional[str] = None,\n    ):\n        source = str(source) if source else \"\"\n        try:\n            frames = int(frames)\n        except Exception:\n            frames = 0\n        api_key_hash = self._calculate_api_key_hash(api_key=api_key)\n        if not resource_id and resource_details:\n            resource_id = UsageCollector._calculate_resource_hash(resource_details)\n        with self._resource_details_lock:\n            resource_details = self._resource_details.get(api_key, {}).get(\n                (category, resource_id), {}\n            )\n        with self._system_info_lock:\n            ip_address_hash = self._system_info[\"ip_address_hash\"]\n            is_gpu_available = self._system_info[\"is_gpu_available\"]\n            hostname = self._system_info[\"hostname\"]\n        with UsageCollector._lock:\n            source_usage = self._usage[api_key_hash][f\"{category}:{resource_id}\"]\n            if not source_usage[\"timestamp_start\"]:\n                source_usage[\"timestamp_start\"] = time.time_ns()\n            source_usage[\"timestamp_stop\"] = time.time_ns()\n            source_usage[\"processed_frames\"] += frames if not inference_test_run else 0\n            source_usage[\"source_duration\"] += (\n                frames / fps if fps and not inference_test_run else 0\n            )\n            source_usage[\"fps\"] = fps if isinstance(fps, numbers.Number) else 0\n            source_usage[\"category\"] = category\n            source_usage[\"resource_id\"] = resource_id\n            source_usage[\"resource_details\"] = json.dumps(resource_details)\n            source_usage[\"api_key_hash\"] = api_key_hash\n            source_usage[\"hostname\"] = hostname\n            source_usage[\"ip_address_hash\"] = ip_address_hash\n            source_usage[\"is_gpu_available\"] = is_gpu_available\n            source_usage[\"execution_duration\"] += execution_duration\n            if (\n                roboflow_service_name\n                and roboflow_service_name != \"external\"\n                and roboflow_internal_secret\n            ):\n                source_usage[\"roboflow_service_name\"] = roboflow_service_name\n                source_usage[\"roboflow_internal_secret\"] = roboflow_internal_secret\n\n            exec_session_id = None\n            if execution_id is not None:\n                exec_session_id = execution_id.get()\n            if exec_session_id:\n                source_usage[\"exec_session_id\"] = exec_session_id\n\n    def record_usage(\n        self,\n        source: str,\n        category: str,\n        frames: int = 1,\n        api_key: APIKey = \"\",\n        resource_details: Optional[Dict[str, Any]] = None,\n        resource_id: str = \"\",\n        inference_test_run: bool = False,\n        fps: float = 0,\n        execution_duration: float = 0,\n        roboflow_service_name: Optional[str] = None,\n        roboflow_internal_secret: Optional[str] = None,\n    ):\n        if not api_key:\n            return\n        self.record_system_info()\n        self.record_resource_details(\n            category=category,\n            resource_details=resource_details,\n            resource_id=resource_id,\n            api_key=api_key,\n        )\n        self._update_usage_payload(\n            source=source,\n            category=category,\n            frames=frames,\n            api_key=api_key,\n            resource_details=resource_details,\n            resource_id=resource_id,\n            inference_test_run=inference_test_run,\n            fps=fps,\n            execution_duration=execution_duration,\n            roboflow_service_name=roboflow_service_name,\n            roboflow_internal_secret=roboflow_internal_secret,\n        )\n\n    async def async_record_usage(\n        self,\n        source: str,\n        category: str,\n        frames: int = 1,\n        api_key: APIKey = \"\",\n        resource_details: Optional[Dict[str, Any]] = None,\n        resource_id: str = \"\",\n        inference_test_run: bool = False,\n        fps: float = 0,\n        execution_duration: float = 0,\n        roboflow_service_name: Optional[str] = None,\n        roboflow_internal_secret: Optional[str] = None,\n    ):\n        if self._async_lock:\n            async with self._async_lock:\n                self.record_usage(\n                    source=source,\n                    category=category,\n                    frames=frames,\n                    api_key=api_key,\n                    resource_details=resource_details,\n                    resource_id=resource_id,\n                    inference_test_run=inference_test_run,\n                    fps=fps,\n                    execution_duration=execution_duration,\n                    roboflow_service_name=roboflow_service_name,\n                    roboflow_internal_secret=roboflow_internal_secret,\n                )\n        else:\n            self.record_usage(\n                source=source,\n                category=category,\n                frames=frames,\n                api_key=api_key,\n                resource_details=resource_details,\n                resource_id=resource_id,\n                inference_test_run=inference_test_run,\n                fps=fps,\n                execution_duration=execution_duration,\n                roboflow_service_name=roboflow_service_name,\n                roboflow_internal_secret=roboflow_internal_secret,\n            )\n\n    def _usage_collector(self):\n        while True:\n            if self._terminate_collector_thread.wait(self._settings.flush_interval):\n                break\n            self._enqueue_usage_payload()\n        logger.debug(\"Terminating collector thread\")\n        self._enqueue_usage_payload()\n\n    def _enqueue_usage_payload(self):\n        if not self._usage:\n            return\n        with UsageCollector._lock:\n            self._enqueue_payload(payload=self._usage)\n            self._usage = self.empty_usage_dict(exec_session_id=self._exec_session_id)\n\n    def _usage_sender(self):\n        while True:\n            if self._terminate_sender_thread.wait(self._settings.flush_interval):\n                break\n            self._flush_queue()\n        logger.debug(\"Terminating sender thread\")\n        self._flush_queue()\n\n    def _flush_queue(self):\n        usage_payloads = self._dump_usage_queue_with_lock()\n        if not usage_payloads:\n            return\n        merged_payloads: APIKeyUsage = zip_usage_payloads(\n            usage_payloads=usage_payloads,\n        )\n        self._offload_to_api(payloads=merged_payloads)\n\n    def _offload_to_api(self, payloads: List[APIKeyUsage]):\n        ssl_verify = True\n        if \"localhost\" in self._settings.api_usage_endpoint_url.lower():\n            ssl_verify = False\n        if \"127.0.0.1\" in self._settings.api_usage_endpoint_url.lower():\n            ssl_verify = False\n\n        hashes_to_api_keys = dict(a[::-1] for a in self._hashed_api_keys.items())\n\n        for payload in payloads:\n            for api_key_hash, resource_payloads in payload.items():\n                if api_key_hash not in hashes_to_api_keys:\n                    logger.debug(\n                        \"Cannot obtain plan details, api key hash cannot be resolved\"\n                    )\n                    continue\n                api_key = hashes_to_api_keys[api_key_hash]\n                api_key_plan_details = self._plan_details.get_api_key_plan(\n                    api_key=api_key\n                )\n\n                for resource_payload in resource_payloads.values():\n                    resource_payload[\"enterprise\"] = api_key_plan_details[\n                        self._plan_details._is_enterprise_col_name\n                    ]\n\n            api_keys_hashes_failed = send_usage_payload(\n                payload=payload,\n                api_usage_endpoint_url=self._settings.api_usage_endpoint_url,\n                hashes_to_api_keys=hashes_to_api_keys,\n                ssl_verify=ssl_verify,\n                extra_headers=build_roboflow_api_headers(),\n            )\n            if api_keys_hashes_failed:\n                logger.debug(\n                    \"Failed to send usage following usage payloads: %s\",\n                    api_keys_hashes_failed,\n                )\n            for api_key_hash in list(payload.keys()):\n                if api_key_hash not in api_keys_hashes_failed:\n                    del payload[api_key_hash]\n            if payload:\n                logger.debug(\"Enqueuing back unsent payload\")\n                self._enqueue_payload(payload=payload)\n\n    def push_usage_payloads(self):\n        self._enqueue_usage_payload()\n        self._flush_queue()\n\n    async def async_push_usage_payloads(self):\n        if self._async_lock:\n            async with self._async_lock:\n                self.push_usage_payloads()\n        else:\n            self.push_usage_payloads()\n\n    @staticmethod\n    def _extract_usage_params_from_func_kwargs(\n        usage_fps: float,\n        usage_api_key: str,\n        usage_workflow_id: str,\n        usage_workflow_preview: bool,\n        usage_inference_test_run: bool,\n        usage_billable: bool,\n        execution_duration: float,\n        func: Callable[[Any], Any],\n        category: Literal[\"model\", \"workflows\", \"request\", \"modal\"],\n        exc: Optional[str],\n        args: List[Any],\n        kwargs: Dict[str, Any],\n    ) -> Dict[str, Any]:\n        func_kwargs = collect_func_params(func, args, kwargs)\n        resource_details = {\n            \"billable\": usage_billable,\n        }\n        if DEDICATED_DEPLOYMENT_ID:\n            resource_details[\"dedicated_deployment_id\"] = DEDICATED_DEPLOYMENT_ID\n        if DEVICE_ID:\n            resource_details[\"device_id\"] = DEVICE_ID\n        if exc is not None:\n            resource_details[\"error\"] = exc\n        resource_id = \"\"\n        # TODO: add requires_api_key, True if workflow definition comes from platform or model comes from workspace\n        if category == \"workflows\":\n            workflow_api_key = get_workflow_api_key_from_kwargs(func_kwargs)\n            if workflow_api_key:\n                usage_api_key = workflow_api_key\n            workflow_resource_details = get_workflow_resource_details_from_kwargs(\n                func_kwargs\n            )\n            if not usage_workflow_id:\n                if workflow_resource_details:\n                    usage_workflow_id = UsageCollector._calculate_resource_hash(\n                        resource_details=workflow_resource_details\n                    )\n                else:\n                    usage_workflow_id = \"unknown\"\n            resource_id = usage_workflow_id\n            workflow_resource_details[\"is_preview\"] = usage_workflow_preview\n            resource_details = {**resource_details, **workflow_resource_details}\n        elif category == \"model\":\n            model_id = get_model_id_from_kwargs(func_kwargs)\n            if model_id:\n                resource_id = model_id\n            else:\n                resource_id = \"unknown\"\n            model_resource_details = get_model_resource_details_from_kwargs(func_kwargs)\n            if model_resource_details:\n                resource_details = {**resource_details, **model_resource_details}\n        elif category == \"request\":\n            request_api_key = get_request_api_key_from_kwargs(func_kwargs)\n            request_resource_details = get_request_resource_details_from_kwargs(\n                func_kwargs\n            )\n            request_resource_id = get_request_resource_id_from_kwargs(func_kwargs)\n            if request_api_key:\n                usage_api_key = request_api_key\n            if request_resource_details:\n                resource_details = {**resource_details, **request_resource_details}\n            if request_resource_id:\n                resource_id = request_resource_id\n            else:\n                resource_id = \"unknown\"\n        else:\n            resource_id = \"unknown\"\n            category = \"unknown\"\n\n        source = None\n        runtime_parameters = func_kwargs.get(\"runtime_parameters\")\n        if (\n            isinstance(runtime_parameters, dict)\n            and \"image\" in func_kwargs[\"runtime_parameters\"]\n        ):\n            images = runtime_parameters[\"image\"]\n            if not isinstance(images, list):\n                images = [images]\n            image = images[0]\n            if isinstance(image, dict):\n                source = image.get(\"value\")\n            elif hasattr(image, \"_image_reference\"):\n                source = image._image_reference\n\n        if not usage_api_key:\n            if \"api_key\" in func_kwargs and func_kwargs[\"api_key\"]:\n                usage_api_key = func_kwargs[\"api_key\"]\n            elif \"self\" in func_kwargs:\n                _self = func_kwargs.get(\"self\")\n                if hasattr(_self, \"api_key\") and _self.api_key:\n                    usage_api_key = _self.api_key\n            if (\n                not usage_api_key\n                and \"kwargs\" in func_kwargs\n                and isinstance(func_kwargs[\"kwargs\"], dict)\n                and \"api_key\" in func_kwargs[\"kwargs\"]\n                and func_kwargs[\"kwargs\"][\"api_key\"]\n            ):\n                usage_api_key = func_kwargs[\"kwargs\"][\"api_key\"]\n\n        roboflow_service_name = func_kwargs.get(\"source_info\")\n        roboflow_internal_secret = func_kwargs.get(\"service_secret\")\n\n        return {\n            \"source\": source,\n            \"api_key\": usage_api_key,\n            \"category\": category,\n            \"resource_details\": resource_details,\n            \"resource_id\": resource_id,\n            \"inference_test_run\": usage_inference_test_run,\n            \"fps\": usage_fps,\n            \"execution_duration\": execution_duration,\n            \"roboflow_service_name\": roboflow_service_name,\n            \"roboflow_internal_secret\": roboflow_internal_secret,\n        }\n\n    @staticmethod\n    def _compute_execution_duration(t1: float, t2: float) -> float:\n        raw = t2 - t1\n        if not GCP_SERVERLESS:\n            return raw\n        if apply_duration_minimum is not None:\n            try:\n                if apply_duration_minimum.get():\n                    return max(raw, 0.1)\n                return raw\n            except LookupError:\n                pass\n        return max(raw, 0.1)\n\n    def __call__(\n        self, category: Literal[\"model\", \"workflows\", \"request\"]\n    ) -> Callable[P, T]:\n        def decorator(func: Callable[P, T]) -> Callable[P, T]:\n            @wraps(func)\n            def sync_wrapper(\n                *args: P.args,\n                usage_fps: float = 0,\n                usage_api_key: APIKey = \"\",\n                usage_workflow_id: str = \"\",\n                usage_workflow_preview: bool = False,\n                usage_inference_test_run: bool = False,\n                usage_billable: bool = True,\n                **kwargs: P.kwargs,\n            ) -> T:\n                try:\n                    t1 = time.time()\n                    res = func(*args, **kwargs)\n                    t2 = time.time()\n                    execution_duration = self._compute_execution_duration(t1, t2)\n                    self.record_usage(\n                        **self._extract_usage_params_from_func_kwargs(\n                            usage_fps=usage_fps,\n                            usage_api_key=usage_api_key,\n                            usage_workflow_id=usage_workflow_id,\n                            usage_workflow_preview=usage_workflow_preview,\n                            usage_inference_test_run=usage_inference_test_run,\n                            usage_billable=usage_billable,\n                            execution_duration=execution_duration,\n                            func=func,\n                            category=category,\n                            exc=None,\n                            args=args,\n                            kwargs=kwargs,\n                        )\n                    )\n                except Exception as exc:\n                    t2 = time.time()\n                    execution_duration = self._compute_execution_duration(t1, t2)\n                    exc_type = type(exc).__name__\n                    if hasattr(exc, \"inner_error_type\"):\n                        exc_type = exc.inner_error_type\n                    exc_str = f\"{exc_type}: {str(exc)}\"\n                    self.record_usage(\n                        **self._extract_usage_params_from_func_kwargs(\n                            usage_fps=usage_fps,\n                            usage_api_key=usage_api_key,\n                            usage_workflow_id=usage_workflow_id,\n                            usage_workflow_preview=usage_workflow_preview,\n                            usage_inference_test_run=usage_inference_test_run,\n                            usage_billable=usage_billable,\n                            execution_duration=execution_duration,\n                            func=func,\n                            category=category,\n                            exc=exc_str,\n                            args=args,\n                            kwargs=kwargs,\n                        )\n                    )\n                    raise\n                return res\n\n            @wraps(func)\n            async def async_wrapper(\n                *args: P.args,\n                usage_fps: float = 0,\n                usage_api_key: APIKey = \"\",\n                usage_workflow_id: str = \"\",\n                usage_workflow_preview: bool = False,\n                usage_inference_test_run: bool = False,\n                usage_billable: bool = True,\n                **kwargs: P.kwargs,\n            ) -> T:\n                try:\n                    t1 = time.time()\n                    res = await func(*args, **kwargs)\n                    t2 = time.time()\n                    execution_duration = self._compute_execution_duration(t1, t2)\n                    await self.async_record_usage(\n                        **self._extract_usage_params_from_func_kwargs(\n                            usage_fps=usage_fps,\n                            usage_api_key=usage_api_key,\n                            usage_workflow_id=usage_workflow_id,\n                            usage_workflow_preview=usage_workflow_preview,\n                            usage_inference_test_run=usage_inference_test_run,\n                            usage_billable=usage_billable,\n                            execution_duration=execution_duration,\n                            func=func,\n                            category=category,\n                            exc=None,\n                            args=args,\n                            kwargs=kwargs,\n                        )\n                    )\n                except Exception as exc:\n                    t2 = time.time()\n                    execution_duration = self._compute_execution_duration(t1, t2)\n                    exc_type = type(exc).__name__\n                    if hasattr(exc, \"inner_error_type\"):\n                        exc_type = exc.inner_error_type\n                    exc_str = f\"{exc_type}: {str(exc)}\"\n                    await self.async_record_usage(\n                        **self._extract_usage_params_from_func_kwargs(\n                            usage_fps=usage_fps,\n                            usage_api_key=usage_api_key,\n                            usage_workflow_id=usage_workflow_id,\n                            usage_workflow_preview=usage_workflow_preview,\n                            usage_inference_test_run=usage_inference_test_run,\n                            usage_billable=usage_billable,\n                            execution_duration=execution_duration,\n                            func=func,\n                            category=category,\n                            exc=exc_str,\n                            args=args,\n                            kwargs=kwargs,\n                        )\n                    )\n                    raise\n                return res\n\n            if asyncio.iscoroutinefunction(func):\n                return async_wrapper\n            else:\n                return sync_wrapper\n\n        return decorator\n\n    def _cleanup(self):\n        self._terminate_collector_thread.set()\n        self._collector_thread.join()\n        self._terminate_sender_thread.set()\n        self._sender_thread.join()\n\n\nusage_collector = UsageCollector()\n",
    "patch": null
  },
  {
    "trace_id": "e50182e7-6211-48fb-9500-0aa48db3cbf1",
    "function_name": "maybe_register_datapoint_at_roboflow",
    "file_path": "inference/core/workflows/core_steps/sinks/roboflow/dataset_upload/v2.py",
    "speedup_x": 0.47185871778874366,
    "review_quality": "high",
    "pre_optimization_commit": "5172cfc4e59a6b29dd81a1c98238759ced9f16a0",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def maybe_register_datapoint_at_roboflow(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    usage_quota_name: str,\n    data_percentage: float,\n    persist_predictions: bool,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    fire_and_forget: bool,\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    background_tasks: Optional[BackgroundTasks],\n    thread_pool_executor: Optional[ThreadPoolExecutor],\n    api_key: str,\n    image_name: Optional[str] = None,\n) -> Tuple[bool, str]:\n    normalised_probability = data_percentage / 100\n    if random.random() < normalised_probability:\n        return register_datapoint_at_roboflow(\n            image=image,\n            prediction=prediction,\n            target_project=target_project,\n            usage_quota_name=usage_quota_name,\n            persist_predictions=persist_predictions,\n            minutely_usage_limit=minutely_usage_limit,\n            hourly_usage_limit=hourly_usage_limit,\n            daily_usage_limit=daily_usage_limit,\n            max_image_size=max_image_size,\n            compression_level=compression_level,\n            registration_tags=registration_tags,\n            fire_and_forget=fire_and_forget,\n            labeling_batch_prefix=labeling_batch_prefix,\n            new_labeling_batch_frequency=new_labeling_batch_frequency,\n            cache=cache,\n            background_tasks=background_tasks,\n            thread_pool_executor=thread_pool_executor,\n            api_key=api_key,\n            image_name=image_name,\n        )\n    return False, \"Registration skipped due to sampling settings\"\n",
    "optimized_function_code": "import random\nimport supervision as sv\nfrom concurrent.futures import ThreadPoolExecutor\nfrom fastapi import BackgroundTasks\nfrom inference.core.cache.base import BaseCache\nfrom inference.core.workflows.core_steps.sinks.roboflow.dataset_upload.v1 import register_datapoint_at_roboflow\nfrom inference.core.workflows.execution_engine.entities.base import WorkflowImageData\nfrom typing import List, Literal, Optional, Tuple, Union\n\nBatchCreationFrequency = Literal[\"never\", \"daily\", \"weekly\", \"monthly\"]\n\n\ndef maybe_register_datapoint_at_roboflow(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    usage_quota_name: str,\n    data_percentage: float,\n    persist_predictions: bool,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    fire_and_forget: bool,\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    background_tasks: Optional[BackgroundTasks],\n    thread_pool_executor: Optional[ThreadPoolExecutor],\n    api_key: str,\n    image_name: Optional[str] = None,\n) -> Tuple[bool, str]:\n    normalised_probability = data_percentage / 100\n    if random.random() < normalised_probability:\n        return register_datapoint_at_roboflow(\n            image,\n            prediction,\n            target_project,\n            usage_quota_name,\n            persist_predictions,\n            minutely_usage_limit,\n            hourly_usage_limit,\n            daily_usage_limit,\n            max_image_size,\n            compression_level,\n            registration_tags,\n            fire_and_forget,\n            labeling_batch_prefix,\n            new_labeling_batch_frequency,\n            cache,\n            background_tasks,\n            thread_pool_executor,\n            api_key,\n            image_name,\n        )\n    return False, \"Registration skipped due to sampling settings\"",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/sinks/roboflow/dataset_upload/v1.py\nimport supervision as sv\nfrom concurrent.futures import ThreadPoolExecutor\nfrom fastapi import BackgroundTasks\nfrom inference.core.cache.base import BaseCache\nfrom inference.core.workflows.execution_engine.entities.base import WorkflowImageData\nfrom typing import List, Literal, Optional, Tuple, Union\n\nWORKSPACE_NAME_CACHE_EXPIRE = 900  # 15 min\nTIMESTAMP_FORMAT = \"%Y_%m_%d\"\nDUPLICATED_STATUS = \"Duplicated image\"\nBatchCreationFrequency = Literal[\"never\", \"daily\", \"weekly\", \"monthly\"]\n\n\ndef register_datapoint_at_roboflow(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    usage_quota_name: str,\n    persist_predictions: bool,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    fire_and_forget: bool,\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    background_tasks: Optional[BackgroundTasks],\n    thread_pool_executor: Optional[ThreadPoolExecutor],\n    api_key: str,\n    image_name: Optional[str] = None,\n) -> Tuple[bool, str]:\n    if fire_and_forget and background_tasks:\n        background_tasks.add_task(\n            execute_registration,\n            image,\n            prediction,\n            target_project,\n            persist_predictions,\n            usage_quota_name,\n            minutely_usage_limit,\n            hourly_usage_limit,\n            daily_usage_limit,\n            max_image_size,\n            compression_level,\n            registration_tags,\n            labeling_batch_prefix,\n            new_labeling_batch_frequency,\n            cache,\n            api_key,\n            image_name,\n        )\n        return False, \"Element registration happens in the background task\"\n    if fire_and_forget and thread_pool_executor:\n        thread_pool_executor.submit(\n            execute_registration,\n            image,\n            prediction,\n            target_project,\n            persist_predictions,\n            usage_quota_name,\n            minutely_usage_limit,\n            hourly_usage_limit,\n            daily_usage_limit,\n            max_image_size,\n            compression_level,\n            registration_tags,\n            labeling_batch_prefix,\n            new_labeling_batch_frequency,\n            cache,\n            api_key,\n            image_name,\n        )\n        return False, \"Element registration happens in the background task\"\n    return execute_registration(\n        image,\n        prediction,\n        target_project,\n        persist_predictions,\n        usage_quota_name,\n        minutely_usage_limit,\n        hourly_usage_limit,\n        daily_usage_limit,\n        max_image_size,\n        compression_level,\n        registration_tags,\n        labeling_batch_prefix,\n        new_labeling_batch_frequency,\n        cache,\n        api_key,\n        image_name,\n    )\n\n\nRECREATION_INTERVAL2TIMESTAMP_GENERATOR = {\n    \"daily\": generate_today_timestamp,\n    \"weekly\": generate_start_timestamp_for_this_week,\n    \"monthly\": generate_start_timestamp_for_this_month,\n}\n```\n```python:inference/core/workflows/core_steps/sinks/roboflow/dataset_upload/v2.py\nimport random\nimport supervision as sv\nfrom concurrent.futures import ThreadPoolExecutor\nfrom fastapi import BackgroundTasks\nfrom inference.core.cache.base import BaseCache\nfrom inference.core.workflows.core_steps.sinks.roboflow.dataset_upload.v1 import register_datapoint_at_roboflow\nfrom inference.core.workflows.execution_engine.entities.base import WorkflowImageData\nfrom typing import List, Literal, Optional, Tuple, Union\n\nBatchCreationFrequency = Literal[\"never\", \"daily\", \"weekly\", \"monthly\"]\n\n\ndef maybe_register_datapoint_at_roboflow(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    usage_quota_name: str,\n    data_percentage: float,\n    persist_predictions: bool,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    fire_and_forget: bool,\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    background_tasks: Optional[BackgroundTasks],\n    thread_pool_executor: Optional[ThreadPoolExecutor],\n    api_key: str,\n    image_name: Optional[str] = None,\n) -> Tuple[bool, str]:\n    normalised_probability = data_percentage / 100\n    if random.random() < normalised_probability:\n        return register_datapoint_at_roboflow(\n            image,\n            prediction,\n            target_project,\n            usage_quota_name,\n            persist_predictions,\n            minutely_usage_limit,\n            hourly_usage_limit,\n            daily_usage_limit,\n            max_image_size,\n            compression_level,\n            registration_tags,\n            fire_and_forget,\n            labeling_batch_prefix,\n            new_labeling_batch_frequency,\n            cache,\n            background_tasks,\n            thread_pool_executor,\n            api_key,\n            image_name,\n        )\n    return False, \"Registration skipped due to sampling settings\"\n```",
    "optimized_function_only": "def maybe_register_datapoint_at_roboflow(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    usage_quota_name: str,\n    data_percentage: float,\n    persist_predictions: bool,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    fire_and_forget: bool,\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    background_tasks: Optional[BackgroundTasks],\n    thread_pool_executor: Optional[ThreadPoolExecutor],\n    api_key: str,\n    image_name: Optional[str] = None,\n) -> Tuple[bool, str]:\n    normalised_probability = data_percentage / 100\n    if random.random() < normalised_probability:\n        return register_datapoint_at_roboflow(\n            image,\n            prediction,\n            target_project,\n            usage_quota_name,\n            persist_predictions,\n            minutely_usage_limit,\n            hourly_usage_limit,\n            daily_usage_limit,\n            max_image_size,\n            compression_level,\n            registration_tags,\n            fire_and_forget,\n            labeling_batch_prefix,\n            new_labeling_batch_frequency,\n            cache,\n            background_tasks,\n            thread_pool_executor,\n            api_key,\n            image_name,\n        )\n    return False, \"Registration skipped due to sampling settings\"",
    "original_file_content": "import random\nfrom concurrent.futures import ThreadPoolExecutor\nfrom typing import List, Literal, Optional, Tuple, Type, Union\n\nimport supervision as sv\nfrom fastapi import BackgroundTasks\nfrom pydantic import AliasChoices, ConfigDict, Field\nfrom typing_extensions import Annotated\n\nfrom inference.core.cache.base import BaseCache\nfrom inference.core.workflows.core_steps.sinks.roboflow.dataset_upload.v1 import (\n    register_datapoint_at_roboflow,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    BOOLEAN_KIND,\n    CLASSIFICATION_PREDICTION_KIND,\n    FLOAT_KIND,\n    IMAGE_KIND,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    KEYPOINT_DETECTION_PREDICTION_KIND,\n    LIST_OF_VALUES_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    ROBOFLOW_PROJECT_KIND,\n    STRING_KIND,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nFloatZeroToHundred = Annotated[float, Field(ge=0.0, le=100.0)]\n\nSHORT_DESCRIPTION = \"Save images and predictions to your Roboflow Dataset.\"\n\nLONG_DESCRIPTION = \"\"\"\nUpload images and model predictions to a Roboflow dataset for active learning, model improvement, and data collection, with configurable usage quotas, probabilistic sampling, batch organization, image compression, and optional annotation persistence.\n\n## How This Block Works\n\nThis block uploads workflow images and predictions to your Roboflow dataset for storage, labeling, and model training. The block:\n\n1. Takes images and optional model predictions (object detection, instance segmentation, keypoint detection, or classification) as input\n2. Validates the Roboflow API key is available (required for uploading)\n3. Applies probabilistic sampling based on `data_percentage` setting, randomly selecting a percentage of inputs to upload (e.g., 50% uploads half the data, 100% uploads everything)\n4. Checks usage quotas (minutely, hourly, daily limits) to ensure uploads stay within configured rate limits for active learning strategies\n5. Prepares images by resizing if they exceed maximum size (maintaining aspect ratio) and compressing to specified quality level\n6. Generates labeling batch names based on the prefix and batch creation frequency (never, daily, weekly, or monthly), organizing uploaded data into batches\n7. Optionally persists model predictions as annotations if `persist_predictions` is enabled, allowing predictions to serve as pre-labels for review and correction\n8. Attaches registration tags to images for organization and filtering in the Roboflow platform\n9. Registers the image (and annotations if enabled) to the specified Roboflow project via the Roboflow API\n10. Executes synchronously or asynchronously based on `fire_and_forget` setting, allowing non-blocking uploads for faster workflow execution\n11. Returns error status and messages indicating upload success, failure, or sampling skip\n\nThe block supports active learning workflows by implementing usage quotas that prevent excessive data collection, helping focus on collecting valuable training data within rate limits. The probabilistic sampling feature (new in v2) allows you to randomly sample a percentage of data for upload, enabling cost-effective data collection strategies where you want to collect representative samples rather than all data. Images are organized into labeling batches that can be automatically recreated on a schedule (daily, weekly, monthly), making it easier to manage and review collected data over time. The block can operate in fire-and-forget mode for asynchronous execution, allowing workflows to continue processing without waiting for uploads to complete, or synchronously for debugging and error handling.\n\n## Version Differences (v2 vs v1)\n\n**New Features in v2:**\n\n- **Probabilistic Data Sampling**: Added `data_percentage` parameter (0-100%) that enables random sampling of data for upload. This allows you to upload only a percentage of workflow inputs (e.g., 25% samples one in four images), reducing storage and annotation costs while still collecting representative data. When sampling skips an upload, the block returns a message indicating the skip.\n\n- **Improved Default Settings**: \n  - `max_image_size` default increased from (512, 512) to (1920, 1080) for higher resolution data collection\n  - `compression_level` default increased from 75 to 95 for better image quality preservation\n\n**Behavior Changes:**\n\n- By default, `data_percentage` is set to 100, so v2 behaves identically to v1 unless sampling is explicitly configured\n- The block now uses probabilistic sampling before quota checking and image preparation, allowing efficient filtering before resource-intensive operations\n\n## Requirements\n\n**API Key Required**: This block requires a valid Roboflow API key to upload data. The API key must be configured in your environment or workflow configuration. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve an API key.\n\n## Common Use Cases\n\n- **Active Learning Data Collection**: Collect images and predictions from production environments where models struggle or are uncertain (e.g., low-confidence detections, edge cases), enabling iterative model improvement by gathering challenging examples for retraining\n- **Probabilistic Data Sampling**: Use `data_percentage` to randomly sample a subset of data for upload (e.g., upload 20% of all detections, 50% of low-confidence cases), enabling cost-effective data collection strategies that reduce storage and annotation overhead while maintaining dataset diversity\n- **Production Data Logging**: Continuously upload production inference data to Roboflow datasets for monitoring, analysis, and future model training, creating a growing dataset from real-world deployments\n- **Pre-Labeled Data Collection**: Upload images with model predictions as pre-labels (when `persist_predictions` is enabled), accelerating annotation workflows by providing initial labels that can be reviewed and corrected rather than starting from scratch\n- **Stratified Data Sampling**: Combine probabilistic sampling with rate limiting and quotas to selectively collect data based on specific criteria (e.g., sample 30% of detections that pass filters), ensuring diverse and balanced dataset collection without overwhelming storage or annotation resources\n- **Batch-Based Labeling Workflows**: Organize uploaded data into batches with automatic recreation schedules (daily, weekly, monthly), making it easier to manage labeling tasks, track progress, and organize data collection efforts over time\n\n## Connecting to Other Blocks\n\nThis block receives data from workflow steps and uploads it to Roboflow:\n\n- **After detection or analysis blocks** (e.g., Object Detection Model, Instance Segmentation Model, Classification Model, Keypoint Detection Model) to upload images along with their predictions, enabling active learning by collecting inference data with model outputs for annotation and retraining\n- **After filtering or analytics blocks** (e.g., Detections Filter, Continue If, Overlap Filter) to selectively upload only specific types of data (e.g., low-confidence detections, overlapping objects, specific classes), focusing data collection on valuable edge cases or interesting scenarios\n- **After rate limiter blocks** (e.g., Rate Limiter) to throttle upload frequency and stay within usage quotas, ensuring controlled data collection that respects rate limits and prevents excessive storage usage\n- **Image inputs or preprocessing blocks** to upload raw images or processed images (e.g., crops, transformed images) without predictions, enabling collection of image data for future labeling or analysis\n- **Conditional workflows** using flow control blocks (e.g., Continue If) to upload data only when certain conditions are met (e.g., upload only when detection count exceeds threshold, upload only errors or failures), enabling selective data collection based on workflow state\n- **Batch processing workflows** where multiple images or predictions are generated, allowing bulk upload of workflow outputs to Roboflow datasets with probabilistic sampling for organized and cost-effective data collection\n\"\"\"\n\nWORKSPACE_NAME_CACHE_EXPIRE = 900  # 15 min\nTIMESTAMP_FORMAT = \"%Y_%m_%d\"\nDUPLICATED_STATUS = \"Duplicated image\"\nBatchCreationFrequency = Literal[\"never\", \"daily\", \"weekly\", \"monthly\"]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Roboflow Dataset Upload\",\n            \"version\": \"v2\",\n            \"short_description\": SHORT_DESCRIPTION,\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"sink\",\n            \"ui_manifest\": {\n                \"section\": \"data_storage\",\n                \"icon\": \"fal fa-upload\",\n                \"blockPriority\": 0,\n                \"popular\": True,\n                \"requires_rf_key\": True,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/roboflow_dataset_upload@v2\"]\n    images: Selector(kind=[IMAGE_KIND]) = Field(\n        title=\"Image\",\n        description=\"Image(s) to upload to the Roboflow dataset. Can be a single image or batch of images from workflow inputs or processing steps. Images are randomly sampled based on data_percentage, resized if they exceed max_image_size, and compressed before uploading. Supports batch processing.\",\n        examples=[\"$inputs.image\", \"$steps.cropping.crops\"],\n        validation_alias=AliasChoices(\"images\", \"image\"),\n    )\n    target_project: Union[Selector(kind=[ROBOFLOW_PROJECT_KIND]), str] = Field(\n        description=\"Roboflow project identifier where uploaded images and annotations will be saved. Must be a valid project in your Roboflow workspace. The project name can be specified directly or referenced from workflow inputs.\",\n        examples=[\"my_dataset\", \"$inputs.target_al_dataset\"],\n    )\n    predictions: Optional[\n        Selector(\n            kind=[\n                OBJECT_DETECTION_PREDICTION_KIND,\n                INSTANCE_SEGMENTATION_PREDICTION_KIND,\n                KEYPOINT_DETECTION_PREDICTION_KIND,\n                CLASSIFICATION_PREDICTION_KIND,\n            ]\n        )\n    ] = Field(\n        default=None,\n        description=\"Optional model predictions to upload alongside images. Predictions are saved as annotations (pre-labels) in the Roboflow dataset when persist_predictions is enabled, allowing predictions to serve as starting points for annotation review and correction. Supports object detection, instance segmentation, keypoint detection, and classification predictions. If None, only images are uploaded.\",\n        examples=[\"$steps.object_detection_model.predictions\"],\n        json_schema_extra={\"always_visible\": True},\n    )\n    data_percentage: Union[FloatZeroToHundred, Selector(kind=[FLOAT_KIND])] = Field(\n        default=100,\n        description=\"Percentage of input data (0.0 to 100.0) to randomly sample for upload. This enables probabilistic data collection where only a subset of inputs are uploaded, reducing storage and annotation costs. For example, 25.0 uploads approximately 25% of images (one in four on average), 50.0 uploads half, and 100.0 uploads everything (no sampling). Random sampling occurs before quota checking and image processing, making it efficient for large-scale data collection workflows.\",\n        examples=[100, 25, 50, \"$inputs.sampling_rate\"],\n    )\n    minutely_usage_limit: int = Field(\n        default=10,\n        description=\"Maximum number of image uploads allowed per minute for this quota. Part of the usage quota system that enforces rate limits for active learning data collection. Uploads exceeding this limit are skipped to prevent excessive data collection. Works together with hourly_usage_limit and daily_usage_limit to provide multi-level rate limiting. Note: This quota is checked after probabilistic sampling via data_percentage.\",\n        examples=[10, 60],\n    )\n    hourly_usage_limit: int = Field(\n        default=100,\n        description=\"Maximum number of image uploads allowed per hour for this quota. Part of the usage quota system that enforces rate limits for active learning data collection. Uploads exceeding this limit are skipped to prevent excessive data collection. Works together with minutely_usage_limit and daily_usage_limit to provide multi-level rate limiting. Note: This quota is checked after probabilistic sampling via data_percentage.\",\n        examples=[10, 60],\n    )\n    daily_usage_limit: int = Field(\n        default=1000,\n        description=\"Maximum number of image uploads allowed per day for this quota. Part of the usage quota system that enforces rate limits for active learning data collection. Uploads exceeding this limit are skipped to prevent excessive data collection. Works together with minutely_usage_limit and hourly_usage_limit to provide multi-level rate limiting. Note: This quota is checked after probabilistic sampling via data_percentage.\",\n        examples=[10, 60],\n    )\n    usage_quota_name: str = Field(\n        description=\"Unique identifier for tracking usage quotas (minutely, hourly, daily limits). Used internally to manage rate limiting across multiple upload operations. Each unique quota name maintains separate counters, allowing different upload strategies or data collection workflows to have independent rate limits.\",\n        examples=[\"quota-for-data-sampling-1\"],\n        json_schema_extra={\"hidden\": True},\n    )\n    max_image_size: Tuple[int, int] = Field(\n        default=(1920, 1080),\n        description=\"Maximum dimensions (width, height) for uploaded images. Images exceeding these dimensions are automatically resized while preserving aspect ratio before uploading. Default is (1920, 1080) for higher resolution data collection. Use smaller sizes (e.g., (512, 512)) for efficient storage and faster uploads, or keep the default for preserving image quality.\",\n        examples=[(1920, 1080), (512, 512)],\n    )\n    compression_level: int = Field(\n        default=95,\n        gt=0,\n        le=100,\n        description=\"JPEG compression quality level for uploaded images, ranging from 1 (highest compression, smallest file size, lower quality) to 100 (no compression, largest file size, highest quality). Default is 95 for better image quality preservation. Higher values preserve more image quality but increase storage and bandwidth usage. Typical values range from 70-95 for balanced quality and size.\",\n        examples=[95, 75],\n    )\n    registration_tags: Union[\n        List[Union[Selector(kind=[STRING_KIND]), str]],\n        Selector(kind=[LIST_OF_VALUES_KIND]),\n    ] = Field(\n        default_factory=list,\n        description=\"List of tags to attach to uploaded images for organization and filtering in Roboflow. Tags can be static strings (e.g., 'location-florida', 'camera-1') or dynamic values from workflow inputs. Tags help organize collected data, filter images in Roboflow, and add metadata for dataset management. Can be an empty list if no tags are needed.\",\n        examples=[\n            [\"location-florida\", \"factory-name\", \"$inputs.dynamic_tag\"],\n            \"$inputs.tags\",\n        ],\n    )\n    persist_predictions: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=True,\n        description=\"If True, model predictions are saved as annotations (pre-labels) in the Roboflow dataset alongside images. This enables predictions to serve as starting points for annotation, allowing reviewers to correct or approve labels rather than creating them from scratch. If False, only images are uploaded without annotations. Enabling this accelerates annotation workflows by providing initial labels.\",\n        examples=[True, False, \"$inputs.persist_predictions\"],\n    )\n    disable_sink: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=False,\n        description=\"If True, the block execution is disabled and no uploads occur. This allows temporarily disabling data collection without removing the block from workflows, useful for testing, debugging, or conditional data collection. When disabled, returns a message indicating the sink was disabled. Default is False (uploads enabled).\",\n        examples=[True, \"$inputs.disable_active_learning\"],\n    )\n    fire_and_forget: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=True,\n        description=\"If True, uploads execute asynchronously (fire-and-forget mode), allowing the workflow to continue immediately without waiting for upload completion. This improves workflow performance but prevents error handling. If False, uploads execute synchronously, blocking workflow execution until completion and allowing proper error handling and status reporting. Use async mode (True) for production workflows where speed is prioritized, and sync mode (False) for debugging or when error handling is critical.\",\n    )\n    labeling_batch_prefix: Union[str, Selector(kind=[STRING_KIND])] = Field(\n        default=\"workflows_data_collector\",\n        description=\"Prefix used to generate labeling batch names for organizing uploaded images in Roboflow. Combined with the batch recreation frequency and timestamps to create batch names like 'workflows_data_collector_2024_01_15'. Batches help organize collected data for labeling, making it easier to manage and review uploaded images in groups. Can be customized to match your organization scheme.\",\n        examples=[\"my_labeling_batch_name\"],\n    )\n    labeling_batches_recreation_frequency: BatchCreationFrequency = Field(\n        default=\"never\",\n        description=\"Frequency at which new labeling batches are automatically created for uploaded images. Options: 'never' (all images go to the same batch), 'daily' (new batch each day), 'weekly' (new batch each week), 'monthly' (new batch each month). Batch timestamps are appended to the labeling_batch_prefix to create unique batch names. Automatically organizing uploads into time-based batches simplifies dataset management and makes it easier to track and review collected data over time.\",\n        examples=[\"never\", \"daily\"],\n    )\n    image_name: Optional[Union[str, Selector(kind=[STRING_KIND])]] = Field(\n        default=None,\n        description=\"Optional custom name for the uploaded image. This is useful when you want to preserve the original filename or use a meaningful identifier (e.g., serial number, timestamp) for the image in the Roboflow dataset. The name should not include file extension. If not provided, a UUID will be generated automatically.\",\n        examples=[\"serial_12345\", \"camera1_frame_001\", \"$inputs.filename\"],\n    )\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return [\"images\", \"predictions\", \"image_name\"]\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"error_status\", kind=[BOOLEAN_KIND]),\n            OutputDefinition(name=\"message\", kind=[STRING_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass RoboflowDatasetUploadBlockV2(WorkflowBlock):\n\n    def __init__(\n        self,\n        cache: BaseCache,\n        api_key: Optional[str],\n        background_tasks: Optional[BackgroundTasks],\n        thread_pool_executor: Optional[ThreadPoolExecutor],\n    ):\n        self._cache = cache\n        self._api_key = api_key\n        self._background_tasks = background_tasks\n        self._thread_pool_executor = thread_pool_executor\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"cache\", \"api_key\", \"background_tasks\", \"thread_pool_executor\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        predictions: Optional[Batch[Union[sv.Detections, dict]]],\n        target_project: str,\n        usage_quota_name: str,\n        data_percentage: float,\n        minutely_usage_limit: int,\n        persist_predictions: bool,\n        hourly_usage_limit: int,\n        daily_usage_limit: int,\n        max_image_size: Tuple[int, int],\n        compression_level: int,\n        registration_tags: List[str],\n        disable_sink: bool,\n        fire_and_forget: bool,\n        labeling_batch_prefix: str,\n        labeling_batches_recreation_frequency: BatchCreationFrequency,\n        image_name: Optional[Batch[Optional[str]]] = None,\n    ) -> BlockResult:\n        if self._api_key is None:\n            raise ValueError(\n                \"RoboflowDataCollector block cannot run without Roboflow API key. \"\n                \"If you do not know how to get API key - visit \"\n                \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to \"\n                \"retrieve one.\"\n            )\n        if disable_sink:\n            return [\n                {\n                    \"error_status\": False,\n                    \"message\": \"Sink was disabled by parameter `disable_sink`\",\n                }\n                for _ in range(len(images))\n            ]\n        result = []\n        predictions = [None] * len(images) if predictions is None else predictions\n        image_names = [None] * len(images) if image_name is None else image_name\n        for image, prediction, img_name in zip(images, predictions, image_names):\n            error_status, message = maybe_register_datapoint_at_roboflow(\n                image=image,\n                prediction=prediction,\n                target_project=target_project,\n                usage_quota_name=usage_quota_name,\n                data_percentage=data_percentage,\n                persist_predictions=persist_predictions,\n                minutely_usage_limit=minutely_usage_limit,\n                hourly_usage_limit=hourly_usage_limit,\n                daily_usage_limit=daily_usage_limit,\n                max_image_size=max_image_size,\n                compression_level=compression_level,\n                registration_tags=registration_tags,\n                fire_and_forget=fire_and_forget,\n                labeling_batch_prefix=labeling_batch_prefix,\n                new_labeling_batch_frequency=labeling_batches_recreation_frequency,\n                cache=self._cache,\n                background_tasks=self._background_tasks,\n                thread_pool_executor=self._thread_pool_executor,\n                api_key=self._api_key,\n                image_name=img_name,\n            )\n            result.append({\"error_status\": error_status, \"message\": message})\n        return result\n\n\ndef maybe_register_datapoint_at_roboflow(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    usage_quota_name: str,\n    data_percentage: float,\n    persist_predictions: bool,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    fire_and_forget: bool,\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    background_tasks: Optional[BackgroundTasks],\n    thread_pool_executor: Optional[ThreadPoolExecutor],\n    api_key: str,\n    image_name: Optional[str] = None,\n) -> Tuple[bool, str]:\n    normalised_probability = data_percentage / 100\n    if random.random() < normalised_probability:\n        return register_datapoint_at_roboflow(\n            image=image,\n            prediction=prediction,\n            target_project=target_project,\n            usage_quota_name=usage_quota_name,\n            persist_predictions=persist_predictions,\n            minutely_usage_limit=minutely_usage_limit,\n            hourly_usage_limit=hourly_usage_limit,\n            daily_usage_limit=daily_usage_limit,\n            max_image_size=max_image_size,\n            compression_level=compression_level,\n            registration_tags=registration_tags,\n            fire_and_forget=fire_and_forget,\n            labeling_batch_prefix=labeling_batch_prefix,\n            new_labeling_batch_frequency=new_labeling_batch_frequency,\n            cache=cache,\n            background_tasks=background_tasks,\n            thread_pool_executor=thread_pool_executor,\n            api_key=api_key,\n            image_name=image_name,\n        )\n    return False, \"Registration skipped due to sampling settings\"\n",
    "patch": null
  },
  {
    "trace_id": "5a3ae559-9d07-4338-9bcd-ced8f44cfaee",
    "function_name": "RoboflowDatasetUploadBlockV1.run",
    "file_path": "inference/core/workflows/core_steps/sinks/roboflow/dataset_upload/v1.py",
    "speedup_x": 0.2623346563771581,
    "review_quality": "high",
    "pre_optimization_commit": "c20359386c628a08bde69f5f3f780cedd782c50c",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        predictions: Optional[Batch[Union[sv.Detections, dict]]],\n        target_project: str,\n        usage_quota_name: str,\n        minutely_usage_limit: int,\n        persist_predictions: bool,\n        hourly_usage_limit: int,\n        daily_usage_limit: int,\n        max_image_size: Tuple[int, int],\n        compression_level: int,\n        registration_tags: List[str],\n        disable_sink: bool,\n        fire_and_forget: bool,\n        labeling_batch_prefix: str,\n        labeling_batches_recreation_frequency: BatchCreationFrequency,\n        image_name: Optional[Batch[Optional[str]]] = None,\n    ) -> BlockResult:\n        if self._api_key is None:\n            raise ValueError(\n                \"RoboflowDataCollector block cannot run without Roboflow API key. \"\n                \"If you do not know how to get API key - visit \"\n                \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to \"\n                \"retrieve one.\"\n            )\n        if disable_sink:\n            return [\n                {\n                    \"error_status\": False,\n                    \"message\": \"Sink was disabled by parameter `disable_sink`\",\n                }\n                for _ in range(len(images))\n            ]\n        result = []\n        predictions = [None] * len(images) if predictions is None else predictions\n        image_names = [None] * len(images) if image_name is None else image_name\n        for image, prediction, img_name in zip(images, predictions, image_names):\n            error_status, message = register_datapoint_at_roboflow(\n                image=image,\n                prediction=prediction,\n                target_project=target_project,\n                usage_quota_name=usage_quota_name,\n                persist_predictions=persist_predictions,\n                minutely_usage_limit=minutely_usage_limit,\n                hourly_usage_limit=hourly_usage_limit,\n                daily_usage_limit=daily_usage_limit,\n                max_image_size=max_image_size,\n                compression_level=compression_level,\n                registration_tags=registration_tags,\n                fire_and_forget=fire_and_forget,\n                labeling_batch_prefix=labeling_batch_prefix,\n                new_labeling_batch_frequency=labeling_batches_recreation_frequency,\n                cache=self._cache,\n                background_tasks=self._background_tasks,\n                thread_pool_executor=self._thread_pool_executor,\n                api_key=self._api_key,\n                image_name=img_name,\n            )\n            result.append({\"error_status\": error_status, \"message\": message})\n        return result\n",
    "optimized_function_code": "from __future__ import annotations\n\nfrom concurrent.futures import ThreadPoolExecutor\nfrom functools import partial\nfrom typing import List, Literal, Optional, Tuple, Union\n\nimport supervision as sv\nfrom fastapi import BackgroundTasks\nfrom inference.core.cache.base import BaseCache\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch, WorkflowImageData)\nfrom inference.core.workflows.prototypes.block import (BlockResult,\n                                                       WorkflowBlock)\n\nWORKSPACE_NAME_CACHE_EXPIRE = 900  # 15 min\nTIMESTAMP_FORMAT = \"%Y_%m_%d\"\nDUPLICATED_STATUS = \"Duplicated image\"\nBatchCreationFrequency = Literal[\"never\", \"daily\", \"weekly\", \"monthly\"]\n\n\nclass RoboflowDatasetUploadBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        cache: BaseCache,\n        api_key: Optional[str],\n        background_tasks: Optional[BackgroundTasks],\n        thread_pool_executor: Optional[ThreadPoolExecutor],\n    ):\n        self._cache = cache\n        self._api_key = api_key\n        self._background_tasks = background_tasks\n        self._thread_pool_executor = thread_pool_executor\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        predictions: Optional[Batch[Union[sv.Detections, dict]]],\n        target_project: str,\n        usage_quota_name: str,\n        minutely_usage_limit: int,\n        persist_predictions: bool,\n        hourly_usage_limit: int,\n        daily_usage_limit: int,\n        max_image_size: Tuple[int, int],\n        compression_level: int,\n        registration_tags: List[str],\n        disable_sink: bool,\n        fire_and_forget: bool,\n        labeling_batch_prefix: str,\n        labeling_batches_recreation_frequency: BatchCreationFrequency,\n        image_name: Optional[Batch[Optional[str]]] = None,\n    ) -> BlockResult:\n        if self._api_key is None:\n            raise ValueError(\n                \"RoboflowDataCollector block cannot run without Roboflow API key. \"\n                \"If you do not know how to get API key - visit \"\n                \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to \"\n                \"retrieve one.\"\n            )\n        if disable_sink:\n            return [\n                {\n                    \"error_status\": False,\n                    \"message\": \"Sink was disabled by parameter `disable_sink`\",\n                }\n                for _ in range(len(images))\n            ]\n        predictions = [None] * len(images) if predictions is None else predictions\n        image_names = [None] * len(images) if image_name is None else image_name\n\n        # If fire-and-forget and we have a background mechanism, schedule a single pooled/background job\n        if fire_and_forget and (self._background_tasks or self._thread_pool_executor):\n            # Worker that will process all registrations sequentially in background\n            def _bulk_register(\n                imgs: Batch[WorkflowImageData],\n                preds: Batch[Optional[Union[sv.Detections, dict]]],\n                names: Batch[Optional[str]],\n                tgt_project: str,\n                usage_quota: str,\n                persist_preds: bool,\n                minutely_limit: int,\n                hourly_limit: int,\n                daily_limit: int,\n                max_size: Tuple[int, int],\n                compression_lvl: int,\n                tags: List[str],\n                labeling_prefix: str,\n                recreation_freq: BatchCreationFrequency,\n                cache: BaseCache,\n                api_key: str,\n            ) -> None:\n                # Sequentially register each datapoint in the background worker.\n                for img, pred, nm in zip(imgs, preds, names):\n                    try:\n                        # Call execute_registration directly to avoid partial object creation\n                        execute_registration(\n                            image=img,\n                            prediction=pred,\n                            target_project=tgt_project,\n                            persist_predictions=persist_preds,\n                            usage_quota_name=usage_quota,\n                            minutely_usage_limit=minutely_limit,\n                            hourly_usage_limit=hourly_limit,\n                            daily_usage_limit=daily_limit,\n                            max_image_size=max_size,\n                            compression_level=compression_lvl,\n                            registration_tags=tags,\n                            labeling_batch_prefix=labeling_prefix,\n                            new_labeling_batch_frequency=recreation_freq,\n                            cache=cache,\n                            api_key=api_key,\n                            image_name=nm,\n                        )\n                    except Exception:\n                        # preserve original behavior: execute_registration logs exceptions itself\n                        # swallow exceptions to ensure background worker continues processing\n                        pass\n\n            # Schedule single background job using background_tasks preferentially\n            if self._background_tasks:\n                # BackgroundTasks accepts kwargs; pass them to avoid partial creation\n                self._background_tasks.add_task(\n                    _bulk_register,\n                    images,\n                    predictions,\n                    image_names,\n                    target_project,\n                    usage_quota_name,\n                    persist_predictions,\n                    minutely_usage_limit,\n                    hourly_usage_limit,\n                    daily_usage_limit,\n                    max_image_size,\n                    compression_level,\n                    registration_tags,\n                    labeling_batch_prefix,\n                    labeling_batches_recreation_frequency,\n                    self._cache,\n                    self._api_key,\n                )\n            else:\n                # Submit the bulk worker to the thread pool\n                self._thread_pool_executor.submit(\n                    _bulk_register,\n                    images,\n                    predictions,\n                    image_names,\n                    target_project,\n                    usage_quota_name,\n                    persist_predictions,\n                    minutely_usage_limit,\n                    hourly_usage_limit,\n                    daily_usage_limit,\n                    max_image_size,\n                    compression_level,\n                    registration_tags,\n                    labeling_batch_prefix,\n                    labeling_batches_recreation_frequency,\n                    self._cache,\n                    self._api_key,\n                )\n\n            # Return immediate success messages for all items as original behavior\n            return [\n                {\n                    \"error_status\": False,\n                    \"message\": \"Element registration happens in the background task\",\n                }\n                for _ in range(len(images))\n            ]\n\n        # Synchronous or no background mechanism: process one-by-one\n        result: List[dict] = []\n        for image, prediction, img_name in zip(images, predictions, image_names):\n            error_status, message = register_datapoint_at_roboflow(\n                image=image,\n                prediction=prediction,\n                target_project=target_project,\n                usage_quota_name=usage_quota_name,\n                persist_predictions=persist_predictions,\n                minutely_usage_limit=minutely_usage_limit,\n                hourly_usage_limit=hourly_usage_limit,\n                daily_usage_limit=daily_usage_limit,\n                max_image_size=max_image_size,\n                compression_level=compression_level,\n                registration_tags=registration_tags,\n                fire_and_forget=fire_and_forget,\n                labeling_batch_prefix=labeling_batch_prefix,\n                new_labeling_batch_frequency=labeling_batches_recreation_frequency,\n                cache=self._cache,\n                background_tasks=self._background_tasks,\n                thread_pool_executor=self._thread_pool_executor,\n                api_key=self._api_key,\n                image_name=img_name,\n            )\n            result.append({\"error_status\": error_status, \"message\": message})\n        return result\n\n\ndef register_datapoint_at_roboflow(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    usage_quota_name: str,\n    persist_predictions: bool,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    fire_and_forget: bool,\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    background_tasks: Optional[BackgroundTasks],\n    thread_pool_executor: Optional[ThreadPoolExecutor],\n    api_key: str,\n    image_name: Optional[str] = None,\n) -> Tuple[bool, str]:\n    # Avoid creating a partial unless necessary; call execute_registration directly for synchronous path\n    if fire_and_forget:\n        # Prefer BackgroundTasks if provided\n        if background_tasks:\n            # Use add_task with keyword args to avoid creating a partial object\n            background_tasks.add_task(\n                execute_registration,\n                image=image,\n                prediction=prediction,\n                target_project=target_project,\n                persist_predictions=persist_predictions,\n                usage_quota_name=usage_quota_name,\n                minutely_usage_limit=minutely_usage_limit,\n                hourly_usage_limit=hourly_usage_limit,\n                daily_usage_limit=daily_usage_limit,\n                max_image_size=max_image_size,\n                compression_level=compression_level,\n                registration_tags=registration_tags,\n                labeling_batch_prefix=labeling_batch_prefix,\n                new_labeling_batch_frequency=new_labeling_batch_frequency,\n                cache=cache,\n                api_key=api_key,\n                image_name=image_name,\n            )\n            return False, \"Element registration happens in the background task\"\n        if thread_pool_executor:\n            # Submit callable with kwargs directly to avoid creating a partial\n            thread_pool_executor.submit(\n                execute_registration,\n                image=image,\n                prediction=prediction,\n                target_project=target_project,\n                persist_predictions=persist_predictions,\n                usage_quota_name=usage_quota_name,\n                minutely_usage_limit=minutely_usage_limit,\n                hourly_usage_limit=hourly_usage_limit,\n                daily_usage_limit=daily_usage_limit,\n                max_image_size=max_image_size,\n                compression_level=compression_level,\n                registration_tags=registration_tags,\n                labeling_batch_prefix=labeling_batch_prefix,\n                new_labeling_batch_frequency=new_labeling_batch_frequency,\n                cache=cache,\n                api_key=api_key,\n                image_name=image_name,\n            )\n            return False, \"Element registration happens in the background task\"\n        # If fire_and_forget requested but no background mechanism provided, fall through to synchronous execution\n\n    # Synchronous execution path: call execute_registration and return its result directly\n    return execute_registration(\n        image=image,\n        prediction=prediction,\n        target_project=target_project,\n        persist_predictions=persist_predictions,\n        usage_quota_name=usage_quota_name,\n        minutely_usage_limit=minutely_usage_limit,\n        hourly_usage_limit=hourly_usage_limit,\n        daily_usage_limit=daily_usage_limit,\n        max_image_size=max_image_size,\n        compression_level=compression_level,\n        registration_tags=registration_tags,\n        labeling_batch_prefix=labeling_batch_prefix,\n        new_labeling_batch_frequency=new_labeling_batch_frequency,\n        cache=cache,\n        api_key=api_key,\n        image_name=image_name,\n    )\n\n\nRECREATION_INTERVAL2TIMESTAMP_GENERATOR = {\n    \"daily\": generate_today_timestamp,\n    \"weekly\": generate_start_timestamp_for_this_week,\n    \"monthly\": generate_start_timestamp_for_this_month,\n}",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/sinks/roboflow/dataset_upload/v1.py\nfrom __future__ import annotations\n\nfrom concurrent.futures import ThreadPoolExecutor\nfrom functools import partial\nfrom typing import List, Literal, Optional, Tuple, Union\n\nimport supervision as sv\nfrom fastapi import BackgroundTasks\nfrom inference.core.cache.base import BaseCache\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch, WorkflowImageData)\nfrom inference.core.workflows.prototypes.block import (BlockResult,\n                                                       WorkflowBlock)\n\nWORKSPACE_NAME_CACHE_EXPIRE = 900  # 15 min\nTIMESTAMP_FORMAT = \"%Y_%m_%d\"\nDUPLICATED_STATUS = \"Duplicated image\"\nBatchCreationFrequency = Literal[\"never\", \"daily\", \"weekly\", \"monthly\"]\n\n\nclass RoboflowDatasetUploadBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        cache: BaseCache,\n        api_key: Optional[str],\n        background_tasks: Optional[BackgroundTasks],\n        thread_pool_executor: Optional[ThreadPoolExecutor],\n    ):\n        self._cache = cache\n        self._api_key = api_key\n        self._background_tasks = background_tasks\n        self._thread_pool_executor = thread_pool_executor\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        predictions: Optional[Batch[Union[sv.Detections, dict]]],\n        target_project: str,\n        usage_quota_name: str,\n        minutely_usage_limit: int,\n        persist_predictions: bool,\n        hourly_usage_limit: int,\n        daily_usage_limit: int,\n        max_image_size: Tuple[int, int],\n        compression_level: int,\n        registration_tags: List[str],\n        disable_sink: bool,\n        fire_and_forget: bool,\n        labeling_batch_prefix: str,\n        labeling_batches_recreation_frequency: BatchCreationFrequency,\n        image_name: Optional[Batch[Optional[str]]] = None,\n    ) -> BlockResult:\n        if self._api_key is None:\n            raise ValueError(\n                \"RoboflowDataCollector block cannot run without Roboflow API key. \"\n                \"If you do not know how to get API key - visit \"\n                \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to \"\n                \"retrieve one.\"\n            )\n        if disable_sink:\n            return [\n                {\n                    \"error_status\": False,\n                    \"message\": \"Sink was disabled by parameter `disable_sink`\",\n                }\n                for _ in range(len(images))\n            ]\n        predictions = [None] * len(images) if predictions is None else predictions\n        image_names = [None] * len(images) if image_name is None else image_name\n\n        # If fire-and-forget and we have a background mechanism, schedule a single pooled/background job\n        if fire_and_forget and (self._background_tasks or self._thread_pool_executor):\n            # Worker that will process all registrations sequentially in background\n            def _bulk_register(\n                imgs: Batch[WorkflowImageData],\n                preds: Batch[Optional[Union[sv.Detections, dict]]],\n                names: Batch[Optional[str]],\n                tgt_project: str,\n                usage_quota: str,\n                persist_preds: bool,\n                minutely_limit: int,\n                hourly_limit: int,\n                daily_limit: int,\n                max_size: Tuple[int, int],\n                compression_lvl: int,\n                tags: List[str],\n                labeling_prefix: str,\n                recreation_freq: BatchCreationFrequency,\n                cache: BaseCache,\n                api_key: str,\n            ) -> None:\n                # Sequentially register each datapoint in the background worker.\n                for img, pred, nm in zip(imgs, preds, names):\n                    try:\n                        # Call execute_registration directly to avoid partial object creation\n                        execute_registration(\n                            image=img,\n                            prediction=pred,\n                            target_project=tgt_project,\n                            persist_predictions=persist_preds,\n                            usage_quota_name=usage_quota,\n                            minutely_usage_limit=minutely_limit,\n                            hourly_usage_limit=hourly_limit,\n                            daily_usage_limit=daily_limit,\n                            max_image_size=max_size,\n                            compression_level=compression_lvl,\n                            registration_tags=tags,\n                            labeling_batch_prefix=labeling_prefix,\n                            new_labeling_batch_frequency=recreation_freq,\n                            cache=cache,\n                            api_key=api_key,\n                            image_name=nm,\n                        )\n                    except Exception:\n                        # preserve original behavior: execute_registration logs exceptions itself\n                        # swallow exceptions to ensure background worker continues processing\n                        pass\n\n            # Schedule single background job using background_tasks preferentially\n            if self._background_tasks:\n                # BackgroundTasks accepts kwargs; pass them to avoid partial creation\n                self._background_tasks.add_task(\n                    _bulk_register,\n                    images,\n                    predictions,\n                    image_names,\n                    target_project,\n                    usage_quota_name,\n                    persist_predictions,\n                    minutely_usage_limit,\n                    hourly_usage_limit,\n                    daily_usage_limit,\n                    max_image_size,\n                    compression_level,\n                    registration_tags,\n                    labeling_batch_prefix,\n                    labeling_batches_recreation_frequency,\n                    self._cache,\n                    self._api_key,\n                )\n            else:\n                # Submit the bulk worker to the thread pool\n                self._thread_pool_executor.submit(\n                    _bulk_register,\n                    images,\n                    predictions,\n                    image_names,\n                    target_project,\n                    usage_quota_name,\n                    persist_predictions,\n                    minutely_usage_limit,\n                    hourly_usage_limit,\n                    daily_usage_limit,\n                    max_image_size,\n                    compression_level,\n                    registration_tags,\n                    labeling_batch_prefix,\n                    labeling_batches_recreation_frequency,\n                    self._cache,\n                    self._api_key,\n                )\n\n            # Return immediate success messages for all items as original behavior\n            return [\n                {\n                    \"error_status\": False,\n                    \"message\": \"Element registration happens in the background task\",\n                }\n                for _ in range(len(images))\n            ]\n\n        # Synchronous or no background mechanism: process one-by-one\n        result: List[dict] = []\n        for image, prediction, img_name in zip(images, predictions, image_names):\n            error_status, message = register_datapoint_at_roboflow(\n                image=image,\n                prediction=prediction,\n                target_project=target_project,\n                usage_quota_name=usage_quota_name,\n                persist_predictions=persist_predictions,\n                minutely_usage_limit=minutely_usage_limit,\n                hourly_usage_limit=hourly_usage_limit,\n                daily_usage_limit=daily_usage_limit,\n                max_image_size=max_image_size,\n                compression_level=compression_level,\n                registration_tags=registration_tags,\n                fire_and_forget=fire_and_forget,\n                labeling_batch_prefix=labeling_batch_prefix,\n                new_labeling_batch_frequency=labeling_batches_recreation_frequency,\n                cache=self._cache,\n                background_tasks=self._background_tasks,\n                thread_pool_executor=self._thread_pool_executor,\n                api_key=self._api_key,\n                image_name=img_name,\n            )\n            result.append({\"error_status\": error_status, \"message\": message})\n        return result\n\n\ndef register_datapoint_at_roboflow(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    usage_quota_name: str,\n    persist_predictions: bool,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    fire_and_forget: bool,\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    background_tasks: Optional[BackgroundTasks],\n    thread_pool_executor: Optional[ThreadPoolExecutor],\n    api_key: str,\n    image_name: Optional[str] = None,\n) -> Tuple[bool, str]:\n    # Avoid creating a partial unless necessary; call execute_registration directly for synchronous path\n    if fire_and_forget:\n        # Prefer BackgroundTasks if provided\n        if background_tasks:\n            # Use add_task with keyword args to avoid creating a partial object\n            background_tasks.add_task(\n                execute_registration,\n                image=image,\n                prediction=prediction,\n                target_project=target_project,\n                persist_predictions=persist_predictions,\n                usage_quota_name=usage_quota_name,\n                minutely_usage_limit=minutely_usage_limit,\n                hourly_usage_limit=hourly_usage_limit,\n                daily_usage_limit=daily_usage_limit,\n                max_image_size=max_image_size,\n                compression_level=compression_level,\n                registration_tags=registration_tags,\n                labeling_batch_prefix=labeling_batch_prefix,\n                new_labeling_batch_frequency=new_labeling_batch_frequency,\n                cache=cache,\n                api_key=api_key,\n                image_name=image_name,\n            )\n            return False, \"Element registration happens in the background task\"\n        if thread_pool_executor:\n            # Submit callable with kwargs directly to avoid creating a partial\n            thread_pool_executor.submit(\n                execute_registration,\n                image=image,\n                prediction=prediction,\n                target_project=target_project,\n                persist_predictions=persist_predictions,\n                usage_quota_name=usage_quota_name,\n                minutely_usage_limit=minutely_usage_limit,\n                hourly_usage_limit=hourly_usage_limit,\n                daily_usage_limit=daily_usage_limit,\n                max_image_size=max_image_size,\n                compression_level=compression_level,\n                registration_tags=registration_tags,\n                labeling_batch_prefix=labeling_batch_prefix,\n                new_labeling_batch_frequency=new_labeling_batch_frequency,\n                cache=cache,\n                api_key=api_key,\n                image_name=image_name,\n            )\n            return False, \"Element registration happens in the background task\"\n        # If fire_and_forget requested but no background mechanism provided, fall through to synchronous execution\n\n    # Synchronous execution path: call execute_registration and return its result directly\n    return execute_registration(\n        image=image,\n        prediction=prediction,\n        target_project=target_project,\n        persist_predictions=persist_predictions,\n        usage_quota_name=usage_quota_name,\n        minutely_usage_limit=minutely_usage_limit,\n        hourly_usage_limit=hourly_usage_limit,\n        daily_usage_limit=daily_usage_limit,\n        max_image_size=max_image_size,\n        compression_level=compression_level,\n        registration_tags=registration_tags,\n        labeling_batch_prefix=labeling_batch_prefix,\n        new_labeling_batch_frequency=new_labeling_batch_frequency,\n        cache=cache,\n        api_key=api_key,\n        image_name=image_name,\n    )\n\n\nRECREATION_INTERVAL2TIMESTAMP_GENERATOR = {\n    \"daily\": generate_today_timestamp,\n    \"weekly\": generate_start_timestamp_for_this_week,\n    \"monthly\": generate_start_timestamp_for_this_month,\n}\n```",
    "optimized_function_only": "    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        predictions: Optional[Batch[Union[sv.Detections, dict]]],\n        target_project: str,\n        usage_quota_name: str,\n        minutely_usage_limit: int,\n        persist_predictions: bool,\n        hourly_usage_limit: int,\n        daily_usage_limit: int,\n        max_image_size: Tuple[int, int],\n        compression_level: int,\n        registration_tags: List[str],\n        disable_sink: bool,\n        fire_and_forget: bool,\n        labeling_batch_prefix: str,\n        labeling_batches_recreation_frequency: BatchCreationFrequency,\n        image_name: Optional[Batch[Optional[str]]] = None,\n    ) -> BlockResult:\n        if self._api_key is None:\n            raise ValueError(\n                \"RoboflowDataCollector block cannot run without Roboflow API key. \"\n                \"If you do not know how to get API key - visit \"\n                \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to \"\n                \"retrieve one.\"\n            )\n        if disable_sink:\n            return [\n                {\n                    \"error_status\": False,\n                    \"message\": \"Sink was disabled by parameter `disable_sink`\",\n                }\n                for _ in range(len(images))\n            ]\n        predictions = [None] * len(images) if predictions is None else predictions\n        image_names = [None] * len(images) if image_name is None else image_name\n\n        # If fire-and-forget and we have a background mechanism, schedule a single pooled/background job\n        if fire_and_forget and (self._background_tasks or self._thread_pool_executor):\n            # Worker that will process all registrations sequentially in background\n            def _bulk_register(\n                imgs: Batch[WorkflowImageData],\n                preds: Batch[Optional[Union[sv.Detections, dict]]],\n                names: Batch[Optional[str]],\n                tgt_project: str,\n                usage_quota: str,\n                persist_preds: bool,\n                minutely_limit: int,\n                hourly_limit: int,\n                daily_limit: int,\n                max_size: Tuple[int, int],\n                compression_lvl: int,\n                tags: List[str],\n                labeling_prefix: str,\n                recreation_freq: BatchCreationFrequency,\n                cache: BaseCache,\n                api_key: str,\n            ) -> None:\n                # Sequentially register each datapoint in the background worker.\n                for img, pred, nm in zip(imgs, preds, names):\n                    try:\n                        # Call execute_registration directly to avoid partial object creation\n                        execute_registration(\n                            image=img,\n                            prediction=pred,\n                            target_project=tgt_project,\n                            persist_predictions=persist_preds,\n                            usage_quota_name=usage_quota,\n                            minutely_usage_limit=minutely_limit,\n                            hourly_usage_limit=hourly_limit,\n                            daily_usage_limit=daily_limit,\n                            max_image_size=max_size,\n                            compression_level=compression_lvl,\n                            registration_tags=tags,\n                            labeling_batch_prefix=labeling_prefix,\n                            new_labeling_batch_frequency=recreation_freq,\n                            cache=cache,\n                            api_key=api_key,\n                            image_name=nm,\n                        )\n                    except Exception:\n                        # preserve original behavior: execute_registration logs exceptions itself\n                        # swallow exceptions to ensure background worker continues processing\n                        pass\n\n            # Schedule single background job using background_tasks preferentially\n            if self._background_tasks:\n                # BackgroundTasks accepts kwargs; pass them to avoid partial creation\n                self._background_tasks.add_task(\n                    _bulk_register,\n                    images,\n                    predictions,\n                    image_names,\n                    target_project,\n                    usage_quota_name,\n                    persist_predictions,\n                    minutely_usage_limit,\n                    hourly_usage_limit,\n                    daily_usage_limit,\n                    max_image_size,\n                    compression_level,\n                    registration_tags,\n                    labeling_batch_prefix,\n                    labeling_batches_recreation_frequency,\n                    self._cache,\n                    self._api_key,\n                )\n            else:\n                # Submit the bulk worker to the thread pool\n                self._thread_pool_executor.submit(\n                    _bulk_register,\n                    images,\n                    predictions,\n                    image_names,\n                    target_project,\n                    usage_quota_name,\n                    persist_predictions,\n                    minutely_usage_limit,\n                    hourly_usage_limit,\n                    daily_usage_limit,\n                    max_image_size,\n                    compression_level,\n                    registration_tags,\n                    labeling_batch_prefix,\n                    labeling_batches_recreation_frequency,\n                    self._cache,\n                    self._api_key,\n                )\n\n            # Return immediate success messages for all items as original behavior\n            return [\n                {\n                    \"error_status\": False,\n                    \"message\": \"Element registration happens in the background task\",\n                }\n                for _ in range(len(images))\n            ]\n\n        # Synchronous or no background mechanism: process one-by-one\n        result: List[dict] = []\n        for image, prediction, img_name in zip(images, predictions, image_names):\n            error_status, message = register_datapoint_at_roboflow(\n                image=image,\n                prediction=prediction,\n                target_project=target_project,\n                usage_quota_name=usage_quota_name,\n                persist_predictions=persist_predictions,\n                minutely_usage_limit=minutely_usage_limit,\n                hourly_usage_limit=hourly_usage_limit,\n                daily_usage_limit=daily_usage_limit,\n                max_image_size=max_image_size,\n                compression_level=compression_level,\n                registration_tags=registration_tags,\n                fire_and_forget=fire_and_forget,\n                labeling_batch_prefix=labeling_batch_prefix,\n                new_labeling_batch_frequency=labeling_batches_recreation_frequency,\n                cache=self._cache,\n                background_tasks=self._background_tasks,\n                thread_pool_executor=self._thread_pool_executor,\n                api_key=self._api_key,\n                image_name=img_name,\n            )\n            result.append({\"error_status\": error_status, \"message\": message})\n        return result\n",
    "original_file_content": "\"\"\"\n*****************************************************************\n*                           WARNING!                            *\n*****************************************************************\nThis module contains the utility functions used by\nRoboflowDatasetUploadBlockV2.\n\nWe do not recommend making multiple blocks dependent on the same code,\nbut the change between v1 and v2 was basically the default value of\nsome parameter - hence we decided not to replicate the code.\n\nIf you need to modify this module beware that you may introduce\nchange to RoboflowDatasetUploadBlockV2! If that happens,\nprobably that's the time to disentangle those blocks and copy the\ncode.\n\"\"\"\n\nimport hashlib\nimport json\nimport logging\nfrom collections import OrderedDict\nfrom concurrent.futures import ThreadPoolExecutor\nfrom datetime import datetime, timedelta\nfrom functools import partial\nfrom typing import Any, Dict, List, Literal, Optional, Tuple, Type, Union\nfrom uuid import uuid4\n\nimport supervision as sv\nfrom fastapi import BackgroundTasks\nfrom pydantic import AliasChoices, ConfigDict, Field\n\nfrom inference.core.active_learning.cache_operations import (\n    return_strategy_credit,\n    use_credit_of_matching_strategy,\n)\nfrom inference.core.active_learning.core import prepare_image_to_registration\nfrom inference.core.active_learning.entities import (\n    ImageDimensions,\n    StrategyLimit,\n    StrategyLimitType,\n)\nfrom inference.core.cache.base import BaseCache\nfrom inference.core.roboflow_api import (\n    annotate_image_at_roboflow,\n    get_roboflow_workspace,\n    register_image_at_roboflow,\n)\nfrom inference.core.workflows.core_steps.common.serializers import (\n    serialise_sv_detections,\n)\nfrom inference.core.workflows.core_steps.common.utils import scale_sv_detections\nfrom inference.core.workflows.execution_engine.constants import INFERENCE_ID_KEY\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    BOOLEAN_KIND,\n    CLASSIFICATION_PREDICTION_KIND,\n    IMAGE_KIND,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    KEYPOINT_DETECTION_PREDICTION_KIND,\n    LIST_OF_VALUES_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    ROBOFLOW_PROJECT_KIND,\n    STRING_KIND,\n    ImageInputField,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    AirGappedAvailability,\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nSHORT_DESCRIPTION = \"Save images and predictions to your Roboflow Dataset.\"\n\nLONG_DESCRIPTION = \"\"\"\nUpload images and model predictions to a Roboflow dataset for active learning, model improvement, and data collection, with configurable usage quotas, batch organization, image compression, and optional annotation persistence.\n\n## How This Block Works\n\nThis block uploads workflow images and predictions to your Roboflow dataset for storage, labeling, and model training. The block:\n\n1. Takes images and optional model predictions (object detection, instance segmentation, keypoint detection, or classification) as input\n2. Validates the Roboflow API key is available (required for uploading)\n3. Checks usage quotas (minutely, hourly, daily limits) to ensure uploads stay within configured rate limits for active learning strategies\n4. Prepares images by resizing if they exceed maximum size (maintaining aspect ratio) and compressing to specified quality level\n5. Generates labeling batch names based on the prefix and batch creation frequency (never, daily, weekly, or monthly), organizing uploaded data into batches\n6. Optionally persists model predictions as annotations if `persist_predictions` is enabled, allowing predictions to serve as pre-labels for review and correction\n7. Attaches registration tags to images for organization and filtering in the Roboflow platform\n8. Registers the image (and annotations if enabled) to the specified Roboflow project via the Roboflow API\n9. Executes synchronously or asynchronously based on `fire_and_forget` setting, allowing non-blocking uploads for faster workflow execution\n10. Returns error status and messages indicating upload success or failure\n\nThe block supports active learning workflows by implementing usage quotas that prevent excessive data collection, helping focus on collecting valuable training data within rate limits. Images are organized into labeling batches that can be automatically recreated on a schedule (daily, weekly, monthly), making it easier to manage and review collected data over time. The block can operate in fire-and-forget mode for asynchronous execution, allowing workflows to continue processing without waiting for uploads to complete, or synchronously for debugging and error handling.\n\n## Requirements\n\n**API Key Required**: This block requires a valid Roboflow API key to upload data. The API key must be configured in your environment or workflow configuration. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve an API key.\n\n## Common Use Cases\n\n- **Active Learning Data Collection**: Collect images and predictions from production environments where models struggle or are uncertain (e.g., low-confidence detections, edge cases), enabling iterative model improvement by gathering challenging examples for retraining\n- **Production Data Logging**: Continuously upload production inference data to Roboflow datasets for monitoring, analysis, and future model training, creating a growing dataset from real-world deployments\n- **Pre-Labeled Data Collection**: Upload images with model predictions as pre-labels (when `persist_predictions` is enabled), accelerating annotation workflows by providing initial labels that can be reviewed and corrected rather than starting from scratch\n- **Stratified Data Sampling**: Use rate limiting and quotas to selectively collect data based on specific criteria (e.g., combine with Rate Limiter or Continue If blocks), ensuring diverse and balanced dataset collection without overwhelming storage or annotation resources\n- **Batch-Based Labeling Workflows**: Organize uploaded data into batches with automatic recreation schedules (daily, weekly, monthly), making it easier to manage labeling tasks, track progress, and organize data collection efforts over time\n- **Tagged Data Organization**: Attach metadata tags to uploaded images (e.g., location, camera ID, time period, model version), enabling filtering and organization of collected data in Roboflow for better dataset management and analysis\n\n## Connecting to Other Blocks\n\nThis block receives data from workflow steps and uploads it to Roboflow:\n\n- **After detection or analysis blocks** (e.g., Object Detection Model, Instance Segmentation Model, Classification Model, Keypoint Detection Model) to upload images along with their predictions, enabling active learning by collecting inference data with model outputs for annotation and retraining\n- **After filtering or analytics blocks** (e.g., Detections Filter, Continue If, Overlap Filter) to selectively upload only specific types of data (e.g., low-confidence detections, overlapping objects, specific classes), focusing data collection on valuable edge cases or interesting scenarios\n- **After rate limiter blocks** (e.g., Rate Limiter) to throttle upload frequency and stay within usage quotas, ensuring controlled data collection that respects rate limits and prevents excessive storage usage\n- **Image inputs or preprocessing blocks** to upload raw images or processed images (e.g., crops, transformed images) without predictions, enabling collection of image data for future labeling or analysis\n- **Conditional workflows** using flow control blocks (e.g., Continue If) to upload data only when certain conditions are met (e.g., upload only when detection count exceeds threshold, upload only errors or failures), enabling selective data collection based on workflow state\n- **Batch processing workflows** where multiple images or predictions are generated, allowing bulk upload of workflow outputs to Roboflow datasets for organized data collection and management\n\"\"\"\n\nWORKSPACE_NAME_CACHE_EXPIRE = 900  # 15 min\nTIMESTAMP_FORMAT = \"%Y_%m_%d\"\nDUPLICATED_STATUS = \"Duplicated image\"\nBatchCreationFrequency = Literal[\"never\", \"daily\", \"weekly\", \"monthly\"]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Roboflow Dataset Upload\",\n            \"version\": \"v1\",\n            \"short_description\": SHORT_DESCRIPTION,\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"sink\",\n            \"ui_manifest\": {\n                \"section\": \"data_storage\",\n                \"icon\": \"fal fa-upload\",\n                \"blockPriority\": 0,\n                \"popular\": True,\n                \"requires_rf_key\": True,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/roboflow_dataset_upload@v1\", \"RoboflowDatasetUpload\"]\n    images: Selector(kind=[IMAGE_KIND]) = Field(\n        title=\"Input Image\",\n        description=\"Image(s) to upload to the Roboflow dataset. Can be a single image or batch of images from workflow inputs or processing steps. Images are resized if they exceed max_image_size and compressed before uploading. Supports batch processing.\",\n        examples=[\"$inputs.image\", \"$steps.cropping.crops\"],\n        validation_alias=AliasChoices(\"image\", \"images\"),\n    )\n    predictions: Optional[\n        Selector(\n            kind=[\n                OBJECT_DETECTION_PREDICTION_KIND,\n                INSTANCE_SEGMENTATION_PREDICTION_KIND,\n                KEYPOINT_DETECTION_PREDICTION_KIND,\n                CLASSIFICATION_PREDICTION_KIND,\n            ]\n        )\n    ] = Field(\n        default=None,\n        description=\"Optional model predictions to upload alongside images. Predictions are saved as annotations (pre-labels) in the Roboflow dataset when persist_predictions is enabled, allowing predictions to serve as starting points for annotation review and correction. Supports object detection, instance segmentation, keypoint detection, and classification predictions. If None, only images are uploaded.\",\n        examples=[\"$steps.object_detection_model.predictions\"],\n    )\n    target_project: Union[Selector(kind=[ROBOFLOW_PROJECT_KIND]), str] = Field(\n        description=\"Roboflow project identifier where uploaded images and annotations will be saved. Must be a valid project in your Roboflow workspace. The project name can be specified directly or referenced from workflow inputs.\",\n        examples=[\"my_project\", \"$inputs.target_project\"],\n    )\n    minutely_usage_limit: int = Field(\n        default=10,\n        description=\"Maximum number of image uploads allowed per minute for this quota. Part of the usage quota system that enforces rate limits for active learning data collection. Uploads exceeding this limit are skipped to prevent excessive data collection. Works together with hourly_usage_limit and daily_usage_limit to provide multi-level rate limiting.\",\n        examples=[10, 60],\n    )\n    hourly_usage_limit: int = Field(\n        default=100,\n        description=\"Maximum number of image uploads allowed per hour for this quota. Part of the usage quota system that enforces rate limits for active learning data collection. Uploads exceeding this limit are skipped to prevent excessive data collection. Works together with minutely_usage_limit and daily_usage_limit to provide multi-level rate limiting.\",\n        examples=[10, 60],\n    )\n    daily_usage_limit: int = Field(\n        default=1000,\n        description=\"Maximum number of image uploads allowed per day for this quota. Part of the usage quota system that enforces rate limits for active learning data collection. Uploads exceeding this limit are skipped to prevent excessive data collection. Works together with minutely_usage_limit and hourly_usage_limit to provide multi-level rate limiting.\",\n        examples=[10, 60],\n    )\n    usage_quota_name: str = Field(\n        description=\"Unique identifier for tracking usage quotas (minutely, hourly, daily limits). Used internally to manage rate limiting across multiple upload operations. Each unique quota name maintains separate counters, allowing different upload strategies or data collection workflows to have independent rate limits.\",\n        examples=[\"quota-for-data-sampling-1\"],\n        json_schema_extra={\"hidden\": True},\n    )\n    max_image_size: Tuple[int, int] = Field(\n        default=(512, 512),\n        description=\"Maximum dimensions (width, height) for uploaded images. Images exceeding these dimensions are automatically resized while preserving aspect ratio before uploading. Smaller sizes reduce storage and bandwidth but may lose image quality. Use larger sizes (e.g., (1920, 1080)) for high-resolution data collection, or smaller sizes (e.g., (512, 512)) for efficient storage and faster uploads.\",\n        examples=[(512, 512), (1920, 1080)],\n    )\n    compression_level: int = Field(\n        default=75,\n        gt=0,\n        le=100,\n        description=\"JPEG compression quality level for uploaded images, ranging from 1 (highest compression, smallest file size, lower quality) to 100 (no compression, largest file size, highest quality). Higher values preserve more image quality but increase storage and bandwidth usage. Typical values range from 70-90 for balanced quality and size. Default of 75 provides good quality with reasonable file sizes.\",\n        examples=[75],\n    )\n    registration_tags: Union[\n        List[Union[Selector(kind=[STRING_KIND]), str]],\n        Selector(kind=[LIST_OF_VALUES_KIND]),\n    ] = Field(\n        default_factory=list,\n        description=\"List of tags to attach to uploaded images for organization and filtering in Roboflow. Tags can be static strings (e.g., 'location-florida', 'camera-1') or dynamic values from workflow inputs. Tags help organize collected data, filter images in Roboflow, and add metadata for dataset management. Can be an empty list if no tags are needed.\",\n        examples=[\n            [\"location-florida\", \"factory-name\", \"$inputs.dynamic_tag\"],\n            \"$inputs.tags\",\n        ],\n    )\n    persist_predictions: bool = Field(\n        default=True,\n        description=\"If True, model predictions are saved as annotations (pre-labels) in the Roboflow dataset alongside images. This enables predictions to serve as starting points for annotation, allowing reviewers to correct or approve labels rather than creating them from scratch. If False, only images are uploaded without annotations. Enabling this accelerates annotation workflows by providing initial labels.\",\n        examples=[True, False],\n    )\n    disable_sink: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=False,\n        description=\"If True, the block execution is disabled and no uploads occur. This allows temporarily disabling data collection without removing the block from workflows, useful for testing, debugging, or conditional data collection. When disabled, returns a message indicating the sink was disabled. Default is False (uploads enabled).\",\n        examples=[True, \"$inputs.disable_active_learning\"],\n    )\n    fire_and_forget: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=True,\n        description=\"If True, uploads execute asynchronously (fire-and-forget mode), allowing the workflow to continue immediately without waiting for upload completion. This improves workflow performance but prevents error handling. If False, uploads execute synchronously, blocking workflow execution until completion and allowing proper error handling and status reporting. Use async mode (True) for production workflows where speed is prioritized, and sync mode (False) for debugging or when error handling is critical.\",\n        examples=[True],\n    )\n    labeling_batch_prefix: Union[str, Selector(kind=[STRING_KIND])] = Field(\n        default=\"workflows_data_collector\",\n        description=\"Prefix used to generate labeling batch names for organizing uploaded images in Roboflow. Combined with the batch recreation frequency and timestamps to create batch names like 'workflows_data_collector_2024_01_15'. Batches help organize collected data for labeling, making it easier to manage and review uploaded images in groups. Can be customized to match your organization scheme.\",\n        examples=[\"my_labeling_batch_name\"],\n    )\n    labeling_batches_recreation_frequency: BatchCreationFrequency = Field(\n        default=\"never\",\n        description=\"Frequency at which new labeling batches are automatically created for uploaded images. Options: 'never' (all images go to the same batch), 'daily' (new batch each day), 'weekly' (new batch each week), 'monthly' (new batch each month). Batch timestamps are appended to the labeling_batch_prefix to create unique batch names. Automatically organizing uploads into time-based batches simplifies dataset management and makes it easier to track and review collected data over time.\",\n        examples=[\"never\", \"daily\"],\n    )\n    image_name: Optional[Union[str, Selector(kind=[STRING_KIND])]] = Field(\n        default=None,\n        description=\"Optional custom name for the uploaded image. If provided, this name will be used instead of an auto-generated UUID. This is useful when you want to preserve the original filename or use a meaningful identifier (e.g., serial number, timestamp) for the image in the Roboflow dataset. The name should not include file extension. If not provided, a UUID will be generated automatically.\",\n        examples=[\"serial_12345\", \"camera1_frame_001\", \"$inputs.filename\"],\n    )\n\n    @classmethod\n    def get_air_gapped_availability(cls) -> AirGappedAvailability:\n        return AirGappedAvailability(available=False, reason=\"requires_internet\")\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return [\"images\", \"predictions\", \"image_name\"]\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"error_status\", kind=[BOOLEAN_KIND]),\n            OutputDefinition(name=\"message\", kind=[STRING_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass RoboflowDatasetUploadBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        cache: BaseCache,\n        api_key: Optional[str],\n        background_tasks: Optional[BackgroundTasks],\n        thread_pool_executor: Optional[ThreadPoolExecutor],\n    ):\n        self._cache = cache\n        self._api_key = api_key\n        self._background_tasks = background_tasks\n        self._thread_pool_executor = thread_pool_executor\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"cache\", \"api_key\", \"background_tasks\", \"thread_pool_executor\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        predictions: Optional[Batch[Union[sv.Detections, dict]]],\n        target_project: str,\n        usage_quota_name: str,\n        minutely_usage_limit: int,\n        persist_predictions: bool,\n        hourly_usage_limit: int,\n        daily_usage_limit: int,\n        max_image_size: Tuple[int, int],\n        compression_level: int,\n        registration_tags: List[str],\n        disable_sink: bool,\n        fire_and_forget: bool,\n        labeling_batch_prefix: str,\n        labeling_batches_recreation_frequency: BatchCreationFrequency,\n        image_name: Optional[Batch[Optional[str]]] = None,\n    ) -> BlockResult:\n        if self._api_key is None:\n            raise ValueError(\n                \"RoboflowDataCollector block cannot run without Roboflow API key. \"\n                \"If you do not know how to get API key - visit \"\n                \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to \"\n                \"retrieve one.\"\n            )\n        if disable_sink:\n            return [\n                {\n                    \"error_status\": False,\n                    \"message\": \"Sink was disabled by parameter `disable_sink`\",\n                }\n                for _ in range(len(images))\n            ]\n        result = []\n        predictions = [None] * len(images) if predictions is None else predictions\n        image_names = [None] * len(images) if image_name is None else image_name\n        for image, prediction, img_name in zip(images, predictions, image_names):\n            error_status, message = register_datapoint_at_roboflow(\n                image=image,\n                prediction=prediction,\n                target_project=target_project,\n                usage_quota_name=usage_quota_name,\n                persist_predictions=persist_predictions,\n                minutely_usage_limit=minutely_usage_limit,\n                hourly_usage_limit=hourly_usage_limit,\n                daily_usage_limit=daily_usage_limit,\n                max_image_size=max_image_size,\n                compression_level=compression_level,\n                registration_tags=registration_tags,\n                fire_and_forget=fire_and_forget,\n                labeling_batch_prefix=labeling_batch_prefix,\n                new_labeling_batch_frequency=labeling_batches_recreation_frequency,\n                cache=self._cache,\n                background_tasks=self._background_tasks,\n                thread_pool_executor=self._thread_pool_executor,\n                api_key=self._api_key,\n                image_name=img_name,\n            )\n            result.append({\"error_status\": error_status, \"message\": message})\n        return result\n\n\ndef register_datapoint_at_roboflow(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    usage_quota_name: str,\n    persist_predictions: bool,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    fire_and_forget: bool,\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    background_tasks: Optional[BackgroundTasks],\n    thread_pool_executor: Optional[ThreadPoolExecutor],\n    api_key: str,\n    image_name: Optional[str] = None,\n    metadata: Optional[Dict[str, Any]] = None,\n) -> Tuple[bool, str]:\n    registration_task = partial(\n        execute_registration,\n        image=image,\n        prediction=prediction,\n        target_project=target_project,\n        usage_quota_name=usage_quota_name,\n        persist_predictions=persist_predictions,\n        minutely_usage_limit=minutely_usage_limit,\n        hourly_usage_limit=hourly_usage_limit,\n        daily_usage_limit=daily_usage_limit,\n        max_image_size=max_image_size,\n        compression_level=compression_level,\n        registration_tags=registration_tags,\n        labeling_batch_prefix=labeling_batch_prefix,\n        new_labeling_batch_frequency=new_labeling_batch_frequency,\n        cache=cache,\n        api_key=api_key,\n        image_name=image_name,\n        metadata=metadata,\n    )\n    if fire_and_forget and background_tasks:\n        background_tasks.add_task(registration_task)\n        return False, \"Element registration happens in the background task\"\n    if fire_and_forget and thread_pool_executor:\n        thread_pool_executor.submit(registration_task)\n        return False, \"Element registration happens in the background task\"\n    return registration_task()\n\n\ndef execute_registration(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    persist_predictions: bool,\n    usage_quota_name: str,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    api_key: str,\n    image_name: Optional[str] = None,\n    metadata: Optional[Dict[str, Any]] = None,\n) -> Tuple[bool, str]:\n    matching_strategies_limits = OrderedDict(\n        {\n            usage_quota_name: [\n                StrategyLimit(\n                    limit_type=StrategyLimitType.MINUTELY, value=minutely_usage_limit\n                ),\n                StrategyLimit(\n                    limit_type=StrategyLimitType.HOURLY, value=hourly_usage_limit\n                ),\n                StrategyLimit(\n                    limit_type=StrategyLimitType.DAILY, value=daily_usage_limit\n                ),\n            ]\n        }\n    )\n    workspace_name = get_workspace_name(api_key=api_key, cache=cache)\n    strategy_with_spare_credit = use_credit_of_matching_strategy(\n        cache=cache,\n        workspace=workspace_name,\n        project=target_project,\n        matching_strategies_limits=matching_strategies_limits,\n    )\n    if strategy_with_spare_credit is None:\n        return False, \"Registration skipped due to usage quota exceeded\"\n    credit_to_be_returned = False\n    try:\n        local_image_id = image_name if image_name else str(uuid4())\n        encoded_image, scaling_factor = prepare_image_to_registration(\n            image=image.numpy_image,\n            desired_size=ImageDimensions(\n                width=max_image_size[0], height=max_image_size[1]\n            ),\n            jpeg_compression_level=compression_level,\n        )\n        batch_name = generate_batch_name(\n            labeling_batch_prefix=labeling_batch_prefix,\n            new_labeling_batch_frequency=new_labeling_batch_frequency,\n        )\n        if isinstance(prediction, sv.Detections):\n            prediction = scale_sv_detections(\n                detections=prediction, scale=scaling_factor\n            )\n        status = register_datapoint(\n            target_project=target_project,\n            encoded_image=encoded_image,\n            local_image_id=local_image_id,\n            prediction=prediction if persist_predictions else None,\n            api_key=api_key,\n            batch_name=batch_name,\n            tags=registration_tags,\n            metadata=metadata,\n        )\n        if status == DUPLICATED_STATUS:\n            credit_to_be_returned = True\n        return False, status\n    except Exception as error:\n        credit_to_be_returned = True\n        logging.exception(\"Failed to register datapoint on the Roboflow platform\")\n        return (\n            True,\n            f\"Error while registration. Error type: {type(error)}. Details: {error}\",\n        )\n    finally:\n        if credit_to_be_returned:\n            return_strategy_credit(\n                cache=cache,\n                workspace=workspace_name,\n                project=target_project,\n                strategy_name=strategy_with_spare_credit,\n            )\n\n\ndef get_workspace_name(\n    api_key: str,\n    cache: BaseCache,\n) -> str:\n    api_key_hash = hashlib.md5(api_key.encode(\"utf-8\")).hexdigest()\n    cache_key = f\"workflows:api_key_to_workspace:{api_key_hash}\"\n    cached_workspace_name = cache.get(cache_key)\n    if cached_workspace_name:\n        return cached_workspace_name\n    workspace_name_from_api = get_roboflow_workspace(api_key=api_key)\n    cache.set(\n        key=cache_key, value=workspace_name_from_api, expire=WORKSPACE_NAME_CACHE_EXPIRE\n    )\n    return workspace_name_from_api\n\n\ndef generate_batch_name(\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n) -> str:\n    if new_labeling_batch_frequency == \"never\":\n        return labeling_batch_prefix\n    timestamp_generator = RECREATION_INTERVAL2TIMESTAMP_GENERATOR[\n        new_labeling_batch_frequency\n    ]\n    timestamp = timestamp_generator()\n    return f\"{labeling_batch_prefix}_{timestamp}\"\n\n\ndef generate_today_timestamp() -> str:\n    return datetime.today().strftime(TIMESTAMP_FORMAT)\n\n\ndef generate_start_timestamp_for_this_week() -> str:\n    today = datetime.today()\n    return (today - timedelta(days=today.weekday())).strftime(TIMESTAMP_FORMAT)\n\n\ndef generate_start_timestamp_for_this_month() -> str:\n    return datetime.today().replace(day=1).strftime(TIMESTAMP_FORMAT)\n\n\nRECREATION_INTERVAL2TIMESTAMP_GENERATOR = {\n    \"daily\": generate_today_timestamp,\n    \"weekly\": generate_start_timestamp_for_this_week,\n    \"monthly\": generate_start_timestamp_for_this_month,\n}\n\n\ndef register_datapoint(\n    target_project: str,\n    encoded_image: bytes,\n    local_image_id: str,\n    prediction: Optional[Union[sv.Detections, dict]],\n    api_key: str,\n    batch_name: str,\n    tags: List[str],\n    metadata: Optional[Dict[str, Any]] = None,\n) -> str:\n    inference_id = None\n    if isinstance(prediction, dict):\n        inference_id = prediction.get(INFERENCE_ID_KEY)\n    if isinstance(prediction, sv.Detections) and len(prediction) > 0:\n        # TODO: Lack of inference ID for empty prediction -\n        #  dependent on https://github.com/roboflow/inference/issues/567\n        inference_id_array = prediction.data.get(INFERENCE_ID_KEY)\n        if inference_id_array is not None:\n            inference_id_list = inference_id_array.tolist()\n            inference_id = inference_id_list[0]\n    roboflow_image_id = safe_register_image_at_roboflow(\n        target_project=target_project,\n        encoded_image=encoded_image,\n        local_image_id=local_image_id,\n        api_key=api_key,\n        batch_name=batch_name,\n        tags=tags,\n        inference_id=inference_id,\n        metadata=metadata,\n    )\n    if roboflow_image_id is None:\n        return DUPLICATED_STATUS\n    if is_prediction_registration_forbidden(prediction=prediction):\n        return \"Successfully registered image\"\n    encoded_prediction, prediction_format = encode_prediction(prediction=prediction)\n    _ = annotate_image_at_roboflow(\n        api_key=api_key,\n        dataset_id=target_project,\n        local_image_id=local_image_id,\n        roboflow_image_id=roboflow_image_id,\n        annotation_content=encoded_prediction,\n        annotation_file_type=prediction_format,\n        is_prediction=True,\n    )\n    return \"Successfully registered image and annotation\"\n\n\ndef safe_register_image_at_roboflow(\n    target_project: str,\n    encoded_image: bytes,\n    local_image_id: str,\n    api_key: str,\n    batch_name: str,\n    tags: List[str],\n    inference_id: Optional[str],\n    metadata: Optional[Dict[str, Any]] = None,\n) -> Optional[str]:\n    registration_response = register_image_at_roboflow(\n        api_key=api_key,\n        dataset_id=target_project,\n        local_image_id=local_image_id,\n        image_bytes=encoded_image,\n        batch_name=batch_name,\n        tags=tags,\n        inference_id=inference_id,\n        metadata=metadata,\n    )\n    image_duplicated = registration_response.get(\"duplicate\", False)\n    if image_duplicated:\n        logging.warning(f\"Image duplication detected: {registration_response}.\")\n        return None\n    return registration_response[\"id\"]\n\n\ndef is_prediction_registration_forbidden(\n    prediction: Optional[Union[sv.Detections, dict]],\n) -> bool:\n    if prediction is None:\n        return True\n    if isinstance(prediction, sv.Detections) and len(prediction) == 0:\n        return True\n    if isinstance(prediction, dict) and (\n        \"top\" not in prediction and \"predicted_classes\" not in prediction\n    ):\n        return True\n    return False\n\n\ndef encode_prediction(\n    prediction: Union[sv.Detections, dict],\n) -> Tuple[str, str]:\n    if isinstance(prediction, dict):\n        if \"predicted_classes\" in prediction:\n            return \",\".join(prediction[\"predicted_classes\"]), \"txt\"\n        return prediction[\"top\"], \"txt\"\n    detections_in_inference_format = serialise_sv_detections(detections=prediction)\n    return json.dumps(detections_in_inference_format), \"json\"\n",
    "patch": null
  },
  {
    "trace_id": "e5ba2799-bba7-4b4b-b232-5e44d3c89337",
    "function_name": "execute_registration",
    "file_path": "inference/core/workflows/core_steps/sinks/roboflow/dataset_upload/v1.py",
    "speedup_x": 0.16656540743593737,
    "review_quality": "high",
    "pre_optimization_commit": "5172cfc4e59a6b29dd81a1c98238759ced9f16a0",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def execute_registration(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    persist_predictions: bool,\n    usage_quota_name: str,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    api_key: str,\n    image_name: Optional[str] = None,\n) -> Tuple[bool, str]:\n    matching_strategies_limits = OrderedDict(\n        {\n            usage_quota_name: [\n                StrategyLimit(\n                    limit_type=StrategyLimitType.MINUTELY, value=minutely_usage_limit\n                ),\n                StrategyLimit(\n                    limit_type=StrategyLimitType.HOURLY, value=hourly_usage_limit\n                ),\n                StrategyLimit(\n                    limit_type=StrategyLimitType.DAILY, value=daily_usage_limit\n                ),\n            ]\n        }\n    )\n    workspace_name = get_workspace_name(api_key=api_key, cache=cache)\n    strategy_with_spare_credit = use_credit_of_matching_strategy(\n        cache=cache,\n        workspace=workspace_name,\n        project=target_project,\n        matching_strategies_limits=matching_strategies_limits,\n    )\n    if strategy_with_spare_credit is None:\n        return False, \"Registration skipped due to usage quota exceeded\"\n    credit_to_be_returned = False\n    try:\n        local_image_id = image_name if image_name else str(uuid4())\n        encoded_image, scaling_factor = prepare_image_to_registration(\n            image=image.numpy_image,\n            desired_size=ImageDimensions(\n                width=max_image_size[0], height=max_image_size[1]\n            ),\n            jpeg_compression_level=compression_level,\n        )\n        batch_name = generate_batch_name(\n            labeling_batch_prefix=labeling_batch_prefix,\n            new_labeling_batch_frequency=new_labeling_batch_frequency,\n        )\n        if isinstance(prediction, sv.Detections):\n            prediction = scale_sv_detections(\n                detections=prediction, scale=scaling_factor\n            )\n        status = register_datapoint(\n            target_project=target_project,\n            encoded_image=encoded_image,\n            local_image_id=local_image_id,\n            prediction=prediction if persist_predictions else None,\n            api_key=api_key,\n            batch_name=batch_name,\n            tags=registration_tags,\n        )\n        if status == DUPLICATED_STATUS:\n            credit_to_be_returned = True\n        return False, status\n    except Exception as error:\n        credit_to_be_returned = True\n        logging.exception(\"Failed to register datapoint on the Roboflow platform\")\n        return (\n            True,\n            f\"Error while registration. Error type: {type(error)}. Details: {error}\",\n        )\n    finally:\n        if credit_to_be_returned:\n            return_strategy_credit(\n                cache=cache,\n                workspace=workspace_name,\n                project=target_project,\n                strategy_name=strategy_with_spare_credit,\n            )\n",
    "optimized_function_code": "from __future__ import annotations\n\nimport hashlib\nimport logging\nfrom collections import OrderedDict\nfrom typing import List, Literal, Optional, Tuple, Union\nfrom uuid import uuid4\n\nimport supervision as sv\nfrom inference.core.active_learning.cache_operations import (\n    return_strategy_credit, use_credit_of_matching_strategy)\nfrom inference.core.active_learning.core import prepare_image_to_registration\nfrom inference.core.active_learning.entities import (ImageDimensions,\n                                                     StrategyLimit,\n                                                     StrategyLimitType)\nfrom inference.core.cache.base import BaseCache\nfrom inference.core.roboflow_api import (annotate_image_at_roboflow,\n                                         get_roboflow_workspace)\nfrom inference.core.workflows.core_steps.common.utils import \\\n    scale_sv_detections\nfrom inference.core.workflows.execution_engine.constants import \\\n    INFERENCE_ID_KEY\nfrom inference.core.workflows.execution_engine.entities.base import \\\n    WorkflowImageData\n\nWORKSPACE_NAME_CACHE_EXPIRE = 900  # 15 min\nTIMESTAMP_FORMAT = \"%Y_%m_%d\"\nDUPLICATED_STATUS = \"Duplicated image\"\nBatchCreationFrequency = Literal[\"never\", \"daily\", \"weekly\", \"monthly\"]\n\n\ndef execute_registration(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    persist_predictions: bool,\n    usage_quota_name: str,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    api_key: str,\n    image_name: Optional[str] = None,\n) -> Tuple[bool, str]:\n    matching_strategies_limits = OrderedDict(\n        {\n            usage_quota_name: [\n                StrategyLimit(\n                    limit_type=StrategyLimitType.MINUTELY, value=minutely_usage_limit\n                ),\n                StrategyLimit(\n                    limit_type=StrategyLimitType.HOURLY, value=hourly_usage_limit\n                ),\n                StrategyLimit(\n                    limit_type=StrategyLimitType.DAILY, value=daily_usage_limit\n                ),\n            ]\n        }\n    )\n    workspace_name = get_workspace_name(api_key=api_key, cache=cache)\n    strategy_with_spare_credit = use_credit_of_matching_strategy(\n        cache=cache,\n        workspace=workspace_name,\n        project=target_project,\n        matching_strategies_limits=matching_strategies_limits,\n    )\n    if strategy_with_spare_credit is None:\n        return False, \"Registration skipped due to usage quota exceeded\"\n    credit_to_be_returned = False\n    try:\n        local_image_id = image_name if image_name else str(uuid4())\n        encoded_image, scaling_factor = prepare_image_to_registration(\n            image=image.numpy_image,\n            desired_size=ImageDimensions(\n                width=max_image_size[0], height=max_image_size[1]\n            ),\n            jpeg_compression_level=compression_level,\n        )\n        batch_name = generate_batch_name(\n            labeling_batch_prefix=labeling_batch_prefix,\n            new_labeling_batch_frequency=new_labeling_batch_frequency,\n        )\n        if isinstance(prediction, sv.Detections):\n            prediction = scale_sv_detections(\n                detections=prediction, scale=scaling_factor\n            )\n        status = register_datapoint(\n            target_project=target_project,\n            encoded_image=encoded_image,\n            local_image_id=local_image_id,\n            prediction=prediction if persist_predictions else None,\n            api_key=api_key,\n            batch_name=batch_name,\n            tags=registration_tags,\n        )\n        if status == DUPLICATED_STATUS:\n            credit_to_be_returned = True\n        return False, status\n    except Exception as error:\n        credit_to_be_returned = True\n        logging.exception(\"Failed to register datapoint on the Roboflow platform\")\n        return (\n            True,\n            f\"Error while registration. Error type: {type(error)}. Details: {error}\",\n        )\n    finally:\n        if credit_to_be_returned:\n            return_strategy_credit(\n                cache=cache,\n                workspace=workspace_name,\n                project=target_project,\n                strategy_name=strategy_with_spare_credit,\n            )\n\n\ndef get_workspace_name(\n    api_key: str,\n    cache: BaseCache,\n) -> str:\n    api_key_hash = hashlib.md5(api_key.encode(\"utf-8\")).hexdigest()\n    cache_key = f\"workflows:api_key_to_workspace:{api_key_hash}\"\n    cached_workspace_name = cache.get(cache_key)\n    if cached_workspace_name:\n        return cached_workspace_name\n    workspace_name_from_api = get_roboflow_workspace(api_key=api_key)\n    cache.set(\n        key=cache_key, value=workspace_name_from_api, expire=WORKSPACE_NAME_CACHE_EXPIRE\n    )\n    return workspace_name_from_api\n\n\ndef generate_batch_name(\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n) -> str:\n    if new_labeling_batch_frequency == \"never\":\n        return labeling_batch_prefix\n    timestamp_generator = RECREATION_INTERVAL2TIMESTAMP_GENERATOR[\n        new_labeling_batch_frequency\n    ]\n    timestamp = timestamp_generator()\n    return f\"{labeling_batch_prefix}_{timestamp}\"\n\n\nRECREATION_INTERVAL2TIMESTAMP_GENERATOR = {\n    \"daily\": generate_today_timestamp,\n    \"weekly\": generate_start_timestamp_for_this_week,\n    \"monthly\": generate_start_timestamp_for_this_month,\n}\n\n\ndef register_datapoint(\n    target_project: str,\n    encoded_image: bytes,\n    local_image_id: str,\n    prediction: Optional[Union[sv.Detections, dict]],\n    api_key: str,\n    batch_name: str,\n    tags: List[str],\n) -> str:\n    inference_id = None\n    if isinstance(prediction, dict):\n        inference_id = prediction.get(INFERENCE_ID_KEY)\n    if isinstance(prediction, sv.Detections) and len(prediction) > 0:\n        # TODO: Lack of inference ID for empty prediction -\n        #  dependent on https://github.com/roboflow/inference/issues/567\n        inference_id_array = prediction.data.get(INFERENCE_ID_KEY)\n        if inference_id_array is not None:\n            inference_id_list = inference_id_array.tolist()\n            inference_id = inference_id_list[0]\n    roboflow_image_id = safe_register_image_at_roboflow(\n        target_project=target_project,\n        encoded_image=encoded_image,\n        local_image_id=local_image_id,\n        api_key=api_key,\n        batch_name=batch_name,\n        tags=tags,\n        inference_id=inference_id,\n    )\n    if roboflow_image_id is None:\n        return DUPLICATED_STATUS\n    if is_prediction_registration_forbidden(prediction=prediction):\n        return \"Successfully registered image\"\n    encoded_prediction, prediction_format = encode_prediction(prediction=prediction)\n    _ = annotate_image_at_roboflow(\n        api_key=api_key,\n        dataset_id=target_project,\n        local_image_id=local_image_id,\n        roboflow_image_id=roboflow_image_id,\n        annotation_content=encoded_prediction,\n        annotation_file_type=prediction_format,\n        is_prediction=True,\n    )\n    return \"Successfully registered image and annotation\"",
    "optimized_raw_markdown": "```python:inference/core/active_learning/entities.py\nfrom dataclasses import dataclass\nfrom enum import Enum\nfrom typing import Tuple\n\n@dataclass(frozen=True)\nclass ImageDimensions:\n    height: int\n    width: int\n\n    def to_hw(self) -> Tuple[int, int]:\n        return self.height, self.width\n\n    def to_wh(self) -> Tuple[int, int]:\n        return self.width, self.height\n\n\nclass StrategyLimitType(Enum):\n    MINUTELY = \"minutely\"\n    HOURLY = \"hourly\"\n    DAILY = \"daily\"\n\n\n@dataclass(frozen=True)\nclass StrategyLimit:\n    limit_type: StrategyLimitType\n    value: int\n\n    @classmethod\n    def from_dict(cls, specification: dict) -> \"StrategyLimit\":\n        return cls(\n            limit_type=StrategyLimitType(specification[\"type\"]),\n            value=specification[\"value\"],\n        )\n```\n```python:inference/core/workflows/core_steps/sinks/roboflow/dataset_upload/v1.py\nfrom __future__ import annotations\n\nimport hashlib\nimport logging\nfrom collections import OrderedDict\nfrom typing import List, Literal, Optional, Tuple, Union\nfrom uuid import uuid4\n\nimport supervision as sv\nfrom inference.core.active_learning.cache_operations import (\n    return_strategy_credit, use_credit_of_matching_strategy)\nfrom inference.core.active_learning.core import prepare_image_to_registration\nfrom inference.core.active_learning.entities import (ImageDimensions,\n                                                     StrategyLimit,\n                                                     StrategyLimitType)\nfrom inference.core.cache.base import BaseCache\nfrom inference.core.roboflow_api import (annotate_image_at_roboflow,\n                                         get_roboflow_workspace)\nfrom inference.core.workflows.core_steps.common.utils import \\\n    scale_sv_detections\nfrom inference.core.workflows.execution_engine.constants import \\\n    INFERENCE_ID_KEY\nfrom inference.core.workflows.execution_engine.entities.base import \\\n    WorkflowImageData\n\nWORKSPACE_NAME_CACHE_EXPIRE = 900  # 15 min\nTIMESTAMP_FORMAT = \"%Y_%m_%d\"\nDUPLICATED_STATUS = \"Duplicated image\"\nBatchCreationFrequency = Literal[\"never\", \"daily\", \"weekly\", \"monthly\"]\n\n\ndef execute_registration(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    persist_predictions: bool,\n    usage_quota_name: str,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    api_key: str,\n    image_name: Optional[str] = None,\n) -> Tuple[bool, str]:\n    matching_strategies_limits = OrderedDict(\n        {\n            usage_quota_name: [\n                StrategyLimit(\n                    limit_type=StrategyLimitType.MINUTELY, value=minutely_usage_limit\n                ),\n                StrategyLimit(\n                    limit_type=StrategyLimitType.HOURLY, value=hourly_usage_limit\n                ),\n                StrategyLimit(\n                    limit_type=StrategyLimitType.DAILY, value=daily_usage_limit\n                ),\n            ]\n        }\n    )\n    workspace_name = get_workspace_name(api_key=api_key, cache=cache)\n    strategy_with_spare_credit = use_credit_of_matching_strategy(\n        cache=cache,\n        workspace=workspace_name,\n        project=target_project,\n        matching_strategies_limits=matching_strategies_limits,\n    )\n    if strategy_with_spare_credit is None:\n        return False, \"Registration skipped due to usage quota exceeded\"\n    credit_to_be_returned = False\n    try:\n        local_image_id = image_name if image_name else str(uuid4())\n        encoded_image, scaling_factor = prepare_image_to_registration(\n            image=image.numpy_image,\n            desired_size=ImageDimensions(\n                width=max_image_size[0], height=max_image_size[1]\n            ),\n            jpeg_compression_level=compression_level,\n        )\n        batch_name = generate_batch_name(\n            labeling_batch_prefix=labeling_batch_prefix,\n            new_labeling_batch_frequency=new_labeling_batch_frequency,\n        )\n        if isinstance(prediction, sv.Detections):\n            prediction = scale_sv_detections(\n                detections=prediction, scale=scaling_factor\n            )\n        status = register_datapoint(\n            target_project=target_project,\n            encoded_image=encoded_image,\n            local_image_id=local_image_id,\n            prediction=prediction if persist_predictions else None,\n            api_key=api_key,\n            batch_name=batch_name,\n            tags=registration_tags,\n        )\n        if status == DUPLICATED_STATUS:\n            credit_to_be_returned = True\n        return False, status\n    except Exception as error:\n        credit_to_be_returned = True\n        logging.exception(\"Failed to register datapoint on the Roboflow platform\")\n        return (\n            True,\n            f\"Error while registration. Error type: {type(error)}. Details: {error}\",\n        )\n    finally:\n        if credit_to_be_returned:\n            return_strategy_credit(\n                cache=cache,\n                workspace=workspace_name,\n                project=target_project,\n                strategy_name=strategy_with_spare_credit,\n            )\n\n\ndef get_workspace_name(\n    api_key: str,\n    cache: BaseCache,\n) -> str:\n    api_key_hash = hashlib.md5(api_key.encode(\"utf-8\")).hexdigest()\n    cache_key = f\"workflows:api_key_to_workspace:{api_key_hash}\"\n    cached_workspace_name = cache.get(cache_key)\n    if cached_workspace_name:\n        return cached_workspace_name\n    workspace_name_from_api = get_roboflow_workspace(api_key=api_key)\n    cache.set(\n        key=cache_key, value=workspace_name_from_api, expire=WORKSPACE_NAME_CACHE_EXPIRE\n    )\n    return workspace_name_from_api\n\n\ndef generate_batch_name(\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n) -> str:\n    if new_labeling_batch_frequency == \"never\":\n        return labeling_batch_prefix\n    timestamp_generator = RECREATION_INTERVAL2TIMESTAMP_GENERATOR[\n        new_labeling_batch_frequency\n    ]\n    timestamp = timestamp_generator()\n    return f\"{labeling_batch_prefix}_{timestamp}\"\n\n\nRECREATION_INTERVAL2TIMESTAMP_GENERATOR = {\n    \"daily\": generate_today_timestamp,\n    \"weekly\": generate_start_timestamp_for_this_week,\n    \"monthly\": generate_start_timestamp_for_this_month,\n}\n\n\ndef register_datapoint(\n    target_project: str,\n    encoded_image: bytes,\n    local_image_id: str,\n    prediction: Optional[Union[sv.Detections, dict]],\n    api_key: str,\n    batch_name: str,\n    tags: List[str],\n) -> str:\n    inference_id = None\n    if isinstance(prediction, dict):\n        inference_id = prediction.get(INFERENCE_ID_KEY)\n    if isinstance(prediction, sv.Detections) and len(prediction) > 0:\n        # TODO: Lack of inference ID for empty prediction -\n        #  dependent on https://github.com/roboflow/inference/issues/567\n        inference_id_array = prediction.data.get(INFERENCE_ID_KEY)\n        if inference_id_array is not None:\n            inference_id_list = inference_id_array.tolist()\n            inference_id = inference_id_list[0]\n    roboflow_image_id = safe_register_image_at_roboflow(\n        target_project=target_project,\n        encoded_image=encoded_image,\n        local_image_id=local_image_id,\n        api_key=api_key,\n        batch_name=batch_name,\n        tags=tags,\n        inference_id=inference_id,\n    )\n    if roboflow_image_id is None:\n        return DUPLICATED_STATUS\n    if is_prediction_registration_forbidden(prediction=prediction):\n        return \"Successfully registered image\"\n    encoded_prediction, prediction_format = encode_prediction(prediction=prediction)\n    _ = annotate_image_at_roboflow(\n        api_key=api_key,\n        dataset_id=target_project,\n        local_image_id=local_image_id,\n        roboflow_image_id=roboflow_image_id,\n        annotation_content=encoded_prediction,\n        annotation_file_type=prediction_format,\n        is_prediction=True,\n    )\n    return \"Successfully registered image and annotation\"\n```\n```python:inference/core/active_learning/cache_operations.py\nfrom datetime import datetime\nfrom inference.core.active_learning.entities import StrategyLimit, StrategyLimitType\nfrom inference.core.active_learning.utils import TIMESTAMP_FORMAT\nfrom inference.core.cache.base import BaseCache\nfrom typing import List, Optional, OrderedDict\n\nMAX_LOCK_TIME = 5\nSECONDS_IN_HOUR = 60 * 60\nUSAGE_KEY = \"usage\"\n\nLIMIT_TYPE2KEY_INFIX_GENERATOR = {\n    StrategyLimitType.MINUTELY: lambda: f\"minute_{datetime.utcnow().minute}\",\n    StrategyLimitType.HOURLY: lambda: f\"hour_{datetime.utcnow().hour}\",\n    StrategyLimitType.DAILY: lambda: f\"day_{datetime.utcnow().strftime(TIMESTAMP_FORMAT)}\",\n}\nLIMIT_TYPE2KEY_EXPIRATION = {\n    StrategyLimitType.MINUTELY: 120,\n    StrategyLimitType.HOURLY: 2 * SECONDS_IN_HOUR,\n    StrategyLimitType.DAILY: 25 * SECONDS_IN_HOUR,\n}\n\n\ndef use_credit_of_matching_strategy(\n    cache: BaseCache,\n    workspace: str,\n    project: str,\n    matching_strategies_limits: OrderedDict[str, List[StrategyLimit]],\n) -> Optional[str]:\n    # In scope of this function, cache keys updates regarding usage limits for\n    # specific :workspace and :project are locked - to ensure increment to be done atomically\n    # Limits are accounted at the moment of registration - which may introduce inaccuracy\n    # given that registration is postponed from prediction\n    # Returns: strategy with spare credit if found - else None\n    with lock_limits(cache=cache, workspace=workspace, project=project):\n        strategy_with_spare_credit = find_strategy_with_spare_usage_credit(\n            cache=cache,\n            workspace=workspace,\n            project=project,\n            matching_strategies_limits=matching_strategies_limits,\n        )\n        if strategy_with_spare_credit is None:\n            return None\n        consume_strategy_limits_usage_credit(\n            cache=cache,\n            workspace=workspace,\n            project=project,\n            strategy_name=strategy_with_spare_credit,\n        )\n        return strategy_with_spare_credit\n\n\ndef return_strategy_credit(\n    cache: BaseCache,\n    workspace: str,\n    project: str,\n    strategy_name: str,\n) -> None:\n    # In scope of this function, cache keys updates regarding usage limits for\n    # specific :workspace and :project are locked - to ensure decrement to be done atomically\n    # Returning strategy is a bit naive (we may add to a pool of credits from the next period - but only\n    # if we have previously taken from the previous one and some credits are used in the new pool) -\n    # in favour of easier implementation.\n    with lock_limits(cache=cache, workspace=workspace, project=project):\n        return_strategy_limits_usage_credit(\n            cache=cache,\n            workspace=workspace,\n            project=project,\n            strategy_name=strategy_name,\n        )\n```\n```python:inference/core/active_learning/core.py\nimport numpy as np\nfrom inference.core.active_learning.entities import ImageDimensions\nfrom inference.core.utils.image_utils import encode_image_to_jpeg_bytes\nfrom inference.core.utils.preprocess import downscale_image_keeping_aspect_ratio\nfrom typing import Optional, Tuple\n\ndef prepare_image_to_registration(\n    image: np.ndarray,\n    desired_size: Optional[ImageDimensions],\n    jpeg_compression_level: int,\n) -> Tuple[bytes, float]:\n    scaling_factor = 1.0\n    if desired_size is not None:\n        height_before_scale = image.shape[0]\n        image = downscale_image_keeping_aspect_ratio(\n            image=image,\n            desired_size=desired_size.to_wh(),\n        )\n        scaling_factor = image.shape[0] / height_before_scale\n    return (\n        encode_image_to_jpeg_bytes(image=image, jpeg_quality=jpeg_compression_level),\n        scaling_factor,\n    )\n```\n```python:inference/core/workflows/core_steps/common/utils.py\nimport numpy as np\nimport supervision as sv\nfrom inference.core.workflows.execution_engine.constants import (\n    IMAGE_DIMENSIONS_KEY, KEYPOINTS_XY_KEY_IN_SV_DETECTIONS,\n    POLYGON_KEY_IN_SV_DETECTIONS, SCALING_RELATIVE_TO_PARENT_KEY,\n    SCALING_RELATIVE_TO_ROOT_PARENT_KEY)\n\n\ndef scale_sv_detections(\n    detections: sv.Detections,\n    scale: float,\n    keypoints_key: str = KEYPOINTS_XY_KEY_IN_SV_DETECTIONS,\n) -> sv.Detections:\n    if len(detections) == 0:\n        return sv.Detections.empty()\n    \n    # Create new detections with scaled xyxy\n    scaled_xyxy = (detections.xyxy * scale).round()\n    \n    # Copy and scale data dictionary\n    scaled_data = {}\n    for key, value in detections.data.items():\n        if key == keypoints_key:\n            scaled_keypoints = []\n            for kp in value:\n                scaled_keypoints.append((kp.astype(np.float32) * scale).round())\n            scaled_data[key] = scaled_keypoints\n        elif key == IMAGE_DIMENSIONS_KEY:\n            scaled_data[key] = (value * scale).round()\n        elif key == POLYGON_KEY_IN_SV_DETECTIONS:\n            scaled_data[key] = (value * scale).round().astype(np.int32)\n        elif key == SCALING_RELATIVE_TO_PARENT_KEY:\n            scaled_data[key] = value * scale\n        elif key == SCALING_RELATIVE_TO_ROOT_PARENT_KEY:\n            scaled_data[key] = value * scale\n        else:\n            scaled_data[key] = value\n    \n    # Add scaling keys if they don't exist\n    if SCALING_RELATIVE_TO_PARENT_KEY not in scaled_data:\n        scaled_data[SCALING_RELATIVE_TO_PARENT_KEY] = np.full(len(detections), scale)\n    if SCALING_RELATIVE_TO_ROOT_PARENT_KEY not in scaled_data:\n        scaled_data[SCALING_RELATIVE_TO_ROOT_PARENT_KEY] = np.full(len(detections), scale)\n    \n    # Handle masks\n    scaled_mask = None\n    if detections.mask is not None:\n        scaled_masks = []\n        original_mask_size_wh = (\n            detections.mask.shape[2],\n            detections.mask.shape[1],\n        )\n        scaled_mask_size_wh = round(original_mask_size_wh[0] * scale), round(\n            original_mask_size_wh[1] * scale\n        )\n        for detection_mask in detections.mask:\n            polygons = sv.mask_to_polygons(mask=detection_mask)\n            polygon_masks = []\n            for polygon in polygons:\n                scaled_polygon = (polygon * scale).round().astype(np.int32)\n                polygon_masks.append(\n                    sv.polygon_to_mask(\n                        polygon=scaled_polygon, resolution_wh=scaled_mask_size_wh\n                    )\n                )\n            scaled_detection_mask = np.sum(polygon_masks, axis=0) > 0\n            scaled_masks.append(scaled_detection_mask)\n        scaled_mask = np.array(scaled_masks)\n    \n    return sv.Detections(\n        xyxy=scaled_xyxy,\n        mask=scaled_mask,\n        confidence=detections.confidence,\n        class_id=detections.class_id,\n        tracker_id=detections.tracker_id,\n        data=scaled_data,\n    )\n```",
    "optimized_function_only": "def execute_registration(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    persist_predictions: bool,\n    usage_quota_name: str,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    api_key: str,\n    image_name: Optional[str] = None,\n) -> Tuple[bool, str]:\n    matching_strategies_limits = OrderedDict(\n        {\n            usage_quota_name: [\n                StrategyLimit(\n                    limit_type=StrategyLimitType.MINUTELY, value=minutely_usage_limit\n                ),\n                StrategyLimit(\n                    limit_type=StrategyLimitType.HOURLY, value=hourly_usage_limit\n                ),\n                StrategyLimit(\n                    limit_type=StrategyLimitType.DAILY, value=daily_usage_limit\n                ),\n            ]\n        }\n    )\n    workspace_name = get_workspace_name(api_key=api_key, cache=cache)\n    strategy_with_spare_credit = use_credit_of_matching_strategy(\n        cache=cache,\n        workspace=workspace_name,\n        project=target_project,\n        matching_strategies_limits=matching_strategies_limits,\n    )\n    if strategy_with_spare_credit is None:\n        return False, \"Registration skipped due to usage quota exceeded\"\n    credit_to_be_returned = False\n    try:\n        local_image_id = image_name if image_name else str(uuid4())\n        encoded_image, scaling_factor = prepare_image_to_registration(\n            image=image.numpy_image,\n            desired_size=ImageDimensions(\n                width=max_image_size[0], height=max_image_size[1]\n            ),\n            jpeg_compression_level=compression_level,\n        )\n        batch_name = generate_batch_name(\n            labeling_batch_prefix=labeling_batch_prefix,\n            new_labeling_batch_frequency=new_labeling_batch_frequency,\n        )\n        if isinstance(prediction, sv.Detections):\n            prediction = scale_sv_detections(\n                detections=prediction, scale=scaling_factor\n            )\n        status = register_datapoint(\n            target_project=target_project,\n            encoded_image=encoded_image,\n            local_image_id=local_image_id,\n            prediction=prediction if persist_predictions else None,\n            api_key=api_key,\n            batch_name=batch_name,\n            tags=registration_tags,\n        )\n        if status == DUPLICATED_STATUS:\n            credit_to_be_returned = True\n        return False, status\n    except Exception as error:\n        credit_to_be_returned = True\n        logging.exception(\"Failed to register datapoint on the Roboflow platform\")\n        return (\n            True,\n            f\"Error while registration. Error type: {type(error)}. Details: {error}\",\n        )\n    finally:\n        if credit_to_be_returned:\n            return_strategy_credit(\n                cache=cache,\n                workspace=workspace_name,\n                project=target_project,\n                strategy_name=strategy_with_spare_credit,\n            )\n",
    "original_file_content": "\"\"\"\n*****************************************************************\n*                           WARNING!                            *\n*****************************************************************\nThis module contains the utility functions used by\nRoboflowDatasetUploadBlockV2.\n\nWe do not recommend making multiple blocks dependent on the same code,\nbut the change between v1 and v2 was basically the default value of\nsome parameter - hence we decided not to replicate the code.\n\nIf you need to modify this module beware that you may introduce\nchange to RoboflowDatasetUploadBlockV2! If that happens,\nprobably that's the time to disentangle those blocks and copy the\ncode.\n\"\"\"\n\nimport hashlib\nimport json\nimport logging\nfrom collections import OrderedDict\nfrom concurrent.futures import ThreadPoolExecutor\nfrom datetime import datetime, timedelta\nfrom functools import partial\nfrom typing import List, Literal, Optional, Tuple, Type, Union\nfrom uuid import uuid4\n\nimport supervision as sv\nfrom fastapi import BackgroundTasks\nfrom pydantic import AliasChoices, ConfigDict, Field\n\nfrom inference.core.active_learning.cache_operations import (\n    return_strategy_credit,\n    use_credit_of_matching_strategy,\n)\nfrom inference.core.active_learning.core import prepare_image_to_registration\nfrom inference.core.active_learning.entities import (\n    ImageDimensions,\n    StrategyLimit,\n    StrategyLimitType,\n)\nfrom inference.core.cache.base import BaseCache\nfrom inference.core.roboflow_api import (\n    annotate_image_at_roboflow,\n    get_roboflow_workspace,\n    register_image_at_roboflow,\n)\nfrom inference.core.workflows.core_steps.common.serializers import (\n    serialise_sv_detections,\n)\nfrom inference.core.workflows.core_steps.common.utils import scale_sv_detections\nfrom inference.core.workflows.execution_engine.constants import INFERENCE_ID_KEY\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    BOOLEAN_KIND,\n    CLASSIFICATION_PREDICTION_KIND,\n    IMAGE_KIND,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    KEYPOINT_DETECTION_PREDICTION_KIND,\n    LIST_OF_VALUES_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    ROBOFLOW_PROJECT_KIND,\n    STRING_KIND,\n    ImageInputField,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nSHORT_DESCRIPTION = \"Save images and predictions to your Roboflow Dataset.\"\n\nLONG_DESCRIPTION = \"\"\"\nUpload images and model predictions to a Roboflow dataset for active learning, model improvement, and data collection, with configurable usage quotas, batch organization, image compression, and optional annotation persistence.\n\n## How This Block Works\n\nThis block uploads workflow images and predictions to your Roboflow dataset for storage, labeling, and model training. The block:\n\n1. Takes images and optional model predictions (object detection, instance segmentation, keypoint detection, or classification) as input\n2. Validates the Roboflow API key is available (required for uploading)\n3. Checks usage quotas (minutely, hourly, daily limits) to ensure uploads stay within configured rate limits for active learning strategies\n4. Prepares images by resizing if they exceed maximum size (maintaining aspect ratio) and compressing to specified quality level\n5. Generates labeling batch names based on the prefix and batch creation frequency (never, daily, weekly, or monthly), organizing uploaded data into batches\n6. Optionally persists model predictions as annotations if `persist_predictions` is enabled, allowing predictions to serve as pre-labels for review and correction\n7. Attaches registration tags to images for organization and filtering in the Roboflow platform\n8. Registers the image (and annotations if enabled) to the specified Roboflow project via the Roboflow API\n9. Executes synchronously or asynchronously based on `fire_and_forget` setting, allowing non-blocking uploads for faster workflow execution\n10. Returns error status and messages indicating upload success or failure\n\nThe block supports active learning workflows by implementing usage quotas that prevent excessive data collection, helping focus on collecting valuable training data within rate limits. Images are organized into labeling batches that can be automatically recreated on a schedule (daily, weekly, monthly), making it easier to manage and review collected data over time. The block can operate in fire-and-forget mode for asynchronous execution, allowing workflows to continue processing without waiting for uploads to complete, or synchronously for debugging and error handling.\n\n## Requirements\n\n**API Key Required**: This block requires a valid Roboflow API key to upload data. The API key must be configured in your environment or workflow configuration. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve an API key.\n\n## Common Use Cases\n\n- **Active Learning Data Collection**: Collect images and predictions from production environments where models struggle or are uncertain (e.g., low-confidence detections, edge cases), enabling iterative model improvement by gathering challenging examples for retraining\n- **Production Data Logging**: Continuously upload production inference data to Roboflow datasets for monitoring, analysis, and future model training, creating a growing dataset from real-world deployments\n- **Pre-Labeled Data Collection**: Upload images with model predictions as pre-labels (when `persist_predictions` is enabled), accelerating annotation workflows by providing initial labels that can be reviewed and corrected rather than starting from scratch\n- **Stratified Data Sampling**: Use rate limiting and quotas to selectively collect data based on specific criteria (e.g., combine with Rate Limiter or Continue If blocks), ensuring diverse and balanced dataset collection without overwhelming storage or annotation resources\n- **Batch-Based Labeling Workflows**: Organize uploaded data into batches with automatic recreation schedules (daily, weekly, monthly), making it easier to manage labeling tasks, track progress, and organize data collection efforts over time\n- **Tagged Data Organization**: Attach metadata tags to uploaded images (e.g., location, camera ID, time period, model version), enabling filtering and organization of collected data in Roboflow for better dataset management and analysis\n\n## Connecting to Other Blocks\n\nThis block receives data from workflow steps and uploads it to Roboflow:\n\n- **After detection or analysis blocks** (e.g., Object Detection Model, Instance Segmentation Model, Classification Model, Keypoint Detection Model) to upload images along with their predictions, enabling active learning by collecting inference data with model outputs for annotation and retraining\n- **After filtering or analytics blocks** (e.g., Detections Filter, Continue If, Overlap Filter) to selectively upload only specific types of data (e.g., low-confidence detections, overlapping objects, specific classes), focusing data collection on valuable edge cases or interesting scenarios\n- **After rate limiter blocks** (e.g., Rate Limiter) to throttle upload frequency and stay within usage quotas, ensuring controlled data collection that respects rate limits and prevents excessive storage usage\n- **Image inputs or preprocessing blocks** to upload raw images or processed images (e.g., crops, transformed images) without predictions, enabling collection of image data for future labeling or analysis\n- **Conditional workflows** using flow control blocks (e.g., Continue If) to upload data only when certain conditions are met (e.g., upload only when detection count exceeds threshold, upload only errors or failures), enabling selective data collection based on workflow state\n- **Batch processing workflows** where multiple images or predictions are generated, allowing bulk upload of workflow outputs to Roboflow datasets for organized data collection and management\n\"\"\"\n\nWORKSPACE_NAME_CACHE_EXPIRE = 900  # 15 min\nTIMESTAMP_FORMAT = \"%Y_%m_%d\"\nDUPLICATED_STATUS = \"Duplicated image\"\nBatchCreationFrequency = Literal[\"never\", \"daily\", \"weekly\", \"monthly\"]\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Roboflow Dataset Upload\",\n            \"version\": \"v1\",\n            \"short_description\": SHORT_DESCRIPTION,\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"sink\",\n            \"ui_manifest\": {\n                \"section\": \"data_storage\",\n                \"icon\": \"fal fa-upload\",\n                \"blockPriority\": 0,\n                \"popular\": True,\n                \"requires_rf_key\": True,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/roboflow_dataset_upload@v1\", \"RoboflowDatasetUpload\"]\n    images: Selector(kind=[IMAGE_KIND]) = Field(\n        title=\"Input Image\",\n        description=\"Image(s) to upload to the Roboflow dataset. Can be a single image or batch of images from workflow inputs or processing steps. Images are resized if they exceed max_image_size and compressed before uploading. Supports batch processing.\",\n        examples=[\"$inputs.image\", \"$steps.cropping.crops\"],\n        validation_alias=AliasChoices(\"image\", \"images\"),\n    )\n    predictions: Optional[\n        Selector(\n            kind=[\n                OBJECT_DETECTION_PREDICTION_KIND,\n                INSTANCE_SEGMENTATION_PREDICTION_KIND,\n                KEYPOINT_DETECTION_PREDICTION_KIND,\n                CLASSIFICATION_PREDICTION_KIND,\n            ]\n        )\n    ] = Field(\n        default=None,\n        description=\"Optional model predictions to upload alongside images. Predictions are saved as annotations (pre-labels) in the Roboflow dataset when persist_predictions is enabled, allowing predictions to serve as starting points for annotation review and correction. Supports object detection, instance segmentation, keypoint detection, and classification predictions. If None, only images are uploaded.\",\n        examples=[\"$steps.object_detection_model.predictions\"],\n    )\n    target_project: Union[Selector(kind=[ROBOFLOW_PROJECT_KIND]), str] = Field(\n        description=\"Roboflow project identifier where uploaded images and annotations will be saved. Must be a valid project in your Roboflow workspace. The project name can be specified directly or referenced from workflow inputs.\",\n        examples=[\"my_project\", \"$inputs.target_project\"],\n    )\n    minutely_usage_limit: int = Field(\n        default=10,\n        description=\"Maximum number of image uploads allowed per minute for this quota. Part of the usage quota system that enforces rate limits for active learning data collection. Uploads exceeding this limit are skipped to prevent excessive data collection. Works together with hourly_usage_limit and daily_usage_limit to provide multi-level rate limiting.\",\n        examples=[10, 60],\n    )\n    hourly_usage_limit: int = Field(\n        default=100,\n        description=\"Maximum number of image uploads allowed per hour for this quota. Part of the usage quota system that enforces rate limits for active learning data collection. Uploads exceeding this limit are skipped to prevent excessive data collection. Works together with minutely_usage_limit and daily_usage_limit to provide multi-level rate limiting.\",\n        examples=[10, 60],\n    )\n    daily_usage_limit: int = Field(\n        default=1000,\n        description=\"Maximum number of image uploads allowed per day for this quota. Part of the usage quota system that enforces rate limits for active learning data collection. Uploads exceeding this limit are skipped to prevent excessive data collection. Works together with minutely_usage_limit and hourly_usage_limit to provide multi-level rate limiting.\",\n        examples=[10, 60],\n    )\n    usage_quota_name: str = Field(\n        description=\"Unique identifier for tracking usage quotas (minutely, hourly, daily limits). Used internally to manage rate limiting across multiple upload operations. Each unique quota name maintains separate counters, allowing different upload strategies or data collection workflows to have independent rate limits.\",\n        examples=[\"quota-for-data-sampling-1\"],\n        json_schema_extra={\"hidden\": True},\n    )\n    max_image_size: Tuple[int, int] = Field(\n        default=(512, 512),\n        description=\"Maximum dimensions (width, height) for uploaded images. Images exceeding these dimensions are automatically resized while preserving aspect ratio before uploading. Smaller sizes reduce storage and bandwidth but may lose image quality. Use larger sizes (e.g., (1920, 1080)) for high-resolution data collection, or smaller sizes (e.g., (512, 512)) for efficient storage and faster uploads.\",\n        examples=[(512, 512), (1920, 1080)],\n    )\n    compression_level: int = Field(\n        default=75,\n        gt=0,\n        le=100,\n        description=\"JPEG compression quality level for uploaded images, ranging from 1 (highest compression, smallest file size, lower quality) to 100 (no compression, largest file size, highest quality). Higher values preserve more image quality but increase storage and bandwidth usage. Typical values range from 70-90 for balanced quality and size. Default of 75 provides good quality with reasonable file sizes.\",\n        examples=[75],\n    )\n    registration_tags: Union[\n        List[Union[Selector(kind=[STRING_KIND]), str]],\n        Selector(kind=[LIST_OF_VALUES_KIND]),\n    ] = Field(\n        default_factory=list,\n        description=\"List of tags to attach to uploaded images for organization and filtering in Roboflow. Tags can be static strings (e.g., 'location-florida', 'camera-1') or dynamic values from workflow inputs. Tags help organize collected data, filter images in Roboflow, and add metadata for dataset management. Can be an empty list if no tags are needed.\",\n        examples=[\n            [\"location-florida\", \"factory-name\", \"$inputs.dynamic_tag\"],\n            \"$inputs.tags\",\n        ],\n    )\n    persist_predictions: bool = Field(\n        default=True,\n        description=\"If True, model predictions are saved as annotations (pre-labels) in the Roboflow dataset alongside images. This enables predictions to serve as starting points for annotation, allowing reviewers to correct or approve labels rather than creating them from scratch. If False, only images are uploaded without annotations. Enabling this accelerates annotation workflows by providing initial labels.\",\n        examples=[True, False],\n    )\n    disable_sink: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=False,\n        description=\"If True, the block execution is disabled and no uploads occur. This allows temporarily disabling data collection without removing the block from workflows, useful for testing, debugging, or conditional data collection. When disabled, returns a message indicating the sink was disabled. Default is False (uploads enabled).\",\n        examples=[True, \"$inputs.disable_active_learning\"],\n    )\n    fire_and_forget: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=True,\n        description=\"If True, uploads execute asynchronously (fire-and-forget mode), allowing the workflow to continue immediately without waiting for upload completion. This improves workflow performance but prevents error handling. If False, uploads execute synchronously, blocking workflow execution until completion and allowing proper error handling and status reporting. Use async mode (True) for production workflows where speed is prioritized, and sync mode (False) for debugging or when error handling is critical.\",\n        examples=[True],\n    )\n    labeling_batch_prefix: Union[str, Selector(kind=[STRING_KIND])] = Field(\n        default=\"workflows_data_collector\",\n        description=\"Prefix used to generate labeling batch names for organizing uploaded images in Roboflow. Combined with the batch recreation frequency and timestamps to create batch names like 'workflows_data_collector_2024_01_15'. Batches help organize collected data for labeling, making it easier to manage and review uploaded images in groups. Can be customized to match your organization scheme.\",\n        examples=[\"my_labeling_batch_name\"],\n    )\n    labeling_batches_recreation_frequency: BatchCreationFrequency = Field(\n        default=\"never\",\n        description=\"Frequency at which new labeling batches are automatically created for uploaded images. Options: 'never' (all images go to the same batch), 'daily' (new batch each day), 'weekly' (new batch each week), 'monthly' (new batch each month). Batch timestamps are appended to the labeling_batch_prefix to create unique batch names. Automatically organizing uploads into time-based batches simplifies dataset management and makes it easier to track and review collected data over time.\",\n        examples=[\"never\", \"daily\"],\n    )\n    image_name: Optional[Union[str, Selector(kind=[STRING_KIND])]] = Field(\n        default=None,\n        description=\"Optional custom name for the uploaded image. If provided, this name will be used instead of an auto-generated UUID. This is useful when you want to preserve the original filename or use a meaningful identifier (e.g., serial number, timestamp) for the image in the Roboflow dataset. The name should not include file extension. If not provided, a UUID will be generated automatically.\",\n        examples=[\"serial_12345\", \"camera1_frame_001\", \"$inputs.filename\"],\n    )\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return [\"images\", \"predictions\", \"image_name\"]\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=\"error_status\", kind=[BOOLEAN_KIND]),\n            OutputDefinition(name=\"message\", kind=[STRING_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass RoboflowDatasetUploadBlockV1(WorkflowBlock):\n\n    def __init__(\n        self,\n        cache: BaseCache,\n        api_key: Optional[str],\n        background_tasks: Optional[BackgroundTasks],\n        thread_pool_executor: Optional[ThreadPoolExecutor],\n    ):\n        self._cache = cache\n        self._api_key = api_key\n        self._background_tasks = background_tasks\n        self._thread_pool_executor = thread_pool_executor\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"cache\", \"api_key\", \"background_tasks\", \"thread_pool_executor\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        predictions: Optional[Batch[Union[sv.Detections, dict]]],\n        target_project: str,\n        usage_quota_name: str,\n        minutely_usage_limit: int,\n        persist_predictions: bool,\n        hourly_usage_limit: int,\n        daily_usage_limit: int,\n        max_image_size: Tuple[int, int],\n        compression_level: int,\n        registration_tags: List[str],\n        disable_sink: bool,\n        fire_and_forget: bool,\n        labeling_batch_prefix: str,\n        labeling_batches_recreation_frequency: BatchCreationFrequency,\n        image_name: Optional[Batch[Optional[str]]] = None,\n    ) -> BlockResult:\n        if self._api_key is None:\n            raise ValueError(\n                \"RoboflowDataCollector block cannot run without Roboflow API key. \"\n                \"If you do not know how to get API key - visit \"\n                \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to \"\n                \"retrieve one.\"\n            )\n        if disable_sink:\n            return [\n                {\n                    \"error_status\": False,\n                    \"message\": \"Sink was disabled by parameter `disable_sink`\",\n                }\n                for _ in range(len(images))\n            ]\n        result = []\n        predictions = [None] * len(images) if predictions is None else predictions\n        image_names = [None] * len(images) if image_name is None else image_name\n        for image, prediction, img_name in zip(images, predictions, image_names):\n            error_status, message = register_datapoint_at_roboflow(\n                image=image,\n                prediction=prediction,\n                target_project=target_project,\n                usage_quota_name=usage_quota_name,\n                persist_predictions=persist_predictions,\n                minutely_usage_limit=minutely_usage_limit,\n                hourly_usage_limit=hourly_usage_limit,\n                daily_usage_limit=daily_usage_limit,\n                max_image_size=max_image_size,\n                compression_level=compression_level,\n                registration_tags=registration_tags,\n                fire_and_forget=fire_and_forget,\n                labeling_batch_prefix=labeling_batch_prefix,\n                new_labeling_batch_frequency=labeling_batches_recreation_frequency,\n                cache=self._cache,\n                background_tasks=self._background_tasks,\n                thread_pool_executor=self._thread_pool_executor,\n                api_key=self._api_key,\n                image_name=img_name,\n            )\n            result.append({\"error_status\": error_status, \"message\": message})\n        return result\n\n\ndef register_datapoint_at_roboflow(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    usage_quota_name: str,\n    persist_predictions: bool,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    fire_and_forget: bool,\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    background_tasks: Optional[BackgroundTasks],\n    thread_pool_executor: Optional[ThreadPoolExecutor],\n    api_key: str,\n    image_name: Optional[str] = None,\n) -> Tuple[bool, str]:\n    registration_task = partial(\n        execute_registration,\n        image=image,\n        prediction=prediction,\n        target_project=target_project,\n        usage_quota_name=usage_quota_name,\n        persist_predictions=persist_predictions,\n        minutely_usage_limit=minutely_usage_limit,\n        hourly_usage_limit=hourly_usage_limit,\n        daily_usage_limit=daily_usage_limit,\n        max_image_size=max_image_size,\n        compression_level=compression_level,\n        registration_tags=registration_tags,\n        labeling_batch_prefix=labeling_batch_prefix,\n        new_labeling_batch_frequency=new_labeling_batch_frequency,\n        cache=cache,\n        api_key=api_key,\n        image_name=image_name,\n    )\n    if fire_and_forget and background_tasks:\n        background_tasks.add_task(registration_task)\n        return False, \"Element registration happens in the background task\"\n    if fire_and_forget and thread_pool_executor:\n        thread_pool_executor.submit(registration_task)\n        return False, \"Element registration happens in the background task\"\n    return registration_task()\n\n\ndef execute_registration(\n    image: WorkflowImageData,\n    prediction: Optional[Union[sv.Detections, dict]],\n    target_project: str,\n    persist_predictions: bool,\n    usage_quota_name: str,\n    minutely_usage_limit: int,\n    hourly_usage_limit: int,\n    daily_usage_limit: int,\n    max_image_size: Tuple[int, int],\n    compression_level: int,\n    registration_tags: List[str],\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n    cache: BaseCache,\n    api_key: str,\n    image_name: Optional[str] = None,\n) -> Tuple[bool, str]:\n    matching_strategies_limits = OrderedDict(\n        {\n            usage_quota_name: [\n                StrategyLimit(\n                    limit_type=StrategyLimitType.MINUTELY, value=minutely_usage_limit\n                ),\n                StrategyLimit(\n                    limit_type=StrategyLimitType.HOURLY, value=hourly_usage_limit\n                ),\n                StrategyLimit(\n                    limit_type=StrategyLimitType.DAILY, value=daily_usage_limit\n                ),\n            ]\n        }\n    )\n    workspace_name = get_workspace_name(api_key=api_key, cache=cache)\n    strategy_with_spare_credit = use_credit_of_matching_strategy(\n        cache=cache,\n        workspace=workspace_name,\n        project=target_project,\n        matching_strategies_limits=matching_strategies_limits,\n    )\n    if strategy_with_spare_credit is None:\n        return False, \"Registration skipped due to usage quota exceeded\"\n    credit_to_be_returned = False\n    try:\n        local_image_id = image_name if image_name else str(uuid4())\n        encoded_image, scaling_factor = prepare_image_to_registration(\n            image=image.numpy_image,\n            desired_size=ImageDimensions(\n                width=max_image_size[0], height=max_image_size[1]\n            ),\n            jpeg_compression_level=compression_level,\n        )\n        batch_name = generate_batch_name(\n            labeling_batch_prefix=labeling_batch_prefix,\n            new_labeling_batch_frequency=new_labeling_batch_frequency,\n        )\n        if isinstance(prediction, sv.Detections):\n            prediction = scale_sv_detections(\n                detections=prediction, scale=scaling_factor\n            )\n        status = register_datapoint(\n            target_project=target_project,\n            encoded_image=encoded_image,\n            local_image_id=local_image_id,\n            prediction=prediction if persist_predictions else None,\n            api_key=api_key,\n            batch_name=batch_name,\n            tags=registration_tags,\n        )\n        if status == DUPLICATED_STATUS:\n            credit_to_be_returned = True\n        return False, status\n    except Exception as error:\n        credit_to_be_returned = True\n        logging.exception(\"Failed to register datapoint on the Roboflow platform\")\n        return (\n            True,\n            f\"Error while registration. Error type: {type(error)}. Details: {error}\",\n        )\n    finally:\n        if credit_to_be_returned:\n            return_strategy_credit(\n                cache=cache,\n                workspace=workspace_name,\n                project=target_project,\n                strategy_name=strategy_with_spare_credit,\n            )\n\n\ndef get_workspace_name(\n    api_key: str,\n    cache: BaseCache,\n) -> str:\n    api_key_hash = hashlib.md5(api_key.encode(\"utf-8\")).hexdigest()\n    cache_key = f\"workflows:api_key_to_workspace:{api_key_hash}\"\n    cached_workspace_name = cache.get(cache_key)\n    if cached_workspace_name:\n        return cached_workspace_name\n    workspace_name_from_api = get_roboflow_workspace(api_key=api_key)\n    cache.set(\n        key=cache_key, value=workspace_name_from_api, expire=WORKSPACE_NAME_CACHE_EXPIRE\n    )\n    return workspace_name_from_api\n\n\ndef generate_batch_name(\n    labeling_batch_prefix: str,\n    new_labeling_batch_frequency: BatchCreationFrequency,\n) -> str:\n    if new_labeling_batch_frequency == \"never\":\n        return labeling_batch_prefix\n    timestamp_generator = RECREATION_INTERVAL2TIMESTAMP_GENERATOR[\n        new_labeling_batch_frequency\n    ]\n    timestamp = timestamp_generator()\n    return f\"{labeling_batch_prefix}_{timestamp}\"\n\n\ndef generate_today_timestamp() -> str:\n    return datetime.today().strftime(TIMESTAMP_FORMAT)\n\n\ndef generate_start_timestamp_for_this_week() -> str:\n    today = datetime.today()\n    return (today - timedelta(days=today.weekday())).strftime(TIMESTAMP_FORMAT)\n\n\ndef generate_start_timestamp_for_this_month() -> str:\n    return datetime.today().replace(day=1).strftime(TIMESTAMP_FORMAT)\n\n\nRECREATION_INTERVAL2TIMESTAMP_GENERATOR = {\n    \"daily\": generate_today_timestamp,\n    \"weekly\": generate_start_timestamp_for_this_week,\n    \"monthly\": generate_start_timestamp_for_this_month,\n}\n\n\ndef register_datapoint(\n    target_project: str,\n    encoded_image: bytes,\n    local_image_id: str,\n    prediction: Optional[Union[sv.Detections, dict]],\n    api_key: str,\n    batch_name: str,\n    tags: List[str],\n) -> str:\n    inference_id = None\n    if isinstance(prediction, dict):\n        inference_id = prediction.get(INFERENCE_ID_KEY)\n    if isinstance(prediction, sv.Detections) and len(prediction) > 0:\n        # TODO: Lack of inference ID for empty prediction -\n        #  dependent on https://github.com/roboflow/inference/issues/567\n        inference_id_array = prediction.data.get(INFERENCE_ID_KEY)\n        if inference_id_array is not None:\n            inference_id_list = inference_id_array.tolist()\n            inference_id = inference_id_list[0]\n    roboflow_image_id = safe_register_image_at_roboflow(\n        target_project=target_project,\n        encoded_image=encoded_image,\n        local_image_id=local_image_id,\n        api_key=api_key,\n        batch_name=batch_name,\n        tags=tags,\n        inference_id=inference_id,\n    )\n    if roboflow_image_id is None:\n        return DUPLICATED_STATUS\n    if is_prediction_registration_forbidden(prediction=prediction):\n        return \"Successfully registered image\"\n    encoded_prediction, prediction_format = encode_prediction(prediction=prediction)\n    _ = annotate_image_at_roboflow(\n        api_key=api_key,\n        dataset_id=target_project,\n        local_image_id=local_image_id,\n        roboflow_image_id=roboflow_image_id,\n        annotation_content=encoded_prediction,\n        annotation_file_type=prediction_format,\n        is_prediction=True,\n    )\n    return \"Successfully registered image and annotation\"\n\n\ndef safe_register_image_at_roboflow(\n    target_project: str,\n    encoded_image: bytes,\n    local_image_id: str,\n    api_key: str,\n    batch_name: str,\n    tags: List[str],\n    inference_id: Optional[str],\n) -> Optional[str]:\n    registration_response = register_image_at_roboflow(\n        api_key=api_key,\n        dataset_id=target_project,\n        local_image_id=local_image_id,\n        image_bytes=encoded_image,\n        batch_name=batch_name,\n        tags=tags,\n        inference_id=inference_id,\n    )\n    image_duplicated = registration_response.get(\"duplicate\", False)\n    if image_duplicated:\n        logging.warning(f\"Image duplication detected: {registration_response}.\")\n        return None\n    return registration_response[\"id\"]\n\n\ndef is_prediction_registration_forbidden(\n    prediction: Optional[Union[sv.Detections, dict]],\n) -> bool:\n    if prediction is None:\n        return True\n    if isinstance(prediction, sv.Detections) and len(prediction) == 0:\n        return True\n    if isinstance(prediction, dict) and all(\n        k not in prediction for k in [\"top\", \"predicted_classes\"]\n    ):\n        return True\n    return False\n\n\ndef encode_prediction(\n    prediction: Union[sv.Detections, dict],\n) -> Tuple[str, str]:\n    if isinstance(prediction, dict):\n        if \"predicted_classes\" in prediction:\n            return \",\".join(prediction[\"predicted_classes\"]), \"txt\"\n        return prediction[\"top\"], \"txt\"\n    detections_in_inference_format = serialise_sv_detections(detections=prediction)\n    return json.dumps(detections_in_inference_format), \"json\"\n",
    "patch": null
  },
  {
    "trace_id": "61f42297-886b-43b0-9870-ce3df0448f2e",
    "function_name": "WorkflowImageData.copy_and_replace",
    "file_path": "inference/core/workflows/execution_engine/entities/base.py",
    "speedup_x": 1.0414808656494587,
    "review_quality": "high",
    "pre_optimization_commit": "a60c2b61fd767f1ffe2bb7f27e5aaa900785d661",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def copy_and_replace(\n        cls, origin_image_data: \"WorkflowImageData\", **kwargs\n    ) -> \"WorkflowImageData\":\n        \"\"\"\n        Creates new instance of `WorkflowImageData` with updated property.\n\n        Properties are passed by kwargs, supported properties are:\n        * parent_metadata\n        * workflow_root_ancestor_metadata\n        * image_reference\n        * base64_image\n        * numpy_image\n        * video_metadata\n        * image_name\n\n        When more than one from [\"numpy_image\", \"base64_image\", \"image_reference\"] args are\n        given, they MUST be compliant.\n        \"\"\"\n        parent_metadata = origin_image_data._parent_metadata\n        workflow_root_ancestor_metadata = (\n            origin_image_data._workflow_root_ancestor_metadata\n        )\n        image_reference = origin_image_data._image_reference\n        base64_image = origin_image_data._base64_image\n        numpy_image = origin_image_data._numpy_image\n        video_metadata = origin_image_data._video_metadata\n        image_name = origin_image_data._image_name\n        if any(k in kwargs for k in [\"numpy_image\", \"base64_image\", \"image_reference\"]):\n            numpy_image = kwargs.get(\"numpy_image\")\n            base64_image = kwargs.get(\"base64_image\")\n            image_reference = kwargs.get(\"image_reference\")\n        if \"parent_metadata\" in kwargs:\n            if workflow_root_ancestor_metadata is parent_metadata:\n                workflow_root_ancestor_metadata = kwargs[\"parent_metadata\"]\n            parent_metadata = kwargs[\"parent_metadata\"]\n        if \"workflow_root_ancestor_metadata\" in kwargs:\n            if parent_metadata is workflow_root_ancestor_metadata:\n                parent_metadata = kwargs[\"workflow_root_ancestor_metadata\"]\n            workflow_root_ancestor_metadata = kwargs[\"workflow_root_ancestor_metadata\"]\n        if \"video_metadata\" in kwargs:\n            video_metadata = kwargs[\"video_metadata\"]\n        if \"image_name\" in kwargs:\n            image_name = kwargs[\"image_name\"]\n        return cls(\n            parent_metadata=parent_metadata,\n            workflow_root_ancestor_metadata=workflow_root_ancestor_metadata,\n            image_reference=image_reference,\n            base64_image=base64_image,\n            numpy_image=numpy_image,\n            video_metadata=video_metadata,\n            image_name=image_name,\n        )\n",
    "optimized_function_code": "import numpy as np\nfrom dataclasses import dataclass\nfrom datetime import datetime\nfrom pydantic import BaseModel, Field\nfrom typing import Optional\n\n\nclass VideoMetadata(BaseModel):\n    video_identifier: str = Field(\n        description=\"Identifier string for video. To be treated as opaque.\"\n    )\n    frame_number: int\n    frame_timestamp: datetime = Field(\n        description=\"The timestamp of video frame. When processing video it is suggested that \"\n        \"blocks rely on `fps` and `frame_number`, as real-world time-elapse will not \"\n        \"match time-elapse in video file\",\n    )\n    fps: Optional[float] = Field(\n        description=\"Field represents FPS value (if possible to be retrieved)\",\n        default=None,\n    )\n    measured_fps: Optional[float] = Field(\n        description=\"Field represents measured FPS of live stream\",\n        default=None,\n    )\n    comes_from_video_file: Optional[bool] = Field(\n        description=\"Field is a flag telling if frame comes from video file or stream - \"\n        \"if not possible to be determined - pass None\",\n        default=None,\n    )\n\n\n@dataclass(frozen=True)\nclass OriginCoordinatesSystem:\n    left_top_x: int\n    left_top_y: int\n    origin_width: int\n    origin_height: int\n\n\n@dataclass(frozen=True)\nclass ImageParentMetadata:\n    parent_id: str\n    origin_coordinates: Optional[OriginCoordinatesSystem] = None\n\n\nclass WorkflowImageData:\n\n    def __init__(\n        self,\n        parent_metadata: ImageParentMetadata,\n        workflow_root_ancestor_metadata: Optional[ImageParentMetadata] = None,\n        image_reference: Optional[str] = None,\n        base64_image: Optional[str] = None,\n        numpy_image: Optional[np.ndarray] = None,\n        video_metadata: Optional[VideoMetadata] = None,\n        image_name: Optional[str] = None,\n    ):\n        if not base64_image and numpy_image is None and not image_reference:\n            raise ValueError(\"Could not initialise empty `WorkflowImageData`.\")\n        self._parent_metadata = parent_metadata\n        self._workflow_root_ancestor_metadata = (\n            workflow_root_ancestor_metadata\n            if workflow_root_ancestor_metadata\n            else self._parent_metadata\n        )\n        self._image_reference = image_reference\n        self._base64_image = base64_image\n        self._numpy_image = numpy_image\n        self._video_metadata = video_metadata\n        self._image_name = image_name\n\n    @classmethod\n    def copy_and_replace(\n        cls, origin_image_data: \"WorkflowImageData\", **kwargs\n    ) -> \"WorkflowImageData\":\n        \"\"\"\n        Creates new instance of `WorkflowImageData` with updated property.\n\n        Properties are passed by kwargs, supported properties are:\n        * parent_metadata\n        * workflow_root_ancestor_metadata\n        * image_reference\n        * base64_image\n        * numpy_image\n        * video_metadata\n        * image_name\n\n        When more than one from [\"numpy_image\", \"base64_image\", \"image_reference\"] args are\n        given, they MUST be compliant.\n        \"\"\"\n        parent_metadata = origin_image_data._parent_metadata\n        workflow_root_ancestor_metadata = (\n            origin_image_data._workflow_root_ancestor_metadata\n        )\n        image_reference = origin_image_data._image_reference\n        base64_image = origin_image_data._base64_image\n        numpy_image = origin_image_data._numpy_image\n        video_metadata = origin_image_data._video_metadata\n        image_name = origin_image_data._image_name\n\n        if (\"numpy_image\" in kwargs) or (\"base64_image\" in kwargs) or (\"image_reference\" in kwargs):\n            numpy_image = kwargs.get(\"numpy_image\")\n            base64_image = kwargs.get(\"base64_image\")\n            image_reference = kwargs.get(\"image_reference\")\n        if \"parent_metadata\" in kwargs:\n            if workflow_root_ancestor_metadata is parent_metadata:\n                workflow_root_ancestor_metadata = kwargs[\"parent_metadata\"]\n            parent_metadata = kwargs[\"parent_metadata\"]\n        if \"workflow_root_ancestor_metadata\" in kwargs:\n            if parent_metadata is workflow_root_ancestor_metadata:\n                parent_metadata = kwargs[\"workflow_root_ancestor_metadata\"]\n            workflow_root_ancestor_metadata = kwargs[\"workflow_root_ancestor_metadata\"]\n        if \"video_metadata\" in kwargs:\n            video_metadata = kwargs[\"video_metadata\"]\n        if \"image_name\" in kwargs:\n            image_name = kwargs[\"image_name\"]\n        return cls(\n            parent_metadata,\n            workflow_root_ancestor_metadata,\n            image_reference,\n            base64_image,\n            numpy_image,\n            video_metadata,\n            image_name,\n        )",
    "optimized_raw_markdown": "```python:inference/core/workflows/execution_engine/entities/base.py\nimport numpy as np\nfrom dataclasses import dataclass\nfrom datetime import datetime\nfrom pydantic import BaseModel, Field\nfrom typing import Optional\n\n\nclass VideoMetadata(BaseModel):\n    video_identifier: str = Field(\n        description=\"Identifier string for video. To be treated as opaque.\"\n    )\n    frame_number: int\n    frame_timestamp: datetime = Field(\n        description=\"The timestamp of video frame. When processing video it is suggested that \"\n        \"blocks rely on `fps` and `frame_number`, as real-world time-elapse will not \"\n        \"match time-elapse in video file\",\n    )\n    fps: Optional[float] = Field(\n        description=\"Field represents FPS value (if possible to be retrieved)\",\n        default=None,\n    )\n    measured_fps: Optional[float] = Field(\n        description=\"Field represents measured FPS of live stream\",\n        default=None,\n    )\n    comes_from_video_file: Optional[bool] = Field(\n        description=\"Field is a flag telling if frame comes from video file or stream - \"\n        \"if not possible to be determined - pass None\",\n        default=None,\n    )\n\n\n@dataclass(frozen=True)\nclass OriginCoordinatesSystem:\n    left_top_x: int\n    left_top_y: int\n    origin_width: int\n    origin_height: int\n\n\n@dataclass(frozen=True)\nclass ImageParentMetadata:\n    parent_id: str\n    origin_coordinates: Optional[OriginCoordinatesSystem] = None\n\n\nclass WorkflowImageData:\n\n    def __init__(\n        self,\n        parent_metadata: ImageParentMetadata,\n        workflow_root_ancestor_metadata: Optional[ImageParentMetadata] = None,\n        image_reference: Optional[str] = None,\n        base64_image: Optional[str] = None,\n        numpy_image: Optional[np.ndarray] = None,\n        video_metadata: Optional[VideoMetadata] = None,\n        image_name: Optional[str] = None,\n    ):\n        if not base64_image and numpy_image is None and not image_reference:\n            raise ValueError(\"Could not initialise empty `WorkflowImageData`.\")\n        self._parent_metadata = parent_metadata\n        self._workflow_root_ancestor_metadata = (\n            workflow_root_ancestor_metadata\n            if workflow_root_ancestor_metadata\n            else self._parent_metadata\n        )\n        self._image_reference = image_reference\n        self._base64_image = base64_image\n        self._numpy_image = numpy_image\n        self._video_metadata = video_metadata\n        self._image_name = image_name\n\n    @classmethod\n    def copy_and_replace(\n        cls, origin_image_data: \"WorkflowImageData\", **kwargs\n    ) -> \"WorkflowImageData\":\n        \"\"\"\n        Creates new instance of `WorkflowImageData` with updated property.\n\n        Properties are passed by kwargs, supported properties are:\n        * parent_metadata\n        * workflow_root_ancestor_metadata\n        * image_reference\n        * base64_image\n        * numpy_image\n        * video_metadata\n        * image_name\n\n        When more than one from [\"numpy_image\", \"base64_image\", \"image_reference\"] args are\n        given, they MUST be compliant.\n        \"\"\"\n        parent_metadata = origin_image_data._parent_metadata\n        workflow_root_ancestor_metadata = (\n            origin_image_data._workflow_root_ancestor_metadata\n        )\n        image_reference = origin_image_data._image_reference\n        base64_image = origin_image_data._base64_image\n        numpy_image = origin_image_data._numpy_image\n        video_metadata = origin_image_data._video_metadata\n        image_name = origin_image_data._image_name\n\n        if (\"numpy_image\" in kwargs) or (\"base64_image\" in kwargs) or (\"image_reference\" in kwargs):\n            numpy_image = kwargs.get(\"numpy_image\")\n            base64_image = kwargs.get(\"base64_image\")\n            image_reference = kwargs.get(\"image_reference\")\n        if \"parent_metadata\" in kwargs:\n            if workflow_root_ancestor_metadata is parent_metadata:\n                workflow_root_ancestor_metadata = kwargs[\"parent_metadata\"]\n            parent_metadata = kwargs[\"parent_metadata\"]\n        if \"workflow_root_ancestor_metadata\" in kwargs:\n            if parent_metadata is workflow_root_ancestor_metadata:\n                parent_metadata = kwargs[\"workflow_root_ancestor_metadata\"]\n            workflow_root_ancestor_metadata = kwargs[\"workflow_root_ancestor_metadata\"]\n        if \"video_metadata\" in kwargs:\n            video_metadata = kwargs[\"video_metadata\"]\n        if \"image_name\" in kwargs:\n            image_name = kwargs[\"image_name\"]\n        return cls(\n            parent_metadata,\n            workflow_root_ancestor_metadata,\n            image_reference,\n            base64_image,\n            numpy_image,\n            video_metadata,\n            image_name,\n        )\n```",
    "optimized_function_only": "    def copy_and_replace(\n        cls, origin_image_data: \"WorkflowImageData\", **kwargs\n    ) -> \"WorkflowImageData\":\n        \"\"\"\n        Creates new instance of `WorkflowImageData` with updated property.\n\n        Properties are passed by kwargs, supported properties are:\n        * parent_metadata\n        * workflow_root_ancestor_metadata\n        * image_reference\n        * base64_image\n        * numpy_image\n        * video_metadata\n        * image_name\n\n        When more than one from [\"numpy_image\", \"base64_image\", \"image_reference\"] args are\n        given, they MUST be compliant.\n        \"\"\"\n        parent_metadata = origin_image_data._parent_metadata\n        workflow_root_ancestor_metadata = (\n            origin_image_data._workflow_root_ancestor_metadata\n        )\n        image_reference = origin_image_data._image_reference\n        base64_image = origin_image_data._base64_image\n        numpy_image = origin_image_data._numpy_image\n        video_metadata = origin_image_data._video_metadata\n        image_name = origin_image_data._image_name\n\n        if (\"numpy_image\" in kwargs) or (\"base64_image\" in kwargs) or (\"image_reference\" in kwargs):\n            numpy_image = kwargs.get(\"numpy_image\")\n            base64_image = kwargs.get(\"base64_image\")\n            image_reference = kwargs.get(\"image_reference\")\n        if \"parent_metadata\" in kwargs:\n            if workflow_root_ancestor_metadata is parent_metadata:\n                workflow_root_ancestor_metadata = kwargs[\"parent_metadata\"]\n            parent_metadata = kwargs[\"parent_metadata\"]\n        if \"workflow_root_ancestor_metadata\" in kwargs:\n            if parent_metadata is workflow_root_ancestor_metadata:\n                parent_metadata = kwargs[\"workflow_root_ancestor_metadata\"]\n            workflow_root_ancestor_metadata = kwargs[\"workflow_root_ancestor_metadata\"]\n        if \"video_metadata\" in kwargs:\n            video_metadata = kwargs[\"video_metadata\"]\n        if \"image_name\" in kwargs:\n            image_name = kwargs[\"image_name\"]\n        return cls(\n            parent_metadata,\n            workflow_root_ancestor_metadata,\n            image_reference,\n            base64_image,\n            numpy_image,\n            video_metadata,\n            image_name,\n        )",
    "original_file_content": "import base64\nfrom copy import copy\nfrom dataclasses import dataclass, replace\nfrom datetime import datetime\nfrom enum import Enum\nfrom typing import (\n    Any,\n    Dict,\n    Generic,\n    Iterator,\n    List,\n    Optional,\n    Set,\n    Tuple,\n    TypeVar,\n    Union,\n)\n\nimport cv2\nimport numpy as np\nfrom pydantic import BaseModel, Field\nfrom typing_extensions import Annotated, Literal\n\nfrom inference.core.utils.image_utils import (\n    attempt_loading_image_from_string,\n    encode_image_to_jpeg_bytes,\n    load_image_from_url,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    IMAGE_KIND,\n    VIDEO_METADATA_KIND,\n    WILDCARD_KIND,\n    Kind,\n)\n\n\nclass OutputDefinition(BaseModel):\n    name: str\n    kind: List[Kind] = Field(default_factory=lambda: [WILDCARD_KIND])\n\n\nclass CoordinatesSystem(Enum):\n    OWN = \"own\"\n    PARENT = \"parent\"\n\n\nclass JsonField(BaseModel):\n    type: Literal[\"JsonField\"]\n    name: str\n    selector: str\n    coordinates_system: CoordinatesSystem = Field(default=CoordinatesSystem.PARENT)\n\n    def get_type(self) -> str:\n        return self.type\n\n\nclass WorkflowInput(BaseModel):\n    type: str\n    name: str\n    kind: List[Union[str, Kind]]\n    dimensionality: int\n\n    @classmethod\n    def is_batch_oriented(cls) -> bool:\n        return False\n\n\nclass WorkflowImage(WorkflowInput):\n    type: Literal[\"WorkflowImage\", \"InferenceImage\"]\n    name: str\n    kind: List[Union[str, Kind]] = Field(default=[IMAGE_KIND])\n    dimensionality: int = Field(default=1, ge=1, le=1)\n\n    @classmethod\n    def is_batch_oriented(cls) -> bool:\n        return True\n\n\nclass WorkflowVideoMetadata(WorkflowInput):\n    type: Literal[\"WorkflowVideoMetadata\"]\n    name: str\n    kind: List[Union[str, Kind]] = Field(default=[VIDEO_METADATA_KIND])\n    dimensionality: int = Field(default=1, ge=1, le=1)\n\n    @classmethod\n    def is_batch_oriented(cls) -> bool:\n        return True\n\n\nclass WorkflowBatchInput(WorkflowInput):\n    type: Literal[\"WorkflowBatchInput\"]\n    name: str\n    kind: List[Union[str, Kind]] = Field(default_factory=lambda: [WILDCARD_KIND])\n    dimensionality: int = Field(default=1)\n\n    @classmethod\n    def is_batch_oriented(cls) -> bool:\n        return True\n\n\nclass WorkflowParameter(WorkflowInput):\n    type: Literal[\"WorkflowParameter\", \"InferenceParameter\"]\n    name: str\n    kind: List[Union[str, Kind]] = Field(default_factory=lambda: [WILDCARD_KIND])\n    default_value: Optional[Union[float, int, str, bool, list, set, dict]] = Field(\n        default=None\n    )\n    dimensionality: int = Field(default=0, ge=0, le=0)\n\n\nInputType = Annotated[\n    Union[WorkflowImage, WorkflowVideoMetadata, WorkflowParameter, WorkflowBatchInput],\n    Field(discriminator=\"type\"),\n]\n\nB = TypeVar(\"B\")\n\n\nclass Batch(Generic[B]):\n\n    @classmethod\n    def init(\n        cls,\n        content: List[B],\n        indices: List[Tuple[int, ...]],\n    ) -> \"Batch\":\n        if len(content) != len(indices):\n            raise ValueError(\n                \"Attempted to initialise Batch object providing batch indices of size differing \"\n                \"from size of the data.\"\n            )\n\n        return cls(content=content, indices=indices)\n\n    def __init__(self, content: List[B], indices: Optional[List[Tuple[int, ...]]]):\n        self._content = content\n        self._indices = indices\n\n    @property\n    def indices(self) -> List[Tuple[int, ...]]:\n        return copy(self._indices)\n\n    def __getitem__(\n        self,\n        index: int,\n    ) -> B:\n        return self._content[index]\n\n    def __len__(self):\n        return len(self._content)\n\n    def __iter__(self) -> Iterator[B]:\n        yield from self._content\n\n    def remove_by_indices(self, indices_to_remove: Set[tuple]) -> \"Batch\":\n        filtered_content = [\n            element\n            for index, element in zip(self._indices, self._content)\n            if index not in indices_to_remove\n        ]\n        filtered_indices = [\n            index for index in self._indices if index not in indices_to_remove\n        ]\n\n        return Batch(content=filtered_content, indices=filtered_indices)\n\n    def iter_with_indices(self) -> Iterator[Tuple[Tuple[int, ...], B]]:\n        return zip(self._indices, self._content)\n\n    def broadcast(self, n: int) -> \"Batch\":\n        if n <= 0:\n            raise ValueError(\n                f\"Broadcast to size {n} requested which is an invalid operation.\"\n            )\n\n        num_content = len(self._content)\n\n        if num_content == n:\n            return self\n\n        if num_content == 1:\n            return Batch(content=self._content * n, indices=self._indices * n)\n\n        raise ValueError(f\"Could not broadcast batch of size {num_content} to size {n}\")\n\n\nclass VideoMetadata(BaseModel):\n    video_identifier: str = Field(\n        description=\"Identifier string for video. To be treated as opaque.\"\n    )\n    frame_number: int\n    frame_timestamp: datetime = Field(\n        description=\"The timestamp of video frame. When processing video it is suggested that \"\n        \"blocks rely on `fps` and `frame_number`, as real-world time-elapse will not \"\n        \"match time-elapse in video file\",\n    )\n    fps: Optional[float] = Field(\n        description=\"Field represents FPS value (if possible to be retrieved)\",\n        default=None,\n    )\n    measured_fps: Optional[float] = Field(\n        description=\"Field represents measured FPS of live stream\",\n        default=None,\n    )\n    comes_from_video_file: Optional[bool] = Field(\n        description=\"Field is a flag telling if frame comes from video file or stream - \"\n        \"if not possible to be determined - pass None\",\n        default=None,\n    )\n\n\nclass ParentOrigin(BaseModel):\n    offset_x: int = Field(\n        description=\"Offset from the left of the parent image in pixels\"\n    )\n    offset_y: int = Field(\n        description=\"Offset from the top of the parent image in pixels\"\n    )\n    width: int = Field(\n        description=\"Width of the parent image in pixels\",\n        gt=0,\n    )\n    height: int = Field(\n        description=\"Height of the parent image in pixels\",\n        gt=0,\n    )\n\n    @classmethod\n    def from_origin_coordinates_system(\n        cls, origin_coordinates_system: \"OriginCoordinatesSystem\"\n    ) -> \"ParentOrigin\":\n        return cls(\n            offset_x=origin_coordinates_system.left_top_x,\n            offset_y=origin_coordinates_system.left_top_y,\n            width=origin_coordinates_system.origin_width,\n            height=origin_coordinates_system.origin_height,\n        )\n\n    def to_origin_coordinates_system(self) -> \"OriginCoordinatesSystem\":\n        return OriginCoordinatesSystem(\n            left_top_x=self.offset_x,\n            left_top_y=self.offset_y,\n            origin_width=self.width,\n            origin_height=self.height,\n        )\n\n\n@dataclass(frozen=True)\nclass OriginCoordinatesSystem:\n    left_top_x: int\n    left_top_y: int\n    origin_width: int\n    origin_height: int\n\n\n@dataclass(frozen=True)\nclass ImageParentMetadata:\n    parent_id: str\n    origin_coordinates: Optional[OriginCoordinatesSystem] = None\n\n\nclass WorkflowImageData:\n\n    def __init__(\n        self,\n        parent_metadata: ImageParentMetadata,\n        workflow_root_ancestor_metadata: Optional[ImageParentMetadata] = None,\n        image_reference: Optional[str] = None,\n        base64_image: Optional[str] = None,\n        numpy_image: Optional[np.ndarray] = None,\n        video_metadata: Optional[VideoMetadata] = None,\n        image_name: Optional[str] = None,\n    ):\n        if not base64_image and numpy_image is None and not image_reference:\n            raise ValueError(\"Could not initialise empty `WorkflowImageData`.\")\n        self._parent_metadata = parent_metadata\n        self._workflow_root_ancestor_metadata = (\n            workflow_root_ancestor_metadata\n            if workflow_root_ancestor_metadata\n            else self._parent_metadata\n        )\n        self._image_reference = image_reference\n        self._base64_image = base64_image\n        self._numpy_image = numpy_image\n        self._video_metadata = video_metadata\n        self._image_name = image_name\n\n    @classmethod\n    def copy_and_replace(\n        cls, origin_image_data: \"WorkflowImageData\", **kwargs\n    ) -> \"WorkflowImageData\":\n        \"\"\"\n        Creates new instance of `WorkflowImageData` with updated property.\n\n        Properties are passed by kwargs, supported properties are:\n        * parent_metadata\n        * workflow_root_ancestor_metadata\n        * image_reference\n        * base64_image\n        * numpy_image\n        * video_metadata\n        * image_name\n\n        When more than one from [\"numpy_image\", \"base64_image\", \"image_reference\"] args are\n        given, they MUST be compliant.\n        \"\"\"\n        parent_metadata = origin_image_data._parent_metadata\n        workflow_root_ancestor_metadata = (\n            origin_image_data._workflow_root_ancestor_metadata\n        )\n        image_reference = origin_image_data._image_reference\n        base64_image = origin_image_data._base64_image\n        numpy_image = origin_image_data._numpy_image\n        video_metadata = origin_image_data._video_metadata\n        image_name = origin_image_data._image_name\n        if any(k in kwargs for k in [\"numpy_image\", \"base64_image\", \"image_reference\"]):\n            numpy_image = kwargs.get(\"numpy_image\")\n            base64_image = kwargs.get(\"base64_image\")\n            image_reference = kwargs.get(\"image_reference\")\n        if \"parent_metadata\" in kwargs:\n            if workflow_root_ancestor_metadata is parent_metadata:\n                workflow_root_ancestor_metadata = kwargs[\"parent_metadata\"]\n            parent_metadata = kwargs[\"parent_metadata\"]\n        if \"workflow_root_ancestor_metadata\" in kwargs:\n            if parent_metadata is workflow_root_ancestor_metadata:\n                parent_metadata = kwargs[\"workflow_root_ancestor_metadata\"]\n            workflow_root_ancestor_metadata = kwargs[\"workflow_root_ancestor_metadata\"]\n        if \"video_metadata\" in kwargs:\n            video_metadata = kwargs[\"video_metadata\"]\n        if \"image_name\" in kwargs:\n            image_name = kwargs[\"image_name\"]\n        return cls(\n            parent_metadata=parent_metadata,\n            workflow_root_ancestor_metadata=workflow_root_ancestor_metadata,\n            image_reference=image_reference,\n            base64_image=base64_image,\n            numpy_image=numpy_image,\n            video_metadata=video_metadata,\n            image_name=image_name,\n        )\n\n    @classmethod\n    def create_crop(\n        cls,\n        origin_image_data: \"WorkflowImageData\",\n        crop_identifier: str,\n        cropped_image: np.ndarray,\n        offset_x: int,\n        offset_y: int,\n        preserve_video_metadata: bool = False,\n    ) -> \"WorkflowImageData\":\n        \"\"\"\n        Creates new instance of `WorkflowImageData` being a crop of original image,\n        making adjustment to all metadata.\n        \"\"\"\n        parent_metadata = ImageParentMetadata(\n            parent_id=crop_identifier,\n            origin_coordinates=OriginCoordinatesSystem(\n                left_top_x=offset_x,\n                left_top_y=offset_y,\n                origin_width=origin_image_data.numpy_image.shape[1],\n                origin_height=origin_image_data.numpy_image.shape[0],\n            ),\n        )\n        workflow_root_ancestor_coordinates = replace(\n            origin_image_data.workflow_root_ancestor_metadata.origin_coordinates,\n            left_top_x=origin_image_data.workflow_root_ancestor_metadata.origin_coordinates.left_top_x\n            + offset_x,\n            left_top_y=origin_image_data.workflow_root_ancestor_metadata.origin_coordinates.left_top_y\n            + offset_y,\n        )\n        workflow_root_ancestor_metadata = ImageParentMetadata(\n            parent_id=origin_image_data.workflow_root_ancestor_metadata.parent_id,\n            origin_coordinates=workflow_root_ancestor_coordinates,\n        )\n        video_metadata = None\n        if preserve_video_metadata and origin_image_data._video_metadata is not None:\n            video_metadata = copy(origin_image_data._video_metadata)\n            video_metadata.video_identifier = (\n                f\"{video_metadata.video_identifier} | crop: {crop_identifier}\"\n            )\n        return WorkflowImageData(\n            parent_metadata=parent_metadata,\n            workflow_root_ancestor_metadata=workflow_root_ancestor_metadata,\n            numpy_image=cropped_image,\n            video_metadata=video_metadata,\n            image_name=origin_image_data._image_name,\n        )\n\n    @property\n    def image_name(self) -> Optional[str]:\n        return self._image_name\n\n    @property\n    def parent_metadata(self) -> ImageParentMetadata:\n        if self._parent_metadata.origin_coordinates is None:\n            numpy_image = self.numpy_image\n            origin_coordinates = OriginCoordinatesSystem(\n                left_top_y=0,\n                left_top_x=0,\n                origin_width=numpy_image.shape[1],\n                origin_height=numpy_image.shape[0],\n            )\n            self._parent_metadata = replace(\n                self._parent_metadata, origin_coordinates=origin_coordinates\n            )\n        return self._parent_metadata\n\n    @property\n    def workflow_root_ancestor_metadata(self) -> ImageParentMetadata:\n        if self._workflow_root_ancestor_metadata.origin_coordinates is None:\n            numpy_image = self.numpy_image\n            origin_coordinates = OriginCoordinatesSystem(\n                left_top_y=0,\n                left_top_x=0,\n                origin_width=numpy_image.shape[1],\n                origin_height=numpy_image.shape[0],\n            )\n            self._workflow_root_ancestor_metadata = replace(\n                self._workflow_root_ancestor_metadata,\n                origin_coordinates=origin_coordinates,\n            )\n        return self._workflow_root_ancestor_metadata\n\n    @property\n    def numpy_image(self) -> np.ndarray:\n        if self._numpy_image is not None:\n            return self._numpy_image\n        if self._base64_image:\n            self._numpy_image = attempt_loading_image_from_string(self._base64_image)[0]\n            return self._numpy_image\n        if self._image_reference.startswith(\n            \"http://\"\n        ) or self._image_reference.startswith(\"https://\"):\n            self._numpy_image = load_image_from_url(value=self._image_reference)\n        else:\n            self._numpy_image = cv2.imread(self._image_reference)\n        return self._numpy_image\n\n    @property\n    def base64_image(self) -> str:\n        if self._base64_image is not None:\n            return self._base64_image\n        numpy_image = self.numpy_image\n        self._base64_image = base64.b64encode(\n            encode_image_to_jpeg_bytes(numpy_image, jpeg_quality=95)\n        ).decode(\"ascii\")\n        return self._base64_image\n\n    @property\n    def video_metadata(self) -> VideoMetadata:\n        if self._video_metadata is not None:\n            return self._video_metadata\n        return VideoMetadata(\n            video_identifier=self.parent_metadata.parent_id,\n            frame_number=0,\n            frame_timestamp=datetime.now(),\n            fps=30,\n            comes_from_video_file=None,\n        )\n\n    def to_inference_format(self, numpy_preferred: bool = False) -> Dict[str, Any]:\n        if numpy_preferred:\n            return {\"type\": \"numpy_object\", \"value\": self.numpy_image}\n        if self._image_reference:\n            if self._image_reference.startswith(\n                \"http://\"\n            ) or self._image_reference.startswith(\"https://\"):\n                return {\"type\": \"url\", \"value\": self._image_reference}\n            return {\"type\": \"file\", \"value\": self._image_reference}\n        if self._base64_image:\n            return {\"type\": \"base64\", \"value\": self.base64_image}\n        return {\"type\": \"numpy_object\", \"value\": self.numpy_image}\n",
    "patch": null
  },
  {
    "trace_id": "c861d267-1b12-4b92-9fbb-22ba88e53a5e",
    "function_name": "deserialize_image_kind",
    "file_path": "inference/core/workflows/core_steps/common/deserializers.py",
    "speedup_x": 0.42304231092995437,
    "review_quality": "high",
    "pre_optimization_commit": "a60c2b61fd767f1ffe2bb7f27e5aaa900785d661",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def deserialize_image_kind(\n    parameter: str,\n    image: Any,\n    prevent_local_images_loading: bool = False,\n) -> WorkflowImageData:\n    if isinstance(image, WorkflowImageData):\n        return image\n\n    is_image_dict = isinstance(image, dict)\n\n    parent_id = image.get(PARENT_ID_KEY, parameter) if is_image_dict else parameter\n    parent_origin = image.get(PARENT_ORIGIN_KEY) if is_image_dict else None\n    parent_metadata = _parse_optional_parent_metadata(\n        parameter=parameter,\n        parent_id=parent_id,\n        parent_origin=parent_origin,\n    )\n\n    root_parent_id = image.get(ROOT_PARENT_ID_KEY) if is_image_dict else None\n    root_parent_origin = image.get(ROOT_PARENT_ORIGIN_KEY) if is_image_dict else None\n    workflow_root_ancestor_metadata = _parse_optional_parent_metadata(\n        parameter=parameter,\n        parent_id=root_parent_id,\n        parent_origin=root_parent_origin,\n    )\n\n    video_metadata = None\n    if is_image_dict and \"video_metadata\" in image:\n        video_metadata = deserialize_video_metadata_kind(\n            parameter=parameter, video_metadata=image[\"video_metadata\"]\n        )\n    image_name = image.get(IMAGE_NAME_KEY) if is_image_dict else None\n    if is_image_dict and isinstance(image.get(\"value\"), np.ndarray):\n        image = image[\"value\"]\n    if isinstance(image, np.ndarray):\n        return WorkflowImageData(\n            parent_metadata=parent_metadata,\n            workflow_root_ancestor_metadata=workflow_root_ancestor_metadata,\n            numpy_image=image,\n            video_metadata=video_metadata,\n            image_name=image_name,\n        )\n    try:\n        if is_image_dict:\n            image = image[\"value\"]\n        if isinstance(image, str):\n            base64_image = None\n            image_reference = None\n            if image.startswith(\"http://\") or image.startswith(\"https://\"):\n                image_reference = image\n                image = load_image_from_url(value=image)\n            elif not prevent_local_images_loading and os.path.exists(image):\n                # prevent_local_images_loading is introduced to eliminate\n                # server vulnerability - namely it prevents local server\n                # file system from being exploited.\n                image_reference = image\n                image = cv2.imread(image)\n            else:\n                base64_image = image\n                image = attempt_loading_image_from_string(image)[0]\n            return WorkflowImageData(\n                parent_metadata=parent_metadata,\n                workflow_root_ancestor_metadata=workflow_root_ancestor_metadata,\n                numpy_image=image,\n                base64_image=base64_image,\n                image_reference=image_reference,\n                video_metadata=video_metadata,\n                image_name=image_name,\n            )\n    except Exception as error:\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` defined as `WorkflowImage` \"\n            f\"that is invalid. Failed on input validation. Details: {error}\",\n            context=\"workflow_execution | runtime_input_validation\",\n        ) from error\n    raise RuntimeInputError(\n        public_message=f\"Detected runtime parameter `{parameter}` defined as `WorkflowImage` \"\n        f\"with type {type(image)} that is invalid. Workflows accept only np.arrays, `WorkflowImageData` \"\n        f\"and dicts with keys `type` and `value` compatible with `inference` (or list of them).\",\n        context=\"workflow_execution | runtime_input_validation\",\n    )\n",
    "optimized_function_code": "import os\nfrom typing import Any, Optional\n\nimport cv2\nimport numpy as np\nfrom inference.core.utils.image_utils import (\n    attempt_loading_image_from_string, load_image_from_url)\n# The deserialize_parent_origin helper (preserved behavior)\nfrom inference.core.workflows.core_steps.common.deserializers import \\\n    deserialize_parent_origin  # type: ignore\nfrom inference.core.workflows.errors import RuntimeInputError\nfrom inference.core.workflows.execution_engine.constants import (\n    IMAGE_NAME_KEY, PARENT_ID_KEY, PARENT_ORIGIN_KEY, ROOT_PARENT_ID_KEY,\n    ROOT_PARENT_ORIGIN_KEY)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    ImageParentMetadata, VideoMetadata, WorkflowImageData)\nfrom pydantic import ValidationError\n\n# Simple cache for common case where parent_origin is falsy (avoid repeated ImageParentMetadata allocation)\n_PARENT_METADATA_CACHE: dict[str, ImageParentMetadata] = {}\n\n\ndef deserialize_image_kind(\n    parameter: str,\n    image: Any,\n    prevent_local_images_loading: bool = False,\n) -> WorkflowImageData:\n    if isinstance(image, WorkflowImageData):\n        return image\n\n    original_image = image\n    is_image_dict = isinstance(original_image, dict)\n\n    # Extract inexpensive fields early\n\n    video_metadata = None\n    image_name = None\n    if is_image_dict:\n        img_dict = original_image  # type: ignore[var-annotated]\n        image_name = img_dict.get(IMAGE_NAME_KEY)\n        if \"video_metadata\" in img_dict:\n            video_metadata = deserialize_video_metadata_kind(\n                parameter=parameter, video_metadata=img_dict[\"video_metadata\"]\n            )\n\n        # Fast path: dict holding numpy array directly as \"value\"\n        maybe_value = img_dict.get(\"value\")\n        if isinstance(maybe_value, np.ndarray):\n            image = maybe_value\n            parent_id = img_dict.get(PARENT_ID_KEY, parameter)\n            parent_origin = img_dict.get(PARENT_ORIGIN_KEY)\n            root_parent_id = img_dict.get(ROOT_PARENT_ID_KEY)\n            root_parent_origin = img_dict.get(ROOT_PARENT_ORIGIN_KEY)\n\n            parent_metadata = _parse_optional_parent_metadata(\n                parameter=parameter,\n                parent_id=parent_id,\n                parent_origin=parent_origin,\n            )\n            workflow_root_ancestor_metadata = _parse_optional_parent_metadata(\n                parameter=parameter,\n                parent_id=root_parent_id,\n                parent_origin=root_parent_origin,\n            )\n            return WorkflowImageData(\n                parent_metadata=parent_metadata,\n                workflow_root_ancestor_metadata=workflow_root_ancestor_metadata,\n                numpy_image=image,\n                video_metadata=video_metadata,\n                image_name=image_name,\n            )\n\n    # Non-dict numpy array fast path\n    if isinstance(original_image, np.ndarray) and not is_image_dict:\n        parent_metadata = _parse_optional_parent_metadata(\n            parameter=parameter,\n            parent_id=parameter,\n            parent_origin=None,\n        )\n        return WorkflowImageData(\n            parent_metadata=parent_metadata,\n            workflow_root_ancestor_metadata=parent_metadata,\n            numpy_image=original_image,\n            video_metadata=None,\n            image_name=None,\n        )\n    try:\n        if is_image_dict:\n            img_dict = original_image  # type: ignore[var-annotated]\n            value = img_dict.get(\"value\")\n        else:\n            value = original_image\n\n        if isinstance(value, str):\n            base64_image = None\n            image_reference = None\n            if value.startswith(\"http://\") or value.startswith(\"https://\"):\n                image_reference = value\n                image = load_image_from_url(value=value)\n            elif not prevent_local_images_loading and os.path.exists(value):\n                # prevent_local_images_loading is introduced to eliminate\n                # server vulnerability - namely it prevents local server\n                # file system from being exploited.\n                image_reference = value\n                image = cv2.imread(value)\n            else:\n                base64_image = value\n                image = attempt_loading_image_from_string(value)[0]\n\n            # Now build parent metadata once we have the value and references\n            parent_id = img_dict.get(PARENT_ID_KEY, parameter) if is_image_dict else parameter\n            parent_origin = img_dict.get(PARENT_ORIGIN_KEY) if is_image_dict else None\n            root_parent_id = img_dict.get(ROOT_PARENT_ID_KEY) if is_image_dict else None\n            root_parent_origin = img_dict.get(ROOT_PARENT_ORIGIN_KEY) if is_image_dict else None\n\n            parent_metadata = _parse_optional_parent_metadata(\n                parameter=parameter,\n                parent_id=parent_id,\n                parent_origin=parent_origin,\n            )\n            workflow_root_ancestor_metadata = _parse_optional_parent_metadata(\n                parameter=parameter,\n                parent_id=root_parent_id,\n                parent_origin=root_parent_origin,\n            )\n\n            return WorkflowImageData(\n                parent_metadata=parent_metadata,\n                workflow_root_ancestor_metadata=workflow_root_ancestor_metadata,\n                numpy_image=image,\n                base64_image=base64_image,\n                image_reference=image_reference,\n                video_metadata=video_metadata,\n                image_name=image_name,\n            )\n    except Exception as error:\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` defined as `WorkflowImage` \"\n            f\"that is invalid. Failed on input validation. Details: {error}\",\n            context=\"workflow_execution | runtime_input_validation\",\n        ) from error\n    raise RuntimeInputError(\n        public_message=f\"Detected runtime parameter `{parameter}` defined as `WorkflowImage` \"\n        f\"with type {type(original_image)} that is invalid. Workflows accept only np.arrays, `WorkflowImageData` \"\n        f\"and dicts with keys `type` and `value` compatible with `inference` (or list of them).\",\n        context=\"workflow_execution | runtime_input_validation\",\n    )\n\n\ndef _parse_optional_parent_metadata(\n    parameter: str,\n    parent_id: Optional[str],\n    parent_origin: Optional[Any],\n) -> Optional[ImageParentMetadata]:\n    if not parent_id:\n        return None\n\n    if not parent_origin:\n        cached = _PARENT_METADATA_CACHE.get(parent_id)\n        if cached is not None:\n            return cached\n        instance = ImageParentMetadata(parent_id=parent_id)\n        _PARENT_METADATA_CACHE[parent_id] = instance\n        return instance\n\n\n    parsed_origin = deserialize_parent_origin(parameter, parent_origin)\n    return ImageParentMetadata(\n        parent_id=parent_id,\n        origin_coordinates=parsed_origin.to_origin_coordinates_system(),\n    )\n\n\ndef deserialize_video_metadata_kind(\n    parameter: str,\n    video_metadata: Any,\n) -> VideoMetadata:\n    if isinstance(video_metadata, VideoMetadata):\n        return video_metadata\n    if not isinstance(video_metadata, dict):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` holding \"\n            f\"`WorkflowVideoMetadata`, but provided value is not a dict.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    try:\n        return VideoMetadata.model_validate(video_metadata)\n    except ValidationError as error:\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` holding \"\n            f\"`WorkflowVideoMetadata`, but provided value is malformed. \"\n            f\"See details in inner error.\",\n            context=\"workflow_execution | runtime_input_validation\",\n            inner_error=error,\n        )",
    "optimized_raw_markdown": "```python:inference/core/workflows/execution_engine/entities/base.py\nfrom dataclasses import dataclass\nfrom datetime import datetime\nfrom typing import Optional\n\nimport numpy as np\nfrom pydantic import BaseModel, Field\n\n\nclass VideoMetadata(BaseModel):\n    video_identifier: str = Field(\n        description=\"Identifier string for video. To be treated as opaque.\"\n    )\n    frame_number: int\n    frame_timestamp: datetime = Field(\n        description=\"The timestamp of video frame. When processing video it is suggested that \"\n        \"blocks rely on `fps` and `frame_number`, as real-world time-elapse will not \"\n        \"match time-elapse in video file\",\n    )\n    fps: Optional[float] = Field(\n        description=\"Field represents FPS value (if possible to be retrieved)\",\n        default=None,\n    )\n    measured_fps: Optional[float] = Field(\n        description=\"Field represents measured FPS of live stream\",\n        default=None,\n    )\n    comes_from_video_file: Optional[bool] = Field(\n        description=\"Field is a flag telling if frame comes from video file or stream - \"\n        \"if not possible to be determined - pass None\",\n        default=None,\n    )\n\n\n@dataclass(frozen=True)\nclass OriginCoordinatesSystem:\n    left_top_x: int\n    left_top_y: int\n    origin_width: int\n    origin_height: int\n\n\n@dataclass(frozen=True)\nclass ImageParentMetadata:\n    parent_id: str\n    origin_coordinates: Optional[OriginCoordinatesSystem] = None\n\n\nclass WorkflowImageData:\n\n    # Use __slots__ to reduce memory footprint and speed attribute access\n    __slots__ = (\n        \"_parent_metadata\",\n        \"_workflow_root_ancestor_metadata\",\n        \"_image_reference\",\n        \"_base64_image\",\n        \"_numpy_image\",\n        \"_video_metadata\",\n        \"_image_name\",\n    )\n\n    def __init__(\n        self,\n        parent_metadata: ImageParentMetadata,\n        workflow_root_ancestor_metadata: Optional[ImageParentMetadata] = None,\n        image_reference: Optional[str] = None,\n        base64_image: Optional[str] = None,\n        numpy_image: Optional[np.ndarray] = None,\n        video_metadata: Optional[VideoMetadata] = None,\n        image_name: Optional[str] = None,\n    ):\n        if not base64_image and numpy_image is None and not image_reference:\n            raise ValueError(\"Could not initialise empty `WorkflowImageData`.\")\n        self._parent_metadata = parent_metadata\n        self._workflow_root_ancestor_metadata = (\n            workflow_root_ancestor_metadata\n            if workflow_root_ancestor_metadata\n            else self._parent_metadata\n        )\n        self._image_reference = image_reference\n        self._base64_image = base64_image\n        self._numpy_image = numpy_image\n        self._video_metadata = video_metadata\n        self._image_name = image_name\n```\n```python:inference/core/workflows/core_steps/common/deserializers.py\nimport os\nfrom typing import Any, Optional\n\nimport cv2\nimport numpy as np\nfrom inference.core.utils.image_utils import (\n    attempt_loading_image_from_string, load_image_from_url)\n# The deserialize_parent_origin helper (preserved behavior)\nfrom inference.core.workflows.core_steps.common.deserializers import \\\n    deserialize_parent_origin  # type: ignore\nfrom inference.core.workflows.errors import RuntimeInputError\nfrom inference.core.workflows.execution_engine.constants import (\n    IMAGE_NAME_KEY, PARENT_ID_KEY, PARENT_ORIGIN_KEY, ROOT_PARENT_ID_KEY,\n    ROOT_PARENT_ORIGIN_KEY)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    ImageParentMetadata, VideoMetadata, WorkflowImageData)\nfrom pydantic import ValidationError\n\n# Simple cache for common case where parent_origin is falsy (avoid repeated ImageParentMetadata allocation)\n_PARENT_METADATA_CACHE: dict[str, ImageParentMetadata] = {}\n\n\ndef deserialize_image_kind(\n    parameter: str,\n    image: Any,\n    prevent_local_images_loading: bool = False,\n) -> WorkflowImageData:\n    if isinstance(image, WorkflowImageData):\n        return image\n\n    original_image = image\n    is_image_dict = isinstance(original_image, dict)\n\n    # Extract inexpensive fields early\n\n    video_metadata = None\n    image_name = None\n    if is_image_dict:\n        img_dict = original_image  # type: ignore[var-annotated]\n        image_name = img_dict.get(IMAGE_NAME_KEY)\n        if \"video_metadata\" in img_dict:\n            video_metadata = deserialize_video_metadata_kind(\n                parameter=parameter, video_metadata=img_dict[\"video_metadata\"]\n            )\n\n        # Fast path: dict holding numpy array directly as \"value\"\n        maybe_value = img_dict.get(\"value\")\n        if isinstance(maybe_value, np.ndarray):\n            image = maybe_value\n            parent_id = img_dict.get(PARENT_ID_KEY, parameter)\n            parent_origin = img_dict.get(PARENT_ORIGIN_KEY)\n            root_parent_id = img_dict.get(ROOT_PARENT_ID_KEY)\n            root_parent_origin = img_dict.get(ROOT_PARENT_ORIGIN_KEY)\n\n            parent_metadata = _parse_optional_parent_metadata(\n                parameter=parameter,\n                parent_id=parent_id,\n                parent_origin=parent_origin,\n            )\n            workflow_root_ancestor_metadata = _parse_optional_parent_metadata(\n                parameter=parameter,\n                parent_id=root_parent_id,\n                parent_origin=root_parent_origin,\n            )\n            return WorkflowImageData(\n                parent_metadata=parent_metadata,\n                workflow_root_ancestor_metadata=workflow_root_ancestor_metadata,\n                numpy_image=image,\n                video_metadata=video_metadata,\n                image_name=image_name,\n            )\n\n    # Non-dict numpy array fast path\n    if isinstance(original_image, np.ndarray) and not is_image_dict:\n        parent_metadata = _parse_optional_parent_metadata(\n            parameter=parameter,\n            parent_id=parameter,\n            parent_origin=None,\n        )\n        return WorkflowImageData(\n            parent_metadata=parent_metadata,\n            workflow_root_ancestor_metadata=parent_metadata,\n            numpy_image=original_image,\n            video_metadata=None,\n            image_name=None,\n        )\n    try:\n        if is_image_dict:\n            img_dict = original_image  # type: ignore[var-annotated]\n            value = img_dict.get(\"value\")\n        else:\n            value = original_image\n\n        if isinstance(value, str):\n            base64_image = None\n            image_reference = None\n            if value.startswith(\"http://\") or value.startswith(\"https://\"):\n                image_reference = value\n                image = load_image_from_url(value=value)\n            elif not prevent_local_images_loading and os.path.exists(value):\n                # prevent_local_images_loading is introduced to eliminate\n                # server vulnerability - namely it prevents local server\n                # file system from being exploited.\n                image_reference = value\n                image = cv2.imread(value)\n            else:\n                base64_image = value\n                image = attempt_loading_image_from_string(value)[0]\n\n            # Now build parent metadata once we have the value and references\n            parent_id = img_dict.get(PARENT_ID_KEY, parameter) if is_image_dict else parameter\n            parent_origin = img_dict.get(PARENT_ORIGIN_KEY) if is_image_dict else None\n            root_parent_id = img_dict.get(ROOT_PARENT_ID_KEY) if is_image_dict else None\n            root_parent_origin = img_dict.get(ROOT_PARENT_ORIGIN_KEY) if is_image_dict else None\n\n            parent_metadata = _parse_optional_parent_metadata(\n                parameter=parameter,\n                parent_id=parent_id,\n                parent_origin=parent_origin,\n            )\n            workflow_root_ancestor_metadata = _parse_optional_parent_metadata(\n                parameter=parameter,\n                parent_id=root_parent_id,\n                parent_origin=root_parent_origin,\n            )\n\n            return WorkflowImageData(\n                parent_metadata=parent_metadata,\n                workflow_root_ancestor_metadata=workflow_root_ancestor_metadata,\n                numpy_image=image,\n                base64_image=base64_image,\n                image_reference=image_reference,\n                video_metadata=video_metadata,\n                image_name=image_name,\n            )\n    except Exception as error:\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` defined as `WorkflowImage` \"\n            f\"that is invalid. Failed on input validation. Details: {error}\",\n            context=\"workflow_execution | runtime_input_validation\",\n        ) from error\n    raise RuntimeInputError(\n        public_message=f\"Detected runtime parameter `{parameter}` defined as `WorkflowImage` \"\n        f\"with type {type(original_image)} that is invalid. Workflows accept only np.arrays, `WorkflowImageData` \"\n        f\"and dicts with keys `type` and `value` compatible with `inference` (or list of them).\",\n        context=\"workflow_execution | runtime_input_validation\",\n    )\n\n\ndef _parse_optional_parent_metadata(\n    parameter: str,\n    parent_id: Optional[str],\n    parent_origin: Optional[Any],\n) -> Optional[ImageParentMetadata]:\n    if not parent_id:\n        return None\n\n    if not parent_origin:\n        cached = _PARENT_METADATA_CACHE.get(parent_id)\n        if cached is not None:\n            return cached\n        instance = ImageParentMetadata(parent_id=parent_id)\n        _PARENT_METADATA_CACHE[parent_id] = instance\n        return instance\n\n\n    parsed_origin = deserialize_parent_origin(parameter, parent_origin)\n    return ImageParentMetadata(\n        parent_id=parent_id,\n        origin_coordinates=parsed_origin.to_origin_coordinates_system(),\n    )\n\n\ndef deserialize_video_metadata_kind(\n    parameter: str,\n    video_metadata: Any,\n) -> VideoMetadata:\n    if isinstance(video_metadata, VideoMetadata):\n        return video_metadata\n    if not isinstance(video_metadata, dict):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` holding \"\n            f\"`WorkflowVideoMetadata`, but provided value is not a dict.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    try:\n        return VideoMetadata.model_validate(video_metadata)\n    except ValidationError as error:\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` holding \"\n            f\"`WorkflowVideoMetadata`, but provided value is malformed. \"\n            f\"See details in inner error.\",\n            context=\"workflow_execution | runtime_input_validation\",\n            inner_error=error,\n        )\n```\n```python:inference/core/utils/image_utils.py\nimport re\nimport urllib.parse\nfrom typing import Tuple, Union\n\nimport cv2\nimport numpy as np\nimport requests\nimport tldextract\nfrom _io import _IOBase\nfrom inference.core.exceptions import (InputFormatInferenceFailed,\n                                       InputImageLoadError,\n                                       InvalidImageTypeDeclared,\n                                       InvalidNumpyInput)\nfrom inference.core.utils.requests import api_key_safe_raise_for_status\nfrom requests import RequestException\n\nBASE64_DATA_TYPE_PATTERN = re.compile(r\"^data:image\\/[a-z]+;base64,\")\n\n\n\n# Reuse a single TLDExtract instance to avoid repeated construction costs.\n_TLD_EXTRACTOR = tldextract.TLDExtract(suffix_list_urls=())\n\n\ndef attempt_loading_image_from_string(\n    value: Union[str, bytes, bytearray, _IOBase],\n    cv_imread_flags: int = cv2.IMREAD_COLOR,\n) -> Tuple[np.ndarray, bool]:\n    \"\"\"\n    Attempt to load an image from a string.\n\n    Args:\n        value (Union[str, bytes, bytearray, _IOBase]): The image data in string format.\n        cv_imread_flags (int): OpenCV flags used for image reading.\n\n    Returns:\n        Tuple[np.ndarray, bool]: A tuple of the loaded image in numpy array format and a boolean flag indicating if the image is in BGR format.\n    \"\"\"\n    try:\n        return load_image_base64(value=value, cv_imread_flags=cv_imread_flags), True\n    except:\n        pass\n    try:\n        return (\n            load_image_from_encoded_bytes(value=value, cv_imread_flags=cv_imread_flags),\n            True,\n        )\n    except:\n        pass\n    try:\n        return (\n            load_image_from_buffer(value=value, cv_imread_flags=cv_imread_flags),\n            True,\n        )\n    except:\n        pass\n    try:\n        return load_image_from_numpy_str(value=value), True\n    except InvalidImageTypeDeclared as error:\n        raise error\n    except InvalidNumpyInput as error:\n        raise InputFormatInferenceFailed(\n            message=\"Input image format could not be inferred from string.\",\n            public_message=\"Input image format could not be inferred from string.\",\n        ) from error\n\n\ndef load_image_from_url(\n    value: str, cv_imread_flags: int = cv2.IMREAD_COLOR\n) -> np.ndarray:\n    \"\"\"Loads an image from a given URL.\n\n    Args:\n        value (str): URL of the image.\n\n    Returns:\n        Image.Image: The loaded PIL image.\n    \"\"\"\n    _ensure_url_input_allowed()\n    try:\n        parsed_url = urllib.parse.urlparse(value)\n    except ValueError as error:\n        message = \"Provided image URL is invalid\"\n        raise InputImageLoadError(\n            message=message,\n            public_message=message,\n        ) from error\n    _ensure_resource_schema_allowed(schema=parsed_url.scheme)\n    domain_extraction_result = _TLD_EXTRACTOR(parsed_url.netloc)  # we get rid of potential ports and parse FQDNs\n    _ensure_resource_fqdn_allowed(fqdn=domain_extraction_result.fqdn)\n    address_parts_concatenated = _concatenate_chunks_of_network_location(\n        extraction_result=domain_extraction_result\n    )  # concatenation of chunks - even if there is no FQDN, but address\n    # it allows white-/black-list verification\n    _ensure_location_matches_destination_whitelist(\n        destination=address_parts_concatenated\n    )\n    _ensure_location_matches_destination_blacklist(\n        destination=address_parts_concatenated\n    )\n    try:\n        response = requests.get(value, stream=True)\n        api_key_safe_raise_for_status(response=response)\n        return load_image_from_encoded_bytes(\n            value=response.content, cv_imread_flags=cv_imread_flags\n        )\n    except (RequestException, ConnectionError) as error:\n        raise InputImageLoadError(\n            message=f\"Could not load image from url: {value}. Details: {error}\",\n            public_message=\"Data pointed by URL could not be decoded into image.\",\n        )\n```",
    "optimized_function_only": "def deserialize_image_kind(\n    parameter: str,\n    image: Any,\n    prevent_local_images_loading: bool = False,\n) -> WorkflowImageData:\n    if isinstance(image, WorkflowImageData):\n        return image\n\n    original_image = image\n    is_image_dict = isinstance(original_image, dict)\n\n    # Extract inexpensive fields early\n\n    video_metadata = None\n    image_name = None\n    if is_image_dict:\n        img_dict = original_image  # type: ignore[var-annotated]\n        image_name = img_dict.get(IMAGE_NAME_KEY)\n        if \"video_metadata\" in img_dict:\n            video_metadata = deserialize_video_metadata_kind(\n                parameter=parameter, video_metadata=img_dict[\"video_metadata\"]\n            )\n\n        # Fast path: dict holding numpy array directly as \"value\"\n        maybe_value = img_dict.get(\"value\")\n        if isinstance(maybe_value, np.ndarray):\n            image = maybe_value\n            parent_id = img_dict.get(PARENT_ID_KEY, parameter)\n            parent_origin = img_dict.get(PARENT_ORIGIN_KEY)\n            root_parent_id = img_dict.get(ROOT_PARENT_ID_KEY)\n            root_parent_origin = img_dict.get(ROOT_PARENT_ORIGIN_KEY)\n\n            parent_metadata = _parse_optional_parent_metadata(\n                parameter=parameter,\n                parent_id=parent_id,\n                parent_origin=parent_origin,\n            )\n            workflow_root_ancestor_metadata = _parse_optional_parent_metadata(\n                parameter=parameter,\n                parent_id=root_parent_id,\n                parent_origin=root_parent_origin,\n            )\n            return WorkflowImageData(\n                parent_metadata=parent_metadata,\n                workflow_root_ancestor_metadata=workflow_root_ancestor_metadata,\n                numpy_image=image,\n                video_metadata=video_metadata,\n                image_name=image_name,\n            )\n\n    # Non-dict numpy array fast path\n    if isinstance(original_image, np.ndarray) and not is_image_dict:\n        parent_metadata = _parse_optional_parent_metadata(\n            parameter=parameter,\n            parent_id=parameter,\n            parent_origin=None,\n        )\n        return WorkflowImageData(\n            parent_metadata=parent_metadata,\n            workflow_root_ancestor_metadata=parent_metadata,\n            numpy_image=original_image,\n            video_metadata=None,\n            image_name=None,\n        )\n    try:\n        if is_image_dict:\n            img_dict = original_image  # type: ignore[var-annotated]\n            value = img_dict.get(\"value\")\n        else:\n            value = original_image\n\n        if isinstance(value, str):\n            base64_image = None\n            image_reference = None\n            if value.startswith(\"http://\") or value.startswith(\"https://\"):\n                image_reference = value\n                image = load_image_from_url(value=value)\n            elif not prevent_local_images_loading and os.path.exists(value):\n                # prevent_local_images_loading is introduced to eliminate\n                # server vulnerability - namely it prevents local server\n                # file system from being exploited.\n                image_reference = value\n                image = cv2.imread(value)\n            else:\n                base64_image = value\n                image = attempt_loading_image_from_string(value)[0]\n\n            # Now build parent metadata once we have the value and references\n            parent_id = img_dict.get(PARENT_ID_KEY, parameter) if is_image_dict else parameter\n            parent_origin = img_dict.get(PARENT_ORIGIN_KEY) if is_image_dict else None\n            root_parent_id = img_dict.get(ROOT_PARENT_ID_KEY) if is_image_dict else None\n            root_parent_origin = img_dict.get(ROOT_PARENT_ORIGIN_KEY) if is_image_dict else None\n\n            parent_metadata = _parse_optional_parent_metadata(\n                parameter=parameter,\n                parent_id=parent_id,\n                parent_origin=parent_origin,\n            )\n            workflow_root_ancestor_metadata = _parse_optional_parent_metadata(\n                parameter=parameter,\n                parent_id=root_parent_id,\n                parent_origin=root_parent_origin,\n            )\n\n            return WorkflowImageData(\n                parent_metadata=parent_metadata,\n                workflow_root_ancestor_metadata=workflow_root_ancestor_metadata,\n                numpy_image=image,\n                base64_image=base64_image,\n                image_reference=image_reference,\n                video_metadata=video_metadata,\n                image_name=image_name,\n            )\n    except Exception as error:\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` defined as `WorkflowImage` \"\n            f\"that is invalid. Failed on input validation. Details: {error}\",\n            context=\"workflow_execution | runtime_input_validation\",\n        ) from error\n    raise RuntimeInputError(\n        public_message=f\"Detected runtime parameter `{parameter}` defined as `WorkflowImage` \"\n        f\"with type {type(original_image)} that is invalid. Workflows accept only np.arrays, `WorkflowImageData` \"\n        f\"and dicts with keys `type` and `value` compatible with `inference` (or list of them).\",\n        context=\"workflow_execution | runtime_input_validation\",\n    )\n",
    "original_file_content": "import os\nfrom datetime import datetime\nfrom typing import Any, List, Optional, Tuple, Union\nfrom uuid import uuid4\n\nimport cv2\nimport numpy as np\nimport pybase64\nimport supervision as sv\nfrom pydantic import ValidationError\n\nfrom inference.core.utils.image_utils import (\n    attempt_loading_image_from_string,\n    load_image_from_url,\n)\nfrom inference.core.workflows.core_steps.common.utils import (\n    add_inference_keypoints_to_sv_detections,\n    filter_out_invalid_polygons,\n)\nfrom inference.core.workflows.errors import RuntimeInputError\nfrom inference.core.workflows.execution_engine.constants import (\n    AREA_CONVERTED_KEY_IN_INFERENCE_RESPONSE,\n    AREA_CONVERTED_KEY_IN_SV_DETECTIONS,\n    AREA_KEY_IN_INFERENCE_RESPONSE,\n    AREA_KEY_IN_SV_DETECTIONS,\n    BOUNDING_RECT_ANGLE_KEY_IN_INFERENCE_RESPONSE,\n    BOUNDING_RECT_ANGLE_KEY_IN_SV_DETECTIONS,\n    BOUNDING_RECT_HEIGHT_KEY_IN_INFERENCE_RESPONSE,\n    BOUNDING_RECT_HEIGHT_KEY_IN_SV_DETECTIONS,\n    BOUNDING_RECT_RECT_KEY_IN_INFERENCE_RESPONSE,\n    BOUNDING_RECT_RECT_KEY_IN_SV_DETECTIONS,\n    BOUNDING_RECT_WIDTH_KEY_IN_INFERENCE_RESPONSE,\n    BOUNDING_RECT_WIDTH_KEY_IN_SV_DETECTIONS,\n    DETECTED_CODE_KEY,\n    DETECTION_ID_KEY,\n    IMAGE_DIMENSIONS_KEY,\n    IMAGE_NAME_KEY,\n    KEYPOINTS_KEY_IN_INFERENCE_RESPONSE,\n    PARENT_COORDINATES_KEY,\n    PARENT_DIMENSIONS_KEY,\n    PARENT_ID_KEY,\n    PARENT_ORIGIN_KEY,\n    PATH_DEVIATION_KEY_IN_INFERENCE_RESPONSE,\n    PATH_DEVIATION_KEY_IN_SV_DETECTIONS,\n    POLYGON_KEY_IN_INFERENCE_RESPONSE,\n    POLYGON_KEY_IN_SV_DETECTIONS,\n    RLE_MASK_KEY_IN_INFERENCE_RESPONSE,\n    RLE_MASK_KEY_IN_SV_DETECTIONS,\n    ROOT_PARENT_COORDINATES_KEY,\n    ROOT_PARENT_DIMENSIONS_KEY,\n    ROOT_PARENT_ID_KEY,\n    ROOT_PARENT_ORIGIN_KEY,\n    SMOOTHED_SPEED_KEY_IN_INFERENCE_RESPONSE,\n    SMOOTHED_SPEED_KEY_IN_SV_DETECTIONS,\n    SMOOTHED_VELOCITY_KEY_IN_INFERENCE_RESPONSE,\n    SMOOTHED_VELOCITY_KEY_IN_SV_DETECTIONS,\n    SPEED_KEY_IN_INFERENCE_RESPONSE,\n    SPEED_KEY_IN_SV_DETECTIONS,\n    TIME_IN_ZONE_KEY_IN_INFERENCE_RESPONSE,\n    TIME_IN_ZONE_KEY_IN_SV_DETECTIONS,\n    VELOCITY_KEY_IN_INFERENCE_RESPONSE,\n    VELOCITY_KEY_IN_SV_DETECTIONS,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    ImageParentMetadata,\n    ParentOrigin,\n    VideoMetadata,\n    WorkflowImageData,\n)\n\nAnyNumber = Union[int, float]\n\n\ndef deserialize_image_kind(\n    parameter: str,\n    image: Any,\n    prevent_local_images_loading: bool = False,\n) -> WorkflowImageData:\n    if isinstance(image, WorkflowImageData):\n        return image\n\n    is_image_dict = isinstance(image, dict)\n\n    parent_id = image.get(PARENT_ID_KEY, parameter) if is_image_dict else parameter\n    parent_origin = image.get(PARENT_ORIGIN_KEY) if is_image_dict else None\n    parent_metadata = _parse_optional_parent_metadata(\n        parameter=parameter,\n        parent_id=parent_id,\n        parent_origin=parent_origin,\n    )\n\n    root_parent_id = image.get(ROOT_PARENT_ID_KEY) if is_image_dict else None\n    root_parent_origin = image.get(ROOT_PARENT_ORIGIN_KEY) if is_image_dict else None\n    workflow_root_ancestor_metadata = _parse_optional_parent_metadata(\n        parameter=parameter,\n        parent_id=root_parent_id,\n        parent_origin=root_parent_origin,\n    )\n\n    video_metadata = None\n    if is_image_dict and \"video_metadata\" in image:\n        video_metadata = deserialize_video_metadata_kind(\n            parameter=parameter, video_metadata=image[\"video_metadata\"]\n        )\n    image_name = image.get(IMAGE_NAME_KEY) if is_image_dict else None\n    if is_image_dict and isinstance(image.get(\"value\"), np.ndarray):\n        image = image[\"value\"]\n    if isinstance(image, np.ndarray):\n        return WorkflowImageData(\n            parent_metadata=parent_metadata,\n            workflow_root_ancestor_metadata=workflow_root_ancestor_metadata,\n            numpy_image=image,\n            video_metadata=video_metadata,\n            image_name=image_name,\n        )\n    try:\n        if is_image_dict:\n            image = image[\"value\"]\n        if isinstance(image, str):\n            base64_image = None\n            image_reference = None\n            if image.startswith(\"http://\") or image.startswith(\"https://\"):\n                image_reference = image\n                image = load_image_from_url(value=image)\n            elif not prevent_local_images_loading and os.path.exists(image):\n                # prevent_local_images_loading is introduced to eliminate\n                # server vulnerability - namely it prevents local server\n                # file system from being exploited.\n                image_reference = image\n                image = cv2.imread(image)\n            else:\n                base64_image = image\n                image = attempt_loading_image_from_string(image)[0]\n            return WorkflowImageData(\n                parent_metadata=parent_metadata,\n                workflow_root_ancestor_metadata=workflow_root_ancestor_metadata,\n                numpy_image=image,\n                base64_image=base64_image,\n                image_reference=image_reference,\n                video_metadata=video_metadata,\n                image_name=image_name,\n            )\n    except Exception as error:\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` defined as `WorkflowImage` \"\n            f\"that is invalid. Failed on input validation. Details: {error}\",\n            context=\"workflow_execution | runtime_input_validation\",\n        ) from error\n    raise RuntimeInputError(\n        public_message=f\"Detected runtime parameter `{parameter}` defined as `WorkflowImage` \"\n        f\"with type {type(image)} that is invalid. Workflows accept only np.arrays, `WorkflowImageData` \"\n        f\"and dicts with keys `type` and `value` compatible with `inference` (or list of them).\",\n        context=\"workflow_execution | runtime_input_validation\",\n    )\n\n\ndef _parse_optional_parent_metadata(\n    parameter: str,\n    parent_id: Optional[str],\n    parent_origin: Optional[Any],\n) -> Optional[ImageParentMetadata]:\n    if not parent_id:\n        return None\n\n    if not parent_origin:\n        return ImageParentMetadata(parent_id=parent_id)\n\n    parsed_origin = deserialize_parent_origin(parameter, parent_origin)\n    return ImageParentMetadata(\n        parent_id=parent_id,\n        origin_coordinates=parsed_origin.to_origin_coordinates_system(),\n    )\n\n\ndef deserialize_parent_origin(parameter: str, parent_origin: Any) -> ParentOrigin:\n    if isinstance(parent_origin, ParentOrigin):\n        return parent_origin\n    if not isinstance(parent_origin, dict):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` holding \"\n            f\"`ParentOrigin`, but provided value is not a dict.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    try:\n        return ParentOrigin.model_validate(parent_origin)\n    except ValidationError as error:\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` holding \"\n            f\"`ParentOrigin`, but provided value is malformed. \"\n            f\"See details in inner error.\",\n            context=\"workflow_execution | runtime_input_validation\",\n            inner_error=error,\n        )\n\n\ndef deserialize_video_metadata_kind(\n    parameter: str,\n    video_metadata: Any,\n) -> VideoMetadata:\n    if isinstance(video_metadata, VideoMetadata):\n        return video_metadata\n    if not isinstance(video_metadata, dict):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` holding \"\n            f\"`WorkflowVideoMetadata`, but provided value is not a dict.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    try:\n        return VideoMetadata.model_validate(video_metadata)\n    except ValidationError as error:\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` holding \"\n            f\"`WorkflowVideoMetadata`, but provided value is malformed. \"\n            f\"See details in inner error.\",\n            context=\"workflow_execution | runtime_input_validation\",\n            inner_error=error,\n        )\n\n\ndef deserialize_detections_kind(\n    parameter: str,\n    detections: Any,\n) -> sv.Detections:\n    if isinstance(detections, sv.Detections):\n        return detections\n    if not isinstance(detections, dict):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"detections, but invalid type of data found.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    if \"predictions\" not in detections or \"image\" not in detections:\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"detections, but dictionary misses required keys.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    parsed_detections = sv.Detections.from_inference(detections)\n    if len(parsed_detections) == 0:\n        return parsed_detections\n    height, width = detections[\"image\"][\"height\"], detections[\"image\"][\"width\"]\n    image_metadata = np.array([[height, width]] * len(parsed_detections))\n    parsed_detections.data[IMAGE_DIMENSIONS_KEY] = image_metadata\n    raw_predictions = detections[\"predictions\"]\n    if len(parsed_detections) != len(raw_predictions):\n        raw_predictions = filter_out_invalid_polygons(predictions=raw_predictions)\n    detection_ids = [\n        detection.get(DETECTION_ID_KEY, str(uuid4())) for detection in raw_predictions\n    ]\n    parsed_detections.data[DETECTION_ID_KEY] = np.array(detection_ids)\n\n    parent_ids = [\n        detection.get(PARENT_ID_KEY, parameter) for detection in raw_predictions\n    ]\n    parsed_detections[PARENT_ID_KEY] = np.array(parent_ids)\n\n    _attach_parent_coordinates_and_dimensions(\n        parameter=parameter,\n        raw_detections=raw_predictions,\n        parsed_detections=parsed_detections,\n        origin_key=PARENT_ORIGIN_KEY,\n        coordinates_key=PARENT_COORDINATES_KEY,\n        dimensions_key=PARENT_DIMENSIONS_KEY,\n    )\n\n    root_parent_ids = [\n        detection.get(ROOT_PARENT_ID_KEY, parameter) for detection in raw_predictions\n    ]\n    if root_parent_ids:\n        parsed_detections.data[ROOT_PARENT_ID_KEY] = np.array(root_parent_ids)\n\n        _attach_parent_coordinates_and_dimensions(\n            parameter=parameter,\n            raw_detections=raw_predictions,\n            parsed_detections=parsed_detections,\n            origin_key=ROOT_PARENT_ORIGIN_KEY,\n            coordinates_key=ROOT_PARENT_COORDINATES_KEY,\n            dimensions_key=ROOT_PARENT_DIMENSIONS_KEY,\n        )\n\n    optional_elements_keys = [\n        (PATH_DEVIATION_KEY_IN_INFERENCE_RESPONSE, PATH_DEVIATION_KEY_IN_SV_DETECTIONS),\n        (TIME_IN_ZONE_KEY_IN_INFERENCE_RESPONSE, TIME_IN_ZONE_KEY_IN_SV_DETECTIONS),\n        (POLYGON_KEY_IN_INFERENCE_RESPONSE, POLYGON_KEY_IN_SV_DETECTIONS),\n        (\n            BOUNDING_RECT_ANGLE_KEY_IN_INFERENCE_RESPONSE,\n            BOUNDING_RECT_ANGLE_KEY_IN_SV_DETECTIONS,\n        ),\n        (\n            BOUNDING_RECT_RECT_KEY_IN_INFERENCE_RESPONSE,\n            BOUNDING_RECT_RECT_KEY_IN_SV_DETECTIONS,\n        ),\n        (\n            BOUNDING_RECT_HEIGHT_KEY_IN_INFERENCE_RESPONSE,\n            BOUNDING_RECT_HEIGHT_KEY_IN_SV_DETECTIONS,\n        ),\n        (\n            BOUNDING_RECT_WIDTH_KEY_IN_INFERENCE_RESPONSE,\n            BOUNDING_RECT_WIDTH_KEY_IN_SV_DETECTIONS,\n        ),\n        (DETECTED_CODE_KEY, DETECTED_CODE_KEY),\n        (SPEED_KEY_IN_INFERENCE_RESPONSE, SPEED_KEY_IN_SV_DETECTIONS),\n        (SMOOTHED_SPEED_KEY_IN_INFERENCE_RESPONSE, SMOOTHED_SPEED_KEY_IN_SV_DETECTIONS),\n        (\n            SMOOTHED_VELOCITY_KEY_IN_INFERENCE_RESPONSE,\n            SMOOTHED_VELOCITY_KEY_IN_SV_DETECTIONS,\n        ),\n        (VELOCITY_KEY_IN_INFERENCE_RESPONSE, VELOCITY_KEY_IN_SV_DETECTIONS),\n        (AREA_KEY_IN_INFERENCE_RESPONSE, AREA_KEY_IN_SV_DETECTIONS),\n        (AREA_CONVERTED_KEY_IN_INFERENCE_RESPONSE, AREA_CONVERTED_KEY_IN_SV_DETECTIONS),\n    ]\n    for raw_detection_key, parsed_detection_key in optional_elements_keys:\n        parsed_detections = _attach_optional_detection_element(\n            raw_detections=raw_predictions,\n            parsed_detections=parsed_detections,\n            raw_detection_key=raw_detection_key,\n            parsed_detection_key=parsed_detection_key,\n        )\n    return _attach_optional_key_points_detections(\n        raw_detections=raw_predictions,\n        parsed_detections=parsed_detections,\n    )\n\n\ndef deserialize_rle_detections_kind(\n    parameter: str,\n    detections: Any,\n) -> sv.Detections:\n    parsed_detections = deserialize_detections_kind(\n        parameter=parameter,\n        detections=detections,\n    )\n    if len(parsed_detections) == 0:\n        return parsed_detections\n\n    if isinstance(detections, dict) and \"predictions\" in detections:\n        rle_masks_list = []\n        for pred in detections[\"predictions\"]:\n            rle = pred.get(RLE_MASK_KEY_IN_INFERENCE_RESPONSE)\n            if rle is not None:\n                rle_masks_list.append(rle)\n\n        if rle_masks_list and len(rle_masks_list) == len(parsed_detections):\n            parsed_detections[RLE_MASK_KEY_IN_SV_DETECTIONS] = np.array(\n                rle_masks_list, dtype=object\n            )\n\n    return parsed_detections\n\n\ndef _attach_parent_coordinates_and_dimensions(\n    parameter: str,\n    raw_detections: List[dict],\n    parsed_detections: sv.Detections,\n    origin_key: str,\n    coordinates_key: str,\n    dimensions_key: str,\n) -> None:\n    coordinates = []\n    dimensions = []\n    for detection in raw_detections:\n        parent_origin = detection.get(origin_key)\n        if parent_origin:\n            parsed_origin = deserialize_parent_origin(parameter, parent_origin)\n            coordinates.append([parsed_origin.offset_x, parsed_origin.offset_y])\n            dimensions.append([parsed_origin.height, parsed_origin.width])\n        else:\n            return\n    if coordinates and dimensions:\n        parsed_detections.data[coordinates_key] = np.array(coordinates)\n        parsed_detections.data[dimensions_key] = np.array(dimensions)\n\n\ndef _attach_optional_detection_element(\n    raw_detections: List[dict],\n    parsed_detections: sv.Detections,\n    raw_detection_key: str,\n    parsed_detection_key: str,\n) -> sv.Detections:\n    if raw_detection_key not in raw_detections[0]:\n        return parsed_detections\n    result = []\n    for detection in raw_detections:\n        result.append(detection[raw_detection_key])\n    parsed_detections.data[parsed_detection_key] = np.array(result)\n    return parsed_detections\n\n\ndef _attach_optional_key_points_detections(\n    raw_detections: List[dict],\n    parsed_detections: sv.Detections,\n) -> sv.Detections:\n    if KEYPOINTS_KEY_IN_INFERENCE_RESPONSE not in raw_detections[0]:\n        return parsed_detections\n    return add_inference_keypoints_to_sv_detections(\n        inference_prediction=raw_detections,\n        detections=parsed_detections,\n    )\n\n\ndef deserialize_numpy_array(parameter: str, raw_array: Any) -> np.ndarray:\n    if isinstance(raw_array, np.ndarray):\n        return raw_array\n    if not isinstance(raw_array, list):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"numpy array value, but invalid type of data found (`{type(raw_array).__name__}`).\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    return np.array(raw_array)\n\n\ndef deserialize_optional_string_kind(parameter: str, value: Any) -> Optional[str]:\n    if value is None:\n        return None\n    return deserialize_string_kind(parameter=parameter, value=value)\n\n\ndef deserialize_string_kind(parameter: str, value: Any) -> str:\n    if not isinstance(value, str):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"string value, but invalid type of data found (`{type(value).__name__}`).\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    return value\n\n\ndef deserialize_float_zero_to_one_kind(parameter: str, value: Any) -> float:\n    value = deserialize_float_kind(parameter=parameter, value=value)\n    if not (0.0 <= value <= 1.0):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"float value in range [0.0, 1.0], but value out of range detected.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    return value\n\n\ndef deserialize_float_kind(parameter: str, value: Any) -> float:\n    if not isinstance(value, float) and not isinstance(value, int):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"float value, but invalid type of data found (`{type(value).__name__}`).\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    return float(value)\n\n\ndef deserialize_list_of_values_kind(parameter: str, value: Any) -> list:\n    if not isinstance(value, list) and not isinstance(value, tuple):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"list, but invalid type of data found (`{type(value).__name__}`).\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    if not isinstance(value, list):\n        return list(value)\n    return value\n\n\ndef deserialize_boolean_kind(parameter: str, value: Any) -> bool:\n    if not isinstance(value, bool):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"boolean value, but invalid type of data found (`{type(value).__name__}`).\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    return value\n\n\ndef deserialize_integer_kind(parameter: str, value: Any) -> int:\n    if not isinstance(value, int):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"integer value, but invalid type of data found (`{type(value).__name__}`).\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    return value\n\n\nREQUIRED_CLASSIFICATION_PREDICTION_KEYS = {\n    \"image\",\n    \"predictions\",\n}\n\n\ndef deserialize_classification_prediction_kind(parameter: str, value: Any) -> dict:\n    value = deserialize_dictionary_kind(parameter=parameter, value=value)\n    if any(k not in value for k in REQUIRED_CLASSIFICATION_PREDICTION_KEYS):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"classification prediction value, but found that one of required keys \"\n            f\"({list(REQUIRED_CLASSIFICATION_PREDICTION_KEYS)}) \"\n            f\"is missing.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    if \"predicted_classes\" not in value and (\n        \"top\" not in value or \"confidence\" not in value\n    ):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"classification prediction value, but found that passed value misses \"\n            f\"prediction details.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    if \"prediction_type\" not in value:\n        value[\"prediction_type\"] = \"classification\"\n    if \"inference_id\" not in value:\n        value[\"inference_id\"] = str(uuid4())\n    if \"parent_id\" not in value:\n        value[\"parent_id\"] = parameter\n    if \"root_parent_id\" not in value:\n        value[\"root_parent_id\"] = parameter\n    return value\n\n\ndef deserialize_dictionary_kind(parameter: str, value: Any) -> dict:\n    if not isinstance(value, dict):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"dict value, but invalid type of data found (`{type(value).__name__}`).\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    return value\n\n\ndef deserialize_point_kind(parameter: str, value: Any) -> Tuple[AnyNumber, AnyNumber]:\n    if not isinstance(value, list) and not isinstance(value, tuple):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"point coordinates, but invalid type of data found (`{type(value).__name__}`).\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    if len(value) < 2:\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"point coordinates, but missing point coordinates detected.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    value = tuple(value[:2])\n    if any(not _is_number(e) for e in value):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"point coordinates, but at least one of the coordinate is not number\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    return value\n\n\ndef deserialize_zone_kind(\n    parameter: str, value: Any\n) -> List[List[Tuple[AnyNumber, AnyNumber]]]:\n    if not isinstance(value, list) or len(value) < 3:\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"zone coordinates, but defined zone is not a list with at least 3 points coordinates.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    if any(\n        (not isinstance(e, list) and not isinstance(e, tuple)) or len(e) != 2\n        for e in value\n    ):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"zone coordinates, but defined zone contains at least one element which is not a point with\"\n            f\"exactly two coordinates (x, y).\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    if any(not _is_number(e[0]) or not _is_number(e[1]) for e in value):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"zone coordinates, but defined zone contains at least one element which is not a point with\"\n            f\"exactly two coordinates (x, y) being numbers.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    return value\n\n\ndef deserialize_rgb_color_kind(\n    parameter: str, value: Any\n) -> Union[Tuple[int, int, int], str]:\n    if (\n        not isinstance(value, list)\n        and not isinstance(value, tuple)\n        and not isinstance(value, str)\n    ):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"RGB color, but invalid type of data found (`{type(value).__name__}`).\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    if isinstance(value, str):\n        return value\n    if len(value) < 3:\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"RGB color, but not all colors defined.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    return tuple(value[:3])\n\n\ndef deserialize_bytes_kind(parameter: str, value: Any) -> bytes:\n    if not isinstance(value, str) and not isinstance(value, bytes):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"bytes string, but invalid type of data found (`{type(value).__name__}`).\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    if isinstance(value, bytes):\n        return value\n    return pybase64.b64decode(value)\n\n\ndef deserialize_timestamp(parameter: str, value: Any) -> datetime:\n    if isinstance(value, datetime):\n        return value\n    if not isinstance(value, str):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"datetime, but invalid type of data found (`{type(value).__name__}`).\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    try:\n        return datetime.fromisoformat(value)\n    except Exception as error:\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"datetime, but could not decode input data: {error}.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        ) from error\n\n\ndef _is_number(value: Any) -> bool:\n    return isinstance(value, int) or isinstance(value, float)\n",
    "patch": null
  },
  {
    "trace_id": "70a9f585-bb0f-411b-8de4-f78fa99a86b3",
    "function_name": "_prepare_workflow_response_cache_key",
    "file_path": "inference/core/roboflow_api.py",
    "speedup_x": 1.3872049562758035,
    "review_quality": "high",
    "pre_optimization_commit": "c0839e1361a6223eb15b804626afc5de2d15dab5",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def _prepare_workflow_response_cache_key(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> str:\n    api_key_hash = (\n        hashlib.md5(api_key.encode(\"utf-8\")).hexdigest()\n        if api_key is not None\n        else \"None\"\n    )\n    workflow_version_suffix = (\n        f\":workflow_version={workflow_version_id}\" if workflow_version_id else \"\"\n    )\n    return f\"workflow_definition:{workspace_id}:{workflow_id}{workflow_version_suffix}:{api_key_hash}\"\n",
    "optimized_function_code": "import hashlib\nfrom functools import lru_cache\nfrom typing import Optional\n\nfrom inference.core.entities.types import WorkspaceID\n\n\n@lru_cache(maxsize=2048)\ndef _cached_api_key_hash(api_key: Optional[str]) -> str:\n    if api_key is None:\n        return \"None\"\n    return hashlib.md5(api_key.encode(\"utf-8\")).hexdigest()\n\ndef _prepare_workflow_response_cache_key(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> str:\n    api_key_hash = _cached_api_key_hash(api_key)\n    workflow_version_suffix = (\n        f\":workflow_version={workflow_version_id}\" if workflow_version_id else \"\"\n    )\n    return f\"workflow_definition:{workspace_id}:{workflow_id}{workflow_version_suffix}:{api_key_hash}\"",
    "optimized_raw_markdown": "```python:inference/core/roboflow_api.py\nimport hashlib\nfrom functools import lru_cache\nfrom typing import Optional\n\nfrom inference.core.entities.types import WorkspaceID\n\n\n@lru_cache(maxsize=2048)\ndef _cached_api_key_hash(api_key: Optional[str]) -> str:\n    if api_key is None:\n        return \"None\"\n    return hashlib.md5(api_key.encode(\"utf-8\")).hexdigest()\n\ndef _prepare_workflow_response_cache_key(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> str:\n    api_key_hash = _cached_api_key_hash(api_key)\n    workflow_version_suffix = (\n        f\":workflow_version={workflow_version_id}\" if workflow_version_id else \"\"\n    )\n    return f\"workflow_definition:{workspace_id}:{workflow_id}{workflow_version_suffix}:{api_key_hash}\"\n```",
    "optimized_function_only": "def _prepare_workflow_response_cache_key(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> str:\n    api_key_hash = _cached_api_key_hash(api_key)\n    workflow_version_suffix = (\n        f\":workflow_version={workflow_version_id}\" if workflow_version_id else \"\"\n    )\n    return f\"workflow_definition:{workspace_id}:{workflow_id}{workflow_version_suffix}:{api_key_hash}\"",
    "original_file_content": "import asyncio\nimport base64\nimport binascii\nimport hashlib\nimport json\nimport os\nimport re\nimport urllib.parse\nfrom enum import Enum\nfrom hashlib import sha256\nfrom json import JSONDecodeError\nfrom pathlib import Path\nfrom typing import Any, Callable, Dict, List, Optional, Tuple, Type, Union\n\nimport aiohttp\nimport backoff\nimport requests\nfrom cachetools.func import ttl_cache\nfrom requests import Response, Timeout\nfrom requests_toolbelt import MultipartEncoder\n\nfrom inference.core import logger\nfrom inference.core.cache import cache\nfrom inference.core.cache.base import BaseCache\nfrom inference.core.cache.model_artifacts import get_cache_dir, initialise_cache\nfrom inference.core.entities.types import (\n    DatasetID,\n    ModelID,\n    ModelType,\n    TaskType,\n    VersionID,\n    WorkspaceID,\n)\nfrom inference.core.env import (\n    API_BASE_URL,\n    ENFORCE_CREDITS_VERIFICATION,\n    GCP_SERVERLESS,\n    INTERNAL_WEIGHTS_URL_SUFFIX,\n    MD5_VERIFICATION_ENABLED,\n    MODEL_CACHE_DIR,\n    MODELS_CACHE_AUTH_CACHE_MAX_SIZE,\n    MODELS_CACHE_AUTH_CACHE_TTL,\n    MODELS_CACHE_AUTH_ENABLED,\n    RETRY_CONNECTION_ERRORS_TO_ROBOFLOW_API,\n    ROBOFLOW_API_EXTRA_HEADERS,\n    ROBOFLOW_API_REQUEST_TIMEOUT,\n    ROBOFLOW_API_VERIFY_SSL,\n    ROBOFLOW_SERVICE_SECRET,\n    TRANSIENT_ROBOFLOW_API_ERRORS,\n    TRANSIENT_ROBOFLOW_API_ERRORS_RETRIES,\n    TRANSIENT_ROBOFLOW_API_ERRORS_RETRY_INTERVAL,\n    USE_FILE_CACHE_FOR_WORKFLOWS_DEFINITIONS,\n    WORKFLOWS_DEFINITION_CACHE_EXPIRY,\n)\nfrom inference.core.exceptions import (\n    MalformedRoboflowAPIResponseError,\n    MalformedWorkflowResponseError,\n    MissingDefaultModelError,\n    RetryRequestError,\n    RoboflowAPIConnectionError,\n    RoboflowAPIForbiddenError,\n    RoboflowAPIIAlreadyAnnotatedError,\n    RoboflowAPIIAnnotationRejectionError,\n    RoboflowAPIImageUploadRejectionError,\n    RoboflowAPINotAuthorizedError,\n    RoboflowAPINotNotFoundError,\n    RoboflowAPITimeoutError,\n    RoboflowAPIUnsuccessfulRequestError,\n    WorkspaceLoadError,\n)\nfrom inference.core.utils.file_system import sanitize_path_segment\nfrom inference.core.utils.requests import (\n    api_key_safe_raise_for_status,\n    api_key_safe_raise_for_status_aiohttp,\n)\nfrom inference.core.utils.url_utils import wrap_url\nfrom inference.core.version import __version__\n\nENFORCE_CREDITS_VERIFICATION_HEADER = \"x-enforce-credits-verification\"\nENFORCE_INTERNAL_ARTIFACTS_URLS_HEADER = \"x-enforce-internal-artefacts-urls\"\n\nMODEL_TYPE_DEFAULTS = {\n    \"object-detection\": \"yolov5v2s\",\n    \"instance-segmentation\": \"yolact\",\n    \"classification\": \"vit\",\n    \"keypoint-detection\": \"yolov8n\",\n}\nPROJECT_TASK_TYPE_KEY = \"project_task_type\"\nMODEL_TYPE_KEY = \"model_type\"\n\nNOT_FOUND_ERROR_MESSAGE = (\n    \"Could not find requested Roboflow resource. Check that the provided dataset and \"\n    \"version are correct, and check that the provided Roboflow API key has the correct permissions.\"\n)\n\nROBOFLOW_INFERENCE_VERSION_HEADER = \"X-Roboflow-Inference-Version\"\nALLOW_CHUNKED_RESPONSE_HEADER = \"X-Allow-Chunked\"\n\n\ndef raise_from_lambda(\n    inner_error: Exception, exception_type: Type[Exception], message: str\n) -> None:\n    raise exception_type(message) from inner_error\n\n\nDEFAULT_ERROR_HANDLERS = {\n    401: lambda e: raise_from_lambda(\n        e,\n        RoboflowAPINotAuthorizedError,\n        \"Unauthorized access to roboflow API - check API key. Visit \"\n        \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve one.\",\n    ),\n    403: lambda e: raise_from_lambda(\n        e,\n        RoboflowAPIForbiddenError,\n        \"Unauthorized access to roboflow API - check API key regarding correctness and required scopes. Visit \"\n        \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve one.\",\n    ),\n    404: lambda e: raise_from_lambda(\n        e, RoboflowAPINotNotFoundError, NOT_FOUND_ERROR_MESSAGE\n    ),\n}\n\n\ndef wrap_roboflow_api_errors(\n    http_errors_handlers: Optional[\n        Dict[int, Callable[[Union[requests.exceptions.HTTPError]], None]]\n    ] = None,\n) -> callable:\n    def decorator(function: callable) -> callable:\n        def wrapper(*args, **kwargs) -> Any:\n            try:\n                try:\n                    return function(*args, **kwargs)\n                except RetryRequestError as error:\n                    raise error.inner_error\n            except Timeout as error:\n                raise RoboflowAPITimeoutError(\n                    \"Timeout when attempting to connect to Roboflow API.\"\n                ) from error\n            except (requests.exceptions.ConnectionError, ConnectionError) as error:\n                raise RoboflowAPIConnectionError(\n                    \"Could not connect to Roboflow API.\"\n                ) from error\n            except requests.exceptions.HTTPError as error:\n                user_handler_override = (\n                    http_errors_handlers if http_errors_handlers is not None else {}\n                )\n                status_code = error.response.status_code\n                default_handler = DEFAULT_ERROR_HANDLERS.get(status_code)\n                error_handler = user_handler_override.get(status_code, default_handler)\n                if error_handler is not None:\n                    error_handler(error)\n                raise RoboflowAPIUnsuccessfulRequestError(\n                    f\"Unsuccessful request to Roboflow API with response code: {status_code}\"\n                ) from error\n            except requests.exceptions.InvalidJSONError as error:\n                raise MalformedRoboflowAPIResponseError(\n                    \"Could not decode JSON response from Roboflow API.\"\n                ) from error\n\n        return wrapper\n\n    return decorator\n\n\ndef wrap_roboflow_api_errors_async(\n    http_errors_handlers: Optional[\n        Dict[int, Callable[[Union[aiohttp.ClientError]], None]]\n    ] = None,\n) -> callable:\n    def decorator(function: callable) -> callable:\n        async def wrapper(*args, **kwargs) -> Any:\n            try:\n                try:\n                    return await function(*args, **kwargs)\n                except RetryRequestError as error:\n                    raise error.inner_error\n            except asyncio.TimeoutError as error:\n                raise RoboflowAPITimeoutError(\n                    \"Timeout when attempting to connect to Roboflow API.\"\n                ) from error\n            except (aiohttp.ClientConnectionError, ConnectionError) as error:\n                raise RoboflowAPIConnectionError(\n                    \"Could not connect to Roboflow API.\"\n                ) from error\n            except (aiohttp.ContentTypeError, JSONDecodeError) as error:\n                raise MalformedRoboflowAPIResponseError(\n                    \"Could not decode JSON response from Roboflow API.\"\n                ) from error\n            except aiohttp.ClientResponseError as error:\n                user_handler_override = (\n                    http_errors_handlers if http_errors_handlers is not None else {}\n                )\n                status_code = error.status\n                default_handler = DEFAULT_ERROR_HANDLERS.get(status_code)\n                error_handler = user_handler_override.get(status_code, default_handler)\n                if error_handler is not None:\n                    error_handler(error)\n                raise RoboflowAPIUnsuccessfulRequestError(\n                    f\"Unsuccessful request to Roboflow API with response code: {status_code}\"\n                ) from error\n            # remaining aiohttp.ClientError seems to qualify to simply pass-through raise, as\n            # this seems to be adequate to trigger HTTP 500 upstream or let final client to handle\n            # such cases like invalid pattern of API_BASE_URL (as we are setting it correctly)\n\n        return wrapper\n\n    return decorator\n\n\n@ttl_cache(ttl=MODELS_CACHE_AUTH_CACHE_TTL, maxsize=MODELS_CACHE_AUTH_CACHE_MAX_SIZE)\n@wrap_roboflow_api_errors()\ndef get_roboflow_workspace(api_key: str) -> WorkspaceID:\n    if not api_key:\n        raise WorkspaceLoadError(\"Empty workspace encountered, check your API key.\")\n\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/\",\n        params=[(\"api_key\", api_key), (\"nocache\", \"true\")],\n    )\n    api_key_info = _get_from_url(url=api_url)\n    workspace_id = api_key_info.get(\"workspace\")\n    if workspace_id is None:\n        raise WorkspaceLoadError(\"Empty workspace encountered, check your API key.\")\n    return workspace_id\n\n\n@wrap_roboflow_api_errors_async()\n@backoff.on_exception(\n    backoff.constant,\n    exception=RetryRequestError,\n    max_tries=TRANSIENT_ROBOFLOW_API_ERRORS_RETRIES,\n    interval=TRANSIENT_ROBOFLOW_API_ERRORS_RETRY_INTERVAL,\n)\nasync def get_roboflow_workspace_async(api_key: str) -> WorkspaceID:\n    try:\n        headers = build_roboflow_api_headers()\n        async with aiohttp.ClientSession() as session:\n            async with session.get(\n                f\"{API_BASE_URL}/\",\n                params={\"api_key\": api_key, \"nocache\": \"true\"},\n                headers=headers,\n                timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n            ) as response:\n                try:\n                    api_key_safe_raise_for_status_aiohttp(response=response)\n                except Exception as error:\n                    if response.status in TRANSIENT_ROBOFLOW_API_ERRORS:\n                        raise RetryRequestError(\n                            message=str(error), inner_error=error\n                        ) from error\n                    raise error\n                response_payload = await response.json()\n                workspace_id = response_payload.get(\"workspace\")\n                if workspace_id is None:\n                    raise WorkspaceLoadError(\n                        \"Empty workspace encountered, check your API key.\"\n                    )\n                return workspace_id\n    except (aiohttp.ClientConnectionError, ConnectionError) as error:\n        if RETRY_CONNECTION_ERRORS_TO_ROBOFLOW_API:\n            raise RetryRequestError(\n                message=\"Connectivity error\", inner_error=error\n            ) from error\n        raise error\n\n\n@wrap_roboflow_api_errors()\ndef add_custom_metadata(\n    api_key: str,\n    workspace_id: WorkspaceID,\n    inference_ids: List[str],\n    field_name: str,\n    field_value: str,\n):\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/inference-stats/metadata\",\n        params=[(\"api_key\", api_key), (\"nocache\", \"true\")],\n    )\n    response = requests.post(\n        url=api_url,\n        json={\n            \"data\": [\n                {\n                    \"inference_ids\": inference_ids,\n                    \"field_name\": field_name,\n                    \"field_value\": field_value,\n                }\n            ]\n        },\n        headers=build_roboflow_api_headers(),\n        timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n        verify=ROBOFLOW_API_VERIFY_SSL,\n    )\n    api_key_safe_raise_for_status(response=response)\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_dataset_type(\n    api_key: str, workspace_id: WorkspaceID, dataset_id: DatasetID\n) -> TaskType:\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/{dataset_id}\",\n        params=[(\"api_key\", api_key), (\"nocache\", \"true\")],\n    )\n    dataset_info = _get_from_url(url=api_url)\n    project_task_type = dataset_info.get(\"project\", {})\n    if \"type\" not in project_task_type:\n        logger.warning(\n            f\"Project task type not defined for workspace={workspace_id} and dataset={dataset_id}, defaulting \"\n            f\"to object-detection.\"\n        )\n    return project_task_type.get(\"type\", \"object-detection\")\n\n\n@wrap_roboflow_api_errors(\n    http_errors_handlers={\n        500: lambda e: raise_from_lambda(\n            e, RoboflowAPINotNotFoundError, NOT_FOUND_ERROR_MESSAGE\n        )\n        # this is temporary solution, empirically checked that backend API responds HTTP 500 on incorrect version.\n        # TO BE FIXED at backend, otherwise this error handling may overshadow existing backend problems.\n    }\n)\ndef get_roboflow_model_type(\n    api_key: str,\n    workspace_id: WorkspaceID,\n    dataset_id: DatasetID,\n    version_id: VersionID,\n    project_task_type: ModelType,\n) -> ModelType:\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/{dataset_id}/{version_id}\",\n        params=[(\"api_key\", api_key), (\"nocache\", \"true\")],\n    )\n    version_info = _get_from_url(url=api_url)\n    model_type = version_info[\"version\"]\n    if \"modelType\" not in model_type:\n        if project_task_type not in MODEL_TYPE_DEFAULTS:\n            raise MissingDefaultModelError(\n                f\"Could not set default model for {project_task_type}\"\n            )\n        logger.warning(\n            f\"Model type not defined - using default for {project_task_type} task.\"\n        )\n    return model_type.get(\"modelType\", MODEL_TYPE_DEFAULTS[project_task_type])\n\n\nclass ModelEndpointType(Enum):\n    ORT = \"ort\"\n    CORE_MODEL = \"core_model\"\n    OWLV2 = \"owlv2\"\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_model_data(\n    api_key: str,\n    model_id: str,\n    endpoint_type: ModelEndpointType,\n    device_id: str,\n    countinference: Optional[bool] = None,\n    service_secret: Optional[str] = None,\n) -> dict:\n    api_data_cache_key = f\"roboflow_api_data:{endpoint_type.value}:{model_id}\"\n    api_data = None\n    if not MODELS_CACHE_AUTH_ENABLED:\n        api_data = cache.get(api_data_cache_key)\n    if api_data is not None:\n        logger.debug(f\"Loaded model data from cache with key: {api_data_cache_key}.\")\n        return api_data\n    else:\n        params = [\n            (\"nocache\", \"true\"),\n            (\"device\", device_id),\n            (\"dynamic\", \"true\"),\n        ]\n        if api_key is not None:\n            params.append((\"api_key\", api_key))\n\n        if (\n            INTERNAL_WEIGHTS_URL_SUFFIX == \"serverless\"\n            and countinference is False\n            and service_secret == ROBOFLOW_SERVICE_SECRET\n        ):\n            params.append((\"countinference\", str(countinference).lower()))\n            params.append((\"service_secret\", service_secret))\n\n        api_base_url = urllib.parse.urljoin(API_BASE_URL, INTERNAL_WEIGHTS_URL_SUFFIX)\n        api_url = _add_params_to_url(\n            url=f\"{api_base_url}/{endpoint_type.value}/{model_id}\",\n            params=params,\n        )\n        api_data = _get_from_url(url=api_url)\n        cache.set(\n            api_data_cache_key,\n            api_data,\n            expire=10,\n        )\n        logger.debug(\n            f\"Loaded model data from Roboflow API and saved to cache with key: {api_data_cache_key}.\"\n        )\n        return api_data\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_instant_model_data(\n    api_key: str,\n    model_id: ModelID,\n    cache_prefix: str = \"roboflow_api_data\",\n    countinference: Optional[bool] = None,\n    service_secret: Optional[str] = None,\n) -> dict:\n    api_data_cache_key = f\"{cache_prefix}:{model_id}\"\n    api_data = None\n    if not MODELS_CACHE_AUTH_ENABLED:\n        api_data = cache.get(api_data_cache_key)\n    if api_data is not None:\n        logger.debug(f\"Loaded model data from cache with key: {api_data_cache_key}.\")\n        return api_data\n    else:\n        params = [\n            (\"model\", model_id),\n        ]\n        if api_key is not None:\n            params.append((\"api_key\", api_key))\n\n        if (\n            INTERNAL_WEIGHTS_URL_SUFFIX == \"serverless\"\n            and countinference is False\n            and service_secret == ROBOFLOW_SERVICE_SECRET\n        ):\n            params.append((\"countinference\", str(countinference).lower()))\n            params.append((\"service_secret\", service_secret))\n\n        api_base_url = urllib.parse.urljoin(API_BASE_URL, INTERNAL_WEIGHTS_URL_SUFFIX)\n        api_url = _add_params_to_url(\n            url=f\"{api_base_url}/getWeights\",\n            params=params,\n        )\n        api_data = _get_from_url(url=api_url)\n        cache.set(\n            api_data_cache_key,\n            api_data,\n            expire=10,\n        )\n        logger.debug(\n            f\"Loaded model data from Roboflow API and saved to cache with key: {api_data_cache_key}.\"\n        )\n        return api_data\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_base_lora(\n    api_key: str, repo: str, revision: str, device_id: str\n) -> dict:\n    full_path = f\"{repo.strip('/')}/{revision.strip('/')}\"\n    api_data_cache_key = f\"roboflow_api_data:lora-bases:{full_path}\"\n    api_data = None\n    if not MODELS_CACHE_AUTH_ENABLED:\n        api_data = cache.get(api_data_cache_key)\n    if api_data is not None:\n        logger.debug(f\"Loaded model data from cache with key: {api_data_cache_key}.\")\n        return api_data\n    else:\n        params = [\n            (\"nocache\", \"true\"),\n            (\"device\", device_id),\n            (\"repoAndRevision\", full_path),\n        ]\n        if api_key is not None:\n            params.append((\"api_key\", api_key))\n        api_url = _add_params_to_url(\n            url=f\"{API_BASE_URL}/lora_bases\",\n            params=params,\n        )\n        api_data = _get_from_url(url=api_url)\n        cache.set(\n            api_data_cache_key,\n            api_data,\n            expire=10,\n        )\n        logger.debug(\n            f\"Loaded lora base model data from Roboflow API and saved to cache with key: {api_data_cache_key}.\"\n        )\n        return api_data\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_active_learning_configuration(\n    api_key: str,\n    workspace_id: WorkspaceID,\n    dataset_id: DatasetID,\n) -> dict:\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/{dataset_id}/active_learning\",\n        params=[(\"api_key\", api_key)],\n    )\n    return _get_from_url(url=api_url)\n\n\n@wrap_roboflow_api_errors()\ndef register_image_at_roboflow(\n    api_key: str,\n    dataset_id: DatasetID,\n    local_image_id: str,\n    image_bytes: bytes,\n    batch_name: str,\n    tags: Optional[List[str]] = None,\n    inference_id: Optional[str] = None,\n) -> dict:\n    url = f\"{API_BASE_URL}/dataset/{dataset_id}/upload\"\n    params = [\n        (\"api_key\", api_key),\n        (\"batch\", batch_name),\n    ]\n    if inference_id is not None:\n        params.append((\"inference_id\", inference_id))\n    tags = tags if tags is not None else []\n    for tag in tags:\n        params.append((\"tag\", tag))\n    wrapped_url = wrap_url(_add_params_to_url(url=url, params=params))\n    m = MultipartEncoder(\n        fields={\n            \"name\": f\"{local_image_id}.jpg\",\n            \"file\": (\"imageToUpload\", image_bytes, \"image/jpeg\"),\n        }\n    )\n    headers = build_roboflow_api_headers(\n        explicit_headers={\"Content-Type\": m.content_type},\n    )\n    response = requests.post(\n        url=wrapped_url,\n        data=m,\n        headers=headers,\n        timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n        verify=ROBOFLOW_API_VERIFY_SSL,\n    )\n    api_key_safe_raise_for_status(response=response)\n    parsed_response = response.json()\n    if not parsed_response.get(\"duplicate\") and not parsed_response.get(\"success\"):\n        raise RoboflowAPIImageUploadRejectionError(\n            f\"Server rejected image: {parsed_response}\"\n        )\n    return parsed_response\n\n\n@wrap_roboflow_api_errors(\n    http_errors_handlers={\n        409: lambda e: raise_from_lambda(\n            e,\n            RoboflowAPIIAlreadyAnnotatedError,\n            \"Given datapoint already has annotation.\",\n        )\n    }\n)\ndef annotate_image_at_roboflow(\n    api_key: str,\n    dataset_id: DatasetID,\n    local_image_id: str,\n    roboflow_image_id: str,\n    annotation_content: str,\n    annotation_file_type: str,\n    is_prediction: bool = True,\n) -> dict:\n    url = f\"{API_BASE_URL}/dataset/{dataset_id}/annotate/{roboflow_image_id}\"\n    params = [\n        (\"api_key\", api_key),\n        (\"name\", f\"{local_image_id}.{annotation_file_type}\"),\n        (\"prediction\", str(is_prediction).lower()),\n    ]\n    wrapped_url = wrap_url(_add_params_to_url(url=url, params=params))\n    headers = build_roboflow_api_headers(\n        explicit_headers={\"Content-Type\": \"text/plain\"},\n    )\n    response = requests.post(\n        wrapped_url,\n        data=annotation_content,\n        headers=headers,\n        timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n        verify=ROBOFLOW_API_VERIFY_SSL,\n    )\n    api_key_safe_raise_for_status(response=response)\n    parsed_response = response.json()\n    if \"error\" in parsed_response or not parsed_response.get(\"success\"):\n        raise RoboflowAPIIAnnotationRejectionError(\n            f\"Failed to save annotation for {roboflow_image_id}. API response: {parsed_response}\"\n        )\n    return parsed_response\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_labeling_batches(\n    api_key: str, workspace_id: WorkspaceID, dataset_id: str\n) -> dict:\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/{dataset_id}/batches\",\n        params=[(\"api_key\", api_key)],\n    )\n    return _get_from_url(url=api_url)\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_labeling_jobs(\n    api_key: str, workspace_id: WorkspaceID, dataset_id: str\n) -> dict:\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/{dataset_id}/jobs\",\n        params=[(\"api_key\", api_key)],\n    )\n    return _get_from_url(url=api_url)\n\n\ndef get_workflow_cache_file(\n    workspace_id: WorkspaceID, workflow_id: str, api_key: Optional[str]\n) -> str:\n    sanitized_workspace_id = sanitize_path_segment(workspace_id)\n    sanitized_workflow_id = sanitize_path_segment(workflow_id)\n    api_key_hash = (\n        hashlib.md5(api_key.encode(\"utf-8\")).hexdigest()\n        if api_key is not None\n        else \"None\"\n    )\n    prefix = os.path.abspath(os.path.join(MODEL_CACHE_DIR, \"workflow\"))\n    result = os.path.abspath(\n        os.path.join(\n            prefix,\n            sanitized_workspace_id,\n            f\"{sanitized_workflow_id}_{api_key_hash}.json\",\n        )\n    )\n    if not result.startswith(prefix):\n        raise ValueError(\n            \"Detected attempt to save workflow definition in insecure location\"\n        )\n    return result\n\n\ndef cache_workflow_response(\n    workspace_id: WorkspaceID, workflow_id: str, api_key: Optional[str], response: dict\n):\n    workflow_cache_file = get_workflow_cache_file(\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        api_key=api_key,\n    )\n    workflow_cache_dir = os.path.dirname(workflow_cache_file)\n    if not os.path.exists(workflow_cache_dir):\n        os.makedirs(workflow_cache_dir, exist_ok=True)\n    with open(workflow_cache_file, \"w\") as f:\n        json.dump(response, f)\n\n\ndef delete_cached_workflow_response_if_exists(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n) -> None:\n    workflow_cache_file = get_workflow_cache_file(\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        api_key=api_key,\n    )\n    if os.path.exists(workflow_cache_file):\n        os.remove(workflow_cache_file)\n\n\ndef load_cached_workflow_response(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n) -> Optional[dict]:\n    workflow_cache_file = get_workflow_cache_file(\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        api_key=api_key,\n    )\n    if not os.path.exists(workflow_cache_file):\n        return None\n    try:\n        with open(workflow_cache_file, \"r\") as f:\n            return json.load(f)\n    except Exception:\n        delete_cached_workflow_response_if_exists(\n            workspace_id=workspace_id,\n            workflow_id=workflow_id,\n            api_key=api_key,\n        )\n\n\n@wrap_roboflow_api_errors()\ndef get_workflow_specification(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    use_cache: bool = True,\n    ephemeral_cache: Optional[BaseCache] = None,\n    workflow_version_id: Optional[str] = None,\n) -> dict:\n    ephemeral_cache = ephemeral_cache or cache\n    if use_cache:\n        cached_entry = _retrieve_workflow_specification_from_ephemeral_cache(\n            api_key=api_key,\n            workspace_id=workspace_id,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n            ephemeral_cache=ephemeral_cache,\n        )\n        if cached_entry:\n            return cached_entry\n\n    if workspace_id == \"local\":\n        if not re.match(r\"^[\\w\\-]+$\", workflow_id):\n            raise ValueError(\"Invalid workflow id\")\n\n        workflow_hash = sha256(workflow_id.encode()).hexdigest()\n        local_file_path = (\n            Path(MODEL_CACHE_DIR) / \"workflow\" / \"local\" / f\"{workflow_hash}.json\"\n        )\n        if not local_file_path.exists():\n            raise FileNotFoundError(f\"Local workflow file not found: {local_file_path}\")\n\n        with local_file_path.open(\"r\", encoding=\"utf-8\") as f:\n            local_config = json.load(f)\n\n        # Mimic the same shape as the cloud response:\n        response = {\"workflow\": local_config}\n    else:\n        params = []\n        if api_key is not None:\n            params.append((\"api_key\", api_key))\n        if workflow_version_id is not None:\n            params.append((\"workflow_version\", workflow_version_id))\n        api_url = _add_params_to_url(\n            url=f\"{API_BASE_URL}/{workspace_id}/workflows/{workflow_id}\",\n            params=params,\n        )\n        try:\n            response = _get_from_url(url=api_url)\n            if USE_FILE_CACHE_FOR_WORKFLOWS_DEFINITIONS:\n                cache_workflow_response(\n                    workspace_id=workspace_id,\n                    workflow_id=workflow_id,\n                    api_key=api_key,\n                    response=response,\n                )\n        except (requests.exceptions.ConnectionError, ConnectionError) as error:\n            if not USE_FILE_CACHE_FOR_WORKFLOWS_DEFINITIONS:\n                raise error\n            response = load_cached_workflow_response(\n                workspace_id=workspace_id,\n                workflow_id=workflow_id,\n                api_key=api_key,\n            )\n            if response is None:\n                raise error\n\n    if \"workflow\" not in response or \"config\" not in response[\"workflow\"]:\n        raise MalformedWorkflowResponseError(\n            \"Could not find workflow specification in API response\"\n        )\n    try:\n        workflow_config = json.loads(response[\"workflow\"][\"config\"])\n        specification = workflow_config[\"specification\"]\n        if isinstance(specification, dict):\n            specification[\"id\"] = response[\"workflow\"].get(\"id\")\n        if use_cache:\n            _cache_workflow_specification_in_ephemeral_cache(\n                api_key=api_key,\n                workspace_id=workspace_id,\n                workflow_id=workflow_id,\n                workflow_version_id=workflow_version_id,\n                specification=specification,\n                ephemeral_cache=ephemeral_cache,\n            )\n        return specification\n    except KeyError as error:\n        raise MalformedWorkflowResponseError(\n            \"Workflow specification not found in Roboflow API response\"\n        ) from error\n    except (ValueError, TypeError) as error:\n        raise MalformedWorkflowResponseError(\n            \"Could not decode workflow specification in Roboflow API response\"\n        ) from error\n\n\ndef _retrieve_workflow_specification_from_ephemeral_cache(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    ephemeral_cache: BaseCache,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[dict]:\n    cache_key = _prepare_workflow_response_cache_key(\n        api_key=api_key,\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        workflow_version_id=workflow_version_id,\n    )\n    return ephemeral_cache.get(key=cache_key)\n\n\ndef _cache_workflow_specification_in_ephemeral_cache(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    specification: dict,\n    ephemeral_cache: BaseCache,\n    workflow_version_id: Optional[str] = None,\n) -> None:\n    cache_key = _prepare_workflow_response_cache_key(\n        api_key=api_key,\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        workflow_version_id=workflow_version_id,\n    )\n    ephemeral_cache.set(\n        key=cache_key,\n        value=specification,\n        expire=WORKFLOWS_DEFINITION_CACHE_EXPIRY,\n    )\n\n\ndef _prepare_workflow_response_cache_key(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> str:\n    api_key_hash = (\n        hashlib.md5(api_key.encode(\"utf-8\")).hexdigest()\n        if api_key is not None\n        else \"None\"\n    )\n    workflow_version_suffix = (\n        f\":workflow_version={workflow_version_id}\" if workflow_version_id else \"\"\n    )\n    return f\"workflow_definition:{workspace_id}:{workflow_id}{workflow_version_suffix}:{api_key_hash}\"\n\n\n@wrap_roboflow_api_errors()\ndef get_from_url(\n    url: str,\n    json_response: bool = True,\n) -> Union[Response, dict]:\n    return _get_from_url(\n        url=url,\n        json_response=json_response,\n    )\n\n\n@backoff.on_exception(\n    backoff.constant,\n    exception=RetryRequestError,\n    max_tries=TRANSIENT_ROBOFLOW_API_ERRORS_RETRIES,\n    interval=TRANSIENT_ROBOFLOW_API_ERRORS_RETRY_INTERVAL,\n)\ndef _get_from_url(\n    url: str,\n    json_response: bool = True,\n) -> Union[Response, dict]:\n    full_url = wrap_url(url)\n    try:\n        response = requests.get(\n            full_url,\n            headers=build_roboflow_api_headers(),\n            timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n            verify=ROBOFLOW_API_VERIFY_SSL,\n        )\n\n    except (ConnectionError, Timeout, requests.exceptions.ConnectionError) as error:\n        if RETRY_CONNECTION_ERRORS_TO_ROBOFLOW_API:\n            raise RetryRequestError(\n                message=\"Connectivity error\", inner_error=error\n            ) from error\n        raise error\n    try:\n        api_key_safe_raise_for_status(response=response)\n    except Exception as error:\n        if response.status_code in TRANSIENT_ROBOFLOW_API_ERRORS:\n            raise RetryRequestError(message=str(error), inner_error=error) from error\n        raise error\n\n    if MD5_VERIFICATION_ENABLED:\n        x_goog_hash = response.headers.get(\"x-goog-hash\")\n        if x_goog_hash is None:\n            logger.warning(\n                f\"MD5 verification enabled but response missing x-goog-hash header. \"\n                f\"Request url: {_url_for_safe_logging(full_url)}\"\n            )\n        else:\n            md5_part = None\n            for part in x_goog_hash.split(\",\"):\n                if part.strip().startswith(\"md5=\"):\n                    md5_part = part.strip()[4:]\n                    break\n            if md5_part is not None:\n                try:\n                    md5_from_header = base64.b64decode(md5_part)\n                except binascii.Error as decode_error:\n                    raise RoboflowAPIUnsuccessfulRequestError(\n                        \"Invalid MD5 value in x-goog-hash header: not valid base64\"\n                    ) from decode_error\n                if md5_from_header != hashlib.md5(response.content).digest():\n                    raise RoboflowAPIUnsuccessfulRequestError(\n                        \"MD5 hash does not match MD5 received from x-goog-hash header\"\n                    )\n            else:\n                logger.warning(\n                    f\"MD5 verification enabled but x-goog-hash header has no md5= part. \"\n                    f\"Request url: {_url_for_safe_logging(full_url)}\"\n                )\n\n    if json_response:\n        return response.json()\n    return response\n\n\ndef _test_range_request(url: str, timeout: int = 10) -> bool:\n    \"\"\"Test if server actually honors range requests by making a real range GET request.\n\n    Note: We can't rely on Accept-Ranges header alone because some servers/CDNs\n    advertise range support but return 200 (full file) instead of 206 (partial).\n    \"\"\"\n    try:\n        headers = {\"Range\": \"bytes=0-0\"}\n        response = requests.get(url, headers=headers, stream=True, timeout=timeout)\n        response.close()\n        if response.status_code == 206:\n            return True\n\n        return False\n    except Exception as e:\n        logger.warning(\n            f\"Failed to test range request support: {e}. Falling back to single-threaded download.\"\n        )\n        return False\n\n\ndef stream_url_to_cache(\n    url: str,\n    filename: str,\n    model_id: str,\n) -> None:\n    from inference_models.utils.download import download_files_to_directory\n\n    initialise_cache(model_id=model_id)\n    cache_dir = get_cache_dir(model_id=model_id)\n    md5_hash = None\n\n    max_threads = 8 if _test_range_request(url) else 1\n\n    try:\n        download_files_to_directory(\n            target_dir=cache_dir,\n            files_specs=[(filename, url, md5_hash)],\n            verbose=True,\n            download_files_without_hash=True,\n            verify_hash_while_download=False,\n            max_threads_per_download=max_threads,\n        )\n    except Exception as e:\n        raise RoboflowAPIUnsuccessfulRequestError(\n            f\"Failed to download {filename}: {str(e)}\"\n        ) from e\n\n\ndef _url_for_safe_logging(url: str) -> str:\n    \"\"\"Return a URL safe to log by stripping the query string (and params/fragment).\n\n    Expects the full URL as used for the request (e.g. already wrapped).\n    Use this when logging request URLs so that sensitive query parameters\n    (e.g. api_key, tokens) are never written to logs.\n    \"\"\"\n    parsed = urllib.parse.urlparse(url)\n    return urllib.parse.urlunparse(\n        (parsed.scheme, parsed.netloc, parsed.path, \"\", \"\", \"\")\n    )\n\n\ndef _add_params_to_url(url: str, params: List[Tuple[str, str]]) -> str:\n    if len(params) == 0:\n        return url\n    params_chunks = [\n        f\"{name}={urllib.parse.quote_plus(value)}\" for name, value in params\n    ]\n    parameters_string = \"&\".join(params_chunks)\n    return f\"{url}?{parameters_string}\"\n\n\n@wrap_roboflow_api_errors()\ndef send_inference_results_to_model_monitoring(\n    api_key: str,\n    workspace_id: WorkspaceID,\n    inference_data: dict,\n):\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/inference-stats\",\n        params=[(\"api_key\", api_key)],\n    )\n    response = requests.post(\n        url=api_url,\n        json=inference_data,\n        headers=build_roboflow_api_headers(),\n        timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n        verify=ROBOFLOW_API_VERIFY_SSL,\n    )\n    api_key_safe_raise_for_status(response=response)\n\n\ndef get_extra_weights_provider_headers() -> Optional[Dict[str, str]]:\n    headers = {}\n    if GCP_SERVERLESS:\n        headers[ENFORCE_INTERNAL_ARTIFACTS_URLS_HEADER] = \"true\"\n    if ENFORCE_CREDITS_VERIFICATION:\n        headers[ENFORCE_CREDITS_VERIFICATION_HEADER] = \"true\"\n    return build_roboflow_api_headers(explicit_headers=headers)\n\n\ndef build_roboflow_api_headers(\n    explicit_headers: Optional[Dict[str, Union[str, List[str]]]] = None,\n) -> Dict[str, Union[str, List[str]]]:\n    if explicit_headers is None:\n        explicit_headers = {}\n    explicit_headers = {\n        **explicit_headers,\n        ROBOFLOW_INFERENCE_VERSION_HEADER: __version__,\n        ALLOW_CHUNKED_RESPONSE_HEADER: \"true\",\n    }\n    if not ROBOFLOW_API_EXTRA_HEADERS:\n        return explicit_headers\n    try:\n        extra_headers: dict = json.loads(ROBOFLOW_API_EXTRA_HEADERS)\n        if explicit_headers:\n            extra_headers.update(explicit_headers)\n        return extra_headers\n    except ValueError:\n        logger.warning(\"Could not decode ROBOFLOW_API_EXTRA_HEADERS\")\n        return explicit_headers\n\n\ndef post_to_roboflow_api(\n    endpoint: str,\n    api_key: Optional[str],\n    payload: Optional[dict] = None,\n    params: Optional[List[Tuple[str, str]]] = None,\n    http_errors_handlers: Optional[\n        Dict[int, Callable[[Union[requests.exceptions.HTTPError]], None]]\n    ] = None,\n) -> dict:\n    \"\"\"Generic function to make a POST request to the Roboflow API.\n\n    Args:\n        endpoint: API endpoint path\n        api_key: Roboflow API key\n        payload: JSON payload\n        params: Additional URL parameters\n        http_errors_handlers: Optional custom HTTP error handlers by status code\n    \"\"\"\n\n    @wrap_roboflow_api_errors(http_errors_handlers=http_errors_handlers)\n    def _make_request():\n        url_params = []\n        if api_key:\n            url_params.append((\"api_key\", api_key))\n        if params:\n            url_params.extend(params)\n\n        full_url = _add_params_to_url(\n            url=f\"{API_BASE_URL}/{endpoint.strip('/')}\", params=url_params\n        )\n        wrapped_url = wrap_url(full_url)\n\n        headers = build_roboflow_api_headers()\n\n        response = requests.post(\n            url=wrapped_url,\n            json=payload,\n            headers=headers,\n            timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n            verify=ROBOFLOW_API_VERIFY_SSL,\n        )\n        api_key_safe_raise_for_status(response=response)\n        return response.json()\n\n    return _make_request()\n",
    "patch": null
  },
  {
    "trace_id": "fb279f81-1aa0-4ad0-bdce-3a1fc2fad123",
    "function_name": "load_cached_workflow_response",
    "file_path": "inference/core/roboflow_api.py",
    "speedup_x": 0.38406526568340627,
    "review_quality": "high",
    "pre_optimization_commit": "7ebca7153d72dbe3d62dea55854fe932aef1bd3d",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def load_cached_workflow_response(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    workflow_version_id: Optional[str] = None,\n) -> Optional[dict]:\n    workflow_cache_file = get_workflow_cache_file(\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        api_key=api_key,\n        workflow_version_id=workflow_version_id,\n    )\n    if not os.path.exists(workflow_cache_file):\n        return None\n    try:\n        with open(workflow_cache_file, \"r\") as f:\n            return json.load(f)\n    except Exception:\n        delete_cached_workflow_response_if_exists(\n            workspace_id=workspace_id,\n            workflow_id=workflow_id,\n            api_key=api_key,\n            workflow_version_id=workflow_version_id,\n        )\n",
    "optimized_function_code": "import hashlib\nimport json\nimport os\nfrom functools import lru_cache\nfrom inference.core.entities.types import WorkspaceID\nfrom inference.core.env import MODEL_CACHE_DIR, SINGLE_TENANT_WORKFLOW_CACHE\nfrom inference.core.utils.file_system import sanitize_path_segment\nfrom typing import Optional\n\n_WORKFLOW_CACHE_PREFIX = os.path.abspath(os.path.join(MODEL_CACHE_DIR, \"workflow\"))\n_cached_sanitize_path_segment = lru_cache(maxsize=8192)(sanitize_path_segment)\n\n@lru_cache(maxsize=4096)\ndef _cached_fingerprint(cache_seed: str) -> str:\n    return hashlib.sha256(cache_seed.encode(\"utf-8\"), usedforsecurity=False).hexdigest()\n\n\n@lru_cache(maxsize=16384)\ndef get_workflow_cache_file(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    workflow_version_id: Optional[str] = None,\n) -> str:\n    sanitized_workspace_id = _cached_sanitize_path_segment(workspace_id)\n    sanitized_workflow_id = _cached_sanitize_path_segment(workflow_id)\n    if SINGLE_TENANT_WORKFLOW_CACHE:\n        version_suffix = (\n            f\"_v{_cached_sanitize_path_segment(workflow_version_id)}\"\n            if workflow_version_id\n            else \"\"\n        )\n        filename = f\"{sanitized_workflow_id}{version_suffix}.json\"\n    else:\n        cache_seed = f\"{workspace_id}:{api_key or ''}\"\n        cache_fingerprint = _cached_fingerprint(cache_seed)\n        filename = f\"{sanitized_workflow_id}_{cache_fingerprint}.json\"\n    prefix = _WORKFLOW_CACHE_PREFIX\n    result = os.path.abspath(\n        os.path.join(\n            prefix,\n            sanitized_workspace_id,\n            filename,\n        )\n    )\n    if not result.startswith(prefix):\n        raise ValueError(\n            \"Detected attempt to save workflow definition in insecure location\"\n        )\n    return result\n\n\ndef delete_cached_workflow_response_if_exists(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    workflow_version_id: Optional[str] = None,\n) -> None:\n    workflow_cache_file = get_workflow_cache_file(\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        api_key=api_key,\n        workflow_version_id=workflow_version_id,\n    )\n    if os.path.exists(workflow_cache_file):\n        os.remove(workflow_cache_file)\n\n\ndef load_cached_workflow_response(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    workflow_version_id: Optional[str] = None,\n) -> Optional[dict]:\n    workflow_cache_file = get_workflow_cache_file(\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        api_key=api_key,\n        workflow_version_id=workflow_version_id,\n    )\n    if not os.path.exists(workflow_cache_file):\n        return None\n    try:\n        with open(workflow_cache_file, \"r\") as f:\n            return json.load(f)\n    except Exception:\n        delete_cached_workflow_response_if_exists(\n            workspace_id=workspace_id,\n            workflow_id=workflow_id,\n            api_key=api_key,\n            workflow_version_id=workflow_version_id,\n        )",
    "optimized_raw_markdown": "```python:inference/core/roboflow_api.py\nimport hashlib\nimport json\nimport os\nfrom functools import lru_cache\nfrom inference.core.entities.types import WorkspaceID\nfrom inference.core.env import MODEL_CACHE_DIR, SINGLE_TENANT_WORKFLOW_CACHE\nfrom inference.core.utils.file_system import sanitize_path_segment\nfrom typing import Optional\n\n_WORKFLOW_CACHE_PREFIX = os.path.abspath(os.path.join(MODEL_CACHE_DIR, \"workflow\"))\n_cached_sanitize_path_segment = lru_cache(maxsize=8192)(sanitize_path_segment)\n\n@lru_cache(maxsize=4096)\ndef _cached_fingerprint(cache_seed: str) -> str:\n    return hashlib.sha256(cache_seed.encode(\"utf-8\"), usedforsecurity=False).hexdigest()\n\n\n@lru_cache(maxsize=16384)\ndef get_workflow_cache_file(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    workflow_version_id: Optional[str] = None,\n) -> str:\n    sanitized_workspace_id = _cached_sanitize_path_segment(workspace_id)\n    sanitized_workflow_id = _cached_sanitize_path_segment(workflow_id)\n    if SINGLE_TENANT_WORKFLOW_CACHE:\n        version_suffix = (\n            f\"_v{_cached_sanitize_path_segment(workflow_version_id)}\"\n            if workflow_version_id\n            else \"\"\n        )\n        filename = f\"{sanitized_workflow_id}{version_suffix}.json\"\n    else:\n        cache_seed = f\"{workspace_id}:{api_key or ''}\"\n        cache_fingerprint = _cached_fingerprint(cache_seed)\n        filename = f\"{sanitized_workflow_id}_{cache_fingerprint}.json\"\n    prefix = _WORKFLOW_CACHE_PREFIX\n    result = os.path.abspath(\n        os.path.join(\n            prefix,\n            sanitized_workspace_id,\n            filename,\n        )\n    )\n    if not result.startswith(prefix):\n        raise ValueError(\n            \"Detected attempt to save workflow definition in insecure location\"\n        )\n    return result\n\n\ndef delete_cached_workflow_response_if_exists(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    workflow_version_id: Optional[str] = None,\n) -> None:\n    workflow_cache_file = get_workflow_cache_file(\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        api_key=api_key,\n        workflow_version_id=workflow_version_id,\n    )\n    if os.path.exists(workflow_cache_file):\n        os.remove(workflow_cache_file)\n\n\ndef load_cached_workflow_response(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    workflow_version_id: Optional[str] = None,\n) -> Optional[dict]:\n    workflow_cache_file = get_workflow_cache_file(\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        api_key=api_key,\n        workflow_version_id=workflow_version_id,\n    )\n    if not os.path.exists(workflow_cache_file):\n        return None\n    try:\n        with open(workflow_cache_file, \"r\") as f:\n            return json.load(f)\n    except Exception:\n        delete_cached_workflow_response_if_exists(\n            workspace_id=workspace_id,\n            workflow_id=workflow_id,\n            api_key=api_key,\n            workflow_version_id=workflow_version_id,\n        )\n```",
    "optimized_function_only": "def load_cached_workflow_response(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    workflow_version_id: Optional[str] = None,\n) -> Optional[dict]:\n    workflow_cache_file = get_workflow_cache_file(\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        api_key=api_key,\n        workflow_version_id=workflow_version_id,\n    )\n    if not os.path.exists(workflow_cache_file):\n        return None\n    try:\n        with open(workflow_cache_file, \"r\") as f:\n            return json.load(f)\n    except Exception:\n        delete_cached_workflow_response_if_exists(\n            workspace_id=workspace_id,\n            workflow_id=workflow_id,\n            api_key=api_key,\n            workflow_version_id=workflow_version_id,\n        )",
    "original_file_content": "import asyncio\nimport base64\nimport binascii\nimport hashlib\nimport json\nimport os\nimport re\nimport time\nimport urllib.parse\nfrom enum import Enum\nfrom hashlib import sha256\nfrom json import JSONDecodeError\nfrom pathlib import Path\nfrom typing import Any, Callable, Dict, List, Optional, Tuple, Type, Union\n\nimport aiohttp\nimport backoff\nimport requests\nfrom cachetools.func import ttl_cache\nfrom requests import Response, Timeout\nfrom requests_toolbelt import MultipartEncoder\n\nfrom inference.core import logger\nfrom inference.core.cache import cache\nfrom inference.core.cache.base import BaseCache\nfrom inference.core.cache.model_artifacts import get_cache_dir, initialise_cache\nfrom inference.core.entities.types import (\n    DatasetID,\n    ModelID,\n    ModelType,\n    TaskType,\n    VersionID,\n    WorkspaceID,\n)\nfrom inference.core.env import (\n    API_BASE_URL,\n    ENFORCE_CREDITS_VERIFICATION,\n    GCP_SERVERLESS,\n    INTERNAL_WEIGHTS_URL_SUFFIX,\n    MD5_VERIFICATION_ENABLED,\n    MODEL_CACHE_DIR,\n    MODELS_CACHE_AUTH_CACHE_MAX_SIZE,\n    MODELS_CACHE_AUTH_CACHE_TTL,\n    MODELS_CACHE_AUTH_ENABLED,\n    RETRY_CONNECTION_ERRORS_TO_ROBOFLOW_API,\n    ROBOFLOW_API_EXTRA_HEADERS,\n    ROBOFLOW_API_REQUEST_TIMEOUT,\n    ROBOFLOW_API_VERIFY_SSL,\n    ROBOFLOW_SERVICE_SECRET,\n    SINGLE_TENANT_WORKFLOW_CACHE,\n    TRANSIENT_ROBOFLOW_API_ERRORS,\n    TRANSIENT_ROBOFLOW_API_ERRORS_RETRIES,\n    TRANSIENT_ROBOFLOW_API_ERRORS_RETRY_INTERVAL,\n    USE_FILE_CACHE_FOR_WORKFLOWS_DEFINITIONS,\n    WORKFLOWS_DEFINITION_CACHE_EXPIRY,\n)\nfrom inference.core.exceptions import (\n    MalformedRoboflowAPIResponseError,\n    MalformedWorkflowResponseError,\n    MissingDefaultModelError,\n    PaymentRequiredError,\n    RetryRequestError,\n    RoboflowAPIConnectionError,\n    RoboflowAPIForbiddenError,\n    RoboflowAPIIAlreadyAnnotatedError,\n    RoboflowAPIIAnnotationRejectionError,\n    RoboflowAPIImageUploadRejectionError,\n    RoboflowAPINotAuthorizedError,\n    RoboflowAPINotNotFoundError,\n    RoboflowAPITimeoutError,\n    RoboflowAPIUnsuccessfulRequestError,\n    RoboflowAPIUsagePausedError,\n    WorkspaceLoadError,\n)\nfrom inference.core.telemetry import record_api_call, record_error, start_span\nfrom inference.core.utils.file_system import sanitize_path_segment\nfrom inference.core.utils.requests import (\n    api_key_safe_raise_for_status,\n    api_key_safe_raise_for_status_aiohttp,\n)\nfrom inference.core.utils.url_utils import wrap_url\nfrom inference.core.version import __version__\n\nLOCAL_API_KEY = \"local\"\n\nENFORCE_CREDITS_VERIFICATION_HEADER = \"x-enforce-credits-verification\"\nENFORCE_INTERNAL_ARTIFACTS_URLS_HEADER = \"x-enforce-internal-artefacts-urls\"\n\nMODEL_TYPE_DEFAULTS = {\n    \"object-detection\": \"yolov5v2s\",\n    \"instance-segmentation\": \"yolact\",\n    \"classification\": \"vit\",\n    \"keypoint-detection\": \"yolov8n\",\n}\nPROJECT_TASK_TYPE_KEY = \"project_task_type\"\nMODEL_TYPE_KEY = \"model_type\"\n\nNOT_FOUND_ERROR_MESSAGE = (\n    \"Could not find requested Roboflow resource. Check that the provided dataset and \"\n    \"version are correct, and check that the provided Roboflow API key has the correct permissions.\"\n)\n\nROBOFLOW_INFERENCE_VERSION_HEADER = \"X-Roboflow-Inference-Version\"\nALLOW_CHUNKED_RESPONSE_HEADER = \"X-Allow-Chunked\"\n\n\ndef raise_from_lambda(\n    inner_error: Exception, exception_type: Type[Exception], message: str\n) -> None:\n    raise exception_type(message) from inner_error\n\n\nDEFAULT_ERROR_HANDLERS = {\n    401: lambda e: raise_from_lambda(\n        e,\n        RoboflowAPINotAuthorizedError,\n        \"Unauthorized access to roboflow API - check API key. Visit \"\n        \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve one.\",\n    ),\n    402: lambda e: raise_from_lambda(\n        e,\n        PaymentRequiredError,\n        \"Not enough credits to perform this request. Verify your workspace billing page.\",\n    ),\n    403: lambda e: raise_from_lambda(\n        e,\n        RoboflowAPIForbiddenError,\n        \"Unauthorized access to roboflow API - check API key regarding correctness and required scopes. Visit \"\n        \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve one.\",\n    ),\n    404: lambda e: raise_from_lambda(\n        e, RoboflowAPINotNotFoundError, NOT_FOUND_ERROR_MESSAGE\n    ),\n    423: lambda e: raise_from_lambda(\n        e,\n        RoboflowAPIUsagePausedError,\n        \"Roboflow API usage is paused. Please contact your workspace administrator to re-enable api keys.\",\n    ),\n}\n\n\ndef wrap_roboflow_api_errors(\n    http_errors_handlers: Optional[\n        Dict[int, Callable[[Union[requests.exceptions.HTTPError]], None]]\n    ] = None,\n) -> callable:\n    def decorator(function: callable) -> callable:\n        def wrapper(*args, **kwargs) -> Any:\n            t_start = time.perf_counter()\n            with start_span(\n                \"roboflow_api.call\",\n                {\"roboflow_api.function\": function.__name__},\n            ):\n                try:\n                    try:\n                        return function(*args, **kwargs)\n                    except RetryRequestError as error:\n                        raise error.inner_error\n                except Timeout as error:\n                    record_error(error)\n                    raise RoboflowAPITimeoutError(\n                        \"Timeout when attempting to connect to Roboflow API.\"\n                    ) from error\n                except (\n                    requests.exceptions.ConnectionError,\n                    ConnectionError,\n                ) as error:\n                    record_error(error)\n                    raise RoboflowAPIConnectionError(\n                        \"Could not connect to Roboflow API.\"\n                    ) from error\n                except requests.exceptions.HTTPError as error:\n                    record_error(error)\n                    user_handler_override = (\n                        http_errors_handlers if http_errors_handlers is not None else {}\n                    )\n                    status_code = error.response.status_code\n                    default_handler = DEFAULT_ERROR_HANDLERS.get(status_code)\n                    error_handler = user_handler_override.get(\n                        status_code, default_handler\n                    )\n                    if error_handler is not None:\n                        error_handler(error)\n                    raise RoboflowAPIUnsuccessfulRequestError(\n                        f\"Unsuccessful request to Roboflow API with response code: {status_code}\"\n                    ) from error\n                except requests.exceptions.InvalidJSONError as error:\n                    record_error(error)\n                    raise MalformedRoboflowAPIResponseError(\n                        \"Could not decode JSON response from Roboflow API.\"\n                    ) from error\n                finally:\n                    record_api_call(function.__name__, time.perf_counter() - t_start)\n\n        return wrapper\n\n    return decorator\n\n\ndef wrap_roboflow_api_errors_async(\n    http_errors_handlers: Optional[\n        Dict[int, Callable[[Union[aiohttp.ClientError]], None]]\n    ] = None,\n) -> callable:\n    def decorator(function: callable) -> callable:\n        async def wrapper(*args, **kwargs) -> Any:\n            t_start = time.perf_counter()\n            with start_span(\n                \"roboflow_api.call\",\n                {\"roboflow_api.function\": function.__name__},\n            ):\n                try:\n                    try:\n                        return await function(*args, **kwargs)\n                    except RetryRequestError as error:\n                        raise error.inner_error\n                except asyncio.TimeoutError as error:\n                    record_error(error)\n                    raise RoboflowAPITimeoutError(\n                        \"Timeout when attempting to connect to Roboflow API.\"\n                    ) from error\n                except (aiohttp.ClientConnectionError, ConnectionError) as error:\n                    record_error(error)\n                    raise RoboflowAPIConnectionError(\n                        \"Could not connect to Roboflow API.\"\n                    ) from error\n                except (aiohttp.ContentTypeError, JSONDecodeError) as error:\n                    record_error(error)\n                    raise MalformedRoboflowAPIResponseError(\n                        \"Could not decode JSON response from Roboflow API.\"\n                    ) from error\n                except aiohttp.ClientResponseError as error:\n                    record_error(error)\n                    user_handler_override = (\n                        http_errors_handlers if http_errors_handlers is not None else {}\n                    )\n                    status_code = error.status\n                    default_handler = DEFAULT_ERROR_HANDLERS.get(status_code)\n                    error_handler = user_handler_override.get(\n                        status_code, default_handler\n                    )\n                    if error_handler is not None:\n                        error_handler(error)\n                    raise RoboflowAPIUnsuccessfulRequestError(\n                        f\"Unsuccessful request to Roboflow API with response code: {status_code}\"\n                    ) from error\n                # remaining aiohttp.ClientError seems to qualify to simply pass-through raise\n                finally:\n                    record_api_call(function.__name__, time.perf_counter() - t_start)\n\n        return wrapper\n\n    return decorator\n\n\n@ttl_cache(ttl=MODELS_CACHE_AUTH_CACHE_TTL, maxsize=MODELS_CACHE_AUTH_CACHE_MAX_SIZE)\n@wrap_roboflow_api_errors()\ndef get_roboflow_workspace(api_key: str) -> WorkspaceID:\n    if not api_key:\n        raise WorkspaceLoadError(\"Empty workspace encountered, check your API key.\")\n\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/\",\n        params=[(\"api_key\", api_key), (\"nocache\", \"true\")],\n    )\n    api_key_info = _get_from_url(url=api_url)\n    workspace_id = api_key_info.get(\"workspace\")\n    if workspace_id is None:\n        raise WorkspaceLoadError(\"Empty workspace encountered, check your API key.\")\n    return workspace_id\n\n\n@wrap_roboflow_api_errors_async()\n@backoff.on_exception(\n    backoff.constant,\n    exception=RetryRequestError,\n    max_tries=TRANSIENT_ROBOFLOW_API_ERRORS_RETRIES,\n    interval=TRANSIENT_ROBOFLOW_API_ERRORS_RETRY_INTERVAL,\n)\nasync def get_roboflow_workspace_async(api_key: str) -> WorkspaceID:\n    try:\n        headers = build_roboflow_api_headers()\n        async with aiohttp.ClientSession() as session:\n            async with session.get(\n                f\"{API_BASE_URL}/\",\n                params={\"api_key\": api_key, \"nocache\": \"true\"},\n                headers=headers,\n                timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n            ) as response:\n                try:\n                    api_key_safe_raise_for_status_aiohttp(response=response)\n                except Exception as error:\n                    if response.status in TRANSIENT_ROBOFLOW_API_ERRORS:\n                        raise RetryRequestError(\n                            message=str(error), inner_error=error\n                        ) from error\n                    raise error\n                response_payload = await response.json()\n                workspace_id = response_payload.get(\"workspace\")\n                if workspace_id is None:\n                    raise WorkspaceLoadError(\n                        \"Empty workspace encountered, check your API key.\"\n                    )\n                return workspace_id\n    except (aiohttp.ClientConnectionError, ConnectionError) as error:\n        if RETRY_CONNECTION_ERRORS_TO_ROBOFLOW_API:\n            raise RetryRequestError(\n                message=\"Connectivity error\", inner_error=error\n            ) from error\n        raise error\n\n\n@wrap_roboflow_api_errors()\ndef add_custom_metadata(\n    api_key: str,\n    workspace_id: WorkspaceID,\n    inference_ids: List[str],\n    field_name: str,\n    field_value: str,\n):\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/inference-stats/metadata\",\n        params=[(\"api_key\", api_key), (\"nocache\", \"true\")],\n    )\n    response = requests.post(\n        url=api_url,\n        json={\n            \"data\": [\n                {\n                    \"inference_ids\": inference_ids,\n                    \"field_name\": field_name,\n                    \"field_value\": field_value,\n                }\n            ]\n        },\n        headers=build_roboflow_api_headers(),\n        timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n        verify=ROBOFLOW_API_VERIFY_SSL,\n    )\n    api_key_safe_raise_for_status(response=response)\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_dataset_type(\n    api_key: str, workspace_id: WorkspaceID, dataset_id: DatasetID\n) -> TaskType:\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/{dataset_id}\",\n        params=[(\"api_key\", api_key), (\"nocache\", \"true\")],\n    )\n    dataset_info = _get_from_url(url=api_url)\n    project_task_type = dataset_info.get(\"project\", {})\n    if \"type\" not in project_task_type:\n        logger.warning(\n            f\"Project task type not defined for workspace={workspace_id} and dataset={dataset_id}, defaulting \"\n            f\"to object-detection.\"\n        )\n    return project_task_type.get(\"type\", \"object-detection\")\n\n\n@wrap_roboflow_api_errors(\n    http_errors_handlers={\n        500: lambda e: raise_from_lambda(\n            e, RoboflowAPINotNotFoundError, NOT_FOUND_ERROR_MESSAGE\n        )\n        # this is temporary solution, empirically checked that backend API responds HTTP 500 on incorrect version.\n        # TO BE FIXED at backend, otherwise this error handling may overshadow existing backend problems.\n    }\n)\ndef get_roboflow_model_type(\n    api_key: str,\n    workspace_id: WorkspaceID,\n    dataset_id: DatasetID,\n    version_id: VersionID,\n    project_task_type: ModelType,\n) -> ModelType:\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/{dataset_id}/{version_id}\",\n        params=[(\"api_key\", api_key), (\"nocache\", \"true\")],\n    )\n    version_info = _get_from_url(url=api_url)\n    model_type = version_info[\"version\"]\n    if \"modelType\" not in model_type:\n        if project_task_type not in MODEL_TYPE_DEFAULTS:\n            raise MissingDefaultModelError(\n                f\"Could not set default model for {project_task_type}\"\n            )\n        logger.warning(\n            f\"Model type not defined - using default for {project_task_type} task.\"\n        )\n    return model_type.get(\"modelType\", MODEL_TYPE_DEFAULTS[project_task_type])\n\n\nclass ModelEndpointType(Enum):\n    ORT = \"ort\"\n    CORE_MODEL = \"core_model\"\n    OWLV2 = \"owlv2\"\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_model_data(\n    api_key: str,\n    model_id: str,\n    endpoint_type: ModelEndpointType,\n    device_id: str,\n    countinference: Optional[bool] = None,\n    service_secret: Optional[str] = None,\n) -> dict:\n    api_data_cache_key = f\"roboflow_api_data:{endpoint_type.value}:{model_id}\"\n    api_data = None\n    if not MODELS_CACHE_AUTH_ENABLED:\n        api_data = cache.get(api_data_cache_key)\n    if api_data is not None:\n        logger.debug(f\"Loaded model data from cache with key: {api_data_cache_key}.\")\n        return api_data\n    else:\n        params = [\n            (\"nocache\", \"true\"),\n            (\"device\", device_id),\n            (\"dynamic\", \"true\"),\n        ]\n        if api_key is not None and api_key != LOCAL_API_KEY:\n            params.append((\"api_key\", api_key))\n\n        if (\n            INTERNAL_WEIGHTS_URL_SUFFIX == \"serverless\"\n            and countinference is False\n            and service_secret == ROBOFLOW_SERVICE_SECRET\n        ):\n            params.append((\"countinference\", str(countinference).lower()))\n            params.append((\"service_secret\", service_secret))\n\n        api_base_url = urllib.parse.urljoin(API_BASE_URL, INTERNAL_WEIGHTS_URL_SUFFIX)\n        api_url = _add_params_to_url(\n            url=f\"{api_base_url}/{endpoint_type.value}/{model_id}\",\n            params=params,\n        )\n        api_data = _get_from_url(url=api_url)\n        cache.set(\n            api_data_cache_key,\n            api_data,\n            expire=10,\n        )\n        logger.debug(\n            f\"Loaded model data from Roboflow API and saved to cache with key: {api_data_cache_key}.\"\n        )\n        return api_data\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_instant_model_data(\n    api_key: str,\n    model_id: ModelID,\n    cache_prefix: str = \"roboflow_api_data\",\n    countinference: Optional[bool] = None,\n    service_secret: Optional[str] = None,\n) -> dict:\n    api_data_cache_key = f\"{cache_prefix}:{model_id}\"\n    api_data = None\n    if not MODELS_CACHE_AUTH_ENABLED:\n        api_data = cache.get(api_data_cache_key)\n    if api_data is not None:\n        logger.debug(f\"Loaded model data from cache with key: {api_data_cache_key}.\")\n        return api_data\n    else:\n        params = [\n            (\"model\", model_id),\n        ]\n        if api_key is not None and api_key != LOCAL_API_KEY:\n            params.append((\"api_key\", api_key))\n\n        if (\n            INTERNAL_WEIGHTS_URL_SUFFIX == \"serverless\"\n            and countinference is False\n            and service_secret == ROBOFLOW_SERVICE_SECRET\n        ):\n            params.append((\"countinference\", str(countinference).lower()))\n            params.append((\"service_secret\", service_secret))\n\n        api_base_url = urllib.parse.urljoin(API_BASE_URL, INTERNAL_WEIGHTS_URL_SUFFIX)\n        api_url = _add_params_to_url(\n            url=f\"{api_base_url}/getWeights\",\n            params=params,\n        )\n        api_data = _get_from_url(url=api_url)\n        cache.set(\n            api_data_cache_key,\n            api_data,\n            expire=10,\n        )\n        logger.debug(\n            f\"Loaded model data from Roboflow API and saved to cache with key: {api_data_cache_key}.\"\n        )\n        return api_data\n\n\n@wrap_roboflow_api_errors()\ndef get_model_metadata_from_inference_models_registry(\n    api_key: str,\n    model_id: ModelID,\n    cache_prefix: str = \"roboflow_api_data:inference_models_registry\",\n    countinference: Optional[bool] = None,\n    service_secret: Optional[str] = None,\n) -> dict:\n    # Watch out - this function should only be used to substitute get_roboflow_instant_model_data()\n    # and only in terms of getting model type and task type\n    # this is only stub to make sure auth works as it should for models which are not\n    # associated to project via version (for which old auth and metadata retrieval method work).\n    api_data_cache_key = f\"{cache_prefix}:{model_id}\"\n    api_data = None\n    if not MODELS_CACHE_AUTH_ENABLED:\n        api_data = cache.get(api_data_cache_key)\n    if api_data is not None:\n        logger.debug(f\"Loaded model data from cache with key: {api_data_cache_key}.\")\n        return api_data\n    query = [(\"modelId\", model_id)]\n    headers = {\"Authorization\": f\"Bearer {api_key}\"}\n    if GCP_SERVERLESS:\n        headers[ENFORCE_INTERNAL_ARTIFACTS_URLS_HEADER] = \"true\"\n    if ENFORCE_CREDITS_VERIFICATION:\n        skip = (\n            countinference is False\n            and service_secret is not None\n            and service_secret == ROBOFLOW_SERVICE_SECRET\n        )\n        if not skip:\n            headers[ENFORCE_CREDITS_VERIFICATION_HEADER] = \"true\"\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/models/v1/external/weights\",\n        params=query,\n    )\n    raw_api_data = _get_from_url(url=api_url, headers=headers)\n    api_data = {\n        \"modelType\": raw_api_data[\"modelMetadata\"][\"modelArchitecture\"],\n        \"taskType\": raw_api_data[\"modelMetadata\"][\"taskType\"],\n    }\n    cache.set(\n        api_data_cache_key,\n        api_data,\n        expire=10,\n    )\n    logger.debug(\n        f\"Loaded model data from Roboflow API (inference-models registry) \"\n        f\"and saved to cache with key: {api_data_cache_key}.\"\n    )\n    return api_data\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_base_lora(\n    api_key: str, repo: str, revision: str, device_id: str\n) -> dict:\n    full_path = f\"{repo.strip('/')}/{revision.strip('/')}\"\n    api_data_cache_key = f\"roboflow_api_data:lora-bases:{full_path}\"\n    api_data = None\n    if not MODELS_CACHE_AUTH_ENABLED:\n        api_data = cache.get(api_data_cache_key)\n    if api_data is not None:\n        logger.debug(f\"Loaded model data from cache with key: {api_data_cache_key}.\")\n        return api_data\n    else:\n        params = [\n            (\"nocache\", \"true\"),\n            (\"device\", device_id),\n            (\"repoAndRevision\", full_path),\n        ]\n        if api_key is not None and api_key != LOCAL_API_KEY:\n            params.append((\"api_key\", api_key))\n        api_url = _add_params_to_url(\n            url=f\"{API_BASE_URL}/lora_bases\",\n            params=params,\n        )\n        api_data = _get_from_url(url=api_url)\n        cache.set(\n            api_data_cache_key,\n            api_data,\n            expire=10,\n        )\n        logger.debug(\n            f\"Loaded lora base model data from Roboflow API and saved to cache with key: {api_data_cache_key}.\"\n        )\n        return api_data\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_active_learning_configuration(\n    api_key: str,\n    workspace_id: WorkspaceID,\n    dataset_id: DatasetID,\n) -> dict:\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/{dataset_id}/active_learning\",\n        params=[(\"api_key\", api_key)],\n    )\n    return _get_from_url(url=api_url)\n\n\n@wrap_roboflow_api_errors()\ndef register_image_at_roboflow(\n    api_key: str,\n    dataset_id: DatasetID,\n    local_image_id: str,\n    image_bytes: bytes,\n    batch_name: str,\n    tags: Optional[List[str]] = None,\n    inference_id: Optional[str] = None,\n    metadata: Optional[Dict[str, Any]] = None,\n) -> dict:\n    url = f\"{API_BASE_URL}/dataset/{dataset_id}/upload\"\n    params = [\n        (\"api_key\", api_key),\n        (\"batch\", batch_name),\n    ]\n    if inference_id is not None:\n        params.append((\"inference_id\", inference_id))\n    tags = tags if tags is not None else []\n    for tag in tags:\n        params.append((\"tag\", tag))\n    wrapped_url = wrap_url(_add_params_to_url(url=url, params=params))\n    fields = {\n        \"name\": f\"{local_image_id}.jpg\",\n        \"file\": (\"imageToUpload\", image_bytes, \"image/jpeg\"),\n    }\n    if metadata is not None:\n        fields[\"metadata\"] = json.dumps(metadata)\n    m = MultipartEncoder(fields=fields)\n    headers = build_roboflow_api_headers(\n        explicit_headers={\"Content-Type\": m.content_type},\n    )\n    response = requests.post(\n        url=wrapped_url,\n        data=m,\n        headers=headers,\n        timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n        verify=ROBOFLOW_API_VERIFY_SSL,\n    )\n    api_key_safe_raise_for_status(response=response)\n    parsed_response = response.json()\n    if not parsed_response.get(\"duplicate\") and not parsed_response.get(\"success\"):\n        raise RoboflowAPIImageUploadRejectionError(\n            f\"Server rejected image: {parsed_response}\"\n        )\n    return parsed_response\n\n\n@wrap_roboflow_api_errors(\n    http_errors_handlers={\n        409: lambda e: raise_from_lambda(\n            e,\n            RoboflowAPIIAlreadyAnnotatedError,\n            \"Given datapoint already has annotation.\",\n        )\n    }\n)\ndef annotate_image_at_roboflow(\n    api_key: str,\n    dataset_id: DatasetID,\n    local_image_id: str,\n    roboflow_image_id: str,\n    annotation_content: str,\n    annotation_file_type: str,\n    is_prediction: bool = True,\n) -> dict:\n    url = f\"{API_BASE_URL}/dataset/{dataset_id}/annotate/{roboflow_image_id}\"\n    params = [\n        (\"api_key\", api_key),\n        (\"name\", f\"{local_image_id}.{annotation_file_type}\"),\n        (\"prediction\", str(is_prediction).lower()),\n    ]\n    wrapped_url = wrap_url(_add_params_to_url(url=url, params=params))\n    headers = build_roboflow_api_headers(\n        explicit_headers={\"Content-Type\": \"text/plain\"},\n    )\n    response = requests.post(\n        wrapped_url,\n        data=annotation_content,\n        headers=headers,\n        timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n        verify=ROBOFLOW_API_VERIFY_SSL,\n    )\n    api_key_safe_raise_for_status(response=response)\n    parsed_response = response.json()\n    if \"error\" in parsed_response or not parsed_response.get(\"success\"):\n        raise RoboflowAPIIAnnotationRejectionError(\n            f\"Failed to save annotation for {roboflow_image_id}. API response: {parsed_response}\"\n        )\n    return parsed_response\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_labeling_batches(\n    api_key: str, workspace_id: WorkspaceID, dataset_id: str\n) -> dict:\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/{dataset_id}/batches\",\n        params=[(\"api_key\", api_key)],\n    )\n    return _get_from_url(url=api_url)\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_labeling_jobs(\n    api_key: str, workspace_id: WorkspaceID, dataset_id: str\n) -> dict:\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/{dataset_id}/jobs\",\n        params=[(\"api_key\", api_key)],\n    )\n    return _get_from_url(url=api_url)\n\n\ndef get_workflow_cache_file(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    workflow_version_id: Optional[str] = None,\n) -> str:\n    sanitized_workspace_id = sanitize_path_segment(workspace_id)\n    sanitized_workflow_id = sanitize_path_segment(workflow_id)\n    if SINGLE_TENANT_WORKFLOW_CACHE:\n        version_suffix = (\n            f\"_v{sanitize_path_segment(workflow_version_id)}\"\n            if workflow_version_id\n            else \"\"\n        )\n        filename = f\"{sanitized_workflow_id}{version_suffix}.json\"\n    else:\n        cache_seed = f\"{workspace_id}:{api_key or ''}\"\n        cache_fingerprint = hashlib.sha256(\n            cache_seed.encode(\"utf-8\"), usedforsecurity=False\n        ).hexdigest()\n        filename = f\"{sanitized_workflow_id}_{cache_fingerprint}.json\"\n    prefix = os.path.abspath(os.path.join(MODEL_CACHE_DIR, \"workflow\"))\n    result = os.path.abspath(\n        os.path.join(\n            prefix,\n            sanitized_workspace_id,\n            filename,\n        )\n    )\n    if not result.startswith(prefix):\n        raise ValueError(\n            \"Detected attempt to save workflow definition in insecure location\"\n        )\n    return result\n\n\ndef cache_workflow_response(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    response: dict,\n    workflow_version_id: Optional[str] = None,\n):\n    workflow_cache_file = get_workflow_cache_file(\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        api_key=api_key,\n        workflow_version_id=workflow_version_id,\n    )\n    workflow_cache_dir = os.path.dirname(workflow_cache_file)\n    if not os.path.exists(workflow_cache_dir):\n        os.makedirs(workflow_cache_dir, exist_ok=True)\n    with open(workflow_cache_file, \"w\") as f:\n        json.dump(response, f)\n\n\ndef delete_cached_workflow_response_if_exists(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    workflow_version_id: Optional[str] = None,\n) -> None:\n    workflow_cache_file = get_workflow_cache_file(\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        api_key=api_key,\n        workflow_version_id=workflow_version_id,\n    )\n    if os.path.exists(workflow_cache_file):\n        os.remove(workflow_cache_file)\n\n\ndef load_cached_workflow_response(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    workflow_version_id: Optional[str] = None,\n) -> Optional[dict]:\n    workflow_cache_file = get_workflow_cache_file(\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        api_key=api_key,\n        workflow_version_id=workflow_version_id,\n    )\n    if not os.path.exists(workflow_cache_file):\n        return None\n    try:\n        with open(workflow_cache_file, \"r\") as f:\n            return json.load(f)\n    except Exception:\n        delete_cached_workflow_response_if_exists(\n            workspace_id=workspace_id,\n            workflow_id=workflow_id,\n            api_key=api_key,\n            workflow_version_id=workflow_version_id,\n        )\n\n\n@wrap_roboflow_api_errors()\ndef get_workflow_specification(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    use_cache: bool = True,\n    ephemeral_cache: Optional[BaseCache] = None,\n    workflow_version_id: Optional[str] = None,\n) -> dict:\n    ephemeral_cache = ephemeral_cache or cache\n    if use_cache:\n        cached_entry = _retrieve_workflow_specification_from_ephemeral_cache(\n            api_key=api_key,\n            workspace_id=workspace_id,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n            ephemeral_cache=ephemeral_cache,\n        )\n        if cached_entry:\n            return cached_entry\n\n    if workspace_id == \"local\":\n        if not re.match(r\"^[\\w\\-]+$\", workflow_id):\n            raise ValueError(\"Invalid workflow id\")\n\n        workflow_hash = sha256(workflow_id.encode()).hexdigest()\n        local_file_path = (\n            Path(MODEL_CACHE_DIR) / \"workflow\" / \"local\" / f\"{workflow_hash}.json\"\n        )\n        if not local_file_path.exists():\n            raise FileNotFoundError(f\"Local workflow file not found: {local_file_path}\")\n\n        with local_file_path.open(\"r\", encoding=\"utf-8\") as f:\n            local_config = json.load(f)\n\n        # Mimic the same shape as the cloud response:\n        response = {\"workflow\": local_config}\n    else:\n        params = []\n        if api_key is not None and api_key != LOCAL_API_KEY:\n            params.append((\"api_key\", api_key))\n        if workflow_version_id is not None:\n            params.append((\"workflow_version\", workflow_version_id))\n        api_url = _add_params_to_url(\n            url=f\"{API_BASE_URL}/{workspace_id}/workflows/{workflow_id}\",\n            params=params,\n        )\n        try:\n            response = _get_from_url(url=api_url)\n            if USE_FILE_CACHE_FOR_WORKFLOWS_DEFINITIONS:\n                cache_workflow_response(\n                    workspace_id=workspace_id,\n                    workflow_id=workflow_id,\n                    api_key=api_key,\n                    response=response,\n                    workflow_version_id=workflow_version_id,\n                )\n        except (\n            requests.exceptions.ConnectionError,\n            ConnectionError,\n            requests.exceptions.Timeout,\n        ) as error:\n            if not USE_FILE_CACHE_FOR_WORKFLOWS_DEFINITIONS:\n                raise error\n            response = load_cached_workflow_response(\n                workspace_id=workspace_id,\n                workflow_id=workflow_id,\n                api_key=api_key,\n                workflow_version_id=workflow_version_id,\n            )\n            if response is None:\n                raise error\n\n    if \"workflow\" not in response or \"config\" not in response[\"workflow\"]:\n        raise MalformedWorkflowResponseError(\n            \"Could not find workflow specification in API response\"\n        )\n    try:\n        workflow_config = json.loads(response[\"workflow\"][\"config\"])\n        specification = workflow_config[\"specification\"]\n        if isinstance(specification, dict):\n            specification[\"id\"] = response[\"workflow\"].get(\"id\")\n        if use_cache:\n            _cache_workflow_specification_in_ephemeral_cache(\n                api_key=api_key,\n                workspace_id=workspace_id,\n                workflow_id=workflow_id,\n                workflow_version_id=workflow_version_id,\n                specification=specification,\n                ephemeral_cache=ephemeral_cache,\n            )\n        return specification\n    except KeyError as error:\n        raise MalformedWorkflowResponseError(\n            \"Workflow specification not found in Roboflow API response\"\n        ) from error\n    except (ValueError, TypeError) as error:\n        raise MalformedWorkflowResponseError(\n            \"Could not decode workflow specification in Roboflow API response\"\n        ) from error\n\n\ndef _retrieve_workflow_specification_from_ephemeral_cache(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    ephemeral_cache: BaseCache,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[dict]:\n    cache_key = _prepare_workflow_response_cache_key(\n        api_key=api_key,\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        workflow_version_id=workflow_version_id,\n    )\n    return ephemeral_cache.get(key=cache_key)\n\n\ndef _cache_workflow_specification_in_ephemeral_cache(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    specification: dict,\n    ephemeral_cache: BaseCache,\n    workflow_version_id: Optional[str] = None,\n) -> None:\n    cache_key = _prepare_workflow_response_cache_key(\n        api_key=api_key,\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        workflow_version_id=workflow_version_id,\n    )\n    ephemeral_cache.set(\n        key=cache_key,\n        value=specification,\n        expire=WORKFLOWS_DEFINITION_CACHE_EXPIRY,\n    )\n\n\ndef _prepare_workflow_response_cache_key(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> str:\n    workflow_version_suffix = (\n        f\":workflow_version={workflow_version_id}\" if workflow_version_id else \"\"\n    )\n    if SINGLE_TENANT_WORKFLOW_CACHE:\n        return (\n            f\"workflow_definition:{workspace_id}:{workflow_id}{workflow_version_suffix}\"\n        )\n    cache_seed = f\"{workspace_id}:{api_key or ''}\"\n    cache_fingerprint = hashlib.sha256(\n        cache_seed.encode(\"utf-8\"), usedforsecurity=False\n    ).hexdigest()\n    return f\"workflow_definition:{workspace_id}:{workflow_id}{workflow_version_suffix}:{cache_fingerprint}\"\n\n\n@wrap_roboflow_api_errors()\ndef get_from_url(\n    url: str,\n    json_response: bool = True,\n) -> Union[Response, dict]:\n    return _get_from_url(\n        url=url,\n        json_response=json_response,\n    )\n\n\n@backoff.on_exception(\n    backoff.constant,\n    exception=RetryRequestError,\n    max_tries=TRANSIENT_ROBOFLOW_API_ERRORS_RETRIES,\n    interval=TRANSIENT_ROBOFLOW_API_ERRORS_RETRY_INTERVAL,\n)\ndef _get_from_url(\n    url: str,\n    json_response: bool = True,\n    headers: Optional[dict] = None,\n) -> Union[Response, dict]:\n    full_url = wrap_url(url)\n    try:\n        response = requests.get(\n            full_url,\n            headers=build_roboflow_api_headers(explicit_headers=headers),\n            timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n            verify=ROBOFLOW_API_VERIFY_SSL,\n        )\n\n    except (ConnectionError, Timeout, requests.exceptions.ConnectionError) as error:\n        if RETRY_CONNECTION_ERRORS_TO_ROBOFLOW_API:\n            raise RetryRequestError(\n                message=\"Connectivity error\", inner_error=error\n            ) from error\n        raise error\n    try:\n        api_key_safe_raise_for_status(response=response)\n    except Exception as error:\n        if response.status_code in TRANSIENT_ROBOFLOW_API_ERRORS:\n            raise RetryRequestError(message=str(error), inner_error=error) from error\n        raise error\n\n    if MD5_VERIFICATION_ENABLED:\n        x_goog_hash = response.headers.get(\"x-goog-hash\")\n        if x_goog_hash is None:\n            logger.warning(\n                f\"MD5 verification enabled but response missing x-goog-hash header. \"\n                f\"Request url: {_url_for_safe_logging(full_url)}\"\n            )\n        else:\n            md5_part = None\n            for part in x_goog_hash.split(\",\"):\n                if part.strip().startswith(\"md5=\"):\n                    md5_part = part.strip()[4:]\n                    break\n            if md5_part is not None:\n                try:\n                    md5_from_header = base64.b64decode(md5_part)\n                except binascii.Error as decode_error:\n                    raise RoboflowAPIUnsuccessfulRequestError(\n                        \"Invalid MD5 value in x-goog-hash header: not valid base64\"\n                    ) from decode_error\n                if md5_from_header != hashlib.md5(response.content).digest():\n                    raise RoboflowAPIUnsuccessfulRequestError(\n                        \"MD5 hash does not match MD5 received from x-goog-hash header\"\n                    )\n            else:\n                logger.warning(\n                    f\"MD5 verification enabled but x-goog-hash header has no md5= part. \"\n                    f\"Request url: {_url_for_safe_logging(full_url)}\"\n                )\n\n    if json_response:\n        return response.json()\n    return response\n\n\ndef _test_range_request(url: str, timeout: int = 10) -> bool:\n    \"\"\"Test if server actually honors range requests by making a real range GET request.\n\n    Note: We can't rely on Accept-Ranges header alone because some servers/CDNs\n    advertise range support but return 200 (full file) instead of 206 (partial).\n    \"\"\"\n    try:\n        headers = {\"Range\": \"bytes=0-0\"}\n        response = requests.get(url, headers=headers, stream=True, timeout=timeout)\n        response.close()\n        if response.status_code == 206:\n            return True\n\n        return False\n    except Exception as e:\n        logger.warning(\n            f\"Failed to test range request support: {e}. Falling back to single-threaded download.\"\n        )\n        return False\n\n\ndef stream_url_to_cache(\n    url: str,\n    filename: str,\n    model_id: str,\n) -> None:\n    from inference_models.utils.download import download_files_to_directory\n\n    with start_span(\n        \"roboflow_api.download_artifact\",\n        {\"http.url\": _url_for_safe_logging(url), \"model.id\": model_id},\n    ):\n        initialise_cache(model_id=model_id)\n        cache_dir = get_cache_dir(model_id=model_id)\n        md5_hash = None\n\n        max_threads = 8 if _test_range_request(url) else 1\n\n        try:\n            download_files_to_directory(\n                target_dir=cache_dir,\n                files_specs=[(filename, wrap_url(url), md5_hash)],\n                verbose=True,\n                download_files_without_hash=True,\n                verify_hash_while_download=False,\n                max_threads_per_download=max_threads,\n            )\n        except Exception as e:\n            raise RoboflowAPIUnsuccessfulRequestError(\n                f\"Failed to download {filename}: {str(e)}\"\n            ) from e\n\n\ndef _url_for_safe_logging(url: str) -> str:\n    \"\"\"Return a URL safe to log by stripping the query string (and params/fragment).\n\n    Expects the full URL as used for the request (e.g. already wrapped).\n    Use this when logging request URLs so that sensitive query parameters\n    (e.g. api_key, tokens) are never written to logs.\n    \"\"\"\n    parsed = urllib.parse.urlparse(url)\n    return urllib.parse.urlunparse(\n        (parsed.scheme, parsed.netloc, parsed.path, \"\", \"\", \"\")\n    )\n\n\ndef _add_params_to_url(url: str, params: List[Tuple[str, str]]) -> str:\n    if len(params) == 0:\n        return url\n    params_chunks = [\n        f\"{name}={urllib.parse.quote_plus(value)}\" for name, value in params\n    ]\n    parameters_string = \"&\".join(params_chunks)\n    return f\"{url}?{parameters_string}\"\n\n\n@wrap_roboflow_api_errors()\ndef send_inference_results_to_model_monitoring(\n    api_key: str,\n    workspace_id: WorkspaceID,\n    inference_data: dict,\n):\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/inference-stats\",\n        params=[(\"api_key\", api_key)],\n    )\n    response = requests.post(\n        url=api_url,\n        json=inference_data,\n        headers=build_roboflow_api_headers(),\n        timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n        verify=ROBOFLOW_API_VERIFY_SSL,\n    )\n    api_key_safe_raise_for_status(response=response)\n\n\ndef get_extra_weights_provider_headers(\n    countinference: Optional[bool] = None,\n    service_secret: Optional[str] = None,\n) -> Optional[Dict[str, str]]:\n    headers = {}\n    if GCP_SERVERLESS:\n        headers[ENFORCE_INTERNAL_ARTIFACTS_URLS_HEADER] = \"true\"\n    if ENFORCE_CREDITS_VERIFICATION:\n        skip = (\n            countinference is False\n            and service_secret is not None\n            and service_secret == ROBOFLOW_SERVICE_SECRET\n        )\n        if not skip:\n            headers[ENFORCE_CREDITS_VERIFICATION_HEADER] = \"true\"\n    return build_roboflow_api_headers(explicit_headers=headers)\n\n\ndef build_roboflow_api_headers(\n    explicit_headers: Optional[Dict[str, Union[str, List[str]]]] = None,\n) -> Dict[str, Union[str, List[str]]]:\n    if explicit_headers is None:\n        explicit_headers = {}\n    explicit_headers = {\n        **explicit_headers,\n        ROBOFLOW_INFERENCE_VERSION_HEADER: __version__,\n        ALLOW_CHUNKED_RESPONSE_HEADER: \"true\",\n    }\n    if not ROBOFLOW_API_EXTRA_HEADERS:\n        return explicit_headers\n    try:\n        extra_headers: dict = json.loads(ROBOFLOW_API_EXTRA_HEADERS)\n        if explicit_headers:\n            extra_headers.update(explicit_headers)\n        return extra_headers\n    except ValueError:\n        logger.warning(\"Could not decode ROBOFLOW_API_EXTRA_HEADERS\")\n        return explicit_headers\n\n\ndef post_to_roboflow_api(\n    endpoint: str,\n    api_key: Optional[str],\n    payload: Optional[dict] = None,\n    params: Optional[List[Tuple[str, str]]] = None,\n    http_errors_handlers: Optional[\n        Dict[int, Callable[[Union[requests.exceptions.HTTPError]], None]]\n    ] = None,\n) -> dict:\n    \"\"\"Generic function to make a POST request to the Roboflow API.\n\n    Args:\n        endpoint: API endpoint path\n        api_key: Roboflow API key\n        payload: JSON payload\n        params: Additional URL parameters\n        http_errors_handlers: Optional custom HTTP error handlers by status code\n    \"\"\"\n\n    @wrap_roboflow_api_errors(http_errors_handlers=http_errors_handlers)\n    def _make_request():\n        url_params = []\n        if api_key and api_key != LOCAL_API_KEY:\n            url_params.append((\"api_key\", api_key))\n        if params:\n            url_params.extend(params)\n\n        full_url = _add_params_to_url(\n            url=f\"{API_BASE_URL}/{endpoint.strip('/')}\", params=url_params\n        )\n        wrapped_url = wrap_url(full_url)\n\n        headers = build_roboflow_api_headers()\n\n        response = requests.post(\n            url=wrapped_url,\n            json=payload,\n            headers=headers,\n            timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n            verify=ROBOFLOW_API_VERIFY_SSL,\n        )\n        api_key_safe_raise_for_status(response=response)\n        return response.json()\n\n    return _make_request()\n",
    "patch": null
  },
  {
    "trace_id": "c0499e85-cf3b-4963-946e-fc6b44dd4d17",
    "function_name": "load_kinds",
    "file_path": "inference/core/workflows/core_steps/loader.py",
    "speedup_x": 2.683562116666224,
    "review_quality": "high",
    "pre_optimization_commit": "30bef2126dc5d10be627521312d0d2a7fac20b96",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def load_kinds() -> List[Kind]:\n    return [\n        WILDCARD_KIND,\n        IMAGE_KIND,\n        VIDEO_METADATA_KIND,\n        ROBOFLOW_MODEL_ID_KIND,\n        ROBOFLOW_PROJECT_KIND,\n        ROBOFLOW_API_KEY_KIND,\n        FLOAT_ZERO_TO_ONE_KIND,\n        LIST_OF_VALUES_KIND,\n        SERIALISED_PAYLOADS_KIND,\n        BOOLEAN_KIND,\n        INTEGER_KIND,\n        STRING_KIND,\n        TOP_CLASS_KIND,\n        FLOAT_KIND,\n        DICTIONARY_KIND,\n        DETECTION_KIND,\n        CLASSIFICATION_PREDICTION_KIND,\n        POINT_KIND,\n        ZONE_KIND,\n        OBJECT_DETECTION_PREDICTION_KIND,\n        INSTANCE_SEGMENTATION_PREDICTION_KIND,\n        KEYPOINT_DETECTION_PREDICTION_KIND,\n        SEMANTIC_SEGMENTATION_PREDICTION_KIND,\n        RGB_COLOR_KIND,\n        IMAGE_KEYPOINTS_KIND,\n        CONTOURS_KIND,\n        LANGUAGE_MODEL_OUTPUT_KIND,\n        NUMPY_ARRAY_KIND,\n        QR_CODE_DETECTION_KIND,\n        BAR_CODE_DETECTION_KIND,\n        PREDICTION_TYPE_KIND,\n        ROBOFLOW_MANAGED_KEY,\n        PARENT_ID_KIND,\n        IMAGE_METADATA_KIND,\n        BYTES_KIND,\n        INFERENCE_ID_KIND,\n        SECRET_KIND,\n        EMBEDDING_KIND,\n        TIMESTAMP_KIND,\n    ]\n",
    "optimized_function_code": "from inference.core.workflows.execution_engine.entities.types import BAR_CODE_DETECTION_KIND, BOOLEAN_KIND, BYTES_KIND, CLASSIFICATION_PREDICTION_KIND, CONTOURS_KIND, DETECTION_KIND, DICTIONARY_KIND, EMBEDDING_KIND, FLOAT_KIND, FLOAT_ZERO_TO_ONE_KIND, IMAGE_KEYPOINTS_KIND, IMAGE_KIND, IMAGE_METADATA_KIND, INFERENCE_ID_KIND, INSTANCE_SEGMENTATION_PREDICTION_KIND, INTEGER_KIND, KEYPOINT_DETECTION_PREDICTION_KIND, Kind, LANGUAGE_MODEL_OUTPUT_KIND, LIST_OF_VALUES_KIND, NUMPY_ARRAY_KIND, OBJECT_DETECTION_PREDICTION_KIND, PARENT_ID_KIND, POINT_KIND, PREDICTION_TYPE_KIND, QR_CODE_DETECTION_KIND, RGB_COLOR_KIND, ROBOFLOW_API_KEY_KIND, ROBOFLOW_MANAGED_KEY, ROBOFLOW_MODEL_ID_KIND, ROBOFLOW_PROJECT_KIND, SECRET_KIND, SEMANTIC_SEGMENTATION_PREDICTION_KIND, SERIALISED_PAYLOADS_KIND, STRING_KIND, TIMESTAMP_KIND, TOP_CLASS_KIND, VIDEO_METADATA_KIND, WILDCARD_KIND, ZONE_KIND\nfrom typing import List\n\n_KINDS_CACHE = [\n    WILDCARD_KIND,\n    IMAGE_KIND,\n    VIDEO_METADATA_KIND,\n    ROBOFLOW_MODEL_ID_KIND,\n    ROBOFLOW_PROJECT_KIND,\n    ROBOFLOW_API_KEY_KIND,\n    FLOAT_ZERO_TO_ONE_KIND,\n    LIST_OF_VALUES_KIND,\n    SERIALISED_PAYLOADS_KIND,\n    BOOLEAN_KIND,\n    INTEGER_KIND,\n    STRING_KIND,\n    TOP_CLASS_KIND,\n    FLOAT_KIND,\n    DICTIONARY_KIND,\n    DETECTION_KIND,\n    CLASSIFICATION_PREDICTION_KIND,\n    POINT_KIND,\n    ZONE_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    KEYPOINT_DETECTION_PREDICTION_KIND,\n    SEMANTIC_SEGMENTATION_PREDICTION_KIND,\n    RGB_COLOR_KIND,\n    IMAGE_KEYPOINTS_KIND,\n    CONTOURS_KIND,\n    LANGUAGE_MODEL_OUTPUT_KIND,\n    NUMPY_ARRAY_KIND,\n    QR_CODE_DETECTION_KIND,\n    BAR_CODE_DETECTION_KIND,\n    PREDICTION_TYPE_KIND,\n    ROBOFLOW_MANAGED_KEY,\n    PARENT_ID_KIND,\n    IMAGE_METADATA_KIND,\n    BYTES_KIND,\n    INFERENCE_ID_KIND,\n    SECRET_KIND,\n    EMBEDDING_KIND,\n    TIMESTAMP_KIND,\n]\n\ndef load_kinds() -> List[Kind]:\n    return _KINDS_CACHE",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/loader.py\nfrom inference.core.workflows.execution_engine.entities.types import BAR_CODE_DETECTION_KIND, BOOLEAN_KIND, BYTES_KIND, CLASSIFICATION_PREDICTION_KIND, CONTOURS_KIND, DETECTION_KIND, DICTIONARY_KIND, EMBEDDING_KIND, FLOAT_KIND, FLOAT_ZERO_TO_ONE_KIND, IMAGE_KEYPOINTS_KIND, IMAGE_KIND, IMAGE_METADATA_KIND, INFERENCE_ID_KIND, INSTANCE_SEGMENTATION_PREDICTION_KIND, INTEGER_KIND, KEYPOINT_DETECTION_PREDICTION_KIND, Kind, LANGUAGE_MODEL_OUTPUT_KIND, LIST_OF_VALUES_KIND, NUMPY_ARRAY_KIND, OBJECT_DETECTION_PREDICTION_KIND, PARENT_ID_KIND, POINT_KIND, PREDICTION_TYPE_KIND, QR_CODE_DETECTION_KIND, RGB_COLOR_KIND, ROBOFLOW_API_KEY_KIND, ROBOFLOW_MANAGED_KEY, ROBOFLOW_MODEL_ID_KIND, ROBOFLOW_PROJECT_KIND, SECRET_KIND, SEMANTIC_SEGMENTATION_PREDICTION_KIND, SERIALISED_PAYLOADS_KIND, STRING_KIND, TIMESTAMP_KIND, TOP_CLASS_KIND, VIDEO_METADATA_KIND, WILDCARD_KIND, ZONE_KIND\nfrom typing import List\n\n_KINDS_CACHE = [\n    WILDCARD_KIND,\n    IMAGE_KIND,\n    VIDEO_METADATA_KIND,\n    ROBOFLOW_MODEL_ID_KIND,\n    ROBOFLOW_PROJECT_KIND,\n    ROBOFLOW_API_KEY_KIND,\n    FLOAT_ZERO_TO_ONE_KIND,\n    LIST_OF_VALUES_KIND,\n    SERIALISED_PAYLOADS_KIND,\n    BOOLEAN_KIND,\n    INTEGER_KIND,\n    STRING_KIND,\n    TOP_CLASS_KIND,\n    FLOAT_KIND,\n    DICTIONARY_KIND,\n    DETECTION_KIND,\n    CLASSIFICATION_PREDICTION_KIND,\n    POINT_KIND,\n    ZONE_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    KEYPOINT_DETECTION_PREDICTION_KIND,\n    SEMANTIC_SEGMENTATION_PREDICTION_KIND,\n    RGB_COLOR_KIND,\n    IMAGE_KEYPOINTS_KIND,\n    CONTOURS_KIND,\n    LANGUAGE_MODEL_OUTPUT_KIND,\n    NUMPY_ARRAY_KIND,\n    QR_CODE_DETECTION_KIND,\n    BAR_CODE_DETECTION_KIND,\n    PREDICTION_TYPE_KIND,\n    ROBOFLOW_MANAGED_KEY,\n    PARENT_ID_KIND,\n    IMAGE_METADATA_KIND,\n    BYTES_KIND,\n    INFERENCE_ID_KIND,\n    SECRET_KIND,\n    EMBEDDING_KIND,\n    TIMESTAMP_KIND,\n]\n\ndef load_kinds() -> List[Kind]:\n    return _KINDS_CACHE\n```",
    "optimized_function_only": "def load_kinds() -> List[Kind]:\n    return _KINDS_CACHE",
    "original_file_content": "from typing import List, Type\n\nfrom inference.core.cache import cache\nfrom inference.core.env import (\n    ALLOW_WORKFLOW_BLOCKS_ACCESSING_ENVIRONMENTAL_VARIABLES,\n    ALLOW_WORKFLOW_BLOCKS_ACCESSING_LOCAL_STORAGE,\n    API_KEY,\n    SAM3_3D_OBJECTS_ENABLED,\n    WORKFLOW_BLOCKS_WRITE_DIRECTORY,\n    WORKFLOW_DISABLED_BLOCK_PATTERNS,\n    WORKFLOW_DISABLED_BLOCK_TYPES,\n    WORKFLOWS_STEP_EXECUTION_MODE,\n)\nfrom inference.core.workflows.core_steps.analytics.data_aggregator.v1 import (\n    DataAggregatorBlockV1,\n)\nfrom inference.core.workflows.core_steps.analytics.detection_event_log.v1 import (\n    DetectionEventLogBlockV1,\n)\nfrom inference.core.workflows.core_steps.analytics.line_counter.v1 import (\n    LineCounterBlockV1,\n)\nfrom inference.core.workflows.core_steps.analytics.line_counter.v2 import (\n    LineCounterBlockV2,\n)\nfrom inference.core.workflows.core_steps.analytics.overlap.v1 import OverlapBlockV1\nfrom inference.core.workflows.core_steps.analytics.path_deviation.v1 import (\n    PathDeviationAnalyticsBlockV1,\n)\nfrom inference.core.workflows.core_steps.analytics.path_deviation.v2 import (\n    PathDeviationAnalyticsBlockV2,\n)\nfrom inference.core.workflows.core_steps.analytics.time_in_zone.v1 import (\n    TimeInZoneBlockV1,\n)\nfrom inference.core.workflows.core_steps.analytics.time_in_zone.v2 import (\n    TimeInZoneBlockV2,\n)\nfrom inference.core.workflows.core_steps.analytics.time_in_zone.v3 import (\n    TimeInZoneBlockV3,\n)\nfrom inference.core.workflows.core_steps.analytics.velocity.v1 import VelocityBlockV1\nfrom inference.core.workflows.core_steps.cache.cache_get.v1 import CacheGetBlockV1\nfrom inference.core.workflows.core_steps.cache.cache_set.v1 import CacheSetBlockV1\nfrom inference.core.workflows.core_steps.classical_cv.background_subtraction.v1 import (\n    BackgroundSubtractionBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.camera_focus.v1 import (\n    CameraFocusBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.camera_focus.v2 import (\n    CameraFocusBlockV2,\n)\nfrom inference.core.workflows.core_steps.classical_cv.contours.v1 import (\n    ImageContoursDetectionBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.contrast_equalization.v1 import (\n    ContrastEqualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.convert_grayscale.v1 import (\n    ConvertGrayscaleBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.distance_measurement.v1 import (\n    DistanceMeasurementBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.dominant_color.v1 import (\n    DominantColorBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.image_blur.v1 import (\n    ImageBlurBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.image_preprocessing.v1 import (\n    ImagePreprocessingBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.mask_area_measurement.v1 import (\n    MaskAreaMeasurementBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.morphological_transformation.v1 import (\n    MorphologicalTransformationBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.motion_detection.v1 import (\n    MotionDetectionBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.pixel_color_count.v1 import (\n    PixelationCountBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.sift.v1 import SIFTBlockV1\nfrom inference.core.workflows.core_steps.classical_cv.sift_comparison.v1 import (\n    SIFTComparisonBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.sift_comparison.v2 import (\n    SIFTComparisonBlockV2,\n)\nfrom inference.core.workflows.core_steps.classical_cv.size_measurement.v1 import (\n    SizeMeasurementBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.template_matching.v1 import (\n    TemplateMatchingBlockV1,\n)\nfrom inference.core.workflows.core_steps.classical_cv.threshold.v1 import (\n    ImageThresholdBlockV1,\n)\nfrom inference.core.workflows.core_steps.common.deserializers import (\n    deserialize_boolean_kind,\n    deserialize_bytes_kind,\n    deserialize_classification_prediction_kind,\n    deserialize_detections_kind,\n    deserialize_dictionary_kind,\n    deserialize_float_kind,\n    deserialize_float_zero_to_one_kind,\n    deserialize_image_kind,\n    deserialize_integer_kind,\n    deserialize_list_of_values_kind,\n    deserialize_numpy_array,\n    deserialize_optional_string_kind,\n    deserialize_point_kind,\n    deserialize_rgb_color_kind,\n    deserialize_rle_detections_kind,\n    deserialize_string_kind,\n    deserialize_timestamp,\n    deserialize_video_metadata_kind,\n    deserialize_zone_kind,\n)\nfrom inference.core.workflows.core_steps.common.entities import StepExecutionMode\nfrom inference.core.workflows.core_steps.common.serializers import (\n    serialise_image,\n    serialise_rle_sv_detections,\n    serialise_sv_detections,\n    serialize_secret,\n    serialize_timestamp,\n    serialize_video_metadata_kind,\n    serialize_wildcard_kind,\n)\nfrom inference.core.workflows.core_steps.flow_control.continue_if.v1 import (\n    ContinueIfBlockV1,\n)\nfrom inference.core.workflows.core_steps.flow_control.delta_filter.v1 import (\n    DeltaFilterBlockV1,\n)\nfrom inference.core.workflows.core_steps.flow_control.rate_limiter.v1 import (\n    RateLimiterBlockV1,\n)\nfrom inference.core.workflows.core_steps.formatters.csv.v1 import CSVFormatterBlockV1\nfrom inference.core.workflows.core_steps.formatters.expression.v1 import (\n    ExpressionBlockV1,\n)\nfrom inference.core.workflows.core_steps.formatters.first_non_empty_or_default.v1 import (\n    FirstNonEmptyOrDefaultBlockV1,\n)\nfrom inference.core.workflows.core_steps.formatters.json_parser.v1 import (\n    JSONParserBlockV1,\n)\nfrom inference.core.workflows.core_steps.formatters.property_definition.v1 import (\n    PropertyDefinitionBlockV1,\n)\nfrom inference.core.workflows.core_steps.formatters.vlm_as_classifier.v1 import (\n    VLMAsClassifierBlockV1,\n)\nfrom inference.core.workflows.core_steps.formatters.vlm_as_classifier.v2 import (\n    VLMAsClassifierBlockV2,\n)\nfrom inference.core.workflows.core_steps.formatters.vlm_as_detector.v1 import (\n    VLMAsDetectorBlockV1,\n)\nfrom inference.core.workflows.core_steps.formatters.vlm_as_detector.v2 import (\n    VLMAsDetectorBlockV2,\n)\nfrom inference.core.workflows.core_steps.fusion.buffer.v1 import BufferBlockV1\nfrom inference.core.workflows.core_steps.fusion.detections_classes_replacement.v1 import (\n    DetectionsClassesReplacementBlockV1,\n)\nfrom inference.core.workflows.core_steps.fusion.detections_consensus.v1 import (\n    DetectionsConsensusBlockV1,\n)\nfrom inference.core.workflows.core_steps.fusion.detections_list_rollup.v1 import (\n    DetectionsListRollUpBlockV1,\n)\nfrom inference.core.workflows.core_steps.fusion.detections_stitch.v1 import (\n    DetectionsStitchBlockV1,\n)\nfrom inference.core.workflows.core_steps.fusion.dimension_collapse.v1 import (\n    DimensionCollapseBlockV1,\n)\nfrom inference.core.workflows.core_steps.math.cosine_similarity.v1 import (\n    CosineSimilarityBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.anthropic_claude.v1 import (\n    AnthropicClaudeBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.anthropic_claude.v2 import (\n    AnthropicClaudeBlockV2,\n)\nfrom inference.core.workflows.core_steps.models.foundation.anthropic_claude.v3 import (\n    AnthropicClaudeBlockV3,\n)\nfrom inference.core.workflows.core_steps.models.foundation.clip.v1 import (\n    ClipModelBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.clip_comparison.v1 import (\n    ClipComparisonBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.clip_comparison.v2 import (\n    ClipComparisonBlockV2,\n)\nfrom inference.core.workflows.core_steps.models.foundation.cog_vlm.v1 import (\n    CogVLMBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.depth_estimation.v1 import (\n    DepthEstimationBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.easy_ocr.v1 import (\n    EasyOCRBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.florence2.v1 import (\n    Florence2BlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.florence2.v2 import (\n    Florence2BlockV2,\n)\nfrom inference.core.workflows.core_steps.models.foundation.gaze.v1 import GazeBlockV1\nfrom inference.core.workflows.core_steps.models.foundation.glm_ocr.v1 import (\n    GLMOCRBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.google_gemini.v1 import (\n    GoogleGeminiBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.google_gemini.v2 import (\n    GoogleGeminiBlockV2,\n)\nfrom inference.core.workflows.core_steps.models.foundation.google_gemini.v3 import (\n    GoogleGeminiBlockV3,\n)\nfrom inference.core.workflows.core_steps.models.foundation.google_vision_ocr.v1 import (\n    GoogleVisionOCRBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.llama_vision.v1 import (\n    LlamaVisionBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.lmm.v1 import LMMBlockV1\nfrom inference.core.workflows.core_steps.models.foundation.lmm_classifier.v1 import (\n    LMMForClassificationBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.moondream2.v1 import (\n    Moondream2BlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.ocr.v1 import OCRModelBlockV1\nfrom inference.core.workflows.core_steps.models.foundation.openai.v1 import (\n    OpenAIBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.openai.v2 import (\n    OpenAIBlockV2,\n)\nfrom inference.core.workflows.core_steps.models.foundation.openai.v3 import (\n    OpenAIBlockV3,\n)\nfrom inference.core.workflows.core_steps.models.foundation.openai.v4 import (\n    OpenAIBlockV4,\n)\nfrom inference.core.workflows.core_steps.models.foundation.perception_encoder.v1 import (\n    PerceptionEncoderModelBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.qwen3_5vl.v1 import (\n    Qwen35VLBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.qwen3vl.v1 import (\n    Qwen3VLBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.qwen.v1 import (\n    Qwen25VLBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.seg_preview.v1 import (\n    SegPreviewBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.segment_anything2.v1 import (\n    SegmentAnything2BlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.segment_anything3.v1 import (\n    SegmentAnything3BlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.segment_anything3.v2 import (\n    SegmentAnything3BlockV2,\n)\nfrom inference.core.workflows.core_steps.models.foundation.segment_anything3.v3 import (\n    SegmentAnything3BlockV3,\n)\n\nif SAM3_3D_OBJECTS_ENABLED:\n    from inference.core.workflows.core_steps.models.foundation.segment_anything3_3d.v1 import (\n        SegmentAnything3_3D_ObjectsBlockV1,\n    )\n\nfrom inference.core.workflows.core_steps.models.foundation.smolvlm.v1 import (\n    SmolVLM2BlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.stability_ai.image_gen.v1 import (\n    StabilityAIImageGenBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.stability_ai.inpainting.v1 import (\n    StabilityAIInpaintingBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.stability_ai.outpainting.v1 import (\n    StabilityAIOutpaintingBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.foundation.yolo_world.v1 import (\n    YoloWorldModelBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.roboflow.instance_segmentation.v1 import (\n    RoboflowInstanceSegmentationModelBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.roboflow.instance_segmentation.v2 import (\n    RoboflowInstanceSegmentationModelBlockV2,\n)\nfrom inference.core.workflows.core_steps.models.roboflow.keypoint_detection.v1 import (\n    RoboflowKeypointDetectionModelBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.roboflow.keypoint_detection.v2 import (\n    RoboflowKeypointDetectionModelBlockV2,\n)\nfrom inference.core.workflows.core_steps.models.roboflow.multi_class_classification.v1 import (\n    RoboflowClassificationModelBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.roboflow.multi_class_classification.v2 import (\n    RoboflowClassificationModelBlockV2,\n)\nfrom inference.core.workflows.core_steps.models.roboflow.multi_label_classification.v1 import (\n    RoboflowMultiLabelClassificationModelBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.roboflow.multi_label_classification.v2 import (\n    RoboflowMultiLabelClassificationModelBlockV2,\n)\nfrom inference.core.workflows.core_steps.models.roboflow.object_detection.v1 import (\n    RoboflowObjectDetectionModelBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.roboflow.object_detection.v2 import (\n    RoboflowObjectDetectionModelBlockV2,\n)\nfrom inference.core.workflows.core_steps.models.roboflow.semantic_segmentation.v1 import (\n    RoboflowSemanticSegmentationModelBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.third_party.barcode_detection.v1 import (\n    BarcodeDetectorBlockV1,\n)\nfrom inference.core.workflows.core_steps.models.third_party.qr_code_detection.v1 import (\n    QRCodeDetectorBlockV1,\n)\nfrom inference.core.workflows.core_steps.sampling.identify_changes.v1 import (\n    IdentifyChangesBlockV1,\n)\nfrom inference.core.workflows.core_steps.sampling.identify_outliers.v1 import (\n    IdentifyOutliersBlockV1,\n)\nfrom inference.core.workflows.core_steps.secrets_providers.environment_secrets_store.v1 import (\n    EnvironmentSecretsStoreBlockV1,\n)\nfrom inference.core.workflows.core_steps.sinks.email_notification.v1 import (\n    EmailNotificationBlockV1,\n)\nfrom inference.core.workflows.core_steps.sinks.email_notification.v2 import (\n    EmailNotificationBlockV2,\n)\nfrom inference.core.workflows.core_steps.sinks.local_file.v1 import LocalFileSinkBlockV1\nfrom inference.core.workflows.core_steps.sinks.onvif_movement.v1 import ONVIFSinkBlockV1\nfrom inference.core.workflows.core_steps.sinks.roboflow.custom_metadata.v1 import (\n    RoboflowCustomMetadataBlockV1,\n)\nfrom inference.core.workflows.core_steps.sinks.roboflow.dataset_upload.v1 import (\n    RoboflowDatasetUploadBlockV1,\n)\nfrom inference.core.workflows.core_steps.sinks.roboflow.dataset_upload.v2 import (\n    RoboflowDatasetUploadBlockV2,\n)\nfrom inference.core.workflows.core_steps.sinks.roboflow.model_monitoring_inference_aggregator.v1 import (\n    ModelMonitoringInferenceAggregatorBlockV1,\n)\nfrom inference.core.workflows.core_steps.sinks.s3.v1 import S3SinkBlockV1\nfrom inference.core.workflows.core_steps.sinks.slack.notification.v1 import (\n    SlackNotificationBlockV1,\n)\nfrom inference.core.workflows.core_steps.sinks.twilio.sms.v1 import (\n    TwilioSMSNotificationBlockV1,\n)\nfrom inference.core.workflows.core_steps.sinks.twilio.sms.v2 import (\n    TwilioSMSNotificationBlockV2,\n)\nfrom inference.core.workflows.core_steps.sinks.webhook.v1 import WebhookSinkBlockV1\nfrom inference.core.workflows.core_steps.trackers.bytetrack.v1 import (\n    ByteTrackBlockV1 as TrackerByteTrackBlockV1,\n)\nfrom inference.core.workflows.core_steps.trackers.ocsort.v1 import (\n    OCSORTBlockV1 as TrackerOCSORTBlockV1,\n)\nfrom inference.core.workflows.core_steps.trackers.sort.v1 import (\n    SORTBlockV1 as TrackerSORTBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.absolute_static_crop.v1 import (\n    AbsoluteStaticCropBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.bounding_rect.v1 import (\n    BoundingRectBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.byte_tracker.v1 import (\n    ByteTrackerBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.byte_tracker.v2 import (\n    ByteTrackerBlockV2,\n)\nfrom inference.core.workflows.core_steps.transformations.byte_tracker.v3 import (\n    ByteTrackerBlockV3,\n)\nfrom inference.core.workflows.core_steps.transformations.camera_calibration.v1 import (\n    CameraCalibrationBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.detection_offset.v1 import (\n    DetectionOffsetBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.detections_combine.v1 import (\n    DetectionsCombineBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.detections_filter.v1 import (\n    DetectionsFilterBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.detections_merge.v1 import (\n    DetectionsMergeBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.detections_transformation.v1 import (\n    DetectionsTransformationBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.dynamic_crop.v1 import (\n    DynamicCropBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.dynamic_zones.v1 import (\n    DynamicZonesBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.image_slicer.v1 import (\n    ImageSlicerBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.image_slicer.v2 import (\n    ImageSlicerBlockV2,\n)\nfrom inference.core.workflows.core_steps.transformations.perspective_correction.v1 import (\n    PerspectiveCorrectionBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.qr_code_generator.v1 import (\n    QRCodeGeneratorBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.relative_static_crop.v1 import (\n    RelativeStaticCropBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.stabilize_detections.v1 import (\n    StabilizeTrackedDetectionsBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.stitch_images.v1 import (\n    StitchImagesBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.stitch_ocr_detections.v1 import (\n    StitchOCRDetectionsBlockV1,\n)\nfrom inference.core.workflows.core_steps.transformations.stitch_ocr_detections.v2 import (\n    StitchOCRDetectionsBlockV2,\n)\n\n# Visualizers\nfrom inference.core.workflows.core_steps.visualizations.background_color.v1 import (\n    BackgroundColorVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.blur.v1 import (\n    BlurVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.bounding_box.v1 import (\n    BoundingBoxVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.circle.v1 import (\n    CircleVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.classification_label.v1 import (\n    ClassificationLabelVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.color.v1 import (\n    ColorVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.corner.v1 import (\n    CornerVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.crop.v1 import (\n    CropVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.dot.v1 import (\n    DotVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.ellipse.v1 import (\n    EllipseVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.grid.v1 import (\n    GridVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.halo.v1 import (\n    HaloVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.halo.v2 import (\n    HaloVisualizationBlockV2,\n)\nfrom inference.core.workflows.core_steps.visualizations.heatmap.v1 import (\n    HeatmapVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.icon.v1 import (\n    IconVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.keypoint.v1 import (\n    KeypointVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.label.v1 import (\n    LabelVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.line_zone.v1 import (\n    LineCounterZoneVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.mask.v1 import (\n    MaskVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.model_comparison.v1 import (\n    ModelComparisonVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.pixelate.v1 import (\n    PixelateVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.polygon.v1 import (\n    PolygonVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.polygon.v2 import (\n    PolygonVisualizationBlockV2,\n)\nfrom inference.core.workflows.core_steps.visualizations.polygon_zone.v1 import (\n    PolygonZoneVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.reference_path.v1 import (\n    ReferencePathVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.text_display.v1 import (\n    TextDisplayVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.trace.v1 import (\n    TraceVisualizationBlockV1,\n)\nfrom inference.core.workflows.core_steps.visualizations.triangle.v1 import (\n    TriangleVisualizationBlockV1,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    BAR_CODE_DETECTION_KIND,\n    BOOLEAN_KIND,\n    BYTES_KIND,\n    CLASSIFICATION_PREDICTION_KIND,\n    CONTOURS_KIND,\n    DETECTION_KIND,\n    DICTIONARY_KIND,\n    EMBEDDING_KIND,\n    FLOAT_KIND,\n    FLOAT_ZERO_TO_ONE_KIND,\n    IMAGE_KEYPOINTS_KIND,\n    IMAGE_KIND,\n    IMAGE_METADATA_KIND,\n    INFERENCE_ID_KIND,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    INTEGER_KIND,\n    KEYPOINT_DETECTION_PREDICTION_KIND,\n    LANGUAGE_MODEL_OUTPUT_KIND,\n    LIST_OF_VALUES_KIND,\n    NUMPY_ARRAY_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    PARENT_ID_KIND,\n    POINT_KIND,\n    PREDICTION_TYPE_KIND,\n    QR_CODE_DETECTION_KIND,\n    RGB_COLOR_KIND,\n    RLE_INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    ROBOFLOW_API_KEY_KIND,\n    ROBOFLOW_MANAGED_KEY,\n    ROBOFLOW_MODEL_ID_KIND,\n    ROBOFLOW_PROJECT_KIND,\n    SECRET_KIND,\n    SEMANTIC_SEGMENTATION_PREDICTION_KIND,\n    SERIALISED_PAYLOADS_KIND,\n    STRING_KIND,\n    TIMESTAMP_KIND,\n    TOP_CLASS_KIND,\n    VIDEO_METADATA_KIND,\n    WILDCARD_KIND,\n    ZONE_KIND,\n    Kind,\n)\nfrom inference.core.workflows.prototypes.block import WorkflowBlock\n\nREGISTERED_INITIALIZERS = {\n    \"api_key\": API_KEY,\n    \"cache\": cache,\n    \"step_execution_mode\": StepExecutionMode(WORKFLOWS_STEP_EXECUTION_MODE),\n    \"background_tasks\": None,\n    \"thread_pool_executor\": None,\n    \"allow_access_to_file_system\": ALLOW_WORKFLOW_BLOCKS_ACCESSING_LOCAL_STORAGE,\n    \"allowed_write_directory\": WORKFLOW_BLOCKS_WRITE_DIRECTORY,\n    \"allow_access_to_environmental_variables\": ALLOW_WORKFLOW_BLOCKS_ACCESSING_ENVIRONMENTAL_VARIABLES,\n}\n\nKINDS_SERIALIZERS = {\n    IMAGE_KIND.name: serialise_image,\n    VIDEO_METADATA_KIND.name: serialize_video_metadata_kind,\n    OBJECT_DETECTION_PREDICTION_KIND.name: serialise_sv_detections,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND.name: serialise_sv_detections,\n    RLE_INSTANCE_SEGMENTATION_PREDICTION_KIND.name: serialise_rle_sv_detections,\n    KEYPOINT_DETECTION_PREDICTION_KIND.name: serialise_sv_detections,\n    SEMANTIC_SEGMENTATION_PREDICTION_KIND.name: serialise_rle_sv_detections,\n    QR_CODE_DETECTION_KIND.name: serialise_sv_detections,\n    BAR_CODE_DETECTION_KIND.name: serialise_sv_detections,\n    SECRET_KIND.name: serialize_secret,\n    WILDCARD_KIND.name: serialize_wildcard_kind,\n    TIMESTAMP_KIND.name: serialize_timestamp,\n}\nKINDS_DESERIALIZERS = {\n    IMAGE_KIND.name: deserialize_image_kind,\n    VIDEO_METADATA_KIND.name: deserialize_video_metadata_kind,\n    OBJECT_DETECTION_PREDICTION_KIND.name: deserialize_detections_kind,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND.name: deserialize_detections_kind,\n    RLE_INSTANCE_SEGMENTATION_PREDICTION_KIND.name: deserialize_rle_detections_kind,\n    KEYPOINT_DETECTION_PREDICTION_KIND.name: deserialize_detections_kind,\n    QR_CODE_DETECTION_KIND.name: deserialize_detections_kind,\n    BAR_CODE_DETECTION_KIND.name: deserialize_detections_kind,\n    NUMPY_ARRAY_KIND.name: deserialize_numpy_array,\n    ROBOFLOW_MODEL_ID_KIND.name: deserialize_string_kind,\n    ROBOFLOW_PROJECT_KIND.name: deserialize_string_kind,\n    ROBOFLOW_API_KEY_KIND.name: deserialize_optional_string_kind,\n    ROBOFLOW_MANAGED_KEY.name: deserialize_optional_string_kind,\n    FLOAT_ZERO_TO_ONE_KIND.name: deserialize_float_zero_to_one_kind,\n    LIST_OF_VALUES_KIND.name: deserialize_list_of_values_kind,\n    BOOLEAN_KIND.name: deserialize_boolean_kind,\n    INTEGER_KIND.name: deserialize_integer_kind,\n    STRING_KIND.name: deserialize_string_kind,\n    TOP_CLASS_KIND.name: deserialize_string_kind,\n    FLOAT_KIND.name: deserialize_float_kind,\n    DICTIONARY_KIND.name: deserialize_dictionary_kind,\n    SEMANTIC_SEGMENTATION_PREDICTION_KIND.name: deserialize_rle_detections_kind,\n    CLASSIFICATION_PREDICTION_KIND.name: deserialize_classification_prediction_kind,\n    POINT_KIND.name: deserialize_point_kind,\n    ZONE_KIND.name: deserialize_zone_kind,\n    RGB_COLOR_KIND.name: deserialize_rgb_color_kind,\n    LANGUAGE_MODEL_OUTPUT_KIND.name: deserialize_string_kind,\n    PREDICTION_TYPE_KIND.name: deserialize_string_kind,\n    PARENT_ID_KIND.name: deserialize_string_kind,\n    BYTES_KIND.name: deserialize_bytes_kind,\n    INFERENCE_ID_KIND.name: deserialize_string_kind,\n    TIMESTAMP_KIND.name: deserialize_timestamp,\n}\n\n\ndef _should_filter_block(block_class: Type[WorkflowBlock]) -> bool:\n    \"\"\"\n    Check if a block should be filtered out based on configuration.\n\n    Returns True if the block should be filtered (removed), False if it should be kept.\n    \"\"\"\n    if not WORKFLOW_DISABLED_BLOCK_TYPES and not WORKFLOW_DISABLED_BLOCK_PATTERNS:\n        return False\n\n    try:\n        # Get block manifest to check block type\n        manifest_class = block_class.get_manifest()\n        schema = manifest_class.model_json_schema()\n        # Note: Pydantic puts json_schema_extra values at top level of schema\n        block_type = schema.get(\"block_type\", \"\")\n\n        # Check if block type category is disabled\n        if block_type and block_type.lower() in WORKFLOW_DISABLED_BLOCK_TYPES:\n            return True\n\n        # Get the block identifier for pattern matching\n        # We'll check multiple identifiers to be thorough:\n        # 1. The block class name\n        # 2. The full module path\n        # 3. The block name from schema if available\n        block_class_name = block_class.__name__.lower()\n        block_module = block_class.__module__.lower()\n        block_name = schema.get(\"name\", \"\").lower()\n\n        # Check patterns against various identifiers\n        for pattern in WORKFLOW_DISABLED_BLOCK_PATTERNS:\n            pattern_lower = pattern.lower()\n            if (\n                pattern_lower in block_class_name\n                or pattern_lower in block_module\n                or pattern_lower in block_name\n            ):\n                return True\n\n    except Exception:\n        # If we can't determine block info, don't filter it\n        # This ensures we don't accidentally filter blocks due to errors\n        pass\n\n    return False\n\n\ndef load_blocks() -> List[Type[WorkflowBlock]]:\n    blocks = [\n        AbsoluteStaticCropBlockV1,\n        DynamicCropBlockV1,\n        DetectionsFilterBlockV1,\n        DetectionOffsetBlockV1,\n        DepthEstimationBlockV1,\n        ByteTrackerBlockV1,\n        RelativeStaticCropBlockV1,\n        DetectionsTransformationBlockV1,\n        RoboflowDatasetUploadBlockV1,\n        ContinueIfBlockV1,\n        RateLimiterBlockV1,\n        PerspectiveCorrectionBlockV1,\n        DeltaFilterBlockV1,\n        CameraCalibrationBlockV1,\n        DynamicZonesBlockV1,\n        SizeMeasurementBlockV1,\n        BufferBlockV1,\n        DetectionsClassesReplacementBlockV1,\n        ExpressionBlockV1,\n        PropertyDefinitionBlockV1,\n        DimensionCollapseBlockV1,\n        DetectionsListRollUpBlockV1,\n        FirstNonEmptyOrDefaultBlockV1,\n        AnthropicClaudeBlockV1,\n        AnthropicClaudeBlockV2,\n        AnthropicClaudeBlockV3,\n        CosineSimilarityBlockV1,\n        BackgroundColorVisualizationBlockV1,\n        BarcodeDetectorBlockV1,\n        BlurVisualizationBlockV1,\n        BoundingBoxVisualizationBlockV1,\n        BoundingRectBlockV1,\n        DetectionsMergeBlockV1,\n        ByteTrackerBlockV2,\n        CacheGetBlockV1,\n        CacheSetBlockV1,\n        CameraFocusBlockV1,\n        CameraFocusBlockV2,\n        CircleVisualizationBlockV1,\n        ClipComparisonBlockV1,\n        ClipComparisonBlockV2,\n        ClipModelBlockV1,\n        PerceptionEncoderModelBlockV1,\n        CogVLMBlockV1,\n        ColorVisualizationBlockV1,\n        ConvertGrayscaleBlockV1,\n        ContrastEqualizationBlockV1,\n        CornerVisualizationBlockV1,\n        CropVisualizationBlockV1,\n        DetectionsConsensusBlockV1,\n        DetectionsStitchBlockV1,\n        DistanceMeasurementBlockV1,\n        DominantColorBlockV1,\n        DotVisualizationBlockV1,\n        EllipseVisualizationBlockV1,\n        Florence2BlockV1,\n        Florence2BlockV2,\n        GoogleGeminiBlockV1,\n        GoogleGeminiBlockV2,\n        GoogleGeminiBlockV3,\n        GoogleVisionOCRBlockV1,\n        GridVisualizationBlockV1,\n        HaloVisualizationBlockV1,\n        HaloVisualizationBlockV2,\n        IconVisualizationBlockV1,\n        ImageBlurBlockV1,\n        ImageContoursDetectionBlockV1,\n        ImagePreprocessingBlockV1,\n        ImageSlicerBlockV1,\n        HeatmapVisualizationBlockV1,\n        ImageThresholdBlockV1,\n        MotionDetectionBlockV1,\n        BackgroundSubtractionBlockV1,\n        JSONParserBlockV1,\n        LMMBlockV1,\n        LMMForClassificationBlockV1,\n        LabelVisualizationBlockV1,\n        ClassificationLabelVisualizationBlockV1,\n        LineCounterBlockV1,\n        LineCounterBlockV2,\n        LineCounterZoneVisualizationBlockV1,\n        MaskVisualizationBlockV1,\n        ModelComparisonVisualizationBlockV1,\n        MorphologicalTransformationBlockV1,\n        OCRModelBlockV1,\n        OpenAIBlockV1,\n        OpenAIBlockV2,\n        OpenAIBlockV3,\n        OpenAIBlockV4,\n        PathDeviationAnalyticsBlockV1,\n        PathDeviationAnalyticsBlockV2,\n        PixelateVisualizationBlockV1,\n        PixelationCountBlockV1,\n        PolygonVisualizationBlockV1,\n        PolygonVisualizationBlockV2,\n        PolygonZoneVisualizationBlockV1,\n        QRCodeDetectorBlockV1,\n        RoboflowClassificationModelBlockV1,\n        RoboflowCustomMetadataBlockV1,\n        ModelMonitoringInferenceAggregatorBlockV1,\n        RoboflowDatasetUploadBlockV2,\n        RoboflowInstanceSegmentationModelBlockV1,\n        RoboflowKeypointDetectionModelBlockV1,\n        RoboflowMultiLabelClassificationModelBlockV1,\n        RoboflowObjectDetectionModelBlockV1,\n        SIFTBlockV1,\n        SIFTComparisonBlockV1,\n        SIFTComparisonBlockV2,\n        SegmentAnything2BlockV1,\n        SegmentAnything3BlockV1,\n        SegmentAnything3BlockV2,\n        SegmentAnything3BlockV3,\n        SegPreviewBlockV1,\n        StabilityAIInpaintingBlockV1,\n        StabilityAIImageGenBlockV1,\n        StabilityAIOutpaintingBlockV1,\n        StabilizeTrackedDetectionsBlockV1,\n        StitchImagesBlockV1,\n        StitchOCRDetectionsBlockV2,\n        StitchOCRDetectionsBlockV1,\n        TemplateMatchingBlockV1,\n        TimeInZoneBlockV1,\n        TimeInZoneBlockV2,\n        TimeInZoneBlockV3,\n        TriangleVisualizationBlockV1,\n        TextDisplayVisualizationBlockV1,\n        VLMAsClassifierBlockV1,\n        VLMAsDetectorBlockV1,\n        YoloWorldModelBlockV1,\n        KeypointVisualizationBlockV1,\n        DataAggregatorBlockV1,\n        DetectionEventLogBlockV1,\n        CSVFormatterBlockV1,\n        EmailNotificationBlockV1,\n        EmailNotificationBlockV2,\n        LocalFileSinkBlockV1,\n        S3SinkBlockV1,\n        TraceVisualizationBlockV1,\n        ReferencePathVisualizationBlockV1,\n        ByteTrackerBlockV3,\n        TrackerByteTrackBlockV1,\n        TrackerSORTBlockV1,\n        TrackerOCSORTBlockV1,\n        WebhookSinkBlockV1,\n        VelocityBlockV1,\n        RoboflowInstanceSegmentationModelBlockV2,\n        RoboflowSemanticSegmentationModelBlockV1,\n        RoboflowKeypointDetectionModelBlockV2,\n        RoboflowClassificationModelBlockV2,\n        RoboflowMultiLabelClassificationModelBlockV2,\n        RoboflowObjectDetectionModelBlockV2,\n        VLMAsClassifierBlockV2,\n        VLMAsDetectorBlockV2,\n        IdentifyOutliersBlockV1,\n        IdentifyChangesBlockV1,\n        EnvironmentSecretsStoreBlockV1,\n        SlackNotificationBlockV1,\n        TwilioSMSNotificationBlockV1,\n        TwilioSMSNotificationBlockV2,\n        GazeBlockV1,\n        LlamaVisionBlockV1,\n        ImageSlicerBlockV2,\n        Qwen25VLBlockV1,\n        Qwen3VLBlockV1,\n        Qwen35VLBlockV1,\n        SmolVLM2BlockV1,\n        Moondream2BlockV1,\n        OverlapBlockV1,\n        ONVIFSinkBlockV1,\n        GLMOCRBlockV1,\n        EasyOCRBlockV1,\n        QRCodeGeneratorBlockV1,\n        DetectionsCombineBlockV1,\n        MaskAreaMeasurementBlockV1,\n    ]\n    if SAM3_3D_OBJECTS_ENABLED:\n        blocks.append(SegmentAnything3_3D_ObjectsBlockV1)\n\n    # Filter blocks if any disable configuration is set\n    if WORKFLOW_DISABLED_BLOCK_TYPES or WORKFLOW_DISABLED_BLOCK_PATTERNS:\n        filtered_blocks = [block for block in blocks if not _should_filter_block(block)]\n        return filtered_blocks\n\n    return blocks\n\n\ndef load_kinds() -> List[Kind]:\n    return [\n        WILDCARD_KIND,\n        IMAGE_KIND,\n        VIDEO_METADATA_KIND,\n        ROBOFLOW_MODEL_ID_KIND,\n        ROBOFLOW_PROJECT_KIND,\n        ROBOFLOW_API_KEY_KIND,\n        FLOAT_ZERO_TO_ONE_KIND,\n        LIST_OF_VALUES_KIND,\n        SERIALISED_PAYLOADS_KIND,\n        BOOLEAN_KIND,\n        INTEGER_KIND,\n        STRING_KIND,\n        TOP_CLASS_KIND,\n        FLOAT_KIND,\n        DICTIONARY_KIND,\n        DETECTION_KIND,\n        CLASSIFICATION_PREDICTION_KIND,\n        POINT_KIND,\n        ZONE_KIND,\n        OBJECT_DETECTION_PREDICTION_KIND,\n        INSTANCE_SEGMENTATION_PREDICTION_KIND,\n        KEYPOINT_DETECTION_PREDICTION_KIND,\n        SEMANTIC_SEGMENTATION_PREDICTION_KIND,\n        RGB_COLOR_KIND,\n        IMAGE_KEYPOINTS_KIND,\n        CONTOURS_KIND,\n        LANGUAGE_MODEL_OUTPUT_KIND,\n        NUMPY_ARRAY_KIND,\n        QR_CODE_DETECTION_KIND,\n        BAR_CODE_DETECTION_KIND,\n        PREDICTION_TYPE_KIND,\n        ROBOFLOW_MANAGED_KEY,\n        PARENT_ID_KIND,\n        IMAGE_METADATA_KIND,\n        BYTES_KIND,\n        INFERENCE_ID_KIND,\n        SECRET_KIND,\n        EMBEDDING_KIND,\n        TIMESTAMP_KIND,\n    ]\n",
    "patch": null
  },
  {
    "trace_id": "74fb7728-6d23-429c-be66-6d3c6863d02f",
    "function_name": "WithFixedSizeCache.memory_pressure_detected",
    "file_path": "inference/core/managers/decorators/fixed_size_cache.py",
    "speedup_x": 916.0940777655444,
    "review_quality": "high",
    "pre_optimization_commit": "43153d3e62370958317efa40875b161d78c28ff6",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def memory_pressure_detected(self) -> bool:\n        return_boolean = False\n        try:\n            import torch\n\n            if torch.cuda.is_available():\n                free_memory, total_memory = torch.cuda.mem_get_info()\n                return_boolean = (\n                    float(free_memory / total_memory) < MEMORY_FREE_THRESHOLD\n                )\n                if return_boolean and USE_INFERENCE_MODELS:\n                    # we only enable this under condition that USE_INFERENCE_MODELS is True\n                    # and we are about to remove a model\n                    # just to make sure we are not flapping around the threshold for no reason\n                    torch.cuda.empty_cache()\n                    free_memory, total_memory = torch.cuda.mem_get_info()\n                    return_boolean = (\n                        float(free_memory / total_memory) < MEMORY_FREE_THRESHOLD\n                    )\n                logger.debug(\n                    f\"Free memory: {free_memory}, Total memory: {total_memory}, threshold: {MEMORY_FREE_THRESHOLD}, return_boolean: {return_boolean}\"\n                )\n            # TODO: Add memory calculation for other non-CUDA devices\n        except Exception as e:\n            logger.error(\n                f\"Failed to check CUDA memory pressure: {e}, returning {return_boolean}\"\n            )\n        return return_boolean\n",
    "optimized_function_code": "from collections import deque\nfrom inference.core import logger\nfrom inference.core.env import MEMORY_FREE_THRESHOLD, USE_INFERENCE_MODELS\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.managers.decorators.base import ModelManagerDecorator\nfrom threading import Lock\n\n# Move torch import to module level to avoid repeated import overhead\ntry:\n    import torch\n    _CUDA_AVAILABLE = torch.cuda.is_available()\nexcept ImportError:\n    _CUDA_AVAILABLE = False\n\nclass WithFixedSizeCache(ModelManagerDecorator):\n    def __init__(self, model_manager: ModelManager, max_size: int = 8):\n        \"\"\"Cache decorator, models will be evicted based on the last utilization (`.infer` call). Internally, a [double-ended queue](https://docs.python.org/3/library/collections.html#collections.deque) is used to keep track of model utilization.\n\n        Args:\n            model_manager (ModelManager): Instance of a ModelManager.\n            max_size (int, optional): Max number of models at the same time. Defaults to 8.\n        \"\"\"\n        super().__init__(model_manager)\n        self.max_size = max_size\n        self._key_queue = deque(self.model_manager.keys())\n        self._queue_lock = Lock()\n\n    def memory_pressure_detected(self) -> bool:\n        if not _CUDA_AVAILABLE:\n            return False\n        \n        return_boolean = False\n        try:\n            free_memory, total_memory = torch.cuda.mem_get_info()\n            return_boolean = (\n                float(free_memory / total_memory) < MEMORY_FREE_THRESHOLD\n            )\n            if return_boolean and USE_INFERENCE_MODELS:\n                # we only enable this under condition that USE_INFERENCE_MODELS is True\n                # and we are about to remove a model\n                # just to make sure we are not flapping around the threshold for no reason\n                torch.cuda.empty_cache()\n                free_memory, total_memory = torch.cuda.mem_get_info()\n                return_boolean = (\n                    float(free_memory / total_memory) < MEMORY_FREE_THRESHOLD\n                )\n            logger.debug(\n                f\"Free memory: {free_memory}, Total memory: {total_memory}, threshold: {MEMORY_FREE_THRESHOLD}, return_boolean: {return_boolean}\"\n            )\n            # TODO: Add memory calculation for other non-CUDA devices\n        except Exception as e:\n            logger.error(\n                f\"Failed to check CUDA memory pressure: {e}, returning {return_boolean}\"\n            )\n        return return_boolean",
    "optimized_raw_markdown": "```python:inference/core/managers/decorators/fixed_size_cache.py\nfrom collections import deque\nfrom inference.core import logger\nfrom inference.core.env import MEMORY_FREE_THRESHOLD, USE_INFERENCE_MODELS\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.managers.decorators.base import ModelManagerDecorator\nfrom threading import Lock\n\n# Move torch import to module level to avoid repeated import overhead\ntry:\n    import torch\n    _CUDA_AVAILABLE = torch.cuda.is_available()\nexcept ImportError:\n    _CUDA_AVAILABLE = False\n\nclass WithFixedSizeCache(ModelManagerDecorator):\n    def __init__(self, model_manager: ModelManager, max_size: int = 8):\n        \"\"\"Cache decorator, models will be evicted based on the last utilization (`.infer` call). Internally, a [double-ended queue](https://docs.python.org/3/library/collections.html#collections.deque) is used to keep track of model utilization.\n\n        Args:\n            model_manager (ModelManager): Instance of a ModelManager.\n            max_size (int, optional): Max number of models at the same time. Defaults to 8.\n        \"\"\"\n        super().__init__(model_manager)\n        self.max_size = max_size\n        self._key_queue = deque(self.model_manager.keys())\n        self._queue_lock = Lock()\n\n    def memory_pressure_detected(self) -> bool:\n        if not _CUDA_AVAILABLE:\n            return False\n        \n        return_boolean = False\n        try:\n            free_memory, total_memory = torch.cuda.mem_get_info()\n            return_boolean = (\n                float(free_memory / total_memory) < MEMORY_FREE_THRESHOLD\n            )\n            if return_boolean and USE_INFERENCE_MODELS:\n                # we only enable this under condition that USE_INFERENCE_MODELS is True\n                # and we are about to remove a model\n                # just to make sure we are not flapping around the threshold for no reason\n                torch.cuda.empty_cache()\n                free_memory, total_memory = torch.cuda.mem_get_info()\n                return_boolean = (\n                    float(free_memory / total_memory) < MEMORY_FREE_THRESHOLD\n                )\n            logger.debug(\n                f\"Free memory: {free_memory}, Total memory: {total_memory}, threshold: {MEMORY_FREE_THRESHOLD}, return_boolean: {return_boolean}\"\n            )\n            # TODO: Add memory calculation for other non-CUDA devices\n        except Exception as e:\n            logger.error(\n                f\"Failed to check CUDA memory pressure: {e}, returning {return_boolean}\"\n            )\n        return return_boolean\n```",
    "optimized_function_only": "    def memory_pressure_detected(self) -> bool:\n        if not _CUDA_AVAILABLE:\n            return False\n        \n        return_boolean = False\n        try:\n            free_memory, total_memory = torch.cuda.mem_get_info()\n            return_boolean = (\n                float(free_memory / total_memory) < MEMORY_FREE_THRESHOLD\n            )\n            if return_boolean and USE_INFERENCE_MODELS:\n                # we only enable this under condition that USE_INFERENCE_MODELS is True\n                # and we are about to remove a model\n                # just to make sure we are not flapping around the threshold for no reason\n                torch.cuda.empty_cache()\n                free_memory, total_memory = torch.cuda.mem_get_info()\n                return_boolean = (\n                    float(free_memory / total_memory) < MEMORY_FREE_THRESHOLD\n                )\n            logger.debug(\n                f\"Free memory: {free_memory}, Total memory: {total_memory}, threshold: {MEMORY_FREE_THRESHOLD}, return_boolean: {return_boolean}\"\n            )\n            # TODO: Add memory calculation for other non-CUDA devices\n        except Exception as e:\n            logger.error(\n                f\"Failed to check CUDA memory pressure: {e}, returning {return_boolean}\"\n            )\n        return return_boolean",
    "original_file_content": "import gc\nfrom collections import deque\nfrom threading import Lock\nfrom typing import List, Optional\n\nfrom inference.core import logger\nfrom inference.core.entities.requests.inference import InferenceRequest\nfrom inference.core.entities.responses.inference import InferenceResponse\nfrom inference.core.env import (\n    DISK_CACHE_CLEANUP,\n    HOT_MODELS_QUEUE_LOCK_ACQUIRE_TIMEOUT,\n    MEMORY_FREE_THRESHOLD,\n    MODELS_CACHE_AUTH_ENABLED,\n    USE_INFERENCE_MODELS,\n)\nfrom inference.core.exceptions import (\n    ModelManagerLockAcquisitionError,\n    RoboflowAPINotAuthorizedError,\n)\nfrom inference.core.managers.base import Model, ModelManager, acquire_with_timeout\nfrom inference.core.managers.decorators.base import ModelManagerDecorator\nfrom inference.core.managers.entities import ModelDescription\nfrom inference.core.managers.model_load_collector import request_model_ids\nfrom inference.core.registries.roboflow import (\n    ModelEndpointType,\n    _check_if_api_key_has_access_to_model,\n)\n\n\nclass WithFixedSizeCache(ModelManagerDecorator):\n    def __init__(self, model_manager: ModelManager, max_size: int = 8):\n        \"\"\"Cache decorator, models will be evicted based on the last utilization (`.infer` call). Internally, a [double-ended queue](https://docs.python.org/3/library/collections.html#collections.deque) is used to keep track of model utilization.\n\n        Args:\n            model_manager (ModelManager): Instance of a ModelManager.\n            max_size (int, optional): Max number of models at the same time. Defaults to 8.\n        \"\"\"\n        super().__init__(model_manager)\n        self.max_size = max_size\n        self._key_queue = deque(self.model_manager.keys())\n        self._queue_lock = Lock()\n        self._pinned_models: set = set()\n\n    def pin_model(self, model_id: str) -> None:\n        \"\"\"Mark a model as pinned so it won't be evicted by the LRU cache.\n\n        Pinned models (typically preloaded models) are protected from eviction\n        when the cache is full or under memory pressure.\n        \"\"\"\n        self._pinned_models.add(model_id)\n        logger.debug(f\"Model '{model_id}' pinned \u2014 will not be evicted from cache.\")\n\n    def add_model(\n        self,\n        model_id: str,\n        api_key: str,\n        model_id_alias: Optional[str] = None,\n        endpoint_type: ModelEndpointType = ModelEndpointType.ORT,\n        countinference: Optional[bool] = None,\n        service_secret: Optional[str] = None,\n    ) -> None:\n        \"\"\"Adds a model to the manager and evicts the least recently used if the cache is full.\n\n        Args:\n            model_id (str): The identifier of the model.\n            model (Model): The model instance.\n            endpoint_type (ModelEndpointType, optional): The endpoint type to use for the model.\n        \"\"\"\n        if MODELS_CACHE_AUTH_ENABLED:\n            if not _check_if_api_key_has_access_to_model(\n                api_key=api_key,\n                model_id=model_id,\n                endpoint_type=endpoint_type,\n                countinference=countinference,\n                service_secret=service_secret,\n            ):\n                raise RoboflowAPINotAuthorizedError(\n                    f\"API key {api_key} does not have access to model {model_id}\"\n                )\n\n        queue_id = self._resolve_queue_id(\n            model_id=model_id, model_id_alias=model_id_alias\n        )\n        ids_collector = request_model_ids.get(None)\n        if ids_collector is not None:\n            ids_collector.add(queue_id)\n        if queue_id in self:\n            logger.debug(\n                f\"Detected {queue_id} in WithFixedSizeCache models queue -> marking as most recently used.\"\n            )\n            self._refresh_model_position_in_a_queue(model_id=queue_id)\n            return None\n\n        logger.debug(f\"Current capacity of ModelManager: {len(self)}/{self.max_size}\")\n        with acquire_with_timeout(\n            lock=self._queue_lock, timeout=HOT_MODELS_QUEUE_LOCK_ACQUIRE_TIMEOUT\n        ) as acquired:\n            if not acquired:\n                raise ModelManagerLockAcquisitionError(\n                    \"Could not acquire lock on Model Manager state to add model from active models queue.\"\n                )\n            while self._key_queue and (\n                len(self) >= self.max_size\n                or (MEMORY_FREE_THRESHOLD and self.memory_pressure_detected())\n            ):\n                # To prevent flapping around the threshold, remove up to 3 models to make some space.\n                if not self._key_queue:\n                    logger.error(\n                        \"Tried to remove model from cache even though key queue is already empty! \"\n                        \"(max_size: %s, len(self): %s, MEMORY_FREE_THRESHOLD: %s)\",\n                        self.max_size,\n                        len(self),\n                        MEMORY_FREE_THRESHOLD,\n                    )\n                    break\n                evicted_count = 0\n                skipped_pinned = []\n                while evicted_count < 3 and self._key_queue:\n                    to_remove_model_id = self._key_queue.popleft()\n                    if to_remove_model_id in self._pinned_models:\n                        skipped_pinned.append(to_remove_model_id)\n                        continue\n                    super().remove(\n                        to_remove_model_id, delete_from_disk=DISK_CACHE_CLEANUP\n                    )  # LRU model overflow cleanup may or maynot need the weights removed from disk\n                    logger.debug(f\"Model {to_remove_model_id} successfully unloaded.\")\n                    evicted_count += 1\n                # Put pinned models back at the front of the queue\n                for mid in reversed(skipped_pinned):\n                    self._key_queue.appendleft(mid)\n                if evicted_count == 0:\n                    logger.warning(\n                        \"Cannot free model cache space \u2014 all remaining models are pinned (preloaded). \"\n                        \"Proceeding with cache exceeding max_size.\"\n                    )\n                    break\n                gc.collect()\n            logger.debug(f\"Marking new model {queue_id} as most recently used.\")\n            self._key_queue.append(queue_id)\n        try:\n            return super().add_model(\n                model_id,\n                api_key,\n                model_id_alias=model_id_alias,\n                endpoint_type=endpoint_type,\n                countinference=countinference,\n                service_secret=service_secret,\n            )\n        except Exception as error:\n            logger.debug(\n                f\"Could not initialise model {queue_id}. Removing from WithFixedSizeCache models queue.\"\n            )\n            with acquire_with_timeout(\n                lock=self._queue_lock, timeout=HOT_MODELS_QUEUE_LOCK_ACQUIRE_TIMEOUT\n            ) as acquired:\n                if not acquired:\n                    raise ModelManagerLockAcquisitionError(\n                        \"Could not acquire lock on Model Manager state to remove model from active models queue.\"\n                    )\n                self._safe_remove_model_from_queue(queue_id)\n            raise error\n\n    def clear(self) -> None:\n        \"\"\"Removes all models from the manager.\"\"\"\n        for model_id in list(self.keys()):\n            self.remove(model_id)\n\n    def remove(self, model_id: str, delete_from_disk: bool = True) -> Model:\n        with acquire_with_timeout(\n            lock=self._queue_lock, timeout=HOT_MODELS_QUEUE_LOCK_ACQUIRE_TIMEOUT\n        ) as acquired:\n            if not acquired:\n                raise ModelManagerLockAcquisitionError(\n                    \"Could not acquire lock on Model Manager state to remove model from active models queue.\"\n                )\n            self._safe_remove_model_from_queue(model_id=model_id)\n        return super().remove(model_id, delete_from_disk=delete_from_disk)\n\n    async def infer_from_request(\n        self, model_id: str, request: InferenceRequest, **kwargs\n    ) -> InferenceResponse:\n        \"\"\"Processes a complete inference request and updates the cache.\n\n        Args:\n            model_id (str): The identifier of the model.\n            request (InferenceRequest): The request to process.\n\n        Returns:\n            InferenceResponse: The response from the inference.\n        \"\"\"\n        self._refresh_model_position_in_a_queue(model_id=model_id)\n        return await super().infer_from_request(model_id, request, **kwargs)\n\n    def infer_from_request_sync(\n        self, model_id: str, request: InferenceRequest, **kwargs\n    ) -> InferenceResponse:\n        \"\"\"Processes a complete inference request and updates the cache.\n\n        Args:\n            model_id (str): The identifier of the model.\n            request (InferenceRequest): The request to process.\n\n        Returns:\n            InferenceResponse: The response from the inference.\n        \"\"\"\n        self._refresh_model_position_in_a_queue(model_id=model_id)\n        return super().infer_from_request_sync(model_id, request, **kwargs)\n\n    def infer_only(self, model_id: str, request, img_in, img_dims, batch_size=None):\n        \"\"\"Performs only the inference part of a request and updates the cache.\n\n        Args:\n            model_id (str): The identifier of the model.\n            request: The request to process.\n            img_in: Input image.\n            img_dims: Image dimensions.\n            batch_size (int, optional): Batch size.\n\n        Returns:\n            Response from the inference-only operation.\n        \"\"\"\n        self._refresh_model_position_in_a_queue(model_id=model_id)\n        return super().infer_only(model_id, request, img_in, img_dims, batch_size)\n\n    def preprocess(self, model_id: str, request):\n        \"\"\"Processes the preprocessing part of a request and updates the cache.\n\n        Args:\n            model_id (str): The identifier of the model.\n            request (InferenceRequest): The request to preprocess.\n        \"\"\"\n        self._refresh_model_position_in_a_queue(model_id=model_id)\n        return super().preprocess(model_id, request)\n\n    def describe_models(self) -> List[ModelDescription]:\n        return self.model_manager.describe_models()\n\n    def _resolve_queue_id(\n        self, model_id: str, model_id_alias: Optional[str] = None\n    ) -> str:\n        return model_id if model_id_alias is None else model_id_alias\n\n    def _refresh_model_position_in_a_queue(self, model_id: str) -> None:\n        with acquire_with_timeout(\n            lock=self._queue_lock, timeout=HOT_MODELS_QUEUE_LOCK_ACQUIRE_TIMEOUT\n        ) as acquired:\n            if not acquired:\n                raise ModelManagerLockAcquisitionError(\n                    \"Could not acquire lock on Model Manager state to refresh model position in active models queue.\"\n                )\n            self._safe_remove_model_from_queue(model_id=model_id)\n            self._key_queue.append(model_id)\n\n    def _safe_remove_model_from_queue(self, model_id: str) -> None:\n        try:\n            while model_id in self._key_queue:\n                self._key_queue.remove(model_id)\n        except ValueError:\n            logger.warning(\n                f\"Could not successfully purge model {model_id} from  WithFixedSizeCache models queue - \"\n                f\"model id not found.\"\n            )\n\n    def memory_pressure_detected(self) -> bool:\n        return_boolean = False\n        try:\n            import torch\n\n            if torch.cuda.is_available():\n                free_memory, total_memory = torch.cuda.mem_get_info()\n                return_boolean = (\n                    float(free_memory / total_memory) < MEMORY_FREE_THRESHOLD\n                )\n                if return_boolean and USE_INFERENCE_MODELS:\n                    # we only enable this under condition that USE_INFERENCE_MODELS is True\n                    # and we are about to remove a model\n                    # just to make sure we are not flapping around the threshold for no reason\n                    torch.cuda.empty_cache()\n                    free_memory, total_memory = torch.cuda.mem_get_info()\n                    return_boolean = (\n                        float(free_memory / total_memory) < MEMORY_FREE_THRESHOLD\n                    )\n                logger.debug(\n                    f\"Free memory: {free_memory}, Total memory: {total_memory}, threshold: {MEMORY_FREE_THRESHOLD}, return_boolean: {return_boolean}\"\n                )\n            # TODO: Add memory calculation for other non-CUDA devices\n        except Exception as e:\n            logger.error(\n                f\"Failed to check CUDA memory pressure: {e}, returning {return_boolean}\"\n            )\n        return return_boolean\n",
    "patch": null
  },
  {
    "trace_id": "1b11b2d7-042d-47e2-af5c-9ba63adcd295",
    "function_name": "try_releasing_cuda_memory",
    "file_path": "inference/core/managers/base.py",
    "speedup_x": 0.21915130869522595,
    "review_quality": "medium",
    "pre_optimization_commit": "3d23a0e028b2aba8cea9eaf037e6ebccad8cac97",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def try_releasing_cuda_memory() -> None:\n    if not USE_INFERENCE_MODELS:\n        # For now, we only want to have purge CUDA memory when USE_INFERENCE_MODELS is True\n        return None\n    try:\n        import torch\n\n        if torch.cuda.is_available():\n            torch.cuda.empty_cache()\n    except ImportError:\n        pass\n    except Exception as error:\n        logger.warning(f\"Attempted to purge CUDA memory but failed with error: {error}\")\n",
    "optimized_function_code": "from inference.core.env import USE_INFERENCE_MODELS\nfrom inference.core.logger import logger\n\n# Cache torch module at import time if needed\n_torch = None\nif USE_INFERENCE_MODELS:\n    try:\n        import torch\n        _torch = torch\n    except ImportError:\n        pass\n\ndef try_releasing_cuda_memory() -> None:\n    if not USE_INFERENCE_MODELS or _torch is None:\n        # For now, we only want to have purge CUDA memory when USE_INFERENCE_MODELS is True\n        # For now, we only want to have purge CUDA memory when USE_INFERENCE_MODELS is True\n        return None\n    try:\n        if _torch.cuda.is_available():\n            _torch.cuda.empty_cache()\n    except Exception as error:\n        logger.warning(f\"Attempted to purge CUDA memory but failed with error: {error}\")",
    "optimized_raw_markdown": "```python:inference/core/managers/base.py\nfrom inference.core.env import USE_INFERENCE_MODELS\nfrom inference.core.logger import logger\n\n# Cache torch module at import time if needed\n_torch = None\nif USE_INFERENCE_MODELS:\n    try:\n        import torch\n        _torch = torch\n    except ImportError:\n        pass\n\ndef try_releasing_cuda_memory() -> None:\n    if not USE_INFERENCE_MODELS or _torch is None:\n        # For now, we only want to have purge CUDA memory when USE_INFERENCE_MODELS is True\n        # For now, we only want to have purge CUDA memory when USE_INFERENCE_MODELS is True\n        return None\n    try:\n        if _torch.cuda.is_available():\n            _torch.cuda.empty_cache()\n    except Exception as error:\n        logger.warning(f\"Attempted to purge CUDA memory but failed with error: {error}\")\n```",
    "optimized_function_only": "def try_releasing_cuda_memory() -> None:\n    if not USE_INFERENCE_MODELS or _torch is None:\n        # For now, we only want to have purge CUDA memory when USE_INFERENCE_MODELS is True\n        # For now, we only want to have purge CUDA memory when USE_INFERENCE_MODELS is True\n        return None\n    try:\n        if _torch.cuda.is_available():\n            _torch.cuda.empty_cache()\n    except Exception as error:\n        logger.warning(f\"Attempted to purge CUDA memory but failed with error: {error}\")",
    "original_file_content": "import time\nfrom contextlib import contextmanager\nfrom threading import Lock\nfrom typing import Dict, Generator, List, Optional, Tuple, Union\n\nimport numpy as np\nfrom fastapi.encoders import jsonable_encoder\n\nfrom inference.core.cache import cache\nfrom inference.core.cache.serializers import to_cachable_inference_item\nfrom inference.core.devices.utils import GLOBAL_INFERENCE_SERVER_ID\nfrom inference.core.entities.requests.inference import InferenceRequest\nfrom inference.core.entities.responses.inference import InferenceResponse\nfrom inference.core.env import (\n    DISABLE_INFERENCE_CACHE,\n    INTERNAL_WEIGHTS_URL_SUFFIX,\n    METRICS_ENABLED,\n    METRICS_INTERVAL,\n    MODEL_LOCK_ACQUIRE_TIMEOUT,\n    MODELS_CACHE_AUTH_ENABLED,\n    ROBOFLOW_SERVER_UUID,\n    USE_INFERENCE_MODELS,\n)\nfrom inference.core.exceptions import (\n    InferenceModelNotFound,\n    ModelManagerLockAcquisitionError,\n    RoboflowAPINotAuthorizedError,\n)\nfrom inference.core.logger import logger\nfrom inference.core.managers.entities import ModelDescription\nfrom inference.core.managers.model_load_collector import (\n    model_load_info,\n    request_model_ids,\n)\nfrom inference.core.managers.pingback import PingbackInfo\nfrom inference.core.models.base import Model, PreprocessReturnMetadata\nfrom inference.core.registries.base import ModelRegistry\nfrom inference.core.registries.roboflow import (\n    ModelEndpointType,\n    _check_if_api_key_has_access_to_model,\n)\nfrom inference.core.telemetry import (\n    record_error,\n    record_inference,\n    record_model_loaded,\n    record_model_unloaded,\n    set_span_attribute,\n    start_span,\n)\n\n\nclass ModelManager:\n    \"\"\"Model managers keep track of a dictionary of Model objects and is responsible for passing requests to the right model using the infer method.\"\"\"\n\n    def __init__(self, model_registry: ModelRegistry, models: Optional[dict] = None):\n        self.model_registry = model_registry\n        self._models: Dict[str, Model] = models if models is not None else {}\n        self.pingback = None\n        self._state_lock = Lock()\n        self._models_state_locks: Dict[str, Lock] = {}\n\n    def init_pingback(self):\n        \"\"\"Initializes pingback mechanism.\"\"\"\n        self.num_errors = 0  # in the device\n        self.uuid = ROBOFLOW_SERVER_UUID\n        if METRICS_ENABLED:\n            self.pingback = PingbackInfo(self)\n            self.pingback.start()\n\n    def add_model(\n        self,\n        model_id: str,\n        api_key: str,\n        model_id_alias: Optional[str] = None,\n        endpoint_type: ModelEndpointType = ModelEndpointType.ORT,\n        countinference: Optional[bool] = None,\n        service_secret: Optional[str] = None,\n    ) -> None:\n        \"\"\"Adds a new model to the manager.\n\n        Args:\n            model_id (str): The identifier of the model.\n            model (Model): The model instance.\n            endpoint_type (ModelEndpointType, optional): The endpoint type to use for the model.\n        \"\"\"\n        if MODELS_CACHE_AUTH_ENABLED:\n            if not _check_if_api_key_has_access_to_model(\n                api_key=api_key,\n                model_id=model_id,\n                endpoint_type=endpoint_type,\n                countinference=countinference,\n                service_secret=service_secret,\n            ):\n                raise RoboflowAPINotAuthorizedError(\n                    f\"API key {api_key} does not have access to model {model_id}\"\n                )\n\n        logger.debug(\n            f\"ModelManager - Adding model with model_id={model_id}, model_id_alias={model_id_alias}\"\n        )\n        resolved_identifier = model_id if model_id_alias is None else model_id_alias\n        ids_collector = request_model_ids.get(None)\n        if ids_collector is not None:\n            ids_collector.add(resolved_identifier)\n        model_lock = self._get_lock_for_a_model(model_id=resolved_identifier)\n        with acquire_with_timeout(lock=model_lock) as acquired:\n            if not acquired:\n                # if failed to acquire - then in use, no need to purge lock\n                raise ModelManagerLockAcquisitionError(\n                    f\"Could not acquire lock for model with id={resolved_identifier}.\"\n                )\n            if resolved_identifier in self._models:\n                logger.debug(\n                    f\"ModelManager - model with model_id={resolved_identifier} is already loaded.\"\n                )\n                return\n            try:\n                with start_span(\"model.load\", {\"model.id\": resolved_identifier}):\n                    logger.debug(\"ModelManager - model initialisation...\")\n                    t_load_start = time.perf_counter()\n                    model_class = self.model_registry.get_model(\n                        resolved_identifier,\n                        api_key,\n                        countinference=countinference,\n                        service_secret=service_secret,\n                    )\n\n                    model = model_class(\n                        model_id=model_id,\n                        api_key=api_key,\n                        countinference=countinference,\n                        service_secret=service_secret,\n                    )\n\n                    # Pass countinference and service_secret to download_model_artifacts_from_roboflow_api if available\n                    if (\n                        hasattr(model, \"download_model_artifacts_from_roboflow_api\")\n                        and INTERNAL_WEIGHTS_URL_SUFFIX == \"serverless\"\n                    ):\n                        # Only pass these parameters if INTERNAL_WEIGHTS_URL_SUFFIX is \"serverless\"\n                        if (\n                            hasattr(model, \"cache_model_artefacts\")\n                            and not model.has_model_metadata\n                        ):\n                            # Override the download_model_artifacts_from_roboflow_api method with parameters\n                            original_method = (\n                                model.download_model_artifacts_from_roboflow_api\n                            )\n                            model.download_model_artifacts_from_roboflow_api = (\n                                lambda: original_method(\n                                    countinference=countinference,\n                                    service_secret=service_secret,\n                                )\n                            )\n\n                    load_time = time.perf_counter() - t_load_start\n                    set_span_attribute(\"model.load_time_seconds\", load_time)\n                    record_model_loaded(resolved_identifier, load_time)\n                    logger.debug(\n                        f\"ModelManager - model successfully loaded in {load_time:.2f}s.\"\n                    )\n                    self._models[resolved_identifier] = model\n                    collector = model_load_info.get(None)\n                    if collector is not None:\n                        collector.record(\n                            model_id=resolved_identifier, load_time=load_time\n                        )\n            except Exception as error:\n                record_error(error)\n                self._dispose_model_lock(model_id=resolved_identifier)\n                raise error\n\n    def check_for_model(self, model_id: str) -> None:\n        \"\"\"Checks whether the model with the given ID is in the manager.\n\n        Args:\n            model_id (str): The identifier of the model.\n\n        Raises:\n            InferenceModelNotFound: If the model is not found in the manager.\n        \"\"\"\n        if model_id not in self:\n            raise InferenceModelNotFound(f\"Model with id {model_id} not loaded.\")\n\n    async def infer_from_request(\n        self, model_id: str, request: InferenceRequest, **kwargs\n    ) -> InferenceResponse:\n        \"\"\"Runs inference on the specified model with the given request.\n\n        Args:\n            model_id (str): The identifier of the model.\n            request (InferenceRequest): The request to process.\n\n        Returns:\n            InferenceResponse: The response from the inference.\n        \"\"\"\n        logger.debug(\n            f\"ModelManager - inference from request started for model_id={model_id}.\"\n        )\n        enable_model_monitoring = not getattr(\n            request, \"disable_model_monitoring\", False\n        )\n        if METRICS_ENABLED and self.pingback and enable_model_monitoring:\n            logger.debug(\"ModelManager - setting pingback fallback api key...\")\n            self.pingback.fallback_api_key = request.api_key\n        with start_span(\n            \"model.infer\",\n            {\"model.id\": model_id, \"model.infer.caller\": \"infer_from_request\"},\n        ):\n            try:\n                t_infer_start = time.perf_counter()\n                rtn_val = await self.model_infer(\n                    model_id=model_id, request=request, **kwargs\n                )\n                record_inference(model_id, time.perf_counter() - t_infer_start)\n                logger.debug(\n                    f\"ModelManager - inference from request finished for model_id={model_id}.\"\n                )\n                finish_time = time.time()\n                if not DISABLE_INFERENCE_CACHE and enable_model_monitoring:\n                    with start_span(\"model.infer.cache\"):\n                        try:\n                            logger.debug(\n                                f\"ModelManager - caching inference request started for model_id={model_id}\"\n                            )\n                            cache.zadd(\n                                f\"models\",\n                                value=f\"{GLOBAL_INFERENCE_SERVER_ID}:{request.api_key}:{model_id}\",\n                                score=finish_time,\n                                expire=METRICS_INTERVAL * 2,\n                            )\n                            if (\n                                hasattr(request, \"image\")\n                                and hasattr(request.image, \"type\")\n                                and request.image.type == \"numpy\"\n                            ):\n                                request.image.value = str(request.image.value)\n                            cache.zadd(\n                                f\"inference:{GLOBAL_INFERENCE_SERVER_ID}:{model_id}\",\n                                value=to_cachable_inference_item(request, rtn_val),\n                                score=finish_time,\n                                expire=METRICS_INTERVAL * 2,\n                            )\n                            logger.debug(\n                                f\"ModelManager - caching inference request finished for model_id={model_id}\"\n                            )\n                        except Exception as cache_error:\n                            logger.warning(\n                                f\"Failed to cache inference data for model {model_id}: {cache_error}\"\n                            )\n                return rtn_val\n            except Exception as e:\n                record_error(e)\n                finish_time = time.time()\n                if not DISABLE_INFERENCE_CACHE and enable_model_monitoring:\n                    with start_span(\"model.infer.cache_error\"):\n                        try:\n                            cache.zadd(\n                                f\"models\",\n                                value=f\"{GLOBAL_INFERENCE_SERVER_ID}:{request.api_key}:{model_id}\",\n                                score=finish_time,\n                                expire=METRICS_INTERVAL * 2,\n                            )\n                            cache.zadd(\n                                f\"error:{GLOBAL_INFERENCE_SERVER_ID}:{model_id}\",\n                                value={\n                                    \"request\": jsonable_encoder(\n                                        request.dict(\n                                            exclude={\"image\", \"subject\", \"prompt\"}\n                                        )\n                                    ),\n                                    \"error\": str(e),\n                                },\n                                score=finish_time,\n                                expire=METRICS_INTERVAL * 2,\n                            )\n                        except Exception as cache_error:\n                            logger.warning(\n                                f\"Failed to cache error data for model {model_id}: {cache_error}\"\n                            )\n                raise\n\n    def infer_from_request_sync(\n        self, model_id: str, request: InferenceRequest, **kwargs\n    ) -> InferenceResponse:\n        \"\"\"Runs inference on the specified model with the given request.\n\n        Args:\n            model_id (str): The identifier of the model.\n            request (InferenceRequest): The request to process.\n\n        Returns:\n            InferenceResponse: The response from the inference.\n        \"\"\"\n        logger.debug(\n            f\"ModelManager - inference from request started for model_id={model_id}.\"\n        )\n        enable_model_monitoring = not getattr(\n            request, \"disable_model_monitoring\", False\n        )\n        if METRICS_ENABLED and self.pingback and enable_model_monitoring:\n            logger.debug(\"ModelManager - setting pingback fallback api key...\")\n            self.pingback.fallback_api_key = request.api_key\n        with start_span(\n            \"model.infer\",\n            {\"model.id\": model_id, \"model.infer.caller\": \"infer_from_request_sync\"},\n        ):\n            try:\n                t_infer_start = time.perf_counter()\n                rtn_val = self.model_infer_sync(\n                    model_id=model_id, request=request, **kwargs\n                )\n                record_inference(model_id, time.perf_counter() - t_infer_start)\n                logger.debug(\n                    f\"ModelManager - inference from request finished for model_id={model_id}.\"\n                )\n                finish_time = time.time()\n                if not DISABLE_INFERENCE_CACHE and enable_model_monitoring:\n                    with start_span(\"model.infer.cache\"):\n                        try:\n                            logger.debug(\n                                f\"ModelManager - caching inference request started for model_id={model_id}\"\n                            )\n                            cache.zadd(\n                                f\"models\",\n                                value=f\"{GLOBAL_INFERENCE_SERVER_ID}:{request.api_key}:{model_id}\",\n                                score=finish_time,\n                                expire=METRICS_INTERVAL * 2,\n                            )\n                            if (\n                                hasattr(request, \"image\")\n                                and hasattr(request.image, \"type\")\n                                and request.image.type == \"numpy\"\n                            ):\n                                request.image.value = str(request.image.value)\n                            cache.zadd(\n                                f\"inference:{GLOBAL_INFERENCE_SERVER_ID}:{model_id}\",\n                                value=to_cachable_inference_item(request, rtn_val),\n                                score=finish_time,\n                                expire=METRICS_INTERVAL * 2,\n                            )\n                            logger.debug(\n                                f\"ModelManager - caching inference request finished for model_id={model_id}\"\n                            )\n                        except Exception as cache_error:\n                            logger.warning(\n                                f\"Failed to cache inference data for model {model_id}: {cache_error}\"\n                            )\n                return rtn_val\n            except Exception as e:\n                record_error(e)\n                finish_time = time.time()\n                if not DISABLE_INFERENCE_CACHE and enable_model_monitoring:\n                    with start_span(\"model.infer.cache_error\"):\n                        try:\n                            cache.zadd(\n                                f\"models\",\n                                value=f\"{GLOBAL_INFERENCE_SERVER_ID}:{request.api_key}:{model_id}\",\n                                score=finish_time,\n                                expire=METRICS_INTERVAL * 2,\n                            )\n                            cache.zadd(\n                                f\"error:{GLOBAL_INFERENCE_SERVER_ID}:{model_id}\",\n                                value={\n                                    \"request\": jsonable_encoder(\n                                        request.dict(\n                                            exclude={\"image\", \"subject\", \"prompt\"}\n                                        )\n                                    ),\n                                    \"error\": str(e),\n                                },\n                                score=finish_time,\n                                expire=METRICS_INTERVAL * 2,\n                            )\n                        except Exception as cache_error:\n                            logger.warning(\n                                f\"Failed to cache error data for model {model_id}: {cache_error}\"\n                            )\n                raise\n\n    async def model_infer(self, model_id: str, request: InferenceRequest, **kwargs):\n        model = self._get_model_reference(model_id=model_id)\n        return model.infer_from_request(request)\n\n    def model_infer_sync(\n        self, model_id: str, request: InferenceRequest, **kwargs\n    ) -> Union[List[InferenceResponse], InferenceResponse]:\n        model = self._get_model_reference(model_id=model_id)\n        return model.infer_from_request(request)\n\n    def make_response(\n        self, model_id: str, predictions: List[List[float]], *args, **kwargs\n    ) -> InferenceResponse:\n        \"\"\"Creates a response object from the model's predictions.\n\n        Args:\n            model_id (str): The identifier of the model.\n            predictions (List[List[float]]): The model's predictions.\n\n        Returns:\n            InferenceResponse: The created response object.\n        \"\"\"\n        model = self._get_model_reference(model_id=model_id)\n        return model.make_response(predictions, *args, **kwargs)\n\n    def postprocess(\n        self,\n        model_id: str,\n        predictions: Tuple[np.ndarray, ...],\n        preprocess_return_metadata: PreprocessReturnMetadata,\n        *args,\n        **kwargs,\n    ) -> List[List[float]]:\n        \"\"\"Processes the model's predictions after inference.\n\n        Args:\n            model_id (str): The identifier of the model.\n            predictions (np.ndarray): The model's predictions.\n\n        Returns:\n            List[List[float]]: The post-processed predictions.\n        \"\"\"\n        model = self._get_model_reference(model_id=model_id)\n        return model.postprocess(\n            predictions, preprocess_return_metadata, *args, **kwargs\n        )\n\n    def predict(self, model_id: str, *args, **kwargs) -> Tuple[np.ndarray, ...]:\n        \"\"\"Runs prediction on the specified model.\n\n        Args:\n            model_id (str): The identifier of the model.\n\n        Returns:\n            np.ndarray: The predictions from the model.\n        \"\"\"\n        model = self._get_model_reference(model_id=model_id)\n        model.metrics[\"num_inferences\"] += 1\n        tic = time.perf_counter()\n        res = model.predict(*args, **kwargs)\n        toc = time.perf_counter()\n        model.metrics[\"avg_inference_time\"] += toc - tic\n        return res\n\n    def preprocess(\n        self, model_id: str, request: InferenceRequest\n    ) -> Tuple[np.ndarray, PreprocessReturnMetadata]:\n        \"\"\"Preprocesses the request before inference.\n\n        Args:\n            model_id (str): The identifier of the model.\n            request (InferenceRequest): The request to preprocess.\n\n        Returns:\n            Tuple[np.ndarray, List[Tuple[int, int]]]: The preprocessed data.\n        \"\"\"\n        model = self._get_model_reference(model_id=model_id)\n        return model.preprocess(**request.dict())\n\n    def get_class_names(self, model_id):\n        \"\"\"Retrieves the class names for a given model.\n\n        Args:\n            model_id (str): The identifier of the model.\n\n        Returns:\n            List[str]: The class names of the model.\n        \"\"\"\n        model = self._get_model_reference(model_id=model_id)\n        return model.class_names\n\n    def get_task_type(self, model_id: str, api_key: str = None) -> str:\n        \"\"\"Retrieves the task type for a given model.\n\n        Args:\n            model_id (str): The identifier of the model.\n\n        Returns:\n            str: The task type of the model.\n        \"\"\"\n        model = self._get_model_reference(model_id=model_id)\n        return model.task_type\n\n    def remove(self, model_id: str, delete_from_disk: bool = True) -> None:\n        \"\"\"Removes a model from the manager.\n\n        Args:\n            model_id (str): The identifier of the model.\n        \"\"\"\n        try:\n            logger.debug(f\"Removing model {model_id} from base model manager\")\n            model_lock = self._get_lock_for_a_model(model_id=model_id)\n            with acquire_with_timeout(lock=model_lock) as acquired:\n                if not acquired:\n                    raise ModelManagerLockAcquisitionError(\n                        f\"Could not acquire lock for model with id={model_id}.\"\n                    )\n                if model_id not in self._models:\n                    return None\n                self._models[model_id].clear_cache(delete_from_disk=delete_from_disk)\n                del self._models[model_id]\n                record_model_unloaded(model_id)\n                self._dispose_model_lock(model_id=model_id)\n                try_releasing_cuda_memory()\n        except InferenceModelNotFound:\n            logger.warning(\n                f\"Attempted to remove model with id {model_id}, but it is not loaded. Skipping...\"\n            )\n\n    def clear(self) -> None:\n        \"\"\"Removes all models from the manager.\"\"\"\n        model_ids = list(self.keys())\n        for model_id in model_ids:\n            self.remove(model_id)\n\n    def _get_model_reference(self, model_id: str) -> Model:\n        try:\n            return self._models[model_id]\n        except KeyError as error:\n            raise InferenceModelNotFound(\n                f\"Model with id {model_id} not loaded.\"\n            ) from error\n\n    def __contains__(self, model_id: str) -> bool:\n        \"\"\"Checks if the model is contained in the manager.\n\n        Args:\n            model_id (str): The identifier of the model.\n\n        Returns:\n            bool: Whether the model is in the manager.\n        \"\"\"\n        return model_id in self._models\n\n    def __getitem__(self, key: str) -> Model:\n        \"\"\"Retrieve a model from the manager by key.\n\n        Args:\n            key (str): The identifier of the model.\n\n        Returns:\n            Model: The model corresponding to the key.\n        \"\"\"\n        return self._get_model_reference(model_id=key)\n\n    def __len__(self) -> int:\n        \"\"\"Retrieve the number of models in the manager.\n\n        Returns:\n            int: The number of models in the manager.\n        \"\"\"\n        return len(self._models)\n\n    def keys(self):\n        \"\"\"Retrieve the keys (model identifiers) from the manager.\n\n        Returns:\n            List[str]: The keys of the models in the manager.\n        \"\"\"\n        return self._models.keys()\n\n    def models(self) -> Dict[str, Model]:\n        \"\"\"Retrieve the models dictionary from the manager.\n\n        Returns:\n            Dict[str, Model]: The keys of the models in the manager.\n        \"\"\"\n        return self._models\n\n    def describe_models(self) -> List[ModelDescription]:\n        return [\n            ModelDescription(\n                model_id=model_id,\n                task_type=model.task_type,\n                batch_size=getattr(model, \"batch_size\", None),\n                input_width=getattr(model, \"img_size_w\", None),\n                input_height=getattr(model, \"img_size_h\", None),\n            )\n            for model_id, model in self._models.items()\n        ]\n\n    def _get_lock_for_a_model(self, model_id: str) -> Lock:\n        with acquire_with_timeout(lock=self._state_lock) as acquired:\n            if not acquired:\n                raise ModelManagerLockAcquisitionError(\n                    \"Could not acquire lock on Model Manager state to retrieve model lock.\"\n                )\n            if model_id not in self._models_state_locks:\n                self._models_state_locks[model_id] = Lock()\n            return self._models_state_locks[model_id]\n\n    def _dispose_model_lock(self, model_id: str) -> None:\n        with acquire_with_timeout(lock=self._state_lock) as acquired:\n            if not acquired:\n                raise ModelManagerLockAcquisitionError(\n                    \"Could not acquire lock on Model Manager state to dispose model lock.\"\n                )\n            if model_id not in self._models_state_locks:\n                return None\n            del self._models_state_locks[model_id]\n\n\n@contextmanager\ndef acquire_with_timeout(\n    lock: Lock, timeout: float = MODEL_LOCK_ACQUIRE_TIMEOUT\n) -> Generator[bool, None, None]:\n    acquired = lock.acquire(timeout=timeout)\n    try:\n        yield acquired\n    finally:\n        if acquired:\n            lock.release()\n\n\ndef try_releasing_cuda_memory() -> None:\n    if not USE_INFERENCE_MODELS:\n        # For now, we only want to have purge CUDA memory when USE_INFERENCE_MODELS is True\n        return None\n    try:\n        import torch\n\n        if torch.cuda.is_available():\n            torch.cuda.empty_cache()\n    except ImportError:\n        pass\n    except Exception as error:\n        logger.warning(f\"Attempted to purge CUDA memory but failed with error: {error}\")\n",
    "patch": null
  },
  {
    "trace_id": "581f1a3b-f695-4395-99a2-d13e0212f175",
    "function_name": "deserialize_detections_kind",
    "file_path": "inference/core/workflows/core_steps/common/deserializers.py",
    "speedup_x": 0.15433215558971777,
    "review_quality": "high",
    "pre_optimization_commit": "5e6c1f06431d953c2efa8ed663b5f086ece874f3",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def deserialize_detections_kind(\n    parameter: str,\n    detections: Any,\n) -> sv.Detections:\n    if isinstance(detections, sv.Detections):\n        return detections\n    if not isinstance(detections, dict):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"detections, but invalid type of data found.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    if \"predictions\" not in detections or \"image\" not in detections:\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"detections, but dictionary misses required keys.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    parsed_detections = sv.Detections.from_inference(detections)\n    if len(parsed_detections) == 0:\n        return parsed_detections\n    height, width = detections[\"image\"][\"height\"], detections[\"image\"][\"width\"]\n    image_metadata = np.array([[height, width]] * len(parsed_detections))\n    parsed_detections.data[IMAGE_DIMENSIONS_KEY] = image_metadata\n    raw_predictions = detections[\"predictions\"]\n    if len(parsed_detections) != len(raw_predictions):\n        raw_predictions = filter_out_invalid_polygons(predictions=raw_predictions)\n    detection_ids = [\n        detection.get(DETECTION_ID_KEY, str(uuid4())) for detection in raw_predictions\n    ]\n    parsed_detections.data[DETECTION_ID_KEY] = np.array(detection_ids)\n\n    parent_ids = [\n        detection.get(PARENT_ID_KEY, parameter) for detection in raw_predictions\n    ]\n    parsed_detections[PARENT_ID_KEY] = np.array(parent_ids)\n\n    _attach_parent_coordinates_and_dimensions(\n        parameter=parameter,\n        raw_detections=raw_predictions,\n        parsed_detections=parsed_detections,\n        origin_key=PARENT_ORIGIN_KEY,\n        coordinates_key=PARENT_COORDINATES_KEY,\n        dimensions_key=PARENT_DIMENSIONS_KEY,\n    )\n\n    root_parent_ids = [\n        detection.get(ROOT_PARENT_ID_KEY, parameter) for detection in raw_predictions\n    ]\n    if root_parent_ids:\n        parsed_detections.data[ROOT_PARENT_ID_KEY] = np.array(root_parent_ids)\n\n        _attach_parent_coordinates_and_dimensions(\n            parameter=parameter,\n            raw_detections=raw_predictions,\n            parsed_detections=parsed_detections,\n            origin_key=ROOT_PARENT_ORIGIN_KEY,\n            coordinates_key=ROOT_PARENT_COORDINATES_KEY,\n            dimensions_key=ROOT_PARENT_DIMENSIONS_KEY,\n        )\n\n    optional_elements_keys = [\n        (PATH_DEVIATION_KEY_IN_INFERENCE_RESPONSE, PATH_DEVIATION_KEY_IN_SV_DETECTIONS),\n        (TIME_IN_ZONE_KEY_IN_INFERENCE_RESPONSE, TIME_IN_ZONE_KEY_IN_SV_DETECTIONS),\n        (POLYGON_KEY_IN_INFERENCE_RESPONSE, POLYGON_KEY_IN_SV_DETECTIONS),\n        (\n            BOUNDING_RECT_ANGLE_KEY_IN_INFERENCE_RESPONSE,\n            BOUNDING_RECT_ANGLE_KEY_IN_SV_DETECTIONS,\n        ),\n        (\n            BOUNDING_RECT_RECT_KEY_IN_INFERENCE_RESPONSE,\n            BOUNDING_RECT_RECT_KEY_IN_SV_DETECTIONS,\n        ),\n        (\n            BOUNDING_RECT_HEIGHT_KEY_IN_INFERENCE_RESPONSE,\n            BOUNDING_RECT_HEIGHT_KEY_IN_SV_DETECTIONS,\n        ),\n        (\n            BOUNDING_RECT_WIDTH_KEY_IN_INFERENCE_RESPONSE,\n            BOUNDING_RECT_WIDTH_KEY_IN_SV_DETECTIONS,\n        ),\n        (DETECTED_CODE_KEY, DETECTED_CODE_KEY),\n        (SPEED_KEY_IN_INFERENCE_RESPONSE, SPEED_KEY_IN_SV_DETECTIONS),\n        (SMOOTHED_SPEED_KEY_IN_INFERENCE_RESPONSE, SMOOTHED_SPEED_KEY_IN_SV_DETECTIONS),\n        (\n            SMOOTHED_VELOCITY_KEY_IN_INFERENCE_RESPONSE,\n            SMOOTHED_VELOCITY_KEY_IN_SV_DETECTIONS,\n        ),\n        (VELOCITY_KEY_IN_INFERENCE_RESPONSE, VELOCITY_KEY_IN_SV_DETECTIONS),\n        (AREA_KEY_IN_INFERENCE_RESPONSE, AREA_KEY_IN_SV_DETECTIONS),\n        (AREA_CONVERTED_KEY_IN_INFERENCE_RESPONSE, AREA_CONVERTED_KEY_IN_SV_DETECTIONS),\n    ]\n    for raw_detection_key, parsed_detection_key in optional_elements_keys:\n        parsed_detections = _attach_optional_detection_element(\n            raw_detections=raw_predictions,\n            parsed_detections=parsed_detections,\n            raw_detection_key=raw_detection_key,\n            parsed_detection_key=parsed_detection_key,\n        )\n    return _attach_optional_key_points_detections(\n        raw_detections=raw_predictions,\n        parsed_detections=parsed_detections,\n    )\n",
    "optimized_function_code": "from typing import Any, List\nfrom uuid import uuid4\n\nimport numpy as np\nimport supervision as sv\nfrom inference.core.workflows.core_steps.common.utils import (\n    add_inference_keypoints_to_sv_detections, filter_out_invalid_polygons)\nfrom inference.core.workflows.errors import RuntimeInputError\nfrom inference.core.workflows.execution_engine.constants import (\n    AREA_CONVERTED_KEY_IN_INFERENCE_RESPONSE,\n    AREA_CONVERTED_KEY_IN_SV_DETECTIONS, AREA_KEY_IN_INFERENCE_RESPONSE,\n    AREA_KEY_IN_SV_DETECTIONS, BOUNDING_RECT_ANGLE_KEY_IN_INFERENCE_RESPONSE,\n    BOUNDING_RECT_ANGLE_KEY_IN_SV_DETECTIONS,\n    BOUNDING_RECT_HEIGHT_KEY_IN_INFERENCE_RESPONSE,\n    BOUNDING_RECT_HEIGHT_KEY_IN_SV_DETECTIONS,\n    BOUNDING_RECT_RECT_KEY_IN_INFERENCE_RESPONSE,\n    BOUNDING_RECT_RECT_KEY_IN_SV_DETECTIONS,\n    BOUNDING_RECT_WIDTH_KEY_IN_INFERENCE_RESPONSE,\n    BOUNDING_RECT_WIDTH_KEY_IN_SV_DETECTIONS, DETECTED_CODE_KEY,\n    DETECTION_ID_KEY, IMAGE_DIMENSIONS_KEY,\n    KEYPOINTS_KEY_IN_INFERENCE_RESPONSE, PARENT_COORDINATES_KEY,\n    PARENT_DIMENSIONS_KEY, PARENT_ID_KEY, PARENT_ORIGIN_KEY,\n    PATH_DEVIATION_KEY_IN_INFERENCE_RESPONSE,\n    PATH_DEVIATION_KEY_IN_SV_DETECTIONS, POLYGON_KEY_IN_INFERENCE_RESPONSE,\n    POLYGON_KEY_IN_SV_DETECTIONS, ROOT_PARENT_COORDINATES_KEY,\n    ROOT_PARENT_DIMENSIONS_KEY, ROOT_PARENT_ID_KEY, ROOT_PARENT_ORIGIN_KEY,\n    SMOOTHED_SPEED_KEY_IN_INFERENCE_RESPONSE,\n    SMOOTHED_SPEED_KEY_IN_SV_DETECTIONS,\n    SMOOTHED_VELOCITY_KEY_IN_INFERENCE_RESPONSE,\n    SMOOTHED_VELOCITY_KEY_IN_SV_DETECTIONS, SPEED_KEY_IN_INFERENCE_RESPONSE,\n    SPEED_KEY_IN_SV_DETECTIONS, TIME_IN_ZONE_KEY_IN_INFERENCE_RESPONSE,\n    TIME_IN_ZONE_KEY_IN_SV_DETECTIONS, VELOCITY_KEY_IN_INFERENCE_RESPONSE,\n    VELOCITY_KEY_IN_SV_DETECTIONS)\n\n\ndef deserialize_detections_kind(\n    parameter: str,\n    detections: Any,\n) -> sv.Detections:\n    if isinstance(detections, sv.Detections):\n        return detections\n    if not isinstance(detections, dict):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"detections, but invalid type of data found.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    if \"predictions\" not in detections or \"image\" not in detections:\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"detections, but dictionary misses required keys.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    parsed_detections = sv.Detections.from_inference(detections)\n    if len(parsed_detections) == 0:\n        return parsed_detections\n    height, width = detections[\"image\"][\"height\"], detections[\"image\"][\"width\"]\n    # Use numpy tiling to avoid creating a Python list of identical lists\n    image_metadata = np.tile(np.array([height, width]), (len(parsed_detections), 1))\n    parsed_detections.data[IMAGE_DIMENSIONS_KEY] = image_metadata\n    raw_predictions = detections[\"predictions\"]\n    if len(parsed_detections) != len(raw_predictions):\n        raw_predictions = filter_out_invalid_polygons(predictions=raw_predictions)\n    detection_ids = [\n        detection[DETECTION_ID_KEY] if DETECTION_ID_KEY in detection else str(uuid4())\n        for detection in raw_predictions\n    ]\n    parsed_detections.data[DETECTION_ID_KEY] = np.array(detection_ids)\n\n    parent_ids = [\n        detection[PARENT_ID_KEY] if PARENT_ID_KEY in detection else parameter\n        for detection in raw_predictions\n    ]\n    parsed_detections[PARENT_ID_KEY] = np.array(parent_ids)\n\n    _attach_parent_coordinates_and_dimensions(\n        parameter=parameter,\n        raw_detections=raw_predictions,\n        parsed_detections=parsed_detections,\n        origin_key=PARENT_ORIGIN_KEY,\n        coordinates_key=PARENT_COORDINATES_KEY,\n        dimensions_key=PARENT_DIMENSIONS_KEY,\n    )\n\n    root_parent_ids = [\n        detection[ROOT_PARENT_ID_KEY] if ROOT_PARENT_ID_KEY in detection else parameter\n        for detection in raw_predictions\n    ]\n    if root_parent_ids:\n        parsed_detections.data[ROOT_PARENT_ID_KEY] = np.array(root_parent_ids)\n\n        _attach_parent_coordinates_and_dimensions(\n            parameter=parameter,\n            raw_detections=raw_predictions,\n            parsed_detections=parsed_detections,\n            origin_key=ROOT_PARENT_ORIGIN_KEY,\n            coordinates_key=ROOT_PARENT_COORDINATES_KEY,\n            dimensions_key=ROOT_PARENT_DIMENSIONS_KEY,\n        )\n\n    optional_elements_keys = [\n        (PATH_DEVIATION_KEY_IN_INFERENCE_RESPONSE, PATH_DEVIATION_KEY_IN_SV_DETECTIONS),\n        (TIME_IN_ZONE_KEY_IN_INFERENCE_RESPONSE, TIME_IN_ZONE_KEY_IN_SV_DETECTIONS),\n        (POLYGON_KEY_IN_INFERENCE_RESPONSE, POLYGON_KEY_IN_SV_DETECTIONS),\n        (\n            BOUNDING_RECT_ANGLE_KEY_IN_INFERENCE_RESPONSE,\n            BOUNDING_RECT_ANGLE_KEY_IN_SV_DETECTIONS,\n        ),\n        (\n            BOUNDING_RECT_RECT_KEY_IN_INFERENCE_RESPONSE,\n            BOUNDING_RECT_RECT_KEY_IN_SV_DETECTIONS,\n        ),\n        (\n            BOUNDING_RECT_HEIGHT_KEY_IN_INFERENCE_RESPONSE,\n            BOUNDING_RECT_HEIGHT_KEY_IN_SV_DETECTIONS,\n        ),\n        (\n            BOUNDING_RECT_WIDTH_KEY_IN_INFERENCE_RESPONSE,\n            BOUNDING_RECT_WIDTH_KEY_IN_SV_DETECTIONS,\n        ),\n        (DETECTED_CODE_KEY, DETECTED_CODE_KEY),\n        (SPEED_KEY_IN_INFERENCE_RESPONSE, SPEED_KEY_IN_SV_DETECTIONS),\n        (SMOOTHED_SPEED_KEY_IN_INFERENCE_RESPONSE, SMOOTHED_SPEED_KEY_IN_SV_DETECTIONS),\n        (\n            SMOOTHED_VELOCITY_KEY_IN_INFERENCE_RESPONSE,\n            SMOOTHED_VELOCITY_KEY_IN_SV_DETECTIONS,\n        ),\n        (VELOCITY_KEY_IN_INFERENCE_RESPONSE, VELOCITY_KEY_IN_SV_DETECTIONS),\n        (AREA_KEY_IN_INFERENCE_RESPONSE, AREA_KEY_IN_SV_DETECTIONS),\n        (AREA_CONVERTED_KEY_IN_INFERENCE_RESPONSE, AREA_CONVERTED_KEY_IN_SV_DETECTIONS),\n    ]\n    for raw_detection_key, parsed_detection_key in optional_elements_keys:\n        parsed_detections = _attach_optional_detection_element(\n            raw_detections=raw_predictions,\n            parsed_detections=parsed_detections,\n            raw_detection_key=raw_detection_key,\n            parsed_detection_key=parsed_detection_key,\n        )\n    return _attach_optional_key_points_detections(\n        raw_detections=raw_predictions,\n        parsed_detections=parsed_detections,\n    )\n\n\ndef _attach_parent_coordinates_and_dimensions(\n    parameter: str,\n    raw_detections: List[dict],\n    parsed_detections: sv.Detections,\n    origin_key: str,\n    coordinates_key: str,\n    dimensions_key: str,\n) -> None:\n    coordinates = []\n    dimensions = []\n    for detection in raw_detections:\n        parent_origin = detection.get(origin_key)\n        if parent_origin:\n            parsed_origin = deserialize_parent_origin(parameter, parent_origin)\n            coordinates.append([parsed_origin.offset_x, parsed_origin.offset_y])\n            dimensions.append([parsed_origin.height, parsed_origin.width])\n        else:\n            return\n    if coordinates and dimensions:\n        parsed_detections.data[coordinates_key] = np.array(coordinates)\n        parsed_detections.data[dimensions_key] = np.array(dimensions)\n\n\ndef _attach_optional_detection_element(\n    raw_detections: List[dict],\n    parsed_detections: sv.Detections,\n    raw_detection_key: str,\n    parsed_detection_key: str,\n) -> sv.Detections:\n    if raw_detection_key not in raw_detections[0]:\n        return parsed_detections\n    # Use list comprehension which is faster than append-in-loop\n    result = [d[raw_detection_key] for d in raw_detections]\n    parsed_detections.data[parsed_detection_key] = np.array(result)\n    return parsed_detections\n\n\ndef _attach_optional_key_points_detections(\n    raw_detections: List[dict],\n    parsed_detections: sv.Detections,\n) -> sv.Detections:\n    if KEYPOINTS_KEY_IN_INFERENCE_RESPONSE not in raw_detections[0]:\n        return parsed_detections\n    return add_inference_keypoints_to_sv_detections(\n        inference_prediction=raw_detections,\n        detections=parsed_detections,\n    )",
    "optimized_raw_markdown": "```python:inference/core/workflows/errors.py\nfrom typing import Optional\n\nclass WorkflowError(Exception):\n\n    def __init__(\n        self,\n        public_message: str,\n        context: str,\n        inner_error: Optional[Exception] = None,\n    ):\n        super().__init__(public_message)\n        self._public_message = public_message\n        self._context = context\n        self._inner_error = inner_error\n\n    @property\n    def public_message(self) -> str:\n        return self._public_message\n\n    @property\n    def context(self) -> str:\n        return self._context\n\n    @property\n    def inner_error_type(self) -> Optional[str]:\n        if self._inner_error is None:\n            return None\n        return self._inner_error.__class__.__name__\n\n    @property\n    def inner_error(self) -> Optional[Exception]:\n        return self._inner_error\n\n\nclass WorkflowExecutionEngineError(WorkflowError):\n    pass\n\n\nclass RuntimeInputError(WorkflowExecutionEngineError):\n    pass\n```\n```python:inference/core/workflows/core_steps/common/utils.py\nfrom typing import List\n\ndef filter_out_invalid_polygons(predictions: List[dict]) -> List[dict]:\n    return [\n        d for d in predictions if \"points\" not in d or len(d.get(\"points\", [])) >= 3\n    ]\n```\n```python:inference/core/workflows/core_steps/common/deserializers.py\nfrom typing import Any, List\nfrom uuid import uuid4\n\nimport numpy as np\nimport supervision as sv\nfrom inference.core.workflows.core_steps.common.utils import (\n    add_inference_keypoints_to_sv_detections, filter_out_invalid_polygons)\nfrom inference.core.workflows.errors import RuntimeInputError\nfrom inference.core.workflows.execution_engine.constants import (\n    AREA_CONVERTED_KEY_IN_INFERENCE_RESPONSE,\n    AREA_CONVERTED_KEY_IN_SV_DETECTIONS, AREA_KEY_IN_INFERENCE_RESPONSE,\n    AREA_KEY_IN_SV_DETECTIONS, BOUNDING_RECT_ANGLE_KEY_IN_INFERENCE_RESPONSE,\n    BOUNDING_RECT_ANGLE_KEY_IN_SV_DETECTIONS,\n    BOUNDING_RECT_HEIGHT_KEY_IN_INFERENCE_RESPONSE,\n    BOUNDING_RECT_HEIGHT_KEY_IN_SV_DETECTIONS,\n    BOUNDING_RECT_RECT_KEY_IN_INFERENCE_RESPONSE,\n    BOUNDING_RECT_RECT_KEY_IN_SV_DETECTIONS,\n    BOUNDING_RECT_WIDTH_KEY_IN_INFERENCE_RESPONSE,\n    BOUNDING_RECT_WIDTH_KEY_IN_SV_DETECTIONS, DETECTED_CODE_KEY,\n    DETECTION_ID_KEY, IMAGE_DIMENSIONS_KEY,\n    KEYPOINTS_KEY_IN_INFERENCE_RESPONSE, PARENT_COORDINATES_KEY,\n    PARENT_DIMENSIONS_KEY, PARENT_ID_KEY, PARENT_ORIGIN_KEY,\n    PATH_DEVIATION_KEY_IN_INFERENCE_RESPONSE,\n    PATH_DEVIATION_KEY_IN_SV_DETECTIONS, POLYGON_KEY_IN_INFERENCE_RESPONSE,\n    POLYGON_KEY_IN_SV_DETECTIONS, ROOT_PARENT_COORDINATES_KEY,\n    ROOT_PARENT_DIMENSIONS_KEY, ROOT_PARENT_ID_KEY, ROOT_PARENT_ORIGIN_KEY,\n    SMOOTHED_SPEED_KEY_IN_INFERENCE_RESPONSE,\n    SMOOTHED_SPEED_KEY_IN_SV_DETECTIONS,\n    SMOOTHED_VELOCITY_KEY_IN_INFERENCE_RESPONSE,\n    SMOOTHED_VELOCITY_KEY_IN_SV_DETECTIONS, SPEED_KEY_IN_INFERENCE_RESPONSE,\n    SPEED_KEY_IN_SV_DETECTIONS, TIME_IN_ZONE_KEY_IN_INFERENCE_RESPONSE,\n    TIME_IN_ZONE_KEY_IN_SV_DETECTIONS, VELOCITY_KEY_IN_INFERENCE_RESPONSE,\n    VELOCITY_KEY_IN_SV_DETECTIONS)\n\n\ndef deserialize_detections_kind(\n    parameter: str,\n    detections: Any,\n) -> sv.Detections:\n    if isinstance(detections, sv.Detections):\n        return detections\n    if not isinstance(detections, dict):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"detections, but invalid type of data found.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    if \"predictions\" not in detections or \"image\" not in detections:\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"detections, but dictionary misses required keys.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    parsed_detections = sv.Detections.from_inference(detections)\n    if len(parsed_detections) == 0:\n        return parsed_detections\n    height, width = detections[\"image\"][\"height\"], detections[\"image\"][\"width\"]\n    # Use numpy tiling to avoid creating a Python list of identical lists\n    image_metadata = np.tile(np.array([height, width]), (len(parsed_detections), 1))\n    parsed_detections.data[IMAGE_DIMENSIONS_KEY] = image_metadata\n    raw_predictions = detections[\"predictions\"]\n    if len(parsed_detections) != len(raw_predictions):\n        raw_predictions = filter_out_invalid_polygons(predictions=raw_predictions)\n    detection_ids = [\n        detection[DETECTION_ID_KEY] if DETECTION_ID_KEY in detection else str(uuid4())\n        for detection in raw_predictions\n    ]\n    parsed_detections.data[DETECTION_ID_KEY] = np.array(detection_ids)\n\n    parent_ids = [\n        detection[PARENT_ID_KEY] if PARENT_ID_KEY in detection else parameter\n        for detection in raw_predictions\n    ]\n    parsed_detections[PARENT_ID_KEY] = np.array(parent_ids)\n\n    _attach_parent_coordinates_and_dimensions(\n        parameter=parameter,\n        raw_detections=raw_predictions,\n        parsed_detections=parsed_detections,\n        origin_key=PARENT_ORIGIN_KEY,\n        coordinates_key=PARENT_COORDINATES_KEY,\n        dimensions_key=PARENT_DIMENSIONS_KEY,\n    )\n\n    root_parent_ids = [\n        detection[ROOT_PARENT_ID_KEY] if ROOT_PARENT_ID_KEY in detection else parameter\n        for detection in raw_predictions\n    ]\n    if root_parent_ids:\n        parsed_detections.data[ROOT_PARENT_ID_KEY] = np.array(root_parent_ids)\n\n        _attach_parent_coordinates_and_dimensions(\n            parameter=parameter,\n            raw_detections=raw_predictions,\n            parsed_detections=parsed_detections,\n            origin_key=ROOT_PARENT_ORIGIN_KEY,\n            coordinates_key=ROOT_PARENT_COORDINATES_KEY,\n            dimensions_key=ROOT_PARENT_DIMENSIONS_KEY,\n        )\n\n    optional_elements_keys = [\n        (PATH_DEVIATION_KEY_IN_INFERENCE_RESPONSE, PATH_DEVIATION_KEY_IN_SV_DETECTIONS),\n        (TIME_IN_ZONE_KEY_IN_INFERENCE_RESPONSE, TIME_IN_ZONE_KEY_IN_SV_DETECTIONS),\n        (POLYGON_KEY_IN_INFERENCE_RESPONSE, POLYGON_KEY_IN_SV_DETECTIONS),\n        (\n            BOUNDING_RECT_ANGLE_KEY_IN_INFERENCE_RESPONSE,\n            BOUNDING_RECT_ANGLE_KEY_IN_SV_DETECTIONS,\n        ),\n        (\n            BOUNDING_RECT_RECT_KEY_IN_INFERENCE_RESPONSE,\n            BOUNDING_RECT_RECT_KEY_IN_SV_DETECTIONS,\n        ),\n        (\n            BOUNDING_RECT_HEIGHT_KEY_IN_INFERENCE_RESPONSE,\n            BOUNDING_RECT_HEIGHT_KEY_IN_SV_DETECTIONS,\n        ),\n        (\n            BOUNDING_RECT_WIDTH_KEY_IN_INFERENCE_RESPONSE,\n            BOUNDING_RECT_WIDTH_KEY_IN_SV_DETECTIONS,\n        ),\n        (DETECTED_CODE_KEY, DETECTED_CODE_KEY),\n        (SPEED_KEY_IN_INFERENCE_RESPONSE, SPEED_KEY_IN_SV_DETECTIONS),\n        (SMOOTHED_SPEED_KEY_IN_INFERENCE_RESPONSE, SMOOTHED_SPEED_KEY_IN_SV_DETECTIONS),\n        (\n            SMOOTHED_VELOCITY_KEY_IN_INFERENCE_RESPONSE,\n            SMOOTHED_VELOCITY_KEY_IN_SV_DETECTIONS,\n        ),\n        (VELOCITY_KEY_IN_INFERENCE_RESPONSE, VELOCITY_KEY_IN_SV_DETECTIONS),\n        (AREA_KEY_IN_INFERENCE_RESPONSE, AREA_KEY_IN_SV_DETECTIONS),\n        (AREA_CONVERTED_KEY_IN_INFERENCE_RESPONSE, AREA_CONVERTED_KEY_IN_SV_DETECTIONS),\n    ]\n    for raw_detection_key, parsed_detection_key in optional_elements_keys:\n        parsed_detections = _attach_optional_detection_element(\n            raw_detections=raw_predictions,\n            parsed_detections=parsed_detections,\n            raw_detection_key=raw_detection_key,\n            parsed_detection_key=parsed_detection_key,\n        )\n    return _attach_optional_key_points_detections(\n        raw_detections=raw_predictions,\n        parsed_detections=parsed_detections,\n    )\n\n\ndef _attach_parent_coordinates_and_dimensions(\n    parameter: str,\n    raw_detections: List[dict],\n    parsed_detections: sv.Detections,\n    origin_key: str,\n    coordinates_key: str,\n    dimensions_key: str,\n) -> None:\n    coordinates = []\n    dimensions = []\n    for detection in raw_detections:\n        parent_origin = detection.get(origin_key)\n        if parent_origin:\n            parsed_origin = deserialize_parent_origin(parameter, parent_origin)\n            coordinates.append([parsed_origin.offset_x, parsed_origin.offset_y])\n            dimensions.append([parsed_origin.height, parsed_origin.width])\n        else:\n            return\n    if coordinates and dimensions:\n        parsed_detections.data[coordinates_key] = np.array(coordinates)\n        parsed_detections.data[dimensions_key] = np.array(dimensions)\n\n\ndef _attach_optional_detection_element(\n    raw_detections: List[dict],\n    parsed_detections: sv.Detections,\n    raw_detection_key: str,\n    parsed_detection_key: str,\n) -> sv.Detections:\n    if raw_detection_key not in raw_detections[0]:\n        return parsed_detections\n    # Use list comprehension which is faster than append-in-loop\n    result = [d[raw_detection_key] for d in raw_detections]\n    parsed_detections.data[parsed_detection_key] = np.array(result)\n    return parsed_detections\n\n\ndef _attach_optional_key_points_detections(\n    raw_detections: List[dict],\n    parsed_detections: sv.Detections,\n) -> sv.Detections:\n    if KEYPOINTS_KEY_IN_INFERENCE_RESPONSE not in raw_detections[0]:\n        return parsed_detections\n    return add_inference_keypoints_to_sv_detections(\n        inference_prediction=raw_detections,\n        detections=parsed_detections,\n    )\n```",
    "optimized_function_only": "def deserialize_detections_kind(\n    parameter: str,\n    detections: Any,\n) -> sv.Detections:\n    if isinstance(detections, sv.Detections):\n        return detections\n    if not isinstance(detections, dict):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"detections, but invalid type of data found.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    if \"predictions\" not in detections or \"image\" not in detections:\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"detections, but dictionary misses required keys.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    parsed_detections = sv.Detections.from_inference(detections)\n    if len(parsed_detections) == 0:\n        return parsed_detections\n    height, width = detections[\"image\"][\"height\"], detections[\"image\"][\"width\"]\n    # Use numpy tiling to avoid creating a Python list of identical lists\n    image_metadata = np.tile(np.array([height, width]), (len(parsed_detections), 1))\n    parsed_detections.data[IMAGE_DIMENSIONS_KEY] = image_metadata\n    raw_predictions = detections[\"predictions\"]\n    if len(parsed_detections) != len(raw_predictions):\n        raw_predictions = filter_out_invalid_polygons(predictions=raw_predictions)\n    detection_ids = [\n        detection[DETECTION_ID_KEY] if DETECTION_ID_KEY in detection else str(uuid4())\n        for detection in raw_predictions\n    ]\n    parsed_detections.data[DETECTION_ID_KEY] = np.array(detection_ids)\n\n    parent_ids = [\n        detection[PARENT_ID_KEY] if PARENT_ID_KEY in detection else parameter\n        for detection in raw_predictions\n    ]\n    parsed_detections[PARENT_ID_KEY] = np.array(parent_ids)\n\n    _attach_parent_coordinates_and_dimensions(\n        parameter=parameter,\n        raw_detections=raw_predictions,\n        parsed_detections=parsed_detections,\n        origin_key=PARENT_ORIGIN_KEY,\n        coordinates_key=PARENT_COORDINATES_KEY,\n        dimensions_key=PARENT_DIMENSIONS_KEY,\n    )\n\n    root_parent_ids = [\n        detection[ROOT_PARENT_ID_KEY] if ROOT_PARENT_ID_KEY in detection else parameter\n        for detection in raw_predictions\n    ]\n    if root_parent_ids:\n        parsed_detections.data[ROOT_PARENT_ID_KEY] = np.array(root_parent_ids)\n\n        _attach_parent_coordinates_and_dimensions(\n            parameter=parameter,\n            raw_detections=raw_predictions,\n            parsed_detections=parsed_detections,\n            origin_key=ROOT_PARENT_ORIGIN_KEY,\n            coordinates_key=ROOT_PARENT_COORDINATES_KEY,\n            dimensions_key=ROOT_PARENT_DIMENSIONS_KEY,\n        )\n\n    optional_elements_keys = [\n        (PATH_DEVIATION_KEY_IN_INFERENCE_RESPONSE, PATH_DEVIATION_KEY_IN_SV_DETECTIONS),\n        (TIME_IN_ZONE_KEY_IN_INFERENCE_RESPONSE, TIME_IN_ZONE_KEY_IN_SV_DETECTIONS),\n        (POLYGON_KEY_IN_INFERENCE_RESPONSE, POLYGON_KEY_IN_SV_DETECTIONS),\n        (\n            BOUNDING_RECT_ANGLE_KEY_IN_INFERENCE_RESPONSE,\n            BOUNDING_RECT_ANGLE_KEY_IN_SV_DETECTIONS,\n        ),\n        (\n            BOUNDING_RECT_RECT_KEY_IN_INFERENCE_RESPONSE,\n            BOUNDING_RECT_RECT_KEY_IN_SV_DETECTIONS,\n        ),\n        (\n            BOUNDING_RECT_HEIGHT_KEY_IN_INFERENCE_RESPONSE,\n            BOUNDING_RECT_HEIGHT_KEY_IN_SV_DETECTIONS,\n        ),\n        (\n            BOUNDING_RECT_WIDTH_KEY_IN_INFERENCE_RESPONSE,\n            BOUNDING_RECT_WIDTH_KEY_IN_SV_DETECTIONS,\n        ),\n        (DETECTED_CODE_KEY, DETECTED_CODE_KEY),\n        (SPEED_KEY_IN_INFERENCE_RESPONSE, SPEED_KEY_IN_SV_DETECTIONS),\n        (SMOOTHED_SPEED_KEY_IN_INFERENCE_RESPONSE, SMOOTHED_SPEED_KEY_IN_SV_DETECTIONS),\n        (\n            SMOOTHED_VELOCITY_KEY_IN_INFERENCE_RESPONSE,\n            SMOOTHED_VELOCITY_KEY_IN_SV_DETECTIONS,\n        ),\n        (VELOCITY_KEY_IN_INFERENCE_RESPONSE, VELOCITY_KEY_IN_SV_DETECTIONS),\n        (AREA_KEY_IN_INFERENCE_RESPONSE, AREA_KEY_IN_SV_DETECTIONS),\n        (AREA_CONVERTED_KEY_IN_INFERENCE_RESPONSE, AREA_CONVERTED_KEY_IN_SV_DETECTIONS),\n    ]\n    for raw_detection_key, parsed_detection_key in optional_elements_keys:\n        parsed_detections = _attach_optional_detection_element(\n            raw_detections=raw_predictions,\n            parsed_detections=parsed_detections,\n            raw_detection_key=raw_detection_key,\n            parsed_detection_key=parsed_detection_key,\n        )\n    return _attach_optional_key_points_detections(\n        raw_detections=raw_predictions,\n        parsed_detections=parsed_detections,\n    )\n",
    "original_file_content": "import os\nfrom datetime import datetime\nfrom typing import Any, List, Optional, Tuple, Union\nfrom uuid import uuid4\n\nimport cv2\nimport numpy as np\nimport pybase64\nimport supervision as sv\nfrom pydantic import ValidationError\n\nfrom inference.core.utils.image_utils import (\n    attempt_loading_image_from_string,\n    load_image_from_url,\n)\nfrom inference.core.workflows.core_steps.common.utils import (\n    add_inference_keypoints_to_sv_detections,\n    filter_out_invalid_polygons,\n)\nfrom inference.core.workflows.errors import RuntimeInputError\nfrom inference.core.workflows.execution_engine.constants import (\n    AREA_CONVERTED_KEY_IN_INFERENCE_RESPONSE,\n    AREA_CONVERTED_KEY_IN_SV_DETECTIONS,\n    AREA_KEY_IN_INFERENCE_RESPONSE,\n    AREA_KEY_IN_SV_DETECTIONS,\n    BOUNDING_RECT_ANGLE_KEY_IN_INFERENCE_RESPONSE,\n    BOUNDING_RECT_ANGLE_KEY_IN_SV_DETECTIONS,\n    BOUNDING_RECT_HEIGHT_KEY_IN_INFERENCE_RESPONSE,\n    BOUNDING_RECT_HEIGHT_KEY_IN_SV_DETECTIONS,\n    BOUNDING_RECT_RECT_KEY_IN_INFERENCE_RESPONSE,\n    BOUNDING_RECT_RECT_KEY_IN_SV_DETECTIONS,\n    BOUNDING_RECT_WIDTH_KEY_IN_INFERENCE_RESPONSE,\n    BOUNDING_RECT_WIDTH_KEY_IN_SV_DETECTIONS,\n    DETECTED_CODE_KEY,\n    DETECTION_ID_KEY,\n    IMAGE_DIMENSIONS_KEY,\n    KEYPOINTS_KEY_IN_INFERENCE_RESPONSE,\n    PARENT_COORDINATES_KEY,\n    PARENT_DIMENSIONS_KEY,\n    PARENT_ID_KEY,\n    PARENT_ORIGIN_KEY,\n    PATH_DEVIATION_KEY_IN_INFERENCE_RESPONSE,\n    PATH_DEVIATION_KEY_IN_SV_DETECTIONS,\n    POLYGON_KEY_IN_INFERENCE_RESPONSE,\n    POLYGON_KEY_IN_SV_DETECTIONS,\n    RLE_MASK_KEY_IN_INFERENCE_RESPONSE,\n    RLE_MASK_KEY_IN_SV_DETECTIONS,\n    ROOT_PARENT_COORDINATES_KEY,\n    ROOT_PARENT_DIMENSIONS_KEY,\n    ROOT_PARENT_ID_KEY,\n    ROOT_PARENT_ORIGIN_KEY,\n    SMOOTHED_SPEED_KEY_IN_INFERENCE_RESPONSE,\n    SMOOTHED_SPEED_KEY_IN_SV_DETECTIONS,\n    SMOOTHED_VELOCITY_KEY_IN_INFERENCE_RESPONSE,\n    SMOOTHED_VELOCITY_KEY_IN_SV_DETECTIONS,\n    SPEED_KEY_IN_INFERENCE_RESPONSE,\n    SPEED_KEY_IN_SV_DETECTIONS,\n    TIME_IN_ZONE_KEY_IN_INFERENCE_RESPONSE,\n    TIME_IN_ZONE_KEY_IN_SV_DETECTIONS,\n    VELOCITY_KEY_IN_INFERENCE_RESPONSE,\n    VELOCITY_KEY_IN_SV_DETECTIONS,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    ImageParentMetadata,\n    ParentOrigin,\n    VideoMetadata,\n    WorkflowImageData,\n)\n\nAnyNumber = Union[int, float]\n\n\ndef deserialize_image_kind(\n    parameter: str,\n    image: Any,\n    prevent_local_images_loading: bool = False,\n) -> WorkflowImageData:\n    if isinstance(image, WorkflowImageData):\n        return image\n\n    is_image_dict = isinstance(image, dict)\n\n    parent_id = image.get(PARENT_ID_KEY, parameter) if is_image_dict else parameter\n    parent_origin = image.get(PARENT_ORIGIN_KEY) if is_image_dict else None\n    parent_metadata = _parse_optional_parent_metadata(\n        parameter=parameter,\n        parent_id=parent_id,\n        parent_origin=parent_origin,\n    )\n\n    root_parent_id = image.get(ROOT_PARENT_ID_KEY) if is_image_dict else None\n    root_parent_origin = image.get(ROOT_PARENT_ORIGIN_KEY) if is_image_dict else None\n    workflow_root_ancestor_metadata = _parse_optional_parent_metadata(\n        parameter=parameter,\n        parent_id=root_parent_id,\n        parent_origin=root_parent_origin,\n    )\n\n    video_metadata = None\n    if is_image_dict and \"video_metadata\" in image:\n        video_metadata = deserialize_video_metadata_kind(\n            parameter=parameter, video_metadata=image[\"video_metadata\"]\n        )\n    file_name = image.get(\"file_name\") if is_image_dict else None\n    if is_image_dict and isinstance(image.get(\"value\"), np.ndarray):\n        image = image[\"value\"]\n    if isinstance(image, np.ndarray):\n        return WorkflowImageData(\n            parent_metadata=parent_metadata,\n            workflow_root_ancestor_metadata=workflow_root_ancestor_metadata,\n            numpy_image=image,\n            video_metadata=video_metadata,\n            file_name=file_name,\n        )\n    try:\n        if is_image_dict:\n            image = image[\"value\"]\n        if isinstance(image, str):\n            base64_image = None\n            image_reference = None\n            if image.startswith(\"http://\") or image.startswith(\"https://\"):\n                image_reference = image\n                image = load_image_from_url(value=image)\n            elif not prevent_local_images_loading and os.path.exists(image):\n                # prevent_local_images_loading is introduced to eliminate\n                # server vulnerability - namely it prevents local server\n                # file system from being exploited.\n                image_reference = image\n                image = cv2.imread(image)\n            else:\n                base64_image = image\n                image = attempt_loading_image_from_string(image)[0]\n            return WorkflowImageData(\n                parent_metadata=parent_metadata,\n                workflow_root_ancestor_metadata=workflow_root_ancestor_metadata,\n                numpy_image=image,\n                base64_image=base64_image,\n                image_reference=image_reference,\n                video_metadata=video_metadata,\n                file_name=file_name,\n            )\n    except Exception as error:\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` defined as `WorkflowImage` \"\n            f\"that is invalid. Failed on input validation. Details: {error}\",\n            context=\"workflow_execution | runtime_input_validation\",\n        ) from error\n    raise RuntimeInputError(\n        public_message=f\"Detected runtime parameter `{parameter}` defined as `WorkflowImage` \"\n        f\"with type {type(image)} that is invalid. Workflows accept only np.arrays, `WorkflowImageData` \"\n        f\"and dicts with keys `type` and `value` compatible with `inference` (or list of them).\",\n        context=\"workflow_execution | runtime_input_validation\",\n    )\n\n\ndef _parse_optional_parent_metadata(\n    parameter: str,\n    parent_id: Optional[str],\n    parent_origin: Optional[Any],\n) -> Optional[ImageParentMetadata]:\n    if not parent_id:\n        return None\n\n    if not parent_origin:\n        return ImageParentMetadata(parent_id=parent_id)\n\n    parsed_origin = deserialize_parent_origin(parameter, parent_origin)\n    return ImageParentMetadata(\n        parent_id=parent_id,\n        origin_coordinates=parsed_origin.to_origin_coordinates_system(),\n    )\n\n\ndef deserialize_parent_origin(parameter: str, parent_origin: Any) -> ParentOrigin:\n    if isinstance(parent_origin, ParentOrigin):\n        return parent_origin\n    if not isinstance(parent_origin, dict):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` holding \"\n            f\"`ParentOrigin`, but provided value is not a dict.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    try:\n        return ParentOrigin.model_validate(parent_origin)\n    except ValidationError as error:\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` holding \"\n            f\"`ParentOrigin`, but provided value is malformed. \"\n            f\"See details in inner error.\",\n            context=\"workflow_execution | runtime_input_validation\",\n            inner_error=error,\n        )\n\n\ndef deserialize_video_metadata_kind(\n    parameter: str,\n    video_metadata: Any,\n) -> VideoMetadata:\n    if isinstance(video_metadata, VideoMetadata):\n        return video_metadata\n    if not isinstance(video_metadata, dict):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` holding \"\n            f\"`WorkflowVideoMetadata`, but provided value is not a dict.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    try:\n        return VideoMetadata.model_validate(video_metadata)\n    except ValidationError as error:\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` holding \"\n            f\"`WorkflowVideoMetadata`, but provided value is malformed. \"\n            f\"See details in inner error.\",\n            context=\"workflow_execution | runtime_input_validation\",\n            inner_error=error,\n        )\n\n\ndef deserialize_detections_kind(\n    parameter: str,\n    detections: Any,\n) -> sv.Detections:\n    if isinstance(detections, sv.Detections):\n        return detections\n    if not isinstance(detections, dict):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"detections, but invalid type of data found.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    if \"predictions\" not in detections or \"image\" not in detections:\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"detections, but dictionary misses required keys.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    parsed_detections = sv.Detections.from_inference(detections)\n    if len(parsed_detections) == 0:\n        return parsed_detections\n    height, width = detections[\"image\"][\"height\"], detections[\"image\"][\"width\"]\n    image_metadata = np.array([[height, width]] * len(parsed_detections))\n    parsed_detections.data[IMAGE_DIMENSIONS_KEY] = image_metadata\n    raw_predictions = detections[\"predictions\"]\n    if len(parsed_detections) != len(raw_predictions):\n        raw_predictions = filter_out_invalid_polygons(predictions=raw_predictions)\n    detection_ids = [\n        detection.get(DETECTION_ID_KEY, str(uuid4())) for detection in raw_predictions\n    ]\n    parsed_detections.data[DETECTION_ID_KEY] = np.array(detection_ids)\n\n    parent_ids = [\n        detection.get(PARENT_ID_KEY, parameter) for detection in raw_predictions\n    ]\n    parsed_detections[PARENT_ID_KEY] = np.array(parent_ids)\n\n    _attach_parent_coordinates_and_dimensions(\n        parameter=parameter,\n        raw_detections=raw_predictions,\n        parsed_detections=parsed_detections,\n        origin_key=PARENT_ORIGIN_KEY,\n        coordinates_key=PARENT_COORDINATES_KEY,\n        dimensions_key=PARENT_DIMENSIONS_KEY,\n    )\n\n    root_parent_ids = [\n        detection.get(ROOT_PARENT_ID_KEY, parameter) for detection in raw_predictions\n    ]\n    if root_parent_ids:\n        parsed_detections.data[ROOT_PARENT_ID_KEY] = np.array(root_parent_ids)\n\n        _attach_parent_coordinates_and_dimensions(\n            parameter=parameter,\n            raw_detections=raw_predictions,\n            parsed_detections=parsed_detections,\n            origin_key=ROOT_PARENT_ORIGIN_KEY,\n            coordinates_key=ROOT_PARENT_COORDINATES_KEY,\n            dimensions_key=ROOT_PARENT_DIMENSIONS_KEY,\n        )\n\n    optional_elements_keys = [\n        (PATH_DEVIATION_KEY_IN_INFERENCE_RESPONSE, PATH_DEVIATION_KEY_IN_SV_DETECTIONS),\n        (TIME_IN_ZONE_KEY_IN_INFERENCE_RESPONSE, TIME_IN_ZONE_KEY_IN_SV_DETECTIONS),\n        (POLYGON_KEY_IN_INFERENCE_RESPONSE, POLYGON_KEY_IN_SV_DETECTIONS),\n        (\n            BOUNDING_RECT_ANGLE_KEY_IN_INFERENCE_RESPONSE,\n            BOUNDING_RECT_ANGLE_KEY_IN_SV_DETECTIONS,\n        ),\n        (\n            BOUNDING_RECT_RECT_KEY_IN_INFERENCE_RESPONSE,\n            BOUNDING_RECT_RECT_KEY_IN_SV_DETECTIONS,\n        ),\n        (\n            BOUNDING_RECT_HEIGHT_KEY_IN_INFERENCE_RESPONSE,\n            BOUNDING_RECT_HEIGHT_KEY_IN_SV_DETECTIONS,\n        ),\n        (\n            BOUNDING_RECT_WIDTH_KEY_IN_INFERENCE_RESPONSE,\n            BOUNDING_RECT_WIDTH_KEY_IN_SV_DETECTIONS,\n        ),\n        (DETECTED_CODE_KEY, DETECTED_CODE_KEY),\n        (SPEED_KEY_IN_INFERENCE_RESPONSE, SPEED_KEY_IN_SV_DETECTIONS),\n        (SMOOTHED_SPEED_KEY_IN_INFERENCE_RESPONSE, SMOOTHED_SPEED_KEY_IN_SV_DETECTIONS),\n        (\n            SMOOTHED_VELOCITY_KEY_IN_INFERENCE_RESPONSE,\n            SMOOTHED_VELOCITY_KEY_IN_SV_DETECTIONS,\n        ),\n        (VELOCITY_KEY_IN_INFERENCE_RESPONSE, VELOCITY_KEY_IN_SV_DETECTIONS),\n        (AREA_KEY_IN_INFERENCE_RESPONSE, AREA_KEY_IN_SV_DETECTIONS),\n        (AREA_CONVERTED_KEY_IN_INFERENCE_RESPONSE, AREA_CONVERTED_KEY_IN_SV_DETECTIONS),\n    ]\n    for raw_detection_key, parsed_detection_key in optional_elements_keys:\n        parsed_detections = _attach_optional_detection_element(\n            raw_detections=raw_predictions,\n            parsed_detections=parsed_detections,\n            raw_detection_key=raw_detection_key,\n            parsed_detection_key=parsed_detection_key,\n        )\n    return _attach_optional_key_points_detections(\n        raw_detections=raw_predictions,\n        parsed_detections=parsed_detections,\n    )\n\n\ndef deserialize_rle_detections_kind(\n    parameter: str,\n    detections: Any,\n) -> sv.Detections:\n    parsed_detections = deserialize_detections_kind(\n        parameter=parameter,\n        detections=detections,\n    )\n    if len(parsed_detections) == 0:\n        return parsed_detections\n\n    if isinstance(detections, dict) and \"predictions\" in detections:\n        rle_masks_list = []\n        for pred in detections[\"predictions\"]:\n            rle = pred.get(RLE_MASK_KEY_IN_INFERENCE_RESPONSE)\n            if rle is not None:\n                rle_masks_list.append(rle)\n\n        if rle_masks_list and len(rle_masks_list) == len(parsed_detections):\n            parsed_detections[RLE_MASK_KEY_IN_SV_DETECTIONS] = np.array(\n                rle_masks_list, dtype=object\n            )\n\n    return parsed_detections\n\n\ndef _attach_parent_coordinates_and_dimensions(\n    parameter: str,\n    raw_detections: List[dict],\n    parsed_detections: sv.Detections,\n    origin_key: str,\n    coordinates_key: str,\n    dimensions_key: str,\n) -> None:\n    coordinates = []\n    dimensions = []\n    for detection in raw_detections:\n        parent_origin = detection.get(origin_key)\n        if parent_origin:\n            parsed_origin = deserialize_parent_origin(parameter, parent_origin)\n            coordinates.append([parsed_origin.offset_x, parsed_origin.offset_y])\n            dimensions.append([parsed_origin.height, parsed_origin.width])\n        else:\n            return\n    if coordinates and dimensions:\n        parsed_detections.data[coordinates_key] = np.array(coordinates)\n        parsed_detections.data[dimensions_key] = np.array(dimensions)\n\n\ndef _attach_optional_detection_element(\n    raw_detections: List[dict],\n    parsed_detections: sv.Detections,\n    raw_detection_key: str,\n    parsed_detection_key: str,\n) -> sv.Detections:\n    if raw_detection_key not in raw_detections[0]:\n        return parsed_detections\n    result = []\n    for detection in raw_detections:\n        result.append(detection[raw_detection_key])\n    parsed_detections.data[parsed_detection_key] = np.array(result)\n    return parsed_detections\n\n\ndef _attach_optional_key_points_detections(\n    raw_detections: List[dict],\n    parsed_detections: sv.Detections,\n) -> sv.Detections:\n    if KEYPOINTS_KEY_IN_INFERENCE_RESPONSE not in raw_detections[0]:\n        return parsed_detections\n    return add_inference_keypoints_to_sv_detections(\n        inference_prediction=raw_detections,\n        detections=parsed_detections,\n    )\n\n\ndef deserialize_numpy_array(parameter: str, raw_array: Any) -> np.ndarray:\n    if isinstance(raw_array, np.ndarray):\n        return raw_array\n    if not isinstance(raw_array, list):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"numpy array value, but invalid type of data found (`{type(raw_array).__name__}`).\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    return np.array(raw_array)\n\n\ndef deserialize_optional_string_kind(parameter: str, value: Any) -> Optional[str]:\n    if value is None:\n        return None\n    return deserialize_string_kind(parameter=parameter, value=value)\n\n\ndef deserialize_string_kind(parameter: str, value: Any) -> str:\n    if not isinstance(value, str):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"string value, but invalid type of data found (`{type(value).__name__}`).\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    return value\n\n\ndef deserialize_float_zero_to_one_kind(parameter: str, value: Any) -> float:\n    value = deserialize_float_kind(parameter=parameter, value=value)\n    if not (0.0 <= value <= 1.0):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"float value in range [0.0, 1.0], but value out of range detected.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    return value\n\n\ndef deserialize_float_kind(parameter: str, value: Any) -> float:\n    if not isinstance(value, float) and not isinstance(value, int):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"float value, but invalid type of data found (`{type(value).__name__}`).\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    return float(value)\n\n\ndef deserialize_list_of_values_kind(parameter: str, value: Any) -> list:\n    if not isinstance(value, list) and not isinstance(value, tuple):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"list, but invalid type of data found (`{type(value).__name__}`).\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    if not isinstance(value, list):\n        return list(value)\n    return value\n\n\ndef deserialize_boolean_kind(parameter: str, value: Any) -> bool:\n    if not isinstance(value, bool):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"boolean value, but invalid type of data found (`{type(value).__name__}`).\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    return value\n\n\ndef deserialize_integer_kind(parameter: str, value: Any) -> int:\n    if not isinstance(value, int):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"integer value, but invalid type of data found (`{type(value).__name__}`).\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    return value\n\n\nREQUIRED_CLASSIFICATION_PREDICTION_KEYS = {\n    \"image\",\n    \"predictions\",\n}\n\n\ndef deserialize_classification_prediction_kind(parameter: str, value: Any) -> dict:\n    value = deserialize_dictionary_kind(parameter=parameter, value=value)\n    if any(k not in value for k in REQUIRED_CLASSIFICATION_PREDICTION_KEYS):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"classification prediction value, but found that one of required keys \"\n            f\"({list(REQUIRED_CLASSIFICATION_PREDICTION_KEYS)}) \"\n            f\"is missing.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    if \"predicted_classes\" not in value and (\n        \"top\" not in value or \"confidence\" not in value\n    ):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"classification prediction value, but found that passed value misses \"\n            f\"prediction details.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    if \"prediction_type\" not in value:\n        value[\"prediction_type\"] = \"classification\"\n    if \"inference_id\" not in value:\n        value[\"inference_id\"] = str(uuid4())\n    if \"parent_id\" not in value:\n        value[\"parent_id\"] = parameter\n    if \"root_parent_id\" not in value:\n        value[\"root_parent_id\"] = parameter\n    return value\n\n\ndef deserialize_dictionary_kind(parameter: str, value: Any) -> dict:\n    if not isinstance(value, dict):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"dict value, but invalid type of data found (`{type(value).__name__}`).\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    return value\n\n\ndef deserialize_point_kind(parameter: str, value: Any) -> Tuple[AnyNumber, AnyNumber]:\n    if not isinstance(value, list) and not isinstance(value, tuple):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"point coordinates, but invalid type of data found (`{type(value).__name__}`).\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    if len(value) < 2:\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"point coordinates, but missing point coordinates detected.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    value = tuple(value[:2])\n    if any(not _is_number(e) for e in value):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"point coordinates, but at least one of the coordinate is not number\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    return value\n\n\ndef deserialize_zone_kind(\n    parameter: str, value: Any\n) -> List[List[Tuple[AnyNumber, AnyNumber]]]:\n    if not isinstance(value, list) or len(value) < 3:\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"zone coordinates, but defined zone is not a list with at least 3 points coordinates.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    if any(\n        (not isinstance(e, list) and not isinstance(e, tuple)) or len(e) != 2\n        for e in value\n    ):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"zone coordinates, but defined zone contains at least one element which is not a point with\"\n            f\"exactly two coordinates (x, y).\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    if any(not _is_number(e[0]) or not _is_number(e[1]) for e in value):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"zone coordinates, but defined zone contains at least one element which is not a point with\"\n            f\"exactly two coordinates (x, y) being numbers.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    return value\n\n\ndef deserialize_rgb_color_kind(\n    parameter: str, value: Any\n) -> Union[Tuple[int, int, int], str]:\n    if (\n        not isinstance(value, list)\n        and not isinstance(value, tuple)\n        and not isinstance(value, str)\n    ):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"RGB color, but invalid type of data found (`{type(value).__name__}`).\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    if isinstance(value, str):\n        return value\n    if len(value) < 3:\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"RGB color, but not all colors defined.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    return tuple(value[:3])\n\n\ndef deserialize_bytes_kind(parameter: str, value: Any) -> bytes:\n    if not isinstance(value, str) and not isinstance(value, bytes):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"bytes string, but invalid type of data found (`{type(value).__name__}`).\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    if isinstance(value, bytes):\n        return value\n    return pybase64.b64decode(value)\n\n\ndef deserialize_timestamp(parameter: str, value: Any) -> datetime:\n    if isinstance(value, datetime):\n        return value\n    if not isinstance(value, str):\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"datetime, but invalid type of data found (`{type(value).__name__}`).\",\n            context=\"workflow_execution | runtime_input_validation\",\n        )\n    try:\n        return datetime.fromisoformat(value)\n    except Exception as error:\n        raise RuntimeInputError(\n            public_message=f\"Detected runtime parameter `{parameter}` declared to hold \"\n            f\"datetime, but could not decode input data: {error}.\",\n            context=\"workflow_execution | runtime_input_validation\",\n        ) from error\n\n\ndef _is_number(value: Any) -> bool:\n    return isinstance(value, int) or isinstance(value, float)\n",
    "patch": null
  },
  {
    "trace_id": "5c4c38cf-6dcd-462d-b716-0151509c4e02",
    "function_name": "compute_detection_areas",
    "file_path": "inference/core/workflows/core_steps/classical_cv/mask_area_measurement/v1.py",
    "speedup_x": 0.4609984079461013,
    "review_quality": "high",
    "pre_optimization_commit": "105f999298f10401ae23311fb501cac6209f12f2",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def compute_detection_areas(detections: sv.Detections) -> List[float]:\n    \"\"\"Compute the area of all detections in square pixels.\n\n    For bounding-box-only detections, areas are computed in a single vectorized\n    operation. For detections with segmentation masks, the area is the count of\n    non-zero mask pixels (via ``cv2.countNonZero``). This correctly handles masks\n    with holes \u2014 hole pixels are zero and are not counted. Falls back to the\n    bounding box area when the mask pixel count is zero.\n\n    Args:\n        detections: A supervision Detections object.\n\n    Returns:\n        List of areas in square pixels, one per detection.\n    \"\"\"\n    n = len(detections)\n    if n == 0:\n        return []\n\n    areas = []\n    for i in range(n):\n        if detections.mask is not None:\n            count = cv.countNonZero(detections.mask[i].astype(np.uint8))\n            if count > 0:\n                areas.append(float(count))\n                continue\n        x1, y1, x2, y2 = detections.xyxy[i]\n        areas.append(float((x2 - x1) * (y2 - y1)))\n\n    return areas\n",
    "optimized_function_code": "from typing import List\n\nimport cv2 as cv\nimport numpy as np\nimport supervision as sv\n\n\ndef compute_detection_areas(detections: sv.Detections) -> List[float]:\n    \"\"\"Compute the area of all detections in square pixels.\n\n    For bounding-box-only detections, areas are computed in a single vectorized\n    operation. For detections with segmentation masks, the area is the count of\n    non-zero mask pixels (via ``cv2.countNonZero``). This correctly handles masks\n    with holes \u2014 hole pixels are zero and are not counted. Falls back to the\n    bounding box area when the mask pixel count is zero.\n\n    Args:\n        detections: A supervision Detections object.\n\n    Returns:\n        List of areas in square pixels, one per detection.\n    \"\"\"\n    n = len(detections)\n    if n == 0:\n        return []\n\n\n    # Pre-compute bounding box areas for all detections\n    xyxy = detections.xyxy\n    bbox_areas = (xyxy[:, 2] - xyxy[:, 0]) * (xyxy[:, 3] - xyxy[:, 1])\n    \n    if detections.mask is None:\n        return bbox_areas.tolist()\n    \n    areas = []\n    for i in range(n):\n        # Use np.count_nonzero which works directly on boolean arrays\n        count = np.count_nonzero(detections.mask[i])\n        if count > 0:\n            areas.append(float(count))\n        else:\n            areas.append(float(bbox_areas[i]))\n    \n    return areas",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/classical_cv/mask_area_measurement/v1.py\nfrom typing import List\n\nimport cv2 as cv\nimport numpy as np\nimport supervision as sv\n\n\ndef compute_detection_areas(detections: sv.Detections) -> List[float]:\n    \"\"\"Compute the area of all detections in square pixels.\n\n    For bounding-box-only detections, areas are computed in a single vectorized\n    operation. For detections with segmentation masks, the area is the count of\n    non-zero mask pixels (via ``cv2.countNonZero``). This correctly handles masks\n    with holes \u2014 hole pixels are zero and are not counted. Falls back to the\n    bounding box area when the mask pixel count is zero.\n\n    Args:\n        detections: A supervision Detections object.\n\n    Returns:\n        List of areas in square pixels, one per detection.\n    \"\"\"\n    n = len(detections)\n    if n == 0:\n        return []\n\n\n    # Pre-compute bounding box areas for all detections\n    xyxy = detections.xyxy\n    bbox_areas = (xyxy[:, 2] - xyxy[:, 0]) * (xyxy[:, 3] - xyxy[:, 1])\n    \n    if detections.mask is None:\n        return bbox_areas.tolist()\n    \n    areas = []\n    for i in range(n):\n        # Use np.count_nonzero which works directly on boolean arrays\n        count = np.count_nonzero(detections.mask[i])\n        if count > 0:\n            areas.append(float(count))\n        else:\n            areas.append(float(bbox_areas[i]))\n    \n    return areas\n```",
    "optimized_function_only": "def compute_detection_areas(detections: sv.Detections) -> List[float]:\n    \"\"\"Compute the area of all detections in square pixels.\n\n    For bounding-box-only detections, areas are computed in a single vectorized\n    operation. For detections with segmentation masks, the area is the count of\n    non-zero mask pixels (via ``cv2.countNonZero``). This correctly handles masks\n    with holes \u2014 hole pixels are zero and are not counted. Falls back to the\n    bounding box area when the mask pixel count is zero.\n\n    Args:\n        detections: A supervision Detections object.\n\n    Returns:\n        List of areas in square pixels, one per detection.\n    \"\"\"\n    n = len(detections)\n    if n == 0:\n        return []\n\n\n    # Pre-compute bounding box areas for all detections\n    xyxy = detections.xyxy\n    bbox_areas = (xyxy[:, 2] - xyxy[:, 0]) * (xyxy[:, 3] - xyxy[:, 1])\n    \n    if detections.mask is None:\n        return bbox_areas.tolist()\n    \n    areas = []\n    for i in range(n):\n        # Use np.count_nonzero which works directly on boolean arrays\n        count = np.count_nonzero(detections.mask[i])\n        if count > 0:\n            areas.append(float(count))\n        else:\n            areas.append(float(bbox_areas[i]))\n    \n    return areas",
    "original_file_content": "from typing import List, Literal, Optional, Type, Union\n\nimport cv2 as cv\nimport numpy as np\nimport supervision as sv\nfrom pydantic import ConfigDict, Field\n\nfrom inference.core.workflows.execution_engine.constants import (\n    AREA_CONVERTED_KEY_IN_SV_DETECTIONS,\n    AREA_KEY_IN_SV_DETECTIONS,\n)\nfrom inference.core.workflows.execution_engine.entities.base import OutputDefinition\nfrom inference.core.workflows.execution_engine.entities.types import (\n    FLOAT_KIND,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nOUTPUT_KEY = \"predictions\"\nSHORT_DESCRIPTION = (\n    \"Measure the area of detected objects and optionally convert to real-world units.\"\n)\nLONG_DESCRIPTION = \"\"\"\nMeasure the area of detected objects. For instance segmentation masks, the area is computed by counting non-zero mask pixels (correctly handling holes). For bounding-box-only detections, the area is width multiplied by height. Optionally converts pixel areas to real-world units using a `pixels_per_unit` calibration value.\n\n## How This Block Works\n\nThis block calculates the area of each detected object and stores two values per detection:\n\n- **`area_px`** \u2014 area in square pixels (always computed)\n- **`area_converted`** \u2014 area in real-world units: `area_px / (pixels_per_unit ** 2)` (equals `area_px` when `pixels_per_unit` is 1.0)\n\nBoth values are attached to each detection and included in the serialized JSON output. The block returns the input detections with these fields added, so downstream blocks (e.g., label visualization) can display the area values.\n\n### Area Computation\n\nThe block operates in two modes depending on the type of predictions it receives:\n\n1. **Mask Pixel Area (Instance Segmentation)**: When the input detections include segmentation masks, the block counts the non-zero pixels in each mask using `cv2.countNonZero`. This correctly handles masks with holes \u2014 hole pixels are zero and are excluded from the count.\n\n2. **Bounding Box Area (Object Detection)**: When no segmentation mask is available, the block falls back to computing the area as the bounding box width multiplied by height (`w * h`).\n\n### Unit Conversion\n\nSet the `pixels_per_unit` input to convert pixel areas to real-world units (e.g., cm\u00b2, in\u00b2, mm\u00b2). Because area is two-dimensional, the conversion squares the ratio:\n\n```\narea_converted = area_px / (pixels_per_unit ** 2)\n```\n\nFor example, if your calibration is 130 pixels/cm, a detection with `area_px = 16900` would have `area_converted = 16900 / 16900 = 1.0 cm\u00b2`.\n\n**How to determine pixels_per_unit:** Place an object of known size in the camera's field of view (e.g., a ruler or calibration target). Measure its length in pixels in the image and divide by its real-world length. For instance, if a 10 cm reference object spans 1300 pixels, then `pixels_per_cm = 1300 / 10 = 130`. If you are using perspective correction, the calibration object must be placed on the same plane from which the perspective correction was calculated.\n\n## Common Use Cases\n\n- **Size-Based Filtering**: Filter out small noise detections by chaining with a filtering block to keep only detections above a minimum area threshold.\n- **Quality Control**: Verify that manufactured components meet size specifications by comparing measured areas against expected ranges.\n- **Agricultural Analysis**: Measure leaf area, crop coverage, or canopy extent from aerial or close-up imagery.\n- **Medical Imaging**: Quantify the area of wounds, lesions, or anatomical structures. Use `pixels_per_unit` to get real-world measurements for clinical documentation.\n\n## Connecting to Other Blocks\n\n- **Upstream -- Detection and Segmentation Models**: Connect the output of an object detection or instance segmentation model to the `predictions` input. Instance segmentation models (which produce masks) yield more accurate area measurements than bounding-box-only detections.\n- **Upstream -- Camera Calibration Block**: Use `roboflow_core/camera_calibration@v1` upstream to correct lens distortion before detection.\n- **Upstream -- Perspective Correction Block**: Use `roboflow_core/perspective_correction@v1` upstream to transform angled images to a top-down view so that area measurements reflect true object footprints.\n- **Downstream -- Visualization**: Pass the output `predictions` to label or polygon visualization blocks. The `area_px` and `area_converted` fields are available for display as labels.\n- **Downstream -- Filtering Blocks**: Use the enriched detections with a filtering block to keep only detections whose area meets a threshold.\n\n## Requirements\n\nThis block requires detection predictions from an object detection or instance segmentation model. No additional environment variables, API keys, or external dependencies are needed beyond OpenCV and NumPy (included with inference). For the most accurate area measurements, use instance segmentation models that produce per-object masks.\n\"\"\"\n\n\nclass MaskAreaMeasurementManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Mask Area Measurement\",\n            \"version\": \"v1\",\n            \"short_description\": SHORT_DESCRIPTION,\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"transformation\",\n            \"ui_manifest\": {\n                \"section\": \"classical_cv\",\n                \"icon\": \"far fa-ruler-combined\",\n                \"blockPriority\": 12,\n                \"opencv\": True,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/mask_area_measurement@v1\"]\n\n    predictions: Selector(\n        kind=[\n            INSTANCE_SEGMENTATION_PREDICTION_KIND,\n            OBJECT_DETECTION_PREDICTION_KIND,\n        ]\n    ) = Field(\n        description=\"Detection predictions to measure areas for.\",\n        examples=[\"$steps.model.predictions\"],\n    )\n\n    pixels_per_unit: Union[float, Selector(kind=[FLOAT_KIND])] = Field(  # type: ignore\n        default=1.0,\n        description=\"Number of pixels per real-world unit of length (e.g., pixels per cm). \"\n        \"The converted area is computed as area_px / (pixels_per_unit ** 2). \"\n        \"Default 1.0 means no conversion (area_converted equals area_px).\",\n        examples=[1.0, 130.0],\n    )\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(\n                name=OUTPUT_KEY,\n                kind=[\n                    OBJECT_DETECTION_PREDICTION_KIND,\n                    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n                ],\n            ),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\ndef compute_detection_areas(detections: sv.Detections) -> List[float]:\n    \"\"\"Compute the area of all detections in square pixels.\n\n    For bounding-box-only detections, areas are computed in a single vectorized\n    operation. For detections with segmentation masks, the area is the count of\n    non-zero mask pixels (via ``cv2.countNonZero``). This correctly handles masks\n    with holes \u2014 hole pixels are zero and are not counted. Falls back to the\n    bounding box area when the mask pixel count is zero.\n\n    Args:\n        detections: A supervision Detections object.\n\n    Returns:\n        List of areas in square pixels, one per detection.\n    \"\"\"\n    n = len(detections)\n    if n == 0:\n        return []\n\n    areas = []\n    for i in range(n):\n        if detections.mask is not None:\n            count = cv.countNonZero(detections.mask[i].astype(np.uint8))\n            if count > 0:\n                areas.append(float(count))\n                continue\n        x1, y1, x2, y2 = detections.xyxy[i]\n        areas.append(float((x2 - x1) * (y2 - y1)))\n\n    return areas\n\n\nclass MaskAreaMeasurementBlockV1(WorkflowBlock):\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return MaskAreaMeasurementManifest\n\n    def run(\n        self,\n        predictions: sv.Detections,\n        pixels_per_unit: float = 1.0,\n    ) -> BlockResult:\n        areas_px = np.array(compute_detection_areas(predictions))\n        predictions.data[AREA_KEY_IN_SV_DETECTIONS] = areas_px\n        scale = pixels_per_unit**2 if pixels_per_unit > 0 else 1.0\n        predictions.data[AREA_CONVERTED_KEY_IN_SV_DETECTIONS] = areas_px / scale\n        return {OUTPUT_KEY: predictions}\n",
    "patch": null
  },
  {
    "trace_id": "e9c228fb-b455-4b73-9038-3954bc2429d4",
    "function_name": "SemanticSegmentationBaseOnnxRoboflowInferenceModel.make_response",
    "file_path": "inference/core/models/semantic_segmentation_base.py",
    "speedup_x": 0.328167485837892,
    "review_quality": "high",
    "pre_optimization_commit": "HEAD",
    "resolution_method": "db_code_only",
    "source": "db_features",
    "original_function_code": "    def make_response(\n        self, batch_predictions, img_dims, **kwargs\n    ) -> List[SemanticSegmentationInferenceResponse]:\n        # (N,C,H,W)\n        batch_predictions = torch.tensor(batch_predictions)\n        batch_class_probs = torch.nn.functional.softmax(batch_predictions, dim=1)\n        # (N,H,W)\n        batch_confidence, batch_class_ids = torch.max(batch_class_probs, dim=1)\n\n        # we will return class_id and confidence masks as b64-encoded uint8 images but for now\n        # they need to be float for interpolation since torch interpolate doesn't support uint8\n        batch_class_ids = batch_class_ids.to(torch.float)\n        # rescale and discretize confidence scores [0,1]->[0, 255] for later\n        batch_confidence = torch.round(batch_confidence * 255)\n\n        responses = []\n        for confidence, class_ids, img_dim in zip(\n            batch_confidence, batch_class_ids, img_dims\n        ):\n            # resize to original img_dim and convert to uint8\n            confidence = self.resize_img(confidence, img_dim).to(torch.uint8)\n            class_ids = self.resize_img(class_ids, img_dim).to(torch.uint8)\n\n            # pack up response\n            response_image = InferenceResponseImage(width=img_dim[1], height=img_dim[0])\n\n            response_predictions = SemanticSegmentationPrediction(\n                segmentation_mask=self.img_to_b64_str(class_ids),\n                confidence_mask=self.img_to_b64_str(confidence),\n                class_map=self.class_map,\n                image=dict(response_image),\n            )\n\n            response = SemanticSegmentationInferenceResponse(\n                predictions=response_predictions,\n                image=response_image,\n            )\n            responses.append(response)\n\n            return responses\n",
    "optimized_function_code": "import base64\nimport concurrent.futures\nimport io\nimport os\nfrom typing import List, Tuple\n\nimport torch\nfrom inference.core.entities.responses.inference import (\n    InferenceResponseImage, SemanticSegmentationInferenceResponse,\n    SemanticSegmentationPrediction)\nfrom inference.core.models.roboflow import OnnxRoboflowInferenceModel\nfrom PIL import Image\n\n# Reuse a module-level thread pool so we don't pay the thread-creation cost on every call.\n# Use a small upper bound to avoid excessive thread creation on large machines.\n_THREAD_POOL = concurrent.futures.ThreadPoolExecutor(max_workers=min(32, max(2, (os.cpu_count() or 1))))\n\nclass SemanticSegmentationBaseOnnxRoboflowInferenceModel(OnnxRoboflowInferenceModel):\n\n    def make_response(\n        self, batch_predictions, img_dims, **kwargs\n    ) -> List[SemanticSegmentationInferenceResponse]:\n        # (N,C,H,W)\n        # Use as_tensor to avoid an unnecessary copy if batch_predictions is already an array/tensor\n        batch_predictions = torch.as_tensor(batch_predictions)\n        batch_class_probs = torch.nn.functional.softmax(batch_predictions, dim=1)\n        # (N,H,W)\n        batch_confidence, batch_class_ids = torch.max(batch_class_probs, dim=1)\n\n        # we will return class_id and confidence masks as b64-encoded uint8 images but for now\n        # they need to be float for interpolation since torch interpolate doesn't support uint8\n        batch_class_ids = batch_class_ids.to(torch.float)\n        # rescale and discretize confidence scores [0,1]->[0, 255] for later\n        batch_confidence = torch.round(batch_confidence * 255)\n\n        responses = []\n        for confidence, class_ids, img_dim in zip(\n            batch_confidence, batch_class_ids, img_dims\n        ):\n            # resize to original img_dim and convert to uint8\n            confidence = self.resize_img(confidence, img_dim).to(torch.uint8)\n            class_ids = self.resize_img(class_ids, img_dim).to(torch.uint8)\n\n            # pack up response\n            response_image = InferenceResponseImage(width=img_dim[1], height=img_dim[0])\n\n\n            # Encode both images in parallel - encoding PNG is CPU-bound C code and releases the GIL,\n            # so using threads lets the two encodes run concurrently.\n            # Preserve original behavior and ordering of results.\n            seg_future = _THREAD_POOL.submit(self.img_to_b64_str, class_ids)\n            conf_future = _THREAD_POOL.submit(self.img_to_b64_str, confidence)\n            segmentation_b64 = seg_future.result()\n            confidence_b64 = conf_future.result()\n\n            response_predictions = SemanticSegmentationPrediction(\n                segmentation_mask=segmentation_b64,\n                confidence_mask=confidence_b64,\n                class_map=self.class_map,\n                image=dict(response_image),\n            )\n\n            response = SemanticSegmentationInferenceResponse(\n                predictions=response_predictions,\n                image=response_image,\n            )\n            responses.append(response)\n\n            return responses\n\n    def resize_img(self, img: torch.Tensor, img_dim: Tuple[int, int]) -> torch.Tensor:\n        return torch.nn.functional.interpolate(\n            img.unsqueeze(dim=0).unsqueeze(dim=0),\n            size=img_dim,\n            mode=\"nearest\",\n        ).squeeze()\n\n    def img_to_b64_str(self, img: torch.Tensor) -> str:\n        assert img.dtype == torch.uint8\n\n        # Ensure we operate on a CPU numpy array and avoid keeping gradient graph references\n        # Use detach().cpu().numpy() to be robust whether tensor is on CPU/GPU or requires grad.\n        arr = img.detach().cpu().numpy()\n        img = Image.fromarray(arr)\n        buffered = io.BytesIO()\n        img.save(buffered, format=\"PNG\")\n\n        img_str = base64.b64encode(buffered.getvalue())\n        img_str = img_str.decode(\"ascii\")\n\n        return img_str",
    "optimized_raw_markdown": "```python:inference/core/models/semantic_segmentation_base.py\nimport base64\nimport concurrent.futures\nimport io\nimport os\nfrom typing import List, Tuple\n\nimport torch\nfrom inference.core.entities.responses.inference import (\n    InferenceResponseImage, SemanticSegmentationInferenceResponse,\n    SemanticSegmentationPrediction)\nfrom inference.core.models.roboflow import OnnxRoboflowInferenceModel\nfrom PIL import Image\n\n# Reuse a module-level thread pool so we don't pay the thread-creation cost on every call.\n# Use a small upper bound to avoid excessive thread creation on large machines.\n_THREAD_POOL = concurrent.futures.ThreadPoolExecutor(max_workers=min(32, max(2, (os.cpu_count() or 1))))\n\nclass SemanticSegmentationBaseOnnxRoboflowInferenceModel(OnnxRoboflowInferenceModel):\n\n    def make_response(\n        self, batch_predictions, img_dims, **kwargs\n    ) -> List[SemanticSegmentationInferenceResponse]:\n        # (N,C,H,W)\n        # Use as_tensor to avoid an unnecessary copy if batch_predictions is already an array/tensor\n        batch_predictions = torch.as_tensor(batch_predictions)\n        batch_class_probs = torch.nn.functional.softmax(batch_predictions, dim=1)\n        # (N,H,W)\n        batch_confidence, batch_class_ids = torch.max(batch_class_probs, dim=1)\n\n        # we will return class_id and confidence masks as b64-encoded uint8 images but for now\n        # they need to be float for interpolation since torch interpolate doesn't support uint8\n        batch_class_ids = batch_class_ids.to(torch.float)\n        # rescale and discretize confidence scores [0,1]->[0, 255] for later\n        batch_confidence = torch.round(batch_confidence * 255)\n\n        responses = []\n        for confidence, class_ids, img_dim in zip(\n            batch_confidence, batch_class_ids, img_dims\n        ):\n            # resize to original img_dim and convert to uint8\n            confidence = self.resize_img(confidence, img_dim).to(torch.uint8)\n            class_ids = self.resize_img(class_ids, img_dim).to(torch.uint8)\n\n            # pack up response\n            response_image = InferenceResponseImage(width=img_dim[1], height=img_dim[0])\n\n\n            # Encode both images in parallel - encoding PNG is CPU-bound C code and releases the GIL,\n            # so using threads lets the two encodes run concurrently.\n            # Preserve original behavior and ordering of results.\n            seg_future = _THREAD_POOL.submit(self.img_to_b64_str, class_ids)\n            conf_future = _THREAD_POOL.submit(self.img_to_b64_str, confidence)\n            segmentation_b64 = seg_future.result()\n            confidence_b64 = conf_future.result()\n\n            response_predictions = SemanticSegmentationPrediction(\n                segmentation_mask=segmentation_b64,\n                confidence_mask=confidence_b64,\n                class_map=self.class_map,\n                image=dict(response_image),\n            )\n\n            response = SemanticSegmentationInferenceResponse(\n                predictions=response_predictions,\n                image=response_image,\n            )\n            responses.append(response)\n\n            return responses\n\n    def resize_img(self, img: torch.Tensor, img_dim: Tuple[int, int]) -> torch.Tensor:\n        return torch.nn.functional.interpolate(\n            img.unsqueeze(dim=0).unsqueeze(dim=0),\n            size=img_dim,\n            mode=\"nearest\",\n        ).squeeze()\n\n    def img_to_b64_str(self, img: torch.Tensor) -> str:\n        assert img.dtype == torch.uint8\n\n        # Ensure we operate on a CPU numpy array and avoid keeping gradient graph references\n        # Use detach().cpu().numpy() to be robust whether tensor is on CPU/GPU or requires grad.\n        arr = img.detach().cpu().numpy()\n        img = Image.fromarray(arr)\n        buffered = io.BytesIO()\n        img.save(buffered, format=\"PNG\")\n\n        img_str = base64.b64encode(buffered.getvalue())\n        img_str = img_str.decode(\"ascii\")\n\n        return img_str\n```",
    "optimized_function_only": "    def make_response(\n        self, batch_predictions, img_dims, **kwargs\n    ) -> List[SemanticSegmentationInferenceResponse]:\n        # (N,C,H,W)\n        # Use as_tensor to avoid an unnecessary copy if batch_predictions is already an array/tensor\n        batch_predictions = torch.as_tensor(batch_predictions)\n        batch_class_probs = torch.nn.functional.softmax(batch_predictions, dim=1)\n        # (N,H,W)\n        batch_confidence, batch_class_ids = torch.max(batch_class_probs, dim=1)\n\n        # we will return class_id and confidence masks as b64-encoded uint8 images but for now\n        # they need to be float for interpolation since torch interpolate doesn't support uint8\n        batch_class_ids = batch_class_ids.to(torch.float)\n        # rescale and discretize confidence scores [0,1]->[0, 255] for later\n        batch_confidence = torch.round(batch_confidence * 255)\n\n        responses = []\n        for confidence, class_ids, img_dim in zip(\n            batch_confidence, batch_class_ids, img_dims\n        ):\n            # resize to original img_dim and convert to uint8\n            confidence = self.resize_img(confidence, img_dim).to(torch.uint8)\n            class_ids = self.resize_img(class_ids, img_dim).to(torch.uint8)\n\n            # pack up response\n            response_image = InferenceResponseImage(width=img_dim[1], height=img_dim[0])\n\n\n            # Encode both images in parallel - encoding PNG is CPU-bound C code and releases the GIL,\n            # so using threads lets the two encodes run concurrently.\n            # Preserve original behavior and ordering of results.\n            seg_future = _THREAD_POOL.submit(self.img_to_b64_str, class_ids)\n            conf_future = _THREAD_POOL.submit(self.img_to_b64_str, confidence)\n            segmentation_b64 = seg_future.result()\n            confidence_b64 = conf_future.result()\n\n            response_predictions = SemanticSegmentationPrediction(\n                segmentation_mask=segmentation_b64,\n                confidence_mask=confidence_b64,\n                class_map=self.class_map,\n                image=dict(response_image),\n            )\n\n            response = SemanticSegmentationInferenceResponse(\n                predictions=response_predictions,\n                image=response_image,\n            )\n            responses.append(response)\n\n            return responses\n",
    "original_file_content": "import base64\nimport io\nimport torch\nfrom PIL import Image\nfrom inference.core.entities.responses.inference import InferenceResponseImage, SemanticSegmentationInferenceResponse, SemanticSegmentationPrediction\nfrom inference.core.models.roboflow import OnnxRoboflowInferenceModel\nfrom typing import List, Tuple\n\nclass SemanticSegmentationBaseOnnxRoboflowInferenceModel(OnnxRoboflowInferenceModel):\n\n    def make_response(\n        self, batch_predictions, img_dims, **kwargs\n    ) -> List[SemanticSegmentationInferenceResponse]:\n        # (N,C,H,W)\n        batch_predictions = torch.tensor(batch_predictions)\n        batch_class_probs = torch.nn.functional.softmax(batch_predictions, dim=1)\n        # (N,H,W)\n        batch_confidence, batch_class_ids = torch.max(batch_class_probs, dim=1)\n\n        # we will return class_id and confidence masks as b64-encoded uint8 images but for now\n        # they need to be float for interpolation since torch interpolate doesn't support uint8\n        batch_class_ids = batch_class_ids.to(torch.float)\n        # rescale and discretize confidence scores [0,1]->[0, 255] for later\n        batch_confidence = torch.round(batch_confidence * 255)\n\n        responses = []\n        for confidence, class_ids, img_dim in zip(\n            batch_confidence, batch_class_ids, img_dims\n        ):\n            # resize to original img_dim and convert to uint8\n            confidence = self.resize_img(confidence, img_dim).to(torch.uint8)\n            class_ids = self.resize_img(class_ids, img_dim).to(torch.uint8)\n\n            # pack up response\n            response_image = InferenceResponseImage(width=img_dim[1], height=img_dim[0])\n\n            response_predictions = SemanticSegmentationPrediction(\n                segmentation_mask=self.img_to_b64_str(class_ids),\n                confidence_mask=self.img_to_b64_str(confidence),\n                class_map=self.class_map,\n                image=dict(response_image),\n            )\n\n            response = SemanticSegmentationInferenceResponse(\n                predictions=response_predictions,\n                image=response_image,\n            )\n            responses.append(response)\n\n            return responses\n\n    def resize_img(self, img: torch.Tensor, img_dim: Tuple[int, int]) -> torch.Tensor:\n        return torch.nn.functional.interpolate(\n            img.unsqueeze(dim=0).unsqueeze(dim=0),\n            size=img_dim,\n            mode=\"nearest\",\n        ).squeeze()\n\n    def img_to_b64_str(self, img: torch.Tensor) -> str:\n        assert img.dtype == torch.uint8\n\n        img = Image.fromarray(img.numpy())\n        buffered = io.BytesIO()\n        img.save(buffered, format=\"PNG\")\n\n        img_str = base64.b64encode(buffered.getvalue())\n        img_str = img_str.decode(\"ascii\")\n\n        return img_str",
    "patch": null
  },
  {
    "trace_id": "c96f7e25-3382-4409-a6fd-b56f2344cc41",
    "function_name": "get_detection_area",
    "file_path": "inference/core/workflows/core_steps/classical_cv/mask_area_measurement/v1.py",
    "speedup_x": 0.19399736165773107,
    "review_quality": "high",
    "pre_optimization_commit": "0cfcffe66b48e56a5177c252b38aad0ef3f98c27",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def get_detection_area(detection: sv.Detections, index: int) -> float:\n    \"\"\"Compute the area of a single detection in square pixels.\n\n    If a segmentation mask is available, the area is computed from the largest\n    contour found in the mask using ``cv2.contourArea``.  Otherwise the area\n    falls back to bounding-box width * height.\n\n    Args:\n        detection: A supervision Detections object.\n        index: Index of the detection to measure.\n\n    Returns:\n        Area in square pixels.\n    \"\"\"\n    if detection.mask is not None:\n        mask = detection.mask[index].astype(np.uint8)\n        contours, _ = cv.findContours(mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)\n        if contours:\n            largest_contour = max(contours, key=cv.contourArea)\n            area = cv.contourArea(largest_contour)\n            if area > 0:\n                return float(area)\n\n    bbox = detection.xyxy[index]\n    w = bbox[2] - bbox[0]\n    h = bbox[3] - bbox[1]\n    return float(w * h)\n",
    "optimized_function_code": "import cv2 as cv\nimport numpy as np\nimport supervision as sv\n\n\ndef get_detection_area(detection: sv.Detections, index: int) -> float:\n    \"\"\"Compute the area of a single detection in square pixels.\n\n    If a segmentation mask is available, the area is computed from the largest\n    contour found in the mask using ``cv2.contourArea``.  Otherwise the area\n    falls back to bounding-box width * height.\n\n    Args:\n        detection: A supervision Detections object.\n        index: Index of the detection to measure.\n\n    Returns:\n        Area in square pixels.\n    \"\"\"\n    if detection.mask is not None:\n        mask = detection.mask[index]\n        # Only convert if needed to avoid unnecessary copy\n        if mask.dtype != np.uint8:\n            mask = mask.astype(np.uint8)\n        contours, _ = cv.findContours(mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)\n        if contours:\n            # Find the largest contour area in a single pass to avoid\n            # calling cv.contourArea twice for the same contour.\n            largest_contour = None\n            max_area = 0.0\n            for c in contours:\n                a = cv.contourArea(c)\n                if a > max_area:\n                    max_area = a\n                    largest_contour = c\n            if max_area > 0:\n                return float(max_area)\n\n\n    bbox = detection.xyxy[index]\n    w = bbox[2] - bbox[0]\n    h = bbox[3] - bbox[1]\n    return float(w * h)",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/classical_cv/mask_area_measurement/v1.py\nimport cv2 as cv\nimport numpy as np\nimport supervision as sv\n\n\ndef get_detection_area(detection: sv.Detections, index: int) -> float:\n    \"\"\"Compute the area of a single detection in square pixels.\n\n    If a segmentation mask is available, the area is computed from the largest\n    contour found in the mask using ``cv2.contourArea``.  Otherwise the area\n    falls back to bounding-box width * height.\n\n    Args:\n        detection: A supervision Detections object.\n        index: Index of the detection to measure.\n\n    Returns:\n        Area in square pixels.\n    \"\"\"\n    if detection.mask is not None:\n        mask = detection.mask[index]\n        # Only convert if needed to avoid unnecessary copy\n        if mask.dtype != np.uint8:\n            mask = mask.astype(np.uint8)\n        contours, _ = cv.findContours(mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)\n        if contours:\n            # Find the largest contour area in a single pass to avoid\n            # calling cv.contourArea twice for the same contour.\n            largest_contour = None\n            max_area = 0.0\n            for c in contours:\n                a = cv.contourArea(c)\n                if a > max_area:\n                    max_area = a\n                    largest_contour = c\n            if max_area > 0:\n                return float(max_area)\n\n\n    bbox = detection.xyxy[index]\n    w = bbox[2] - bbox[0]\n    h = bbox[3] - bbox[1]\n    return float(w * h)\n```",
    "optimized_function_only": "def get_detection_area(detection: sv.Detections, index: int) -> float:\n    \"\"\"Compute the area of a single detection in square pixels.\n\n    If a segmentation mask is available, the area is computed from the largest\n    contour found in the mask using ``cv2.contourArea``.  Otherwise the area\n    falls back to bounding-box width * height.\n\n    Args:\n        detection: A supervision Detections object.\n        index: Index of the detection to measure.\n\n    Returns:\n        Area in square pixels.\n    \"\"\"\n    if detection.mask is not None:\n        mask = detection.mask[index]\n        # Only convert if needed to avoid unnecessary copy\n        if mask.dtype != np.uint8:\n            mask = mask.astype(np.uint8)\n        contours, _ = cv.findContours(mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)\n        if contours:\n            # Find the largest contour area in a single pass to avoid\n            # calling cv.contourArea twice for the same contour.\n            largest_contour = None\n            max_area = 0.0\n            for c in contours:\n                a = cv.contourArea(c)\n                if a > max_area:\n                    max_area = a\n                    largest_contour = c\n            if max_area > 0:\n                return float(max_area)\n\n\n    bbox = detection.xyxy[index]\n    w = bbox[2] - bbox[0]\n    h = bbox[3] - bbox[1]\n    return float(w * h)",
    "original_file_content": "from typing import List, Literal, Optional, Type\n\nimport cv2 as cv\nimport numpy as np\nimport supervision as sv\nfrom pydantic import ConfigDict, Field\n\nfrom inference.core.workflows.execution_engine.entities.base import OutputDefinition\nfrom inference.core.workflows.execution_engine.entities.types import (\n    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    LIST_OF_VALUES_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nOUTPUT_KEY = \"areas\"\nSHORT_DESCRIPTION = \"Measure the mask area of detected objects in square pixels.\"\nLONG_DESCRIPTION = \"\"\"\nMeasure the area of detected objects in square pixels. For detections with segmentation masks, the area is computed from the largest contour using `cv2.contourArea`. For bounding-box-only detections, the area is the bounding box width multiplied by height.\n\n## How This Block Works\n\nThis block calculates the area of each detected object in an image, returning a list of area values in square pixels. The block operates in two modes depending on the type of predictions it receives:\n\n1. **Polygon/Mask Area (Instance Segmentation)**: When the input detections include segmentation masks, the block extracts the mask for each detection, finds the largest external contour using OpenCV's `findContours`, and computes its area with `cv2.contourArea`. This provides a precise measurement that follows the actual shape of the object rather than its bounding rectangle.\n\n2. **Bounding Box Area (Object Detection)**: When no segmentation mask is available, the block falls back to computing the area as the bounding box width multiplied by height (`w * h`). This is less precise but works with any object detection model output.\n\nThe block processes all detections in the input and returns a list of area values (one per detection) under the `areas` output key.\n\n## Common Use Cases\n\n- **Size-Based Filtering**: Use area measurements to filter out small noise detections or irrelevant objects. Chain the output with a filtering block to keep only detections above a minimum area threshold, reducing false positives from small artifacts.\n- **Agricultural Analysis**: Measure leaf area, crop coverage, or canopy extent from aerial or close-up imagery. Combine with segmentation models trained on plant structures to quantify growth or health metrics.\n- **Quality Control**: Verify that manufactured components meet size specifications by measuring their area in pixels and comparing against expected ranges. Flag parts that fall outside acceptable tolerances.\n- **Medical Imaging**: Quantify the area of wounds, lesions, skin conditions, or anatomical structures in clinical images. When paired with a calibration reference, pixel areas can be converted to real-world units for clinical documentation.\n- **Inventory and Logistics**: Estimate the footprint of packages, pallets, or items on conveyor belts. Area measurements help classify objects by size category or detect misplaced items that differ from expected dimensions.\n\n## Connecting to Other Blocks\n\nThis block receives detection predictions and produces a list of area values:\n\n- **Upstream -- Detection and Segmentation Models**: Connect the output of an object detection or instance segmentation model to the `predictions` input. Instance segmentation models (which produce masks) yield more accurate area measurements than bounding-box-only detections.\n- **Upstream -- Camera Calibration Block**: If your camera introduces lens distortion, run images through the Camera Calibration block before detection to correct geometric distortions. This ensures that area measurements are not skewed by barrel or pincushion distortion.\n- **Upstream -- Perspective Correction Block**: For images captured at an angle (e.g., overhead cameras that are not perfectly perpendicular), apply the Perspective Correction block before detection. This transforms the image to a top-down view so that area measurements reflect true object footprints rather than perspective-distorted projections.\n- **Downstream -- Filtering Blocks**: Pass the `areas` output to a filtering or condition block (e.g., Continue If, Detection Filter) to keep only detections whose area meets a threshold, enabling size-based filtering workflows.\n- **Downstream -- Analytics and Visualization**: Feed area values into analytics blocks for aggregation, charting, or overlay display. Combine with other measurement blocks (Size Measurement, Distance Measurement) for comprehensive spatial analysis.\n\n## Converting Pixel Areas to Real-World Units\n\nThis block returns areas in **square pixels**. To convert to real-world units (e.g., cm\u00b2, in\u00b2, mm\u00b2), you need a calibration value: the number of pixels per unit of length along one axis (pixels_per_unit).\n\n**Important:** Because area is two-dimensional, you must **square** the pixels_per_unit ratio:\n\n```\narea_real = area_px / (pixels_per_unit ** 2)\n```\n\nFor example, if your calibration is 130 pixels/cm:\n\n```\narea_cm\u00b2 = area_px / (130 ** 2) = area_px / 16900\n```\n\nA common mistake is dividing by `pixels_per_unit` instead of `pixels_per_unit\u00b2`, which produces values that are off by a factor of the ratio itself.\n\n**How to determine pixels_per_unit:** Place an object of known size in the camera's field of view (e.g., a ruler or calibration target). Measure its length in pixels in the image and divide by its real-world length. For instance, if a 10 cm reference object spans 1300 pixels, then `pixels_per_cm = 1300 / 10 = 130`.\n\nYou can perform this conversion downstream using a Dynamic Python Block or a simple post-processing step in your application code.\n\n## Handling Camera Distortion\n\nLens distortion (barrel or pincushion) warps the image so that objects near the edges appear stretched or compressed compared to objects near the center. This directly affects area measurements \u2014 the same real-world object will report different pixel areas depending on where it appears in the frame.\n\n**When distortion matters:**\n- Wide-angle or fisheye lenses with visible barrel distortion\n- Applications requiring consistent area measurements across the entire frame\n- When objects of interest appear near the edges of the image\n\n**When distortion can be ignored:**\n- Objects are always near the center of the frame\n- The lens has minimal distortion (e.g., telecentric or narrow field-of-view lenses)\n- Relative area comparisons (larger vs. smaller) are sufficient and absolute accuracy is not required\n\n**How to correct for it:**\n1. **Camera Calibration Block**: Use the `roboflow_core/camera_calibration@v1` block upstream of your detection model. This block applies OpenCV's `undistort` to remove lens distortion before the image is processed, so that mask areas reflect the true object shape.\n2. **Perspective Correction Block**: If the camera views the scene at an angle (not perpendicular), use the `roboflow_core/perspective_correction@v1` block to warp the image to a top-down view. Without this, objects farther from the camera appear smaller and their measured areas will be understated.\n\nBoth corrections should be applied **before** the detection model runs, so that the segmentation masks and bounding boxes are computed on the corrected image.\n\n## Requirements\n\nThis block requires detection predictions from an object detection or instance segmentation model. No additional environment variables, API keys, or external dependencies are needed beyond the standard OpenCV and NumPy libraries included with inference. For the most accurate area measurements, use instance segmentation models that produce per-object masks. Bounding-box-only detections will yield rectangular area approximations.\n\"\"\"\n\n\nclass MaskAreaMeasurementManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Mask Area Measurement\",\n            \"version\": \"v1\",\n            \"short_description\": SHORT_DESCRIPTION,\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"transformation\",\n            \"ui_manifest\": {\n                \"section\": \"classical_cv\",\n                \"icon\": \"far fa-ruler-combined\",\n                \"blockPriority\": 12,\n                \"opencv\": True,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/mask_area_measurement@v1\"]\n\n    predictions: Selector(\n        kind=[\n            INSTANCE_SEGMENTATION_PREDICTION_KIND,\n            OBJECT_DETECTION_PREDICTION_KIND,\n        ]\n    ) = Field(\n        description=\"Detection predictions to measure areas for.\",\n        examples=[\"$steps.model.predictions\"],\n    )\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(name=OUTPUT_KEY, kind=[LIST_OF_VALUES_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\ndef get_detection_area(detection: sv.Detections, index: int) -> float:\n    \"\"\"Compute the area of a single detection in square pixels.\n\n    If a segmentation mask is available, the area is computed from the largest\n    contour found in the mask using ``cv2.contourArea``.  Otherwise the area\n    falls back to bounding-box width * height.\n\n    Args:\n        detection: A supervision Detections object.\n        index: Index of the detection to measure.\n\n    Returns:\n        Area in square pixels.\n    \"\"\"\n    if detection.mask is not None:\n        mask = detection.mask[index].astype(np.uint8)\n        contours, _ = cv.findContours(mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)\n        if contours:\n            largest_contour = max(contours, key=cv.contourArea)\n            area = cv.contourArea(largest_contour)\n            if area > 0:\n                return float(area)\n\n    bbox = detection.xyxy[index]\n    w = bbox[2] - bbox[0]\n    h = bbox[3] - bbox[1]\n    return float(w * h)\n\n\nclass MaskAreaMeasurementBlockV1(WorkflowBlock):\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return MaskAreaMeasurementManifest\n\n    def run(\n        self,\n        predictions: sv.Detections,\n    ) -> BlockResult:\n        areas = []\n        for i in range(len(predictions)):\n            areas.append(get_detection_area(predictions, i))\n        return {OUTPUT_KEY: areas}\n",
    "patch": null
  },
  {
    "trace_id": "7c4697a6-c848-4a2e-bfee-25ecd10221aa",
    "function_name": "_url_for_safe_logging",
    "file_path": "inference/core/roboflow_api.py",
    "speedup_x": 0.4657431609992291,
    "review_quality": "high",
    "pre_optimization_commit": "7ebca7153d72dbe3d62dea55854fe932aef1bd3d",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "def _url_for_safe_logging(url: str) -> str:\n    \"\"\"Return a URL safe to log by stripping the query string (and params/fragment).\n\n    Expects the full URL as used for the request (e.g. already wrapped).\n    Use this when logging request URLs so that sensitive query parameters\n    (e.g. api_key, tokens) are never written to logs.\n    \"\"\"\n    parsed = urllib.parse.urlparse(url)\n    return urllib.parse.urlunparse(\n        (parsed.scheme, parsed.netloc, parsed.path, \"\", \"\", \"\")\n    )\n",
    "optimized_function_code": "import urllib.parse\n\n\ndef _url_for_safe_logging(url: str) -> str:\n    \"\"\"Return a URL safe to log by stripping the query string (and params/fragment).\n\n    Expects the full URL as used for the request (e.g. already wrapped).\n    Use this when logging request URLs so that sensitive query parameters\n    (e.g. api_key, tokens) are never written to logs.\n    \"\"\"\n    # Use urlsplit (faster than urlparse for our needs) to separate scheme/netloc/path/query/fragment.\n    parsed = urllib.parse.urlsplit(url)\n\n    # Remove params from the last path segment (urlparse moves params into a separate attribute;\n    # urlsplit leaves them in the path, so we emulate urlparse's behavior by trimming from the first\n    # ';' after the last '/').\n    path = parsed.path\n    if path:\n        last_slash = path.rfind('/')\n        semicolon_index = path.find(';', last_slash + 1)\n        if semicolon_index != -1:\n            path = path[:semicolon_index]\n\n    # Manually reconstruct the URL without params/query/fragment to avoid urlunparse overhead,\n    # matching urlunparse((scheme, netloc, path, \"\", \"\", \"\")) semantics.\n    if parsed.scheme:\n        if parsed.netloc:\n            return parsed.scheme + \"://\" + parsed.netloc + path\n        else:\n            return parsed.scheme + \":\" + path\n    else:\n        if parsed.netloc:\n            return \"//\" + parsed.netloc + path\n        else:\n            return path",
    "optimized_raw_markdown": "```python:inference/core/roboflow_api.py\nimport urllib.parse\n\n\ndef _url_for_safe_logging(url: str) -> str:\n    \"\"\"Return a URL safe to log by stripping the query string (and params/fragment).\n\n    Expects the full URL as used for the request (e.g. already wrapped).\n    Use this when logging request URLs so that sensitive query parameters\n    (e.g. api_key, tokens) are never written to logs.\n    \"\"\"\n    # Use urlsplit (faster than urlparse for our needs) to separate scheme/netloc/path/query/fragment.\n    parsed = urllib.parse.urlsplit(url)\n\n    # Remove params from the last path segment (urlparse moves params into a separate attribute;\n    # urlsplit leaves them in the path, so we emulate urlparse's behavior by trimming from the first\n    # ';' after the last '/').\n    path = parsed.path\n    if path:\n        last_slash = path.rfind('/')\n        semicolon_index = path.find(';', last_slash + 1)\n        if semicolon_index != -1:\n            path = path[:semicolon_index]\n\n    # Manually reconstruct the URL without params/query/fragment to avoid urlunparse overhead,\n    # matching urlunparse((scheme, netloc, path, \"\", \"\", \"\")) semantics.\n    if parsed.scheme:\n        if parsed.netloc:\n            return parsed.scheme + \"://\" + parsed.netloc + path\n        else:\n            return parsed.scheme + \":\" + path\n    else:\n        if parsed.netloc:\n            return \"//\" + parsed.netloc + path\n        else:\n            return path\n```",
    "optimized_function_only": "def _url_for_safe_logging(url: str) -> str:\n    \"\"\"Return a URL safe to log by stripping the query string (and params/fragment).\n\n    Expects the full URL as used for the request (e.g. already wrapped).\n    Use this when logging request URLs so that sensitive query parameters\n    (e.g. api_key, tokens) are never written to logs.\n    \"\"\"\n    # Use urlsplit (faster than urlparse for our needs) to separate scheme/netloc/path/query/fragment.\n    parsed = urllib.parse.urlsplit(url)\n\n    # Remove params from the last path segment (urlparse moves params into a separate attribute;\n    # urlsplit leaves them in the path, so we emulate urlparse's behavior by trimming from the first\n    # ';' after the last '/').\n    path = parsed.path\n    if path:\n        last_slash = path.rfind('/')\n        semicolon_index = path.find(';', last_slash + 1)\n        if semicolon_index != -1:\n            path = path[:semicolon_index]\n\n    # Manually reconstruct the URL without params/query/fragment to avoid urlunparse overhead,\n    # matching urlunparse((scheme, netloc, path, \"\", \"\", \"\")) semantics.\n    if parsed.scheme:\n        if parsed.netloc:\n            return parsed.scheme + \"://\" + parsed.netloc + path\n        else:\n            return parsed.scheme + \":\" + path\n    else:\n        if parsed.netloc:\n            return \"//\" + parsed.netloc + path\n        else:\n            return path",
    "original_file_content": "import asyncio\nimport base64\nimport binascii\nimport hashlib\nimport json\nimport os\nimport re\nimport time\nimport urllib.parse\nfrom enum import Enum\nfrom hashlib import sha256\nfrom json import JSONDecodeError\nfrom pathlib import Path\nfrom typing import Any, Callable, Dict, List, Optional, Tuple, Type, Union\n\nimport aiohttp\nimport backoff\nimport requests\nfrom cachetools.func import ttl_cache\nfrom requests import Response, Timeout\nfrom requests_toolbelt import MultipartEncoder\n\nfrom inference.core import logger\nfrom inference.core.cache import cache\nfrom inference.core.cache.base import BaseCache\nfrom inference.core.cache.model_artifacts import get_cache_dir, initialise_cache\nfrom inference.core.entities.types import (\n    DatasetID,\n    ModelID,\n    ModelType,\n    TaskType,\n    VersionID,\n    WorkspaceID,\n)\nfrom inference.core.env import (\n    API_BASE_URL,\n    ENFORCE_CREDITS_VERIFICATION,\n    GCP_SERVERLESS,\n    INTERNAL_WEIGHTS_URL_SUFFIX,\n    MD5_VERIFICATION_ENABLED,\n    MODEL_CACHE_DIR,\n    MODELS_CACHE_AUTH_CACHE_MAX_SIZE,\n    MODELS_CACHE_AUTH_CACHE_TTL,\n    MODELS_CACHE_AUTH_ENABLED,\n    RETRY_CONNECTION_ERRORS_TO_ROBOFLOW_API,\n    ROBOFLOW_API_EXTRA_HEADERS,\n    ROBOFLOW_API_REQUEST_TIMEOUT,\n    ROBOFLOW_API_VERIFY_SSL,\n    ROBOFLOW_SERVICE_SECRET,\n    SINGLE_TENANT_WORKFLOW_CACHE,\n    TRANSIENT_ROBOFLOW_API_ERRORS,\n    TRANSIENT_ROBOFLOW_API_ERRORS_RETRIES,\n    TRANSIENT_ROBOFLOW_API_ERRORS_RETRY_INTERVAL,\n    USE_FILE_CACHE_FOR_WORKFLOWS_DEFINITIONS,\n    WORKFLOWS_DEFINITION_CACHE_EXPIRY,\n)\nfrom inference.core.exceptions import (\n    MalformedRoboflowAPIResponseError,\n    MalformedWorkflowResponseError,\n    MissingDefaultModelError,\n    PaymentRequiredError,\n    RetryRequestError,\n    RoboflowAPIConnectionError,\n    RoboflowAPIForbiddenError,\n    RoboflowAPIIAlreadyAnnotatedError,\n    RoboflowAPIIAnnotationRejectionError,\n    RoboflowAPIImageUploadRejectionError,\n    RoboflowAPINotAuthorizedError,\n    RoboflowAPINotNotFoundError,\n    RoboflowAPITimeoutError,\n    RoboflowAPIUnsuccessfulRequestError,\n    RoboflowAPIUsagePausedError,\n    WorkspaceLoadError,\n)\nfrom inference.core.telemetry import record_api_call, record_error, start_span\nfrom inference.core.utils.file_system import sanitize_path_segment\nfrom inference.core.utils.requests import (\n    api_key_safe_raise_for_status,\n    api_key_safe_raise_for_status_aiohttp,\n)\nfrom inference.core.utils.url_utils import wrap_url\nfrom inference.core.version import __version__\n\nLOCAL_API_KEY = \"local\"\n\nENFORCE_CREDITS_VERIFICATION_HEADER = \"x-enforce-credits-verification\"\nENFORCE_INTERNAL_ARTIFACTS_URLS_HEADER = \"x-enforce-internal-artefacts-urls\"\n\nMODEL_TYPE_DEFAULTS = {\n    \"object-detection\": \"yolov5v2s\",\n    \"instance-segmentation\": \"yolact\",\n    \"classification\": \"vit\",\n    \"keypoint-detection\": \"yolov8n\",\n}\nPROJECT_TASK_TYPE_KEY = \"project_task_type\"\nMODEL_TYPE_KEY = \"model_type\"\n\nNOT_FOUND_ERROR_MESSAGE = (\n    \"Could not find requested Roboflow resource. Check that the provided dataset and \"\n    \"version are correct, and check that the provided Roboflow API key has the correct permissions.\"\n)\n\nROBOFLOW_INFERENCE_VERSION_HEADER = \"X-Roboflow-Inference-Version\"\nALLOW_CHUNKED_RESPONSE_HEADER = \"X-Allow-Chunked\"\n\n\ndef raise_from_lambda(\n    inner_error: Exception, exception_type: Type[Exception], message: str\n) -> None:\n    raise exception_type(message) from inner_error\n\n\nDEFAULT_ERROR_HANDLERS = {\n    401: lambda e: raise_from_lambda(\n        e,\n        RoboflowAPINotAuthorizedError,\n        \"Unauthorized access to roboflow API - check API key. Visit \"\n        \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve one.\",\n    ),\n    402: lambda e: raise_from_lambda(\n        e,\n        PaymentRequiredError,\n        \"Not enough credits to perform this request. Verify your workspace billing page.\",\n    ),\n    403: lambda e: raise_from_lambda(\n        e,\n        RoboflowAPIForbiddenError,\n        \"Unauthorized access to roboflow API - check API key regarding correctness and required scopes. Visit \"\n        \"https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key to learn how to retrieve one.\",\n    ),\n    404: lambda e: raise_from_lambda(\n        e, RoboflowAPINotNotFoundError, NOT_FOUND_ERROR_MESSAGE\n    ),\n    423: lambda e: raise_from_lambda(\n        e,\n        RoboflowAPIUsagePausedError,\n        \"Roboflow API usage is paused. Please contact your workspace administrator to re-enable api keys.\",\n    ),\n}\n\n\ndef wrap_roboflow_api_errors(\n    http_errors_handlers: Optional[\n        Dict[int, Callable[[Union[requests.exceptions.HTTPError]], None]]\n    ] = None,\n) -> callable:\n    def decorator(function: callable) -> callable:\n        def wrapper(*args, **kwargs) -> Any:\n            t_start = time.perf_counter()\n            with start_span(\n                \"roboflow_api.call\",\n                {\"roboflow_api.function\": function.__name__},\n            ):\n                try:\n                    try:\n                        return function(*args, **kwargs)\n                    except RetryRequestError as error:\n                        raise error.inner_error\n                except Timeout as error:\n                    record_error(error)\n                    raise RoboflowAPITimeoutError(\n                        \"Timeout when attempting to connect to Roboflow API.\"\n                    ) from error\n                except (\n                    requests.exceptions.ConnectionError,\n                    ConnectionError,\n                ) as error:\n                    record_error(error)\n                    raise RoboflowAPIConnectionError(\n                        \"Could not connect to Roboflow API.\"\n                    ) from error\n                except requests.exceptions.HTTPError as error:\n                    record_error(error)\n                    user_handler_override = (\n                        http_errors_handlers if http_errors_handlers is not None else {}\n                    )\n                    status_code = error.response.status_code\n                    default_handler = DEFAULT_ERROR_HANDLERS.get(status_code)\n                    error_handler = user_handler_override.get(\n                        status_code, default_handler\n                    )\n                    if error_handler is not None:\n                        error_handler(error)\n                    raise RoboflowAPIUnsuccessfulRequestError(\n                        f\"Unsuccessful request to Roboflow API with response code: {status_code}\"\n                    ) from error\n                except requests.exceptions.InvalidJSONError as error:\n                    record_error(error)\n                    raise MalformedRoboflowAPIResponseError(\n                        \"Could not decode JSON response from Roboflow API.\"\n                    ) from error\n                finally:\n                    record_api_call(function.__name__, time.perf_counter() - t_start)\n\n        return wrapper\n\n    return decorator\n\n\ndef wrap_roboflow_api_errors_async(\n    http_errors_handlers: Optional[\n        Dict[int, Callable[[Union[aiohttp.ClientError]], None]]\n    ] = None,\n) -> callable:\n    def decorator(function: callable) -> callable:\n        async def wrapper(*args, **kwargs) -> Any:\n            t_start = time.perf_counter()\n            with start_span(\n                \"roboflow_api.call\",\n                {\"roboflow_api.function\": function.__name__},\n            ):\n                try:\n                    try:\n                        return await function(*args, **kwargs)\n                    except RetryRequestError as error:\n                        raise error.inner_error\n                except asyncio.TimeoutError as error:\n                    record_error(error)\n                    raise RoboflowAPITimeoutError(\n                        \"Timeout when attempting to connect to Roboflow API.\"\n                    ) from error\n                except (aiohttp.ClientConnectionError, ConnectionError) as error:\n                    record_error(error)\n                    raise RoboflowAPIConnectionError(\n                        \"Could not connect to Roboflow API.\"\n                    ) from error\n                except (aiohttp.ContentTypeError, JSONDecodeError) as error:\n                    record_error(error)\n                    raise MalformedRoboflowAPIResponseError(\n                        \"Could not decode JSON response from Roboflow API.\"\n                    ) from error\n                except aiohttp.ClientResponseError as error:\n                    record_error(error)\n                    user_handler_override = (\n                        http_errors_handlers if http_errors_handlers is not None else {}\n                    )\n                    status_code = error.status\n                    default_handler = DEFAULT_ERROR_HANDLERS.get(status_code)\n                    error_handler = user_handler_override.get(\n                        status_code, default_handler\n                    )\n                    if error_handler is not None:\n                        error_handler(error)\n                    raise RoboflowAPIUnsuccessfulRequestError(\n                        f\"Unsuccessful request to Roboflow API with response code: {status_code}\"\n                    ) from error\n                # remaining aiohttp.ClientError seems to qualify to simply pass-through raise\n                finally:\n                    record_api_call(function.__name__, time.perf_counter() - t_start)\n\n        return wrapper\n\n    return decorator\n\n\n@ttl_cache(ttl=MODELS_CACHE_AUTH_CACHE_TTL, maxsize=MODELS_CACHE_AUTH_CACHE_MAX_SIZE)\n@wrap_roboflow_api_errors()\ndef get_roboflow_workspace(api_key: str) -> WorkspaceID:\n    if not api_key:\n        raise WorkspaceLoadError(\"Empty workspace encountered, check your API key.\")\n\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/\",\n        params=[(\"api_key\", api_key), (\"nocache\", \"true\")],\n    )\n    api_key_info = _get_from_url(url=api_url)\n    workspace_id = api_key_info.get(\"workspace\")\n    if workspace_id is None:\n        raise WorkspaceLoadError(\"Empty workspace encountered, check your API key.\")\n    return workspace_id\n\n\n@wrap_roboflow_api_errors_async()\n@backoff.on_exception(\n    backoff.constant,\n    exception=RetryRequestError,\n    max_tries=TRANSIENT_ROBOFLOW_API_ERRORS_RETRIES,\n    interval=TRANSIENT_ROBOFLOW_API_ERRORS_RETRY_INTERVAL,\n)\nasync def get_roboflow_workspace_async(api_key: str) -> WorkspaceID:\n    try:\n        headers = build_roboflow_api_headers()\n        async with aiohttp.ClientSession() as session:\n            async with session.get(\n                f\"{API_BASE_URL}/\",\n                params={\"api_key\": api_key, \"nocache\": \"true\"},\n                headers=headers,\n                timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n            ) as response:\n                try:\n                    api_key_safe_raise_for_status_aiohttp(response=response)\n                except Exception as error:\n                    if response.status in TRANSIENT_ROBOFLOW_API_ERRORS:\n                        raise RetryRequestError(\n                            message=str(error), inner_error=error\n                        ) from error\n                    raise error\n                response_payload = await response.json()\n                workspace_id = response_payload.get(\"workspace\")\n                if workspace_id is None:\n                    raise WorkspaceLoadError(\n                        \"Empty workspace encountered, check your API key.\"\n                    )\n                return workspace_id\n    except (aiohttp.ClientConnectionError, ConnectionError) as error:\n        if RETRY_CONNECTION_ERRORS_TO_ROBOFLOW_API:\n            raise RetryRequestError(\n                message=\"Connectivity error\", inner_error=error\n            ) from error\n        raise error\n\n\n@wrap_roboflow_api_errors()\ndef add_custom_metadata(\n    api_key: str,\n    workspace_id: WorkspaceID,\n    inference_ids: List[str],\n    field_name: str,\n    field_value: str,\n):\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/inference-stats/metadata\",\n        params=[(\"api_key\", api_key), (\"nocache\", \"true\")],\n    )\n    response = requests.post(\n        url=api_url,\n        json={\n            \"data\": [\n                {\n                    \"inference_ids\": inference_ids,\n                    \"field_name\": field_name,\n                    \"field_value\": field_value,\n                }\n            ]\n        },\n        headers=build_roboflow_api_headers(),\n        timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n        verify=ROBOFLOW_API_VERIFY_SSL,\n    )\n    api_key_safe_raise_for_status(response=response)\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_dataset_type(\n    api_key: str, workspace_id: WorkspaceID, dataset_id: DatasetID\n) -> TaskType:\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/{dataset_id}\",\n        params=[(\"api_key\", api_key), (\"nocache\", \"true\")],\n    )\n    dataset_info = _get_from_url(url=api_url)\n    project_task_type = dataset_info.get(\"project\", {})\n    if \"type\" not in project_task_type:\n        logger.warning(\n            f\"Project task type not defined for workspace={workspace_id} and dataset={dataset_id}, defaulting \"\n            f\"to object-detection.\"\n        )\n    return project_task_type.get(\"type\", \"object-detection\")\n\n\n@wrap_roboflow_api_errors(\n    http_errors_handlers={\n        500: lambda e: raise_from_lambda(\n            e, RoboflowAPINotNotFoundError, NOT_FOUND_ERROR_MESSAGE\n        )\n        # this is temporary solution, empirically checked that backend API responds HTTP 500 on incorrect version.\n        # TO BE FIXED at backend, otherwise this error handling may overshadow existing backend problems.\n    }\n)\ndef get_roboflow_model_type(\n    api_key: str,\n    workspace_id: WorkspaceID,\n    dataset_id: DatasetID,\n    version_id: VersionID,\n    project_task_type: ModelType,\n) -> ModelType:\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/{dataset_id}/{version_id}\",\n        params=[(\"api_key\", api_key), (\"nocache\", \"true\")],\n    )\n    version_info = _get_from_url(url=api_url)\n    model_type = version_info[\"version\"]\n    if \"modelType\" not in model_type:\n        if project_task_type not in MODEL_TYPE_DEFAULTS:\n            raise MissingDefaultModelError(\n                f\"Could not set default model for {project_task_type}\"\n            )\n        logger.warning(\n            f\"Model type not defined - using default for {project_task_type} task.\"\n        )\n    return model_type.get(\"modelType\", MODEL_TYPE_DEFAULTS[project_task_type])\n\n\nclass ModelEndpointType(Enum):\n    ORT = \"ort\"\n    CORE_MODEL = \"core_model\"\n    OWLV2 = \"owlv2\"\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_model_data(\n    api_key: str,\n    model_id: str,\n    endpoint_type: ModelEndpointType,\n    device_id: str,\n    countinference: Optional[bool] = None,\n    service_secret: Optional[str] = None,\n) -> dict:\n    api_data_cache_key = f\"roboflow_api_data:{endpoint_type.value}:{model_id}\"\n    api_data = None\n    if not MODELS_CACHE_AUTH_ENABLED:\n        api_data = cache.get(api_data_cache_key)\n    if api_data is not None:\n        logger.debug(f\"Loaded model data from cache with key: {api_data_cache_key}.\")\n        return api_data\n    else:\n        params = [\n            (\"nocache\", \"true\"),\n            (\"device\", device_id),\n            (\"dynamic\", \"true\"),\n        ]\n        if api_key is not None and api_key != LOCAL_API_KEY:\n            params.append((\"api_key\", api_key))\n\n        if (\n            INTERNAL_WEIGHTS_URL_SUFFIX == \"serverless\"\n            and countinference is False\n            and service_secret == ROBOFLOW_SERVICE_SECRET\n        ):\n            params.append((\"countinference\", str(countinference).lower()))\n            params.append((\"service_secret\", service_secret))\n\n        api_base_url = urllib.parse.urljoin(API_BASE_URL, INTERNAL_WEIGHTS_URL_SUFFIX)\n        api_url = _add_params_to_url(\n            url=f\"{api_base_url}/{endpoint_type.value}/{model_id}\",\n            params=params,\n        )\n        api_data = _get_from_url(url=api_url)\n        cache.set(\n            api_data_cache_key,\n            api_data,\n            expire=10,\n        )\n        logger.debug(\n            f\"Loaded model data from Roboflow API and saved to cache with key: {api_data_cache_key}.\"\n        )\n        return api_data\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_instant_model_data(\n    api_key: str,\n    model_id: ModelID,\n    cache_prefix: str = \"roboflow_api_data\",\n    countinference: Optional[bool] = None,\n    service_secret: Optional[str] = None,\n) -> dict:\n    api_data_cache_key = f\"{cache_prefix}:{model_id}\"\n    api_data = None\n    if not MODELS_CACHE_AUTH_ENABLED:\n        api_data = cache.get(api_data_cache_key)\n    if api_data is not None:\n        logger.debug(f\"Loaded model data from cache with key: {api_data_cache_key}.\")\n        return api_data\n    else:\n        params = [\n            (\"model\", model_id),\n        ]\n        if api_key is not None and api_key != LOCAL_API_KEY:\n            params.append((\"api_key\", api_key))\n\n        if (\n            INTERNAL_WEIGHTS_URL_SUFFIX == \"serverless\"\n            and countinference is False\n            and service_secret == ROBOFLOW_SERVICE_SECRET\n        ):\n            params.append((\"countinference\", str(countinference).lower()))\n            params.append((\"service_secret\", service_secret))\n\n        api_base_url = urllib.parse.urljoin(API_BASE_URL, INTERNAL_WEIGHTS_URL_SUFFIX)\n        api_url = _add_params_to_url(\n            url=f\"{api_base_url}/getWeights\",\n            params=params,\n        )\n        api_data = _get_from_url(url=api_url)\n        cache.set(\n            api_data_cache_key,\n            api_data,\n            expire=10,\n        )\n        logger.debug(\n            f\"Loaded model data from Roboflow API and saved to cache with key: {api_data_cache_key}.\"\n        )\n        return api_data\n\n\n@wrap_roboflow_api_errors()\ndef get_model_metadata_from_inference_models_registry(\n    api_key: str,\n    model_id: ModelID,\n    cache_prefix: str = \"roboflow_api_data:inference_models_registry\",\n    countinference: Optional[bool] = None,\n    service_secret: Optional[str] = None,\n) -> dict:\n    # Watch out - this function should only be used to substitute get_roboflow_instant_model_data()\n    # and only in terms of getting model type and task type\n    # this is only stub to make sure auth works as it should for models which are not\n    # associated to project via version (for which old auth and metadata retrieval method work).\n    api_data_cache_key = f\"{cache_prefix}:{model_id}\"\n    api_data = None\n    if not MODELS_CACHE_AUTH_ENABLED:\n        api_data = cache.get(api_data_cache_key)\n    if api_data is not None:\n        logger.debug(f\"Loaded model data from cache with key: {api_data_cache_key}.\")\n        return api_data\n    query = [(\"modelId\", model_id)]\n    headers = {\"Authorization\": f\"Bearer {api_key}\"}\n    if GCP_SERVERLESS:\n        headers[ENFORCE_INTERNAL_ARTIFACTS_URLS_HEADER] = \"true\"\n    if ENFORCE_CREDITS_VERIFICATION:\n        skip = (\n            countinference is False\n            and service_secret is not None\n            and service_secret == ROBOFLOW_SERVICE_SECRET\n        )\n        if not skip:\n            headers[ENFORCE_CREDITS_VERIFICATION_HEADER] = \"true\"\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/models/v1/external/weights\",\n        params=query,\n    )\n    raw_api_data = _get_from_url(url=api_url, headers=headers)\n    api_data = {\n        \"modelType\": raw_api_data[\"modelMetadata\"][\"modelArchitecture\"],\n        \"taskType\": raw_api_data[\"modelMetadata\"][\"taskType\"],\n    }\n    cache.set(\n        api_data_cache_key,\n        api_data,\n        expire=10,\n    )\n    logger.debug(\n        f\"Loaded model data from Roboflow API (inference-models registry) \"\n        f\"and saved to cache with key: {api_data_cache_key}.\"\n    )\n    return api_data\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_base_lora(\n    api_key: str, repo: str, revision: str, device_id: str\n) -> dict:\n    full_path = f\"{repo.strip('/')}/{revision.strip('/')}\"\n    api_data_cache_key = f\"roboflow_api_data:lora-bases:{full_path}\"\n    api_data = None\n    if not MODELS_CACHE_AUTH_ENABLED:\n        api_data = cache.get(api_data_cache_key)\n    if api_data is not None:\n        logger.debug(f\"Loaded model data from cache with key: {api_data_cache_key}.\")\n        return api_data\n    else:\n        params = [\n            (\"nocache\", \"true\"),\n            (\"device\", device_id),\n            (\"repoAndRevision\", full_path),\n        ]\n        if api_key is not None and api_key != LOCAL_API_KEY:\n            params.append((\"api_key\", api_key))\n        api_url = _add_params_to_url(\n            url=f\"{API_BASE_URL}/lora_bases\",\n            params=params,\n        )\n        api_data = _get_from_url(url=api_url)\n        cache.set(\n            api_data_cache_key,\n            api_data,\n            expire=10,\n        )\n        logger.debug(\n            f\"Loaded lora base model data from Roboflow API and saved to cache with key: {api_data_cache_key}.\"\n        )\n        return api_data\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_active_learning_configuration(\n    api_key: str,\n    workspace_id: WorkspaceID,\n    dataset_id: DatasetID,\n) -> dict:\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/{dataset_id}/active_learning\",\n        params=[(\"api_key\", api_key)],\n    )\n    return _get_from_url(url=api_url)\n\n\n@wrap_roboflow_api_errors()\ndef register_image_at_roboflow(\n    api_key: str,\n    dataset_id: DatasetID,\n    local_image_id: str,\n    image_bytes: bytes,\n    batch_name: str,\n    tags: Optional[List[str]] = None,\n    inference_id: Optional[str] = None,\n    metadata: Optional[Dict[str, Any]] = None,\n) -> dict:\n    url = f\"{API_BASE_URL}/dataset/{dataset_id}/upload\"\n    params = [\n        (\"api_key\", api_key),\n        (\"batch\", batch_name),\n    ]\n    if inference_id is not None:\n        params.append((\"inference_id\", inference_id))\n    tags = tags if tags is not None else []\n    for tag in tags:\n        params.append((\"tag\", tag))\n    wrapped_url = wrap_url(_add_params_to_url(url=url, params=params))\n    fields = {\n        \"name\": f\"{local_image_id}.jpg\",\n        \"file\": (\"imageToUpload\", image_bytes, \"image/jpeg\"),\n    }\n    if metadata is not None:\n        fields[\"metadata\"] = json.dumps(metadata)\n    m = MultipartEncoder(fields=fields)\n    headers = build_roboflow_api_headers(\n        explicit_headers={\"Content-Type\": m.content_type},\n    )\n    response = requests.post(\n        url=wrapped_url,\n        data=m,\n        headers=headers,\n        timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n        verify=ROBOFLOW_API_VERIFY_SSL,\n    )\n    api_key_safe_raise_for_status(response=response)\n    parsed_response = response.json()\n    if not parsed_response.get(\"duplicate\") and not parsed_response.get(\"success\"):\n        raise RoboflowAPIImageUploadRejectionError(\n            f\"Server rejected image: {parsed_response}\"\n        )\n    return parsed_response\n\n\n@wrap_roboflow_api_errors(\n    http_errors_handlers={\n        409: lambda e: raise_from_lambda(\n            e,\n            RoboflowAPIIAlreadyAnnotatedError,\n            \"Given datapoint already has annotation.\",\n        )\n    }\n)\ndef annotate_image_at_roboflow(\n    api_key: str,\n    dataset_id: DatasetID,\n    local_image_id: str,\n    roboflow_image_id: str,\n    annotation_content: str,\n    annotation_file_type: str,\n    is_prediction: bool = True,\n) -> dict:\n    url = f\"{API_BASE_URL}/dataset/{dataset_id}/annotate/{roboflow_image_id}\"\n    params = [\n        (\"api_key\", api_key),\n        (\"name\", f\"{local_image_id}.{annotation_file_type}\"),\n        (\"prediction\", str(is_prediction).lower()),\n    ]\n    wrapped_url = wrap_url(_add_params_to_url(url=url, params=params))\n    headers = build_roboflow_api_headers(\n        explicit_headers={\"Content-Type\": \"text/plain\"},\n    )\n    response = requests.post(\n        wrapped_url,\n        data=annotation_content,\n        headers=headers,\n        timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n        verify=ROBOFLOW_API_VERIFY_SSL,\n    )\n    api_key_safe_raise_for_status(response=response)\n    parsed_response = response.json()\n    if \"error\" in parsed_response or not parsed_response.get(\"success\"):\n        raise RoboflowAPIIAnnotationRejectionError(\n            f\"Failed to save annotation for {roboflow_image_id}. API response: {parsed_response}\"\n        )\n    return parsed_response\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_labeling_batches(\n    api_key: str, workspace_id: WorkspaceID, dataset_id: str\n) -> dict:\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/{dataset_id}/batches\",\n        params=[(\"api_key\", api_key)],\n    )\n    return _get_from_url(url=api_url)\n\n\n@wrap_roboflow_api_errors()\ndef get_roboflow_labeling_jobs(\n    api_key: str, workspace_id: WorkspaceID, dataset_id: str\n) -> dict:\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/{dataset_id}/jobs\",\n        params=[(\"api_key\", api_key)],\n    )\n    return _get_from_url(url=api_url)\n\n\ndef get_workflow_cache_file(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    workflow_version_id: Optional[str] = None,\n) -> str:\n    sanitized_workspace_id = sanitize_path_segment(workspace_id)\n    sanitized_workflow_id = sanitize_path_segment(workflow_id)\n    if SINGLE_TENANT_WORKFLOW_CACHE:\n        version_suffix = (\n            f\"_v{sanitize_path_segment(workflow_version_id)}\"\n            if workflow_version_id\n            else \"\"\n        )\n        filename = f\"{sanitized_workflow_id}{version_suffix}.json\"\n    else:\n        cache_seed = f\"{workspace_id}:{api_key or ''}\"\n        cache_fingerprint = hashlib.sha256(\n            cache_seed.encode(\"utf-8\"), usedforsecurity=False\n        ).hexdigest()\n        filename = f\"{sanitized_workflow_id}_{cache_fingerprint}.json\"\n    prefix = os.path.abspath(os.path.join(MODEL_CACHE_DIR, \"workflow\"))\n    result = os.path.abspath(\n        os.path.join(\n            prefix,\n            sanitized_workspace_id,\n            filename,\n        )\n    )\n    if not result.startswith(prefix):\n        raise ValueError(\n            \"Detected attempt to save workflow definition in insecure location\"\n        )\n    return result\n\n\ndef cache_workflow_response(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    response: dict,\n    workflow_version_id: Optional[str] = None,\n):\n    workflow_cache_file = get_workflow_cache_file(\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        api_key=api_key,\n        workflow_version_id=workflow_version_id,\n    )\n    workflow_cache_dir = os.path.dirname(workflow_cache_file)\n    if not os.path.exists(workflow_cache_dir):\n        os.makedirs(workflow_cache_dir, exist_ok=True)\n    with open(workflow_cache_file, \"w\") as f:\n        json.dump(response, f)\n\n\ndef delete_cached_workflow_response_if_exists(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    workflow_version_id: Optional[str] = None,\n) -> None:\n    workflow_cache_file = get_workflow_cache_file(\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        api_key=api_key,\n        workflow_version_id=workflow_version_id,\n    )\n    if os.path.exists(workflow_cache_file):\n        os.remove(workflow_cache_file)\n\n\ndef load_cached_workflow_response(\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    api_key: Optional[str],\n    workflow_version_id: Optional[str] = None,\n) -> Optional[dict]:\n    workflow_cache_file = get_workflow_cache_file(\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        api_key=api_key,\n        workflow_version_id=workflow_version_id,\n    )\n    if not os.path.exists(workflow_cache_file):\n        return None\n    try:\n        with open(workflow_cache_file, \"r\") as f:\n            return json.load(f)\n    except Exception:\n        delete_cached_workflow_response_if_exists(\n            workspace_id=workspace_id,\n            workflow_id=workflow_id,\n            api_key=api_key,\n            workflow_version_id=workflow_version_id,\n        )\n\n\n@wrap_roboflow_api_errors()\ndef get_workflow_specification(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    use_cache: bool = True,\n    ephemeral_cache: Optional[BaseCache] = None,\n    workflow_version_id: Optional[str] = None,\n) -> dict:\n    ephemeral_cache = ephemeral_cache or cache\n    if use_cache:\n        cached_entry = _retrieve_workflow_specification_from_ephemeral_cache(\n            api_key=api_key,\n            workspace_id=workspace_id,\n            workflow_id=workflow_id,\n            workflow_version_id=workflow_version_id,\n            ephemeral_cache=ephemeral_cache,\n        )\n        if cached_entry:\n            return cached_entry\n\n    if workspace_id == \"local\":\n        if not re.match(r\"^[\\w\\-]+$\", workflow_id):\n            raise ValueError(\"Invalid workflow id\")\n\n        workflow_hash = sha256(workflow_id.encode()).hexdigest()\n        local_file_path = (\n            Path(MODEL_CACHE_DIR) / \"workflow\" / \"local\" / f\"{workflow_hash}.json\"\n        )\n        if not local_file_path.exists():\n            raise FileNotFoundError(f\"Local workflow file not found: {local_file_path}\")\n\n        with local_file_path.open(\"r\", encoding=\"utf-8\") as f:\n            local_config = json.load(f)\n\n        # Mimic the same shape as the cloud response:\n        response = {\"workflow\": local_config}\n    else:\n        params = []\n        if api_key is not None and api_key != LOCAL_API_KEY:\n            params.append((\"api_key\", api_key))\n        if workflow_version_id is not None:\n            params.append((\"workflow_version\", workflow_version_id))\n        api_url = _add_params_to_url(\n            url=f\"{API_BASE_URL}/{workspace_id}/workflows/{workflow_id}\",\n            params=params,\n        )\n        try:\n            response = _get_from_url(url=api_url)\n            if USE_FILE_CACHE_FOR_WORKFLOWS_DEFINITIONS:\n                cache_workflow_response(\n                    workspace_id=workspace_id,\n                    workflow_id=workflow_id,\n                    api_key=api_key,\n                    response=response,\n                    workflow_version_id=workflow_version_id,\n                )\n        except (\n            requests.exceptions.ConnectionError,\n            ConnectionError,\n            requests.exceptions.Timeout,\n        ) as error:\n            if not USE_FILE_CACHE_FOR_WORKFLOWS_DEFINITIONS:\n                raise error\n            response = load_cached_workflow_response(\n                workspace_id=workspace_id,\n                workflow_id=workflow_id,\n                api_key=api_key,\n                workflow_version_id=workflow_version_id,\n            )\n            if response is None:\n                raise error\n\n    if \"workflow\" not in response or \"config\" not in response[\"workflow\"]:\n        raise MalformedWorkflowResponseError(\n            \"Could not find workflow specification in API response\"\n        )\n    try:\n        workflow_config = json.loads(response[\"workflow\"][\"config\"])\n        specification = workflow_config[\"specification\"]\n        if isinstance(specification, dict):\n            specification[\"id\"] = response[\"workflow\"].get(\"id\")\n        if use_cache:\n            _cache_workflow_specification_in_ephemeral_cache(\n                api_key=api_key,\n                workspace_id=workspace_id,\n                workflow_id=workflow_id,\n                workflow_version_id=workflow_version_id,\n                specification=specification,\n                ephemeral_cache=ephemeral_cache,\n            )\n        return specification\n    except KeyError as error:\n        raise MalformedWorkflowResponseError(\n            \"Workflow specification not found in Roboflow API response\"\n        ) from error\n    except (ValueError, TypeError) as error:\n        raise MalformedWorkflowResponseError(\n            \"Could not decode workflow specification in Roboflow API response\"\n        ) from error\n\n\ndef _retrieve_workflow_specification_from_ephemeral_cache(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    ephemeral_cache: BaseCache,\n    workflow_version_id: Optional[str] = None,\n) -> Optional[dict]:\n    cache_key = _prepare_workflow_response_cache_key(\n        api_key=api_key,\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        workflow_version_id=workflow_version_id,\n    )\n    return ephemeral_cache.get(key=cache_key)\n\n\ndef _cache_workflow_specification_in_ephemeral_cache(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    specification: dict,\n    ephemeral_cache: BaseCache,\n    workflow_version_id: Optional[str] = None,\n) -> None:\n    cache_key = _prepare_workflow_response_cache_key(\n        api_key=api_key,\n        workspace_id=workspace_id,\n        workflow_id=workflow_id,\n        workflow_version_id=workflow_version_id,\n    )\n    ephemeral_cache.set(\n        key=cache_key,\n        value=specification,\n        expire=WORKFLOWS_DEFINITION_CACHE_EXPIRY,\n    )\n\n\ndef _prepare_workflow_response_cache_key(\n    api_key: Optional[str],\n    workspace_id: WorkspaceID,\n    workflow_id: str,\n    workflow_version_id: Optional[str] = None,\n) -> str:\n    workflow_version_suffix = (\n        f\":workflow_version={workflow_version_id}\" if workflow_version_id else \"\"\n    )\n    if SINGLE_TENANT_WORKFLOW_CACHE:\n        return (\n            f\"workflow_definition:{workspace_id}:{workflow_id}{workflow_version_suffix}\"\n        )\n    cache_seed = f\"{workspace_id}:{api_key or ''}\"\n    cache_fingerprint = hashlib.sha256(\n        cache_seed.encode(\"utf-8\"), usedforsecurity=False\n    ).hexdigest()\n    return f\"workflow_definition:{workspace_id}:{workflow_id}{workflow_version_suffix}:{cache_fingerprint}\"\n\n\n@wrap_roboflow_api_errors()\ndef get_from_url(\n    url: str,\n    json_response: bool = True,\n) -> Union[Response, dict]:\n    return _get_from_url(\n        url=url,\n        json_response=json_response,\n    )\n\n\n@backoff.on_exception(\n    backoff.constant,\n    exception=RetryRequestError,\n    max_tries=TRANSIENT_ROBOFLOW_API_ERRORS_RETRIES,\n    interval=TRANSIENT_ROBOFLOW_API_ERRORS_RETRY_INTERVAL,\n)\ndef _get_from_url(\n    url: str,\n    json_response: bool = True,\n    headers: Optional[dict] = None,\n) -> Union[Response, dict]:\n    full_url = wrap_url(url)\n    try:\n        response = requests.get(\n            full_url,\n            headers=build_roboflow_api_headers(explicit_headers=headers),\n            timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n            verify=ROBOFLOW_API_VERIFY_SSL,\n        )\n\n    except (ConnectionError, Timeout, requests.exceptions.ConnectionError) as error:\n        if RETRY_CONNECTION_ERRORS_TO_ROBOFLOW_API:\n            raise RetryRequestError(\n                message=\"Connectivity error\", inner_error=error\n            ) from error\n        raise error\n    try:\n        api_key_safe_raise_for_status(response=response)\n    except Exception as error:\n        if response.status_code in TRANSIENT_ROBOFLOW_API_ERRORS:\n            raise RetryRequestError(message=str(error), inner_error=error) from error\n        raise error\n\n    if MD5_VERIFICATION_ENABLED:\n        x_goog_hash = response.headers.get(\"x-goog-hash\")\n        if x_goog_hash is None:\n            logger.warning(\n                f\"MD5 verification enabled but response missing x-goog-hash header. \"\n                f\"Request url: {_url_for_safe_logging(full_url)}\"\n            )\n        else:\n            md5_part = None\n            for part in x_goog_hash.split(\",\"):\n                if part.strip().startswith(\"md5=\"):\n                    md5_part = part.strip()[4:]\n                    break\n            if md5_part is not None:\n                try:\n                    md5_from_header = base64.b64decode(md5_part)\n                except binascii.Error as decode_error:\n                    raise RoboflowAPIUnsuccessfulRequestError(\n                        \"Invalid MD5 value in x-goog-hash header: not valid base64\"\n                    ) from decode_error\n                if md5_from_header != hashlib.md5(response.content).digest():\n                    raise RoboflowAPIUnsuccessfulRequestError(\n                        \"MD5 hash does not match MD5 received from x-goog-hash header\"\n                    )\n            else:\n                logger.warning(\n                    f\"MD5 verification enabled but x-goog-hash header has no md5= part. \"\n                    f\"Request url: {_url_for_safe_logging(full_url)}\"\n                )\n\n    if json_response:\n        return response.json()\n    return response\n\n\ndef _test_range_request(url: str, timeout: int = 10) -> bool:\n    \"\"\"Test if server actually honors range requests by making a real range GET request.\n\n    Note: We can't rely on Accept-Ranges header alone because some servers/CDNs\n    advertise range support but return 200 (full file) instead of 206 (partial).\n    \"\"\"\n    try:\n        headers = {\"Range\": \"bytes=0-0\"}\n        response = requests.get(url, headers=headers, stream=True, timeout=timeout)\n        response.close()\n        if response.status_code == 206:\n            return True\n\n        return False\n    except Exception as e:\n        logger.warning(\n            f\"Failed to test range request support: {e}. Falling back to single-threaded download.\"\n        )\n        return False\n\n\ndef stream_url_to_cache(\n    url: str,\n    filename: str,\n    model_id: str,\n) -> None:\n    from inference_models.utils.download import download_files_to_directory\n\n    with start_span(\n        \"roboflow_api.download_artifact\",\n        {\"http.url\": _url_for_safe_logging(url), \"model.id\": model_id},\n    ):\n        initialise_cache(model_id=model_id)\n        cache_dir = get_cache_dir(model_id=model_id)\n        md5_hash = None\n\n        max_threads = 8 if _test_range_request(url) else 1\n\n        try:\n            download_files_to_directory(\n                target_dir=cache_dir,\n                files_specs=[(filename, wrap_url(url), md5_hash)],\n                verbose=True,\n                download_files_without_hash=True,\n                verify_hash_while_download=False,\n                max_threads_per_download=max_threads,\n            )\n        except Exception as e:\n            raise RoboflowAPIUnsuccessfulRequestError(\n                f\"Failed to download {filename}: {str(e)}\"\n            ) from e\n\n\ndef _url_for_safe_logging(url: str) -> str:\n    \"\"\"Return a URL safe to log by stripping the query string (and params/fragment).\n\n    Expects the full URL as used for the request (e.g. already wrapped).\n    Use this when logging request URLs so that sensitive query parameters\n    (e.g. api_key, tokens) are never written to logs.\n    \"\"\"\n    parsed = urllib.parse.urlparse(url)\n    return urllib.parse.urlunparse(\n        (parsed.scheme, parsed.netloc, parsed.path, \"\", \"\", \"\")\n    )\n\n\ndef _add_params_to_url(url: str, params: List[Tuple[str, str]]) -> str:\n    if len(params) == 0:\n        return url\n    params_chunks = [\n        f\"{name}={urllib.parse.quote_plus(value)}\" for name, value in params\n    ]\n    parameters_string = \"&\".join(params_chunks)\n    return f\"{url}?{parameters_string}\"\n\n\n@wrap_roboflow_api_errors()\ndef send_inference_results_to_model_monitoring(\n    api_key: str,\n    workspace_id: WorkspaceID,\n    inference_data: dict,\n):\n    api_url = _add_params_to_url(\n        url=f\"{API_BASE_URL}/{workspace_id}/inference-stats\",\n        params=[(\"api_key\", api_key)],\n    )\n    response = requests.post(\n        url=api_url,\n        json=inference_data,\n        headers=build_roboflow_api_headers(),\n        timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n        verify=ROBOFLOW_API_VERIFY_SSL,\n    )\n    api_key_safe_raise_for_status(response=response)\n\n\ndef get_extra_weights_provider_headers(\n    countinference: Optional[bool] = None,\n    service_secret: Optional[str] = None,\n) -> Optional[Dict[str, str]]:\n    headers = {}\n    if GCP_SERVERLESS:\n        headers[ENFORCE_INTERNAL_ARTIFACTS_URLS_HEADER] = \"true\"\n    if ENFORCE_CREDITS_VERIFICATION:\n        skip = (\n            countinference is False\n            and service_secret is not None\n            and service_secret == ROBOFLOW_SERVICE_SECRET\n        )\n        if not skip:\n            headers[ENFORCE_CREDITS_VERIFICATION_HEADER] = \"true\"\n    return build_roboflow_api_headers(explicit_headers=headers)\n\n\ndef build_roboflow_api_headers(\n    explicit_headers: Optional[Dict[str, Union[str, List[str]]]] = None,\n) -> Dict[str, Union[str, List[str]]]:\n    if explicit_headers is None:\n        explicit_headers = {}\n    explicit_headers = {\n        **explicit_headers,\n        ROBOFLOW_INFERENCE_VERSION_HEADER: __version__,\n        ALLOW_CHUNKED_RESPONSE_HEADER: \"true\",\n    }\n    if not ROBOFLOW_API_EXTRA_HEADERS:\n        return explicit_headers\n    try:\n        extra_headers: dict = json.loads(ROBOFLOW_API_EXTRA_HEADERS)\n        if explicit_headers:\n            extra_headers.update(explicit_headers)\n        return extra_headers\n    except ValueError:\n        logger.warning(\"Could not decode ROBOFLOW_API_EXTRA_HEADERS\")\n        return explicit_headers\n\n\ndef post_to_roboflow_api(\n    endpoint: str,\n    api_key: Optional[str],\n    payload: Optional[dict] = None,\n    params: Optional[List[Tuple[str, str]]] = None,\n    http_errors_handlers: Optional[\n        Dict[int, Callable[[Union[requests.exceptions.HTTPError]], None]]\n    ] = None,\n) -> dict:\n    \"\"\"Generic function to make a POST request to the Roboflow API.\n\n    Args:\n        endpoint: API endpoint path\n        api_key: Roboflow API key\n        payload: JSON payload\n        params: Additional URL parameters\n        http_errors_handlers: Optional custom HTTP error handlers by status code\n    \"\"\"\n\n    @wrap_roboflow_api_errors(http_errors_handlers=http_errors_handlers)\n    def _make_request():\n        url_params = []\n        if api_key and api_key != LOCAL_API_KEY:\n            url_params.append((\"api_key\", api_key))\n        if params:\n            url_params.extend(params)\n\n        full_url = _add_params_to_url(\n            url=f\"{API_BASE_URL}/{endpoint.strip('/')}\", params=url_params\n        )\n        wrapped_url = wrap_url(full_url)\n\n        headers = build_roboflow_api_headers()\n\n        response = requests.post(\n            url=wrapped_url,\n            json=payload,\n            headers=headers,\n            timeout=ROBOFLOW_API_REQUEST_TIMEOUT,\n            verify=ROBOFLOW_API_VERIFY_SSL,\n        )\n        api_key_safe_raise_for_status(response=response)\n        return response.json()\n\n    return _make_request()\n",
    "patch": null
  },
  {
    "trace_id": "55c0e9b1-992d-4daf-8145-df8038354abd",
    "function_name": "AreaMeasurementBlockV1.run",
    "file_path": "inference/core/workflows/core_steps/classical_cv/mask_area_measurement/v1.py",
    "speedup_x": 0.24539359624877435,
    "review_quality": "high",
    "pre_optimization_commit": "HEAD",
    "resolution_method": "db_code_only",
    "source": "db_features",
    "original_function_code": "    def run(\n        self,\n        predictions: sv.Detections,\n    ) -> BlockResult:\n        areas = []\n        for i in range(len(predictions)):\n            areas.append(get_detection_area(predictions, i))\n        return {OUTPUT_KEY: areas}",
    "optimized_function_code": "import cv2 as cv\nimport numpy as np\nimport supervision as sv\nfrom inference.core.workflows.prototypes.block import (BlockResult,\n                                                       WorkflowBlock)\n\nOUTPUT_KEY = \"areas\"\n\n\ndef get_detection_area(detection: sv.Detections, index: int) -> float:\n    \"\"\"Compute the area of a single detection in square pixels.\n\n    If a segmentation mask is available, the area is computed from the largest\n    contour found in the mask using ``cv2.contourArea``.  Otherwise the area\n    falls back to bounding-box width * height.\n\n    Args:\n        detection: A supervision Detections object.\n        index: Index of the detection to measure.\n\n    Returns:\n        Area in square pixels.\n    \"\"\"\n    if detection.mask is not None:\n        mask = detection.mask[index]\n        if mask.dtype != np.uint8:\n            mask = mask.astype(np.uint8)\n        contours, _ = cv.findContours(mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)\n        if contours:\n            largest_contour = max(contours, key=cv.contourArea)\n            area = cv.contourArea(largest_contour)\n            if area > 0:\n                return float(area)\n\n    bbox = detection.xyxy[index]\n    w = bbox[2] - bbox[0]\n    h = bbox[3] - bbox[1]\n    return float(w * h)\n\n\nclass AreaMeasurementBlockV1(WorkflowBlock):\n\n    def run(\n        self,\n        predictions: sv.Detections,\n    ) -> BlockResult:\n        n = len(predictions)\n        \n        if n == 0:\n            return {OUTPUT_KEY: []}\n        \n        # Vectorized bounding box area calculation for fallback\n        xyxy = predictions.xyxy\n        bbox_areas = (xyxy[:, 2] - xyxy[:, 0]) * (xyxy[:, 3] - xyxy[:, 1])\n        \n        if predictions.mask is None:\n            # No masks available, use bbox areas directly\n            return {OUTPUT_KEY: bbox_areas.astype(float).tolist()}\n        \n        # Process masks where available\n        areas = []\n        for i in range(n):\n            mask = predictions.mask[i]\n            if mask.dtype != np.uint8:\n                mask = mask.astype(np.uint8)\n            contours, _ = cv.findContours(mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)\n            if contours:\n                largest_contour = max(contours, key=cv.contourArea)\n                area = cv.contourArea(largest_contour)\n                if area > 0:\n                    areas.append(float(area))\n                    continue\n            # Fallback to bbox area\n            areas.append(float(bbox_areas[i]))\n        \n        return {OUTPUT_KEY: areas}",
    "optimized_raw_markdown": "```python:inference/core/workflows/core_steps/classical_cv/area_measurement/v1.py\nimport cv2 as cv\nimport numpy as np\nimport supervision as sv\nfrom inference.core.workflows.prototypes.block import (BlockResult,\n                                                       WorkflowBlock)\n\nOUTPUT_KEY = \"areas\"\n\n\ndef get_detection_area(detection: sv.Detections, index: int) -> float:\n    \"\"\"Compute the area of a single detection in square pixels.\n\n    If a segmentation mask is available, the area is computed from the largest\n    contour found in the mask using ``cv2.contourArea``.  Otherwise the area\n    falls back to bounding-box width * height.\n\n    Args:\n        detection: A supervision Detections object.\n        index: Index of the detection to measure.\n\n    Returns:\n        Area in square pixels.\n    \"\"\"\n    if detection.mask is not None:\n        mask = detection.mask[index]\n        if mask.dtype != np.uint8:\n            mask = mask.astype(np.uint8)\n        contours, _ = cv.findContours(mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)\n        if contours:\n            largest_contour = max(contours, key=cv.contourArea)\n            area = cv.contourArea(largest_contour)\n            if area > 0:\n                return float(area)\n\n    bbox = detection.xyxy[index]\n    w = bbox[2] - bbox[0]\n    h = bbox[3] - bbox[1]\n    return float(w * h)\n\n\nclass AreaMeasurementBlockV1(WorkflowBlock):\n\n    def run(\n        self,\n        predictions: sv.Detections,\n    ) -> BlockResult:\n        n = len(predictions)\n        \n        if n == 0:\n            return {OUTPUT_KEY: []}\n        \n        # Vectorized bounding box area calculation for fallback\n        xyxy = predictions.xyxy\n        bbox_areas = (xyxy[:, 2] - xyxy[:, 0]) * (xyxy[:, 3] - xyxy[:, 1])\n        \n        if predictions.mask is None:\n            # No masks available, use bbox areas directly\n            return {OUTPUT_KEY: bbox_areas.astype(float).tolist()}\n        \n        # Process masks where available\n        areas = []\n        for i in range(n):\n            mask = predictions.mask[i]\n            if mask.dtype != np.uint8:\n                mask = mask.astype(np.uint8)\n            contours, _ = cv.findContours(mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)\n            if contours:\n                largest_contour = max(contours, key=cv.contourArea)\n                area = cv.contourArea(largest_contour)\n                if area > 0:\n                    areas.append(float(area))\n                    continue\n            # Fallback to bbox area\n            areas.append(float(bbox_areas[i]))\n        \n        return {OUTPUT_KEY: areas}\n```",
    "optimized_function_only": "    def run(\n        self,\n        predictions: sv.Detections,\n    ) -> BlockResult:\n        n = len(predictions)\n        \n        if n == 0:\n            return {OUTPUT_KEY: []}\n        \n        # Vectorized bounding box area calculation for fallback\n        xyxy = predictions.xyxy\n        bbox_areas = (xyxy[:, 2] - xyxy[:, 0]) * (xyxy[:, 3] - xyxy[:, 1])\n        \n        if predictions.mask is None:\n            # No masks available, use bbox areas directly\n            return {OUTPUT_KEY: bbox_areas.astype(float).tolist()}\n        \n        # Process masks where available\n        areas = []\n        for i in range(n):\n            mask = predictions.mask[i]\n            if mask.dtype != np.uint8:\n                mask = mask.astype(np.uint8)\n            contours, _ = cv.findContours(mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)\n            if contours:\n                largest_contour = max(contours, key=cv.contourArea)\n                area = cv.contourArea(largest_contour)\n                if area > 0:\n                    areas.append(float(area))\n                    continue\n            # Fallback to bbox area\n            areas.append(float(bbox_areas[i]))\n        \n        return {OUTPUT_KEY: areas}",
    "original_file_content": "import cv2 as cv\nimport numpy as np\nimport supervision as sv\nfrom inference.core.workflows.prototypes.block import BlockResult, WorkflowBlock\n\nOUTPUT_KEY = \"areas\"\n\n\ndef get_detection_area(detection: sv.Detections, index: int) -> float:\n    \"\"\"Compute the area of a single detection in square pixels.\n\n    If a segmentation mask is available, the area is computed from the largest\n    contour found in the mask using ``cv2.contourArea``.  Otherwise the area\n    falls back to bounding-box width * height.\n\n    Args:\n        detection: A supervision Detections object.\n        index: Index of the detection to measure.\n\n    Returns:\n        Area in square pixels.\n    \"\"\"\n    if detection.mask is not None:\n        mask = detection.mask[index].astype(np.uint8)\n        contours, _ = cv.findContours(mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)\n        if contours:\n            largest_contour = max(contours, key=cv.contourArea)\n            area = cv.contourArea(largest_contour)\n            if area > 0:\n                return float(area)\n\n    bbox = detection.xyxy[index]\n    w = bbox[2] - bbox[0]\n    h = bbox[3] - bbox[1]\n    return float(w * h)\n\n\nclass AreaMeasurementBlockV1(WorkflowBlock):\n\n    def run(\n        self,\n        predictions: sv.Detections,\n    ) -> BlockResult:\n        areas = []\n        for i in range(len(predictions)):\n            areas.append(get_detection_area(predictions, i))\n        return {OUTPUT_KEY: areas}",
    "patch": null
  },
  {
    "trace_id": "e2bf66fb-858a-4a40-bfe6-715c87c91217",
    "function_name": "VideoFrameProcessor._check_termination",
    "file_path": "inference/core/interfaces/webrtc_worker/webrtc.py",
    "speedup_x": 0.3554657970526378,
    "review_quality": "high",
    "pre_optimization_commit": "c600366180f51b15836799274e19ad64db60cbab",
    "resolution_method": "db_code_match",
    "source": "db_features",
    "original_function_code": "    def _check_termination(self):\n        \"\"\"Check if we should terminate based on timeout.\n\n        Does NOT set terminate_event \u2014 callers must call _signal_termination()\n        after sending final data-channel messages to avoid a race with the\n        cleanup task closing the peer connection.\n        \"\"\"\n        if (\n            self._termination_date\n            and self._termination_date < datetime.datetime.now()\n        ):\n            logger.info(\"Timeout reached, terminating inference pipeline\")\n            self._termination_reason = \"timeout_reached\"\n            return True\n        if self._terminate_event and self._terminate_event.is_set():\n            logger.info(\"Terminate event set, terminating inference pipeline\")\n            return True\n        return False\n",
    "optimized_function_code": "import asyncio\nimport datetime\nfrom typing import Callable, List, Optional\n\nfrom aiortc import RTCDataChannel\nfrom aiortc.mediastreams import MediaStreamTrack\nfrom inference.core import logger\nfrom inference.core.env import WEBRTC_DATA_CHANNEL_ACK_WINDOW\nfrom inference.core.exceptions import WebRTCConfigurationError\nfrom inference.core.interfaces.camera.entities import VideoFrameProducer\nfrom inference.core.interfaces.stream.inference_pipeline import \\\n    InferencePipeline\nfrom inference.core.interfaces.stream_manager.manager_app.entities import \\\n    WorkflowConfiguration\nfrom inference.core.interfaces.webrtc_worker.entities import DataOutputMode\nfrom inference.core.interfaces.webrtc_worker.sources.file import \\\n    VideoFileUploadHandler\nfrom inference.core.managers.base import ModelManager\n\n\nclass VideoFrameProcessor:\n\n    def __init__(\n        self,\n        asyncio_loop: asyncio.AbstractEventLoop,\n        workflow_configuration: WorkflowConfiguration,\n        api_key: str,\n        model_manager: Optional[ModelManager] = None,\n        data_output: Optional[List[str]] = None,\n        stream_output: Optional[str] = None,\n        has_video_track: bool = True,\n        declared_fps: float = 30,\n        termination_date: Optional[datetime.datetime] = None,\n        terminate_event: Optional[asyncio.Event] = None,\n        heartbeat_callback: Optional[Callable[[], None]] = None,\n        realtime_processing: bool = True,\n        is_preview: bool = False,\n    ):\n        self._file_processing = False\n        self._loop = asyncio_loop\n        self._termination_date = termination_date\n        self._terminate_event = terminate_event\n        self.track: Optional[MediaStreamTrack] = None\n        self._track_active: bool = False\n        self._av_logging_set: bool = False\n        self._received_frames = 0\n        self._declared_fps = declared_fps\n        self._stop_processing = False\n        self._termination_reason: Optional[str] = None\n        self._processing_complete_sent = False\n        self.heartbeat_callback = heartbeat_callback\n\n        self.has_video_track = has_video_track\n        self.stream_output = stream_output\n        self.data_channel: Optional[RTCDataChannel] = None\n\n        # Video file upload support\n        self.video_upload_handler: Optional[VideoFileUploadHandler] = None\n        self._track_ready_event: asyncio.Event = asyncio.Event()\n        self.realtime_processing = realtime_processing\n        self._rotation_code: Optional[int] = None\n\n        # Optional receiver-paced flow control (enabled only after first ACK is received)\n        self._ack_last: int = 0\n        # If ack=1 and window=4, server may produce/send up to frame 5.\n        # Configurable via WEBRTC_DATACHANNEL_ACK_WINDOW env var.\n        self._ack_window: int = WEBRTC_DATA_CHANNEL_ACK_WINDOW\n        self._ack_event: asyncio.Event = asyncio.Event()\n\n        if data_output is None:\n            self.data_output = None\n            self._data_mode = DataOutputMode.NONE\n        elif isinstance(data_output, list):\n            self.data_output = [f for f in data_output if f]\n            if self.data_output == [\"*\"]:\n                self._data_mode = DataOutputMode.ALL\n            elif len(self.data_output) == 0:\n                self._data_mode = DataOutputMode.NONE\n            else:\n                self._data_mode = DataOutputMode.SPECIFIC\n        else:\n            raise WebRTCConfigurationError(\n                f\"data_output must be list or None, got {type(data_output).__name__}\"\n            )\n\n        self._validate_output_fields(workflow_configuration)\n\n        self._inference_pipeline = InferencePipeline.init_with_workflow(\n            video_reference=VideoFrameProducer,\n            workflow_specification=workflow_configuration.workflow_specification,\n            workspace_name=workflow_configuration.workspace_name,\n            workflow_id=workflow_configuration.workflow_id,\n            api_key=api_key,\n            image_input_name=workflow_configuration.image_input_name,\n            workflows_parameters=workflow_configuration.workflows_parameters,\n            workflows_thread_pool_workers=workflow_configuration.workflows_thread_pool_workers,\n            cancel_thread_pool_tasks_on_exit=workflow_configuration.cancel_thread_pool_tasks_on_exit,\n            video_metadata_input_name=workflow_configuration.video_metadata_input_name,\n            model_manager=model_manager,\n            _is_preview=is_preview,\n        )\n\n    def _check_termination(self):\n        \"\"\"Check if we should terminate based on timeout.\n\n        Does NOT set terminate_event \u2014 callers must call _signal_termination()\n        after sending final data-channel messages to avoid a race with the\n        cleanup task closing the peer connection.\n        \"\"\"\n        if self._termination_date is not None:\n            if self._termination_date < datetime.datetime.now():\n                if self._termination_reason is None:\n                    logger.info(\"Timeout reached, terminating inference pipeline\")\n                    self._termination_reason = \"timeout_reached\"\n                return True\n        if self._terminate_event is not None and self._terminate_event.is_set():\n            if self._termination_reason is None:\n                logger.info(\"Terminate event set, terminating inference pipeline\")\n            return True\n        return False",
    "optimized_raw_markdown": "```python:inference/core/interfaces/webrtc_worker/webrtc.py\nimport asyncio\nimport datetime\nfrom typing import Callable, List, Optional\n\nfrom aiortc import RTCDataChannel\nfrom aiortc.mediastreams import MediaStreamTrack\nfrom inference.core import logger\nfrom inference.core.env import WEBRTC_DATA_CHANNEL_ACK_WINDOW\nfrom inference.core.exceptions import WebRTCConfigurationError\nfrom inference.core.interfaces.camera.entities import VideoFrameProducer\nfrom inference.core.interfaces.stream.inference_pipeline import \\\n    InferencePipeline\nfrom inference.core.interfaces.stream_manager.manager_app.entities import \\\n    WorkflowConfiguration\nfrom inference.core.interfaces.webrtc_worker.entities import DataOutputMode\nfrom inference.core.interfaces.webrtc_worker.sources.file import \\\n    VideoFileUploadHandler\nfrom inference.core.managers.base import ModelManager\n\n\nclass VideoFrameProcessor:\n\n    def __init__(\n        self,\n        asyncio_loop: asyncio.AbstractEventLoop,\n        workflow_configuration: WorkflowConfiguration,\n        api_key: str,\n        model_manager: Optional[ModelManager] = None,\n        data_output: Optional[List[str]] = None,\n        stream_output: Optional[str] = None,\n        has_video_track: bool = True,\n        declared_fps: float = 30,\n        termination_date: Optional[datetime.datetime] = None,\n        terminate_event: Optional[asyncio.Event] = None,\n        heartbeat_callback: Optional[Callable[[], None]] = None,\n        realtime_processing: bool = True,\n        is_preview: bool = False,\n    ):\n        self._file_processing = False\n        self._loop = asyncio_loop\n        self._termination_date = termination_date\n        self._terminate_event = terminate_event\n        self.track: Optional[MediaStreamTrack] = None\n        self._track_active: bool = False\n        self._av_logging_set: bool = False\n        self._received_frames = 0\n        self._declared_fps = declared_fps\n        self._stop_processing = False\n        self._termination_reason: Optional[str] = None\n        self._processing_complete_sent = False\n        self.heartbeat_callback = heartbeat_callback\n\n        self.has_video_track = has_video_track\n        self.stream_output = stream_output\n        self.data_channel: Optional[RTCDataChannel] = None\n\n        # Video file upload support\n        self.video_upload_handler: Optional[VideoFileUploadHandler] = None\n        self._track_ready_event: asyncio.Event = asyncio.Event()\n        self.realtime_processing = realtime_processing\n        self._rotation_code: Optional[int] = None\n\n        # Optional receiver-paced flow control (enabled only after first ACK is received)\n        self._ack_last: int = 0\n        # If ack=1 and window=4, server may produce/send up to frame 5.\n        # Configurable via WEBRTC_DATACHANNEL_ACK_WINDOW env var.\n        self._ack_window: int = WEBRTC_DATA_CHANNEL_ACK_WINDOW\n        self._ack_event: asyncio.Event = asyncio.Event()\n\n        if data_output is None:\n            self.data_output = None\n            self._data_mode = DataOutputMode.NONE\n        elif isinstance(data_output, list):\n            self.data_output = [f for f in data_output if f]\n            if self.data_output == [\"*\"]:\n                self._data_mode = DataOutputMode.ALL\n            elif len(self.data_output) == 0:\n                self._data_mode = DataOutputMode.NONE\n            else:\n                self._data_mode = DataOutputMode.SPECIFIC\n        else:\n            raise WebRTCConfigurationError(\n                f\"data_output must be list or None, got {type(data_output).__name__}\"\n            )\n\n        self._validate_output_fields(workflow_configuration)\n\n        self._inference_pipeline = InferencePipeline.init_with_workflow(\n            video_reference=VideoFrameProducer,\n            workflow_specification=workflow_configuration.workflow_specification,\n            workspace_name=workflow_configuration.workspace_name,\n            workflow_id=workflow_configuration.workflow_id,\n            api_key=api_key,\n            image_input_name=workflow_configuration.image_input_name,\n            workflows_parameters=workflow_configuration.workflows_parameters,\n            workflows_thread_pool_workers=workflow_configuration.workflows_thread_pool_workers,\n            cancel_thread_pool_tasks_on_exit=workflow_configuration.cancel_thread_pool_tasks_on_exit,\n            video_metadata_input_name=workflow_configuration.video_metadata_input_name,\n            model_manager=model_manager,\n            _is_preview=is_preview,\n        )\n\n    def _check_termination(self):\n        \"\"\"Check if we should terminate based on timeout.\n\n        Does NOT set terminate_event \u2014 callers must call _signal_termination()\n        after sending final data-channel messages to avoid a race with the\n        cleanup task closing the peer connection.\n        \"\"\"\n        if self._termination_date is not None:\n            if self._termination_date < datetime.datetime.now():\n                if self._termination_reason is None:\n                    logger.info(\"Timeout reached, terminating inference pipeline\")\n                    self._termination_reason = \"timeout_reached\"\n                return True\n        if self._terminate_event is not None and self._terminate_event.is_set():\n            if self._termination_reason is None:\n                logger.info(\"Terminate event set, terminating inference pipeline\")\n            return True\n        return False\n```",
    "optimized_function_only": "    def _check_termination(self):\n        \"\"\"Check if we should terminate based on timeout.\n\n        Does NOT set terminate_event \u2014 callers must call _signal_termination()\n        after sending final data-channel messages to avoid a race with the\n        cleanup task closing the peer connection.\n        \"\"\"\n        if self._termination_date is not None:\n            if self._termination_date < datetime.datetime.now():\n                if self._termination_reason is None:\n                    logger.info(\"Timeout reached, terminating inference pipeline\")\n                    self._termination_reason = \"timeout_reached\"\n                return True\n        if self._terminate_event is not None and self._terminate_event.is_set():\n            if self._termination_reason is None:\n                logger.info(\"Terminate event set, terminating inference pipeline\")\n            return True\n        return False",
    "original_file_content": "import asyncio\nimport datetime\nimport gzip\nimport json\nimport logging\nimport struct\nimport time\nfrom typing import Any, Callable, Dict, List, Optional, Tuple\n\nfrom aioice import ice\nfrom aiortc import (\n    RTCConfiguration,\n    RTCDataChannel,\n    RTCIceServer,\n    RTCPeerConnection,\n    RTCSessionDescription,\n    VideoStreamTrack,\n)\nfrom aiortc.contrib.media import MediaPlayer, MediaRelay, PlayerStreamTrack\nfrom aiortc.mediastreams import MediaStreamError, MediaStreamTrack\nfrom aiortc.rtcrtpreceiver import RemoteStreamTrack\nfrom av import VideoFrame\nfrom av import logging as av_logging\nfrom pydantic import ValidationError\n\nfrom inference.core import logger\nfrom inference.core.env import (\n    WEBRTC_DATA_CHANNEL_ACK_WINDOW,\n    WEBRTC_DATA_CHANNEL_BUFFER_DRAINING_DELAY,\n    WEBRTC_DATA_CHANNEL_BUFFER_SIZE_LIMIT,\n    WEBRTC_GZIP_PREVIEW_FRAME_COMPRESSION,\n    WEBRTC_MODAL_PUBLIC_STUN_SERVERS,\n    WEBRTC_MODAL_RTSP_PLACEHOLDER,\n    WEBRTC_MODAL_RTSP_PLACEHOLDER_URL,\n    WEBRTC_MODAL_SHUTDOWN_RESERVE,\n)\nfrom inference.core.exceptions import (\n    MissingApiKeyError,\n    RoboflowAPINotAuthorizedError,\n    RoboflowAPINotNotFoundError,\n    WebRTCConfigurationError,\n)\nfrom inference.core.interfaces.camera.entities import VideoFrameProducer\nfrom inference.core.interfaces.stream.inference_pipeline import InferencePipeline\nfrom inference.core.interfaces.stream_manager.manager_app.entities import (\n    WebRTCData,\n    WorkflowConfiguration,\n)\nfrom inference.core.interfaces.webrtc_worker.entities import (\n    DataOutputMode,\n    StreamOutputMode,\n    WebRTCOutput,\n    WebRTCVideoMetadata,\n    WebRTCWorkerRequest,\n    WebRTCWorkerResult,\n)\nfrom inference.core.interfaces.webrtc_worker.serializers import serialize_for_webrtc\nfrom inference.core.interfaces.webrtc_worker.sources.file import (\n    ThreadedVideoFileTrack,\n    VideoFileUploadHandler,\n)\nfrom inference.core.interfaces.webrtc_worker.utils import (\n    detect_image_output,\n    get_cv2_rotation_code,\n    get_video_fps,\n    get_video_rotation,\n    parse_video_file_chunk,\n    process_frame,\n    rotate_video_frame,\n)\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.roboflow_api import get_workflow_specification\nfrom inference.core.workflows.errors import WorkflowError, WorkflowSyntaxError\nfrom inference.core.workflows.execution_engine.entities.base import WorkflowImageData\nfrom inference.usage_tracking.collector import usage_collector\n\nlogging.getLogger(\"aiortc\").setLevel(logging.WARNING)\n\n# WebRTC data channel chunking configuration\nCHUNK_SIZE = 48 * 1024  # 48KB - safe for all WebRTC implementations\n\n\ndef create_chunked_binary_message(\n    frame_id: int, chunk_index: int, total_chunks: int, payload: bytes\n) -> bytes:\n    \"\"\"Create a binary message with standard 12-byte header.\n\n    Format: [frame_id: 4][chunk_index: 4][total_chunks: 4][payload: N]\n    All integers are uint32 little-endian.\n    \"\"\"\n    header = struct.pack(\"<III\", frame_id, chunk_index, total_chunks)\n    return header + payload\n\n\nasync def wait_for_buffer_drain(\n    data_channel: RTCDataChannel,\n    timeout: float = 30.0,\n    heartbeat_callback: Optional[Callable[[], None]] = None,\n    low_threshold: Optional[int] = None,\n) -> bool:\n    \"\"\"Wait for data channel buffer to drain below threshold, with timeout.\n\n    We use a low threshold (1/4 of limit) instead of just below the limit to avoid\n    hysteresis - constantly triggering this wait after sending just a few chunks.\n\n    And we wait WEBRTC_DATA_CHANNEL_BUFFER_DRAINING_DELAY to avoid starving the\n    event loop.\n    \"\"\"\n    if low_threshold is None:\n        low_threshold = WEBRTC_DATA_CHANNEL_BUFFER_SIZE_LIMIT // 4\n\n    start_time = asyncio.get_event_loop().time()\n\n    while data_channel.bufferedAmount > low_threshold:\n        elapsed = asyncio.get_event_loop().time() - start_time\n        if elapsed > timeout:\n            logger.error(\"[BUFFER_DRAIN] Timeout after %.1fs\", timeout)\n            return False\n        if data_channel.readyState != \"open\":\n            logger.error(\"[BUFFER_DRAIN] Channel closed: %s\", data_channel.readyState)\n            return False\n        if heartbeat_callback:\n            heartbeat_callback()\n        await asyncio.sleep(WEBRTC_DATA_CHANNEL_BUFFER_DRAINING_DELAY)\n\n    return True\n\n\nasync def send_chunked_data(\n    data_channel: RTCDataChannel,\n    frame_id: int,\n    payload_bytes: bytes,\n    chunk_size: int = CHUNK_SIZE,\n    heartbeat_callback: Optional[Callable[[], None]] = None,\n    buffer_timeout: float = 120.0,\n) -> bool:\n    \"\"\"Send payload via data channel with chunking and backpressure.\n\n    We chunk large payloads because WebRTC data channels have message size limits.\n    We apply backpressure (wait for buffer to drain) to avoid overwhelming the\n    network and causing ICE connection failures.\n\n    Heads up: buffer_timeout needs to be higher than WEBRTC_DATA_CHANNEL_BUFFER_DRAINING_DELAY!\n    Otherwise we will timeout ourselves.\n    \"\"\"\n\n    if buffer_timeout <= WEBRTC_DATA_CHANNEL_BUFFER_DRAINING_DELAY:\n        logger.warning(\n            \"[SEND_CHUNKED] buffer_timeout (%.2fs) <= WEBRTC_DATA_CHANNEL_BUFFER_DRAINING_DELAY (%.2fs), \"\n            \"this will likely cause immediate timeouts during buffer drain\",\n            buffer_timeout,\n            WEBRTC_DATA_CHANNEL_BUFFER_DRAINING_DELAY,\n        )\n\n    if data_channel.readyState != \"open\":\n        return False\n\n    payload_size = len(payload_bytes)\n    total_chunks = (payload_size + chunk_size - 1) // chunk_size\n    view = memoryview(payload_bytes)\n    high_threshold = WEBRTC_DATA_CHANNEL_BUFFER_SIZE_LIMIT\n\n    for chunk_index in range(total_chunks):\n        if data_channel.readyState != \"open\":\n            logger.error(\n                \"[SEND_CHUNKED] Channel closed at chunk %d/%d\",\n                chunk_index,\n                total_chunks,\n            )\n            return False\n\n        start = chunk_index * chunk_size\n        end = min(start + chunk_size, payload_size)\n        chunk_data = view[start:end]\n\n        message = create_chunked_binary_message(\n            frame_id, chunk_index, total_chunks, chunk_data\n        )\n\n        if data_channel.bufferedAmount > high_threshold:\n            if not await wait_for_buffer_drain(\n                data_channel, buffer_timeout, heartbeat_callback\n            ):\n                logger.error(\n                    \"[SEND_CHUNKED] Buffer drain failed at chunk %d/%d\",\n                    chunk_index,\n                    total_chunks,\n                )\n                return False\n\n        data_channel.send(message)\n\n        if heartbeat_callback:\n            heartbeat_callback()\n        await asyncio.sleep(0.001)\n\n    return True\n\n\nclass RTCPeerConnectionWithLoop(RTCPeerConnection):\n    def __init__(\n        self,\n        asyncio_loop: asyncio.AbstractEventLoop,\n        *args,\n        **kwargs,\n    ):\n        super().__init__(*args, **kwargs)\n        self._loop = asyncio_loop\n\n\nclass VideoFrameProcessor:\n    \"\"\"Base class for processing video frames through workflow.\n\n    Can be used independently for data-only processing (no video track output)\n    or as a base for VideoTransformTrackWithLoop when video output is needed.\n    \"\"\"\n\n    def __init__(\n        self,\n        asyncio_loop: asyncio.AbstractEventLoop,\n        workflow_configuration: WorkflowConfiguration,\n        api_key: str,\n        model_manager: Optional[ModelManager] = None,\n        data_output: Optional[List[str]] = None,\n        stream_output: Optional[str] = None,\n        has_video_track: bool = True,\n        declared_fps: float = 30,\n        termination_date: Optional[datetime.datetime] = None,\n        terminate_event: Optional[asyncio.Event] = None,\n        heartbeat_callback: Optional[Callable[[], None]] = None,\n        realtime_processing: bool = True,\n        is_preview: bool = False,\n    ):\n        self._file_processing = False\n        self._loop = asyncio_loop\n        self._termination_date = termination_date\n        self._terminate_event = terminate_event\n        self.track: Optional[MediaStreamTrack] = None\n        self._track_active: bool = False\n        self._av_logging_set: bool = False\n        self._received_frames = 0\n        self._declared_fps = declared_fps\n        self._stop_processing = False\n        self._termination_reason: Optional[str] = None\n        self._processing_complete_sent = False\n        self.heartbeat_callback = heartbeat_callback\n\n        self.has_video_track = has_video_track\n        self.stream_output = stream_output\n        self.data_channel: Optional[RTCDataChannel] = None\n\n        # Video file upload support\n        self.video_upload_handler: Optional[VideoFileUploadHandler] = None\n        self._track_ready_event: asyncio.Event = asyncio.Event()\n        self.realtime_processing = realtime_processing\n        self._rotation_code: Optional[int] = None\n\n        # Optional receiver-paced flow control (enabled only after first ACK is received)\n        self._ack_last: int = 0\n        # If ack=1 and window=4, server may produce/send up to frame 5.\n        # Configurable via WEBRTC_DATACHANNEL_ACK_WINDOW env var.\n        self._ack_window: int = WEBRTC_DATA_CHANNEL_ACK_WINDOW\n        self._ack_event: asyncio.Event = asyncio.Event()\n\n        if data_output is None:\n            self.data_output = None\n            self._data_mode = DataOutputMode.NONE\n        elif isinstance(data_output, list):\n            self.data_output = [f for f in data_output if f]\n            if self.data_output == [\"*\"]:\n                self._data_mode = DataOutputMode.ALL\n            elif len(self.data_output) == 0:\n                self._data_mode = DataOutputMode.NONE\n            else:\n                self._data_mode = DataOutputMode.SPECIFIC\n        else:\n            raise WebRTCConfigurationError(\n                f\"data_output must be list or None, got {type(data_output).__name__}\"\n            )\n\n        self._validate_output_fields(workflow_configuration)\n\n        self._inference_pipeline = InferencePipeline.init_with_workflow(\n            video_reference=VideoFrameProducer,\n            workflow_specification=workflow_configuration.workflow_specification,\n            workspace_name=workflow_configuration.workspace_name,\n            workflow_id=workflow_configuration.workflow_id,\n            api_key=api_key,\n            image_input_name=workflow_configuration.image_input_name,\n            workflows_parameters=workflow_configuration.workflows_parameters,\n            workflows_thread_pool_workers=workflow_configuration.workflows_thread_pool_workers,\n            cancel_thread_pool_tasks_on_exit=workflow_configuration.cancel_thread_pool_tasks_on_exit,\n            video_metadata_input_name=workflow_configuration.video_metadata_input_name,\n            model_manager=model_manager,\n            _is_preview=is_preview,\n        )\n\n    def set_track(self, track: MediaStreamTrack, rotation_code: Optional[int] = None):\n        if not self.track:\n            self.track = track\n            self._rotation_code = rotation_code\n            self._track_ready_event.set()\n\n    async def close(self):\n        self._track_active = False\n        self._stop_processing = True\n        # Clean up video upload handler if present\n        if self.video_upload_handler is not None:\n            await self.video_upload_handler.cleanup()\n\n    def record_ack(self, ack: int) -> None:\n        \"\"\"Record cumulative ACK from the client.\n\n        ACK semantics: client has fully handled all frames <= ack.\n        Backwards compatible: pacing is disabled until we receive the first ACK.\n        \"\"\"\n        try:\n            ack_int = int(ack)\n        except (TypeError, ValueError):\n            logger.warning(\"Invalid ACK value: %s\", ack)\n            return\n        if ack_int < 0:\n            logger.warning(\"Invalid ACK value: %s\", ack)\n            return\n        if ack_int > self._ack_last:\n            if ack_int % 100 == 1:\n                logger.info(\"ACK received: %s\", ack_int)\n            self._ack_last = ack_int\n            self._ack_event.set()\n\n    async def _wait_for_ack_window(self, next_frame_id: int) -> None:\n        \"\"\"Block frame production when too far ahead of client ACKs.\"\"\"\n        if self.realtime_processing or self._ack_last == 0:\n            return\n\n        wait_counter = 0\n        while not self._stop_processing and next_frame_id > (\n            self._ack_last + self._ack_window\n        ):\n            if self._check_termination():\n                return\n            if self.heartbeat_callback:\n                self.heartbeat_callback()\n\n            self._ack_event.clear()\n            try:\n                await asyncio.wait_for(self._ack_event.wait(), timeout=0.2)\n            except asyncio.TimeoutError:\n                wait_counter += 1\n                if wait_counter % 5 == 1:\n                    logger.info(\n                        \"Waiting for ACK window (next=%d, ack_last=%d, window=%d)\",\n                        next_frame_id,\n                        self._ack_last,\n                        self._ack_window,\n                    )\n\n    def _check_termination(self):\n        \"\"\"Check if we should terminate based on timeout.\n\n        Does NOT set terminate_event \u2014 callers must call _signal_termination()\n        after sending final data-channel messages to avoid a race with the\n        cleanup task closing the peer connection.\n        \"\"\"\n        if (\n            self._termination_date\n            and self._termination_date < datetime.datetime.now()\n        ):\n            logger.info(\"Timeout reached, terminating inference pipeline\")\n            self._termination_reason = \"timeout_reached\"\n            return True\n        if self._terminate_event and self._terminate_event.is_set():\n            logger.info(\"Terminate event set, terminating inference pipeline\")\n            return True\n        return False\n\n    def _signal_termination(self):\n        if self._terminate_event:\n            self._terminate_event.set()\n\n    @staticmethod\n    def serialize_outputs_sync(\n        fields_to_send: List[str],\n        workflow_output: Dict[str, Any],\n        data_output_mode: DataOutputMode,\n    ) -> Tuple[Dict[str, Any], List[str]]:\n        \"\"\"Serialize workflow outputs for WebRTC transmission.\"\"\"\n        serialized = {}\n        serialization_errors = []\n\n        for field_name in fields_to_send:\n            if field_name not in workflow_output:\n                serialization_errors.append(f\"Output '{field_name}' not found\")\n                continue\n\n            output_data = workflow_output[field_name]\n\n            if data_output_mode == DataOutputMode.ALL and isinstance(\n                output_data, WorkflowImageData\n            ):\n                continue\n\n            try:\n                serialized[field_name] = serialize_for_webrtc(output_data)\n            except Exception as e:\n                serialization_errors.append(f\"{field_name}: {e}\")\n                serialized[field_name] = {\"__serialization_error__\": str(e)}\n                logger.error(\"[SERIALIZE] Error: %s - %s\", field_name, e)\n\n        return serialized, serialization_errors\n\n    async def _send_data_output(\n        self,\n        workflow_output: Dict[str, Any],\n        frame_timestamp: datetime.datetime,\n        frame: VideoFrame,\n        errors: List[str],\n    ):\n        frame_id = self._received_frames\n\n        if not self.data_channel or self.data_channel.readyState != \"open\":\n            return\n\n        video_metadata = WebRTCVideoMetadata(\n            frame_id=frame_id,\n            received_at=frame_timestamp.isoformat(),\n            pts=frame.pts,\n            time_base=frame.time_base,\n            declared_fps=self._declared_fps,\n            height=frame.height,\n            width=frame.width,\n        )\n\n        webrtc_output = WebRTCOutput(\n            serialized_output_data=None,\n            video_metadata=video_metadata,\n            errors=errors.copy(),\n        )\n\n        if self._data_mode == DataOutputMode.NONE:\n            json_bytes = await asyncio.to_thread(\n                lambda: json.dumps(webrtc_output.model_dump()).encode(\"utf-8\")\n            )\n            await send_chunked_data(\n                self.data_channel,\n                frame_id,\n                json_bytes,\n                heartbeat_callback=self.heartbeat_callback,\n            )\n            return\n\n        if self._data_mode == DataOutputMode.ALL:\n            fields_to_send = list(workflow_output.keys())\n        else:\n            fields_to_send = self.data_output\n\n        serialized_outputs, serialization_errors = await asyncio.to_thread(\n            VideoFrameProcessor.serialize_outputs_sync,\n            fields_to_send,\n            workflow_output,\n            self._data_mode,\n        )\n\n        webrtc_output.errors.extend(serialization_errors)\n        if serialized_outputs:\n            webrtc_output.serialized_output_data = serialized_outputs\n\n        # TODO: use orjson\n        json_bytes = await asyncio.to_thread(\n            lambda: json.dumps(webrtc_output.model_dump(mode=\"json\")).encode(\"utf-8\")\n        )\n\n        if WEBRTC_GZIP_PREVIEW_FRAME_COMPRESSION:\n\n            def compress_json():\n                return gzip.compress(json_bytes, compresslevel=6)\n\n            output_bytes = await asyncio.to_thread(compress_json)\n        else:\n            output_bytes = json_bytes\n\n        success = await send_chunked_data(\n            self.data_channel,\n            frame_id,\n            output_bytes,\n            heartbeat_callback=self.heartbeat_callback,\n        )\n        if not success:\n            logger.error(\"[SEND_OUTPUT] Frame %d failed\", frame_id)\n\n    async def _send_processing_complete(self):\n        \"\"\"Send final message indicating processing is complete.\n\n        Also drains the data channel buffer to ensure delivery before the\n        connection is closed.\n        \"\"\"\n        if self._processing_complete_sent:\n            return\n        if not self.data_channel or self.data_channel.readyState != \"open\":\n            return\n\n        self._processing_complete_sent = True\n        completion_output = WebRTCOutput(\n            processing_complete=True,\n            termination_reason=self._termination_reason,\n            video_metadata=WebRTCVideoMetadata(\n                frame_id=self._received_frames,\n                received_at=datetime.datetime.now().isoformat(),\n            ),\n        )\n        json_bytes = json.dumps(completion_output.model_dump()).encode(\"utf-8\")\n        await send_chunked_data(\n            self.data_channel, self._received_frames + 1, json_bytes\n        )\n        await wait_for_buffer_drain(\n            self.data_channel, timeout=2.0, low_threshold=0\n        )\n\n    async def process_frames_data_only(self):\n        \"\"\"Process frames for data extraction only, without video track output.\"\"\"\n        if not self._av_logging_set:\n            av_logging.set_libav_level(av_logging.ERROR)\n            self._av_logging_set = True\n\n        try:\n            while not self._stop_processing:\n                await self._wait_for_ack_window(next_frame_id=self._received_frames + 1)\n                if self._check_termination():\n                    await self._send_processing_complete()\n                    self._signal_termination()\n                    break\n                if self.heartbeat_callback:\n                    self.heartbeat_callback()\n                if not self.track or self.track.readyState == \"ended\":\n                    break\n\n                # Drain queue for realtime RTSP\n                if (\n                    isinstance(self.track, PlayerStreamTrack)\n                    and self.realtime_processing\n                ):\n                    while self.track._queue.qsize() > 30:\n                        self.track._queue.get_nowait()\n\n                frame = await self.track.recv()\n                self._received_frames += 1\n                frame_timestamp = datetime.datetime.now()\n\n                workflow_output, _, errors = await self._process_frame_async(\n                    frame=frame,\n                    frame_id=self._received_frames,\n                    render_output=False,\n                    include_errors_on_frame=False,\n                )\n\n                await self._send_data_output(\n                    workflow_output, frame_timestamp, frame, errors\n                )\n\n        except asyncio.CancelledError as exc:\n            # No one will catch this exception as it's executed in a create_task\n            logger.info(\"[DATA_ONLY] Processing cancelled: %s\", exc)\n        except MediaStreamError as exc:\n            logger.info(\"[DATA_ONLY] Media stream ended: %s\", exc)\n        except Exception as exc:\n            logger.error(\n                \"[DATA_ONLY] Error at frame %d: %s\", self._received_frames, exc\n            )\n        finally:\n            await self._send_processing_complete()\n\n    @staticmethod\n    def _ensure_workflow_specification(\n        workflow_configuration: WorkflowConfiguration, api_key: str\n    ) -> None:\n        has_specification = workflow_configuration.workflow_specification is not None\n        has_workspace_and_workflow_id = (\n            workflow_configuration.workspace_name is not None\n            and workflow_configuration.workflow_id is not None\n        )\n\n        if not has_specification and not has_workspace_and_workflow_id:\n            raise WebRTCConfigurationError(\n                \"Either 'workflow_specification' or both 'workspace_name' and 'workflow_id' must be provided\"\n            )\n\n        if not has_specification and has_workspace_and_workflow_id:\n            try:\n                workflow_configuration.workflow_specification = (\n                    get_workflow_specification(\n                        api_key=api_key,\n                        workspace_id=workflow_configuration.workspace_name,\n                        workflow_id=workflow_configuration.workflow_id,\n                    )\n                )\n                workflow_configuration.workspace_name = None\n                workflow_configuration.workflow_id = None\n            except Exception as e:\n                raise WebRTCConfigurationError(\n                    f\"Failed to fetch workflow specification from API: {str(e)}\"\n                )\n\n    def _validate_output_fields(\n        self, workflow_configuration: WorkflowConfiguration\n    ) -> None:\n        if workflow_configuration.workflow_specification is None:\n            return\n\n        workflow_outputs = workflow_configuration.workflow_specification.get(\n            \"outputs\", []\n        )\n        available_output_names = [o.get(\"name\") for o in workflow_outputs]\n\n        if self._data_mode == DataOutputMode.SPECIFIC:\n            invalid_fields = [\n                field\n                for field in self.data_output\n                if field not in available_output_names\n            ]\n            if invalid_fields:\n                raise WebRTCConfigurationError(\n                    f\"Invalid data_output fields: {invalid_fields}. \"\n                    f\"Available workflow outputs: {available_output_names}\"\n                )\n\n        if self.stream_output and self.stream_output not in available_output_names:\n            raise WebRTCConfigurationError(\n                f\"Invalid stream_output field: '{self.stream_output}'. \"\n                f\"Available workflow outputs: {available_output_names}\"\n            )\n\n    async def _process_frame_async(\n        self,\n        frame: VideoFrame,\n        frame_id: int,\n        stream_output: Optional[str] = None,\n        render_output: bool = True,\n        include_errors_on_frame: bool = True,\n    ) -> Tuple[Dict[str, Any], Optional[VideoFrame], List[str]]:\n        \"\"\"Async wrapper for process_frame using executor.\"\"\"\n\n        if self._rotation_code is not None:\n            frame = rotate_video_frame(frame, self._rotation_code)\n\n        loop = asyncio.get_running_loop()\n        return await loop.run_in_executor(\n            None,\n            process_frame,\n            frame,\n            frame_id,\n            self._declared_fps,\n            self._declared_fps,  # TODO: measure fps\n            self._file_processing,\n            self._inference_pipeline,\n            stream_output,\n            render_output,\n            include_errors_on_frame,\n        )\n\n\nclass VideoTransformTrackWithLoop(VideoStreamTrack, VideoFrameProcessor):\n    \"\"\"Video track that processes frames through workflow and sends video back.\n\n    Inherits from both VideoStreamTrack (for WebRTC video track functionality)\n    and VideoFrameProcessor (for workflow processing logic).\n    \"\"\"\n\n    def __init__(\n        self,\n        asyncio_loop: asyncio.AbstractEventLoop,\n        workflow_configuration: WorkflowConfiguration,\n        api_key: str,\n        model_manager: Optional[ModelManager] = None,\n        data_output: Optional[List[str]] = None,\n        stream_output: Optional[str] = None,\n        has_video_track: bool = True,\n        declared_fps: float = 30,\n        termination_date: Optional[datetime.datetime] = None,\n        terminate_event: Optional[asyncio.Event] = None,\n        heartbeat_callback: Optional[Callable[[], None]] = None,\n        realtime_processing: bool = True,\n        is_preview: bool = False,\n        *args,\n        **kwargs,\n    ):\n        VideoStreamTrack.__init__(self, *args, **kwargs)\n        VideoFrameProcessor.__init__(\n            self,\n            asyncio_loop=asyncio_loop,\n            workflow_configuration=workflow_configuration,\n            api_key=api_key,\n            data_output=data_output,\n            stream_output=stream_output,\n            has_video_track=has_video_track,\n            declared_fps=declared_fps,\n            termination_date=termination_date,\n            terminate_event=terminate_event,\n            model_manager=model_manager,\n            heartbeat_callback=heartbeat_callback,\n            realtime_processing=realtime_processing,\n            is_preview=is_preview,\n        )\n\n    async def _auto_detect_stream_output(\n        self, frame: VideoFrame, frame_id: int\n    ) -> None:\n        workflow_output_for_detect, _, _ = await self._process_frame_async(\n            frame=frame,\n            frame_id=frame_id,\n            render_output=False,\n            include_errors_on_frame=False,\n        )\n        detected_output = detect_image_output(workflow_output_for_detect)\n        if detected_output:\n            self.stream_output = detected_output\n            logger.info(f\"Auto-detected stream_output: {detected_output}\")\n        else:\n            logger.warning(\"No image output detected, will use fallback\")\n            self.stream_output = \"\"\n\n    async def recv(self):\n        # Silencing swscaler warnings in multi-threading environment\n        if not self._av_logging_set:\n            av_logging.set_libav_level(av_logging.ERROR)\n            self._av_logging_set = True\n\n        if self.heartbeat_callback:\n            self.heartbeat_callback()\n\n        if self._check_termination():\n            logger.warning(\"[RECV] Termination triggered, closing gracefully\")\n            await self._send_processing_complete()\n            self._signal_termination()\n            raise MediaStreamError(\"Processing terminated due to timeout\")\n\n        # Wait for track to be ready (video file upload case)\n        if self.track is None:\n            logger.info(\"[RECV] Track is None, waiting for track_ready_event...\")\n            await self._track_ready_event.wait()\n            if self.track is None:\n                logger.error(\"[RECV] Track still None after wait!\")\n                raise MediaStreamError(\"Track not available after wait\")\n\n        # Optional ACK pacing: block producing the next frame if we're too far ahead.\n        await self._wait_for_ack_window(next_frame_id=self._received_frames + 1)\n\n        # Drain queue if using PlayerStreamTrack (RTSP/video file)\n        if isinstance(self.track, PlayerStreamTrack) and self.realtime_processing:\n            queue_size = self.track._queue.qsize()\n            if queue_size > 30:\n                drained = 0\n                while self.track._queue.qsize() > 30:\n                    self.track._queue.get_nowait()\n                    drained += 1\n                logger.info(\n                    \"[RECV] Drained %d frames from queue (was %d)\", drained, queue_size\n                )\n\n        try:\n            frame: VideoFrame = await self.track.recv()\n        except MediaStreamError:\n            logger.info(\n                \"[RECV] Track ended after %d frames\", self._received_frames\n            )\n            await self._send_processing_complete()\n            raise\n\n        self._received_frames += 1\n        frame_id = self._received_frames\n        frame_timestamp = datetime.datetime.now()\n\n        if self.stream_output is None and frame_id == 1:\n            await self._auto_detect_stream_output(frame, frame_id)\n\n        workflow_output, new_frame, errors = await self._process_frame_async(\n            frame=frame,\n            frame_id=frame_id,\n            stream_output=self.stream_output,\n            render_output=True,\n            include_errors_on_frame=True,\n        )\n\n        new_frame.pts = frame.pts\n        new_frame.time_base = frame.time_base\n\n        await self._send_data_output(workflow_output, frame_timestamp, frame, errors)\n\n        if errors:\n            logger.warning(\"[RECV] Frame %d errors: %s\", frame_id, errors)\n\n        return new_frame\n\n\nasync def _wait_ice_complete(peer_connection: RTCPeerConnectionWithLoop, timeout=2.0):\n    if peer_connection.iceGatheringState == \"complete\":\n        logger.info(\"ICE gathering state already complete\")\n        return\n    fut = asyncio.get_running_loop().create_future()\n\n    @peer_connection.on(\"icegatheringstatechange\")\n    def _():\n        logger.info(\n            \"ICE gathering state changed to %s\", peer_connection.iceGatheringState\n        )\n        if not fut.done() and peer_connection.iceGatheringState == \"complete\":\n            fut.set_result(True)\n\n    try:\n        logger.info(\"Waiting for ICE gathering to complete...\")\n        await asyncio.wait_for(fut, timeout)\n        logger.info(\"ICE gathering completed\")\n    except asyncio.TimeoutError:\n        logger.info(\"ICE gathering did not complete in %s seconds\", timeout)\n        pass\n\n\nasync def init_rtc_peer_connection_with_loop(\n    webrtc_request: WebRTCWorkerRequest,\n    send_answer: Callable[[WebRTCWorkerResult], None],\n    asyncio_loop: Optional[asyncio.AbstractEventLoop] = None,\n    model_manager: Optional[ModelManager] = None,\n    shutdown_reserve: int = WEBRTC_MODAL_SHUTDOWN_RESERVE,\n    heartbeat_callback: Optional[Callable[[], None]] = None,\n) -> RTCPeerConnectionWithLoop:\n    logger.info(\n        \"=\" * 60 + \"\\n\"\n        \"[WEBRTC_SESSION] STARTING NEW SESSION\\n\"\n        \"  stream_output=%s\\n\"\n        \"  data_output=%s\\n\"\n        \"  timeout=%s\\n\" + \"=\" * 60,\n        webrtc_request.stream_output,\n        webrtc_request.data_output,\n        webrtc_request.processing_timeout,\n    )\n\n    # ice._mdns is instantiated on the module level, it has a lock that is bound to the event loop\n    # avoid RuntimeError: asyncio.locks.Lock is bound to a different event loop\n    if hasattr(ice, \"_mdns\"):\n        if hasattr(ice._mdns, \"lock\"):\n            logger.info(\"Removing lock from aioice.ice._mdns\")\n            delattr(ice._mdns, \"lock\")\n    else:\n        logger.warning(\n            \"aioice.ice implementation was changed, _mdns attribute is not available\"\n        )\n\n    termination_date = None\n    terminate_event = asyncio.Event()\n\n    if webrtc_request.processing_timeout is not None:\n        try:\n            time_limit_seconds = int(webrtc_request.processing_timeout)\n            datetime_now = webrtc_request.processing_session_started\n            if datetime_now is None:\n                datetime_now = datetime.datetime.now()\n            termination_date = datetime_now + datetime.timedelta(\n                seconds=time_limit_seconds - shutdown_reserve\n            )\n            logger.info(\n                \"Setting termination date to %s (%s seconds from %s)\",\n                termination_date.isoformat(),\n                time_limit_seconds,\n                datetime_now.isoformat(),\n            )\n        except (TypeError, ValueError):\n            pass\n    if webrtc_request.stream_output is None:\n        stream_mode = StreamOutputMode.AUTO_DETECT\n        stream_field = None\n    elif len(webrtc_request.stream_output) == 0:\n        stream_mode = StreamOutputMode.NO_VIDEO\n        stream_field = None\n    else:\n        filtered = [s for s in webrtc_request.stream_output if s]\n        if filtered:\n            stream_mode = StreamOutputMode.SPECIFIC_FIELD\n            stream_field = filtered[0]\n        else:\n            stream_mode = StreamOutputMode.NO_VIDEO\n            stream_field = None\n\n    if webrtc_request.data_output is None or len(webrtc_request.data_output) == 0:\n        data_fields = None\n    elif webrtc_request.data_output == [\"*\"]:\n        data_fields = [\"*\"]\n    else:\n        data_fields = webrtc_request.data_output\n\n    try:\n        should_send_video = stream_mode != StreamOutputMode.NO_VIDEO\n\n        if should_send_video:\n            video_processor = VideoTransformTrackWithLoop(\n                asyncio_loop=asyncio_loop,\n                workflow_configuration=webrtc_request.workflow_configuration,\n                model_manager=model_manager,\n                api_key=webrtc_request.api_key,\n                data_output=data_fields,\n                stream_output=stream_field,\n                has_video_track=True,\n                declared_fps=webrtc_request.declared_fps,\n                termination_date=termination_date,\n                terminate_event=terminate_event,\n                heartbeat_callback=heartbeat_callback,\n                realtime_processing=webrtc_request.webrtc_realtime_processing,\n                is_preview=webrtc_request.is_preview,\n            )\n        else:\n            # No video track - use base VideoFrameProcessor\n            video_processor = VideoFrameProcessor(\n                asyncio_loop=asyncio_loop,\n                workflow_configuration=webrtc_request.workflow_configuration,\n                model_manager=model_manager,\n                api_key=webrtc_request.api_key,\n                data_output=data_fields,\n                stream_output=None,\n                has_video_track=False,\n                declared_fps=webrtc_request.declared_fps,\n                termination_date=termination_date,\n                terminate_event=terminate_event,\n                heartbeat_callback=heartbeat_callback,\n                realtime_processing=webrtc_request.webrtc_realtime_processing,\n                is_preview=webrtc_request.is_preview,\n            )\n    except (\n        ValidationError,\n        MissingApiKeyError,\n        KeyError,\n        NotImplementedError,\n    ) as error:\n        # heartbeat to indicate caller error\n        heartbeat_callback()\n        send_answer(\n            WebRTCWorkerResult(\n                exception_type=error.__class__.__name__,\n                error_message=\"Could not decode InferencePipeline initialisation command payload.\",\n            )\n        )\n        return\n    except WebRTCConfigurationError as error:\n        # heartbeat to indicate caller error\n        heartbeat_callback()\n        send_answer(\n            WebRTCWorkerResult(\n                exception_type=error.__class__.__name__,\n                error_message=str(error),\n            )\n        )\n        return\n    except RoboflowAPINotAuthorizedError:\n        # heartbeat to indicate caller error\n        heartbeat_callback()\n        send_answer(\n            WebRTCWorkerResult(\n                exception_type=RoboflowAPINotAuthorizedError.__name__,\n                error_message=\"Invalid API key used or API key is missing. Visit https://docs.roboflow.com/api-reference/authentication#retrieve-an-api-key\",\n            )\n        )\n        return\n    except RoboflowAPINotNotFoundError:\n        # heartbeat to indicate caller error\n        heartbeat_callback()\n        send_answer(\n            WebRTCWorkerResult(\n                exception_type=RoboflowAPINotNotFoundError.__name__,\n                error_message=\"Requested Roboflow resources (models / workflows etc.) not available or wrong API key used.\",\n            )\n        )\n        return\n    except WorkflowSyntaxError as error:\n        # heartbeat to indicate caller error\n        heartbeat_callback()\n        send_answer(\n            WebRTCWorkerResult(\n                exception_type=WorkflowSyntaxError.__name__,\n                error_message=str(error),\n                error_context=str(error.context),\n                inner_error=str(error.inner_error),\n            )\n        )\n        return\n    except WorkflowError as error:\n        # heartbeat to indicate caller error\n        heartbeat_callback()\n        send_answer(\n            WebRTCWorkerResult(\n                exception_type=WorkflowError.__name__,\n                error_message=str(error),\n            )\n        )\n        return\n    except Exception as error:\n        send_answer(\n            WebRTCWorkerResult(\n                exception_type=error.__class__.__name__,\n                error_message=str(error),\n            )\n        )\n        return\n\n    if webrtc_request.webrtc_config is not None:\n        ice_servers = []\n        for ice_server in webrtc_request.webrtc_config.iceServers:\n            ice_servers.append(\n                RTCIceServer(\n                    urls=ice_server.urls,\n                    username=ice_server.username,\n                    credential=ice_server.credential,\n                )\n            )\n        # Always add public stun servers (if specified)\n        if WEBRTC_MODAL_PUBLIC_STUN_SERVERS:\n            for stun_server in WEBRTC_MODAL_PUBLIC_STUN_SERVERS.split(\",\"):\n                try:\n                    ice_servers.append(RTCIceServer(urls=stun_server.strip()))\n                except Exception as e:\n                    logger.warning(\n                        \"Failed to add public stun server '%s': %s\", stun_server, e\n                    )\n    else:\n        ice_servers = None\n    peer_connection = RTCPeerConnectionWithLoop(\n        configuration=RTCConfiguration(iceServers=ice_servers) if ice_servers else None,\n        asyncio_loop=asyncio_loop,\n    )\n\n    relay = MediaRelay()\n\n    # Add video track early for SDP negotiation when stream_output is requested\n    # The track source will be set later by the appropriate handler (RTSP, on_track, video_upload)\n    if should_send_video:\n        logger.info(\"Adding video track early for SDP negotiation\")\n        peer_connection.addTrack(video_processor)\n\n    player: Optional[MediaPlayer] = None\n    if webrtc_request.rtsp_url:\n        if webrtc_request.rtsp_url == WEBRTC_MODAL_RTSP_PLACEHOLDER:\n            webrtc_request.rtsp_url = WEBRTC_MODAL_RTSP_PLACEHOLDER_URL\n        logger.info(\"Processing RTSP URL: %s\", webrtc_request.rtsp_url)\n        player = MediaPlayer(\n            webrtc_request.rtsp_url,\n            format=\"rtsp\",\n            options={\n                \"rtsp_transport\": \"tcp\",\n                \"rtsp_flags\": \"prefer_tcp\",\n                \"stimeout\": \"2000000\",  # 2s socket timeout\n            },\n        )\n        video_processor.set_track(track=player.video)\n\n        # For DATA_ONLY mode, start data-only processing task\n        if not should_send_video:\n            logger.info(\"Starting data-only processing for RTSP stream\")\n            asyncio.create_task(video_processor.process_frames_data_only())\n\n    elif webrtc_request.mjpeg_url:\n        logger.info(\"Processing MJPEG URL: %s\", webrtc_request.mjpeg_url)\n        player = MediaPlayer(webrtc_request.mjpeg_url)\n        video_processor.set_track(track=player.video)\n\n        if not should_send_video:\n            logger.info(\"Starting data-only processing for MJPEG stream\")\n            asyncio.create_task(video_processor.process_frames_data_only())\n\n    @peer_connection.on(\"track\")\n    def on_track(track: RemoteStreamTrack):\n        logger.info(\"Track received from client\")\n        relayed_track = relay.subscribe(\n            track,\n            buffered=False if webrtc_request.webrtc_realtime_processing else True,\n        )\n        video_processor.set_track(track=relayed_track)\n\n        # For DATA_ONLY mode, start data-only processing task\n        if not should_send_video:\n            logger.info(\"Starting data-only processing (no video track)\")\n            asyncio.create_task(video_processor.process_frames_data_only())\n\n    @peer_connection.on(\"connectionstatechange\")\n    async def on_connectionstatechange():\n        state = peer_connection.connectionState\n        ice_state = peer_connection.iceConnectionState\n        logger.warning(\n            \"[CONNECTION_STATE] Changed to: %s (ICE state: %s, \"\n            \"frames_received: %d, data_channel: %s)\",\n            state,\n            ice_state,\n            video_processor._received_frames,\n            (\n                video_processor.data_channel.readyState\n                if video_processor.data_channel\n                else \"N/A\"\n            ),\n        )\n        if state in {\"failed\", \"closed\"}:\n            logger.error(\n                \"[CONNECTION_STATE] FATAL: Connection %s! ICE=%s, \"\n                \"frames_processed=%d. Cleaning up...\",\n                state,\n                ice_state,\n                video_processor._received_frames,\n            )\n            if video_processor.track:\n                logger.info(\"[CONNECTION_STATE] Stopping video processor track\")\n                video_processor.track.stop()\n            await video_processor.close()\n            logger.info(\"[CONNECTION_STATE] Stopping WebRTC peer\")\n            await peer_connection.close()\n            terminate_event.set()\n\n    # Monitor ICE connection state - consent expires after ~30s without STUN refresh\n    @peer_connection.on(\"iceconnectionstatechange\")\n    async def on_iceconnectionstatechange():\n        state = peer_connection.iceConnectionState\n        conn_state = peer_connection.connectionState\n        logger.warning(\n            \"[ICE_STATE] Changed to: %s (connection state: %s, \"\n            \"frames_received: %d, data_channel: %s)\",\n            state,\n            conn_state,\n            video_processor._received_frames,\n            (\n                video_processor.data_channel.readyState\n                if video_processor.data_channel\n                else \"N/A\"\n            ),\n        )\n\n        if state == \"failed\":\n            logger.error(\n                \"[ICE_STATE] FAILED! This typically means STUN consent expired. \"\n                \"Causes: (1) Event loop starvation preventing aioice from sending \"\n                \"STUN packets, (2) Network issues, (3) NAT/firewall blocking. \"\n                \"Check logs for [BUFFER_DRAIN] timeouts or missing asyncio.sleep(0) yields.\"\n            )\n            # The connectionstatechange handler will clean up\n        elif state == \"disconnected\":\n            logger.warning(\n                \"[ICE_STATE] DISCONNECTED - may recover automatically. \"\n                \"If this persists for >30s, will transition to 'failed'.\"\n            )\n        elif state == \"checking\":\n            logger.info(\"[ICE_STATE] Checking connectivity candidates...\")\n        elif state == \"connected\":\n            logger.info(\"[ICE_STATE] Successfully connected via ICE\")\n\n    def process_video_upload_message(\n        message: bytes, video_processor: VideoTransformTrackWithLoop\n    ):\n        chunk_index, total_chunks, data = parse_video_file_chunk(message)\n        video_processor.video_upload_handler.handle_chunk(\n            chunk_index, total_chunks, data\n        )\n\n        video_path = video_processor.video_upload_handler.try_start_processing()\n        return video_path\n\n    @peer_connection.on(\"datachannel\")\n    def on_datachannel(channel: RTCDataChannel):\n        logger.info(\"Data channel '%s' received\", channel.label)\n        # Handle video file upload channel\n        if channel.label == \"video_upload\":\n            logger.info(\"Video upload channel established\")\n\n            video_processor.video_upload_handler = VideoFileUploadHandler()\n\n            @channel.on(\"message\")\n            async def on_upload_message(message):\n                # Keep watchdog alive during upload and keepalive pings\n                if video_processor.heartbeat_callback:\n                    video_processor.heartbeat_callback()\n\n                # Ignore keepalive pings (1-byte messages)\n                if len(message) <= 1:\n                    channel.send(message)\n                    return\n                loop = asyncio.get_running_loop()\n                video_path = await loop.run_in_executor(\n                    None, process_video_upload_message, message, video_processor\n                )\n                if video_path:\n                    video_processor._file_processing = True\n                    logger.info(\n                        \"Video upload complete, processing: realtime=%s, path=%s\",\n                        webrtc_request.webrtc_realtime_processing,\n                        video_path,\n                    )\n\n                    rotation = get_video_rotation(video_path)\n                    rotation_code = get_cv2_rotation_code(rotation)\n                    if rotation_code is not None:\n                        logger.info(\"Video has %d\u00b0 rotation, will correct\", rotation)\n\n                    detected_fps = get_video_fps(video_path)\n                    if detected_fps is not None:\n                        logger.info(\n                            \"FPS detection: detected=%.2f, previous=%s\",\n                            detected_fps,\n                            video_processor._declared_fps,\n                        )\n                        video_processor._declared_fps = detected_fps\n                    else:\n                        logger.warning(\n                            \"FPS detection failed, keeping default: %s\",\n                            video_processor._declared_fps,\n                        )\n\n                    if webrtc_request.webrtc_realtime_processing:\n                        # We are dealing with a live video stream,\n                        player = MediaPlayer(video_path, loop=False)\n                        player._throttle_playback = True\n                        video_processor.set_track(\n                            track=player.video, rotation_code=rotation_code\n                        )\n                    else:\n                        # we are dealing with a video file,\n                        track = ThreadedVideoFileTrack(video_path)\n                        video_processor.set_track(\n                            track=track, rotation_code=rotation_code\n                        )\n\n                    if not should_send_video:\n                        logger.info(\"Starting data-only processing for video file\")\n                        asyncio.create_task(video_processor.process_frames_data_only())\n\n            return\n\n        # Handle inference control channel (bidirectional communication)\n        @channel.on(\"message\")\n        def on_message(message):\n            try:\n                message_data = WebRTCData(**json.loads(message))\n            except json.JSONDecodeError:\n                logger.error(\"Failed to decode webrtc data payload: %s\", message)\n                return\n            # Optional ACK-based flow control (enabled only after first ACK is received)\n            if message_data.ack is not None:\n                video_processor.record_ack(message_data.ack)\n\n            # Handle stream_output changes\n            if message_data.stream_output is not None:\n                if not video_processor.has_video_track:\n                    logger.warning(\n                        \"Cannot change stream_output: video track was not initialized. \"\n                        \"stream_output must be set at initialization to enable video.\"\n                    )\n                else:\n                    if len(message_data.stream_output) == 0:\n                        video_processor.stream_output = None\n                    else:\n                        filtered = [s for s in message_data.stream_output if s]\n                        video_processor.stream_output = (\n                            filtered[0] if filtered else None\n                        )\n\n            # Handle data_output changes (always allowed)\n            if message_data.data_output is not None:\n                video_processor.data_output = message_data.data_output\n                if (\n                    message_data.data_output is None\n                    or len(message_data.data_output) == 0\n                ):\n                    video_processor._data_mode = DataOutputMode.NONE\n                elif message_data.data_output == [\"*\"]:\n                    video_processor._data_mode = DataOutputMode.ALL\n                else:\n                    video_processor._data_mode = DataOutputMode.SPECIFIC\n\n        video_processor.data_channel = channel\n\n    await peer_connection.setRemoteDescription(\n        RTCSessionDescription(\n            sdp=webrtc_request.webrtc_offer.sdp, type=webrtc_request.webrtc_offer.type\n        )\n    )\n    answer = await peer_connection.createAnswer()\n    await peer_connection.setLocalDescription(answer)\n\n    await _wait_ice_complete(peer_connection, timeout=2.0)\n\n    logger.info(\n        \"Initialized RTC peer connection with loop (status: %s), sending answer\",\n        peer_connection.connectionState,\n    )\n\n    send_answer(\n        WebRTCWorkerResult(\n            answer={\n                \"type\": peer_connection.localDescription.type,\n                \"sdp\": peer_connection.localDescription.sdp,\n            },\n        )\n    )\n\n    logger.info(\"Answer sent, waiting for termination event\")\n    await terminate_event.wait()\n    logger.info(\"Termination event received, closing WebRTC connection\")\n    if player:\n        logger.info(\"Stopping player\")\n        player.video.stop()\n    if peer_connection.connectionState != \"closed\":\n        logger.info(\"Closing WebRTC connection\")\n        await peer_connection.close()\n    if video_processor.track:\n        logger.info(\"Stopping video processor track\")\n        video_processor.track.stop()\n    await video_processor.close()\n    await usage_collector.async_push_usage_payloads()\n    logger.info(\"WebRTC peer connection closed\")\n",
    "patch": null
  },
  {
    "trace_id": "eef81d00-fd27-43b8-95e3-a94bc552f21d",
    "function_name": "ExperimentalModelManager.is_loaded",
    "file_path": "inference/core/managers/experimental_model_manager.py",
    "speedup_x": 1.31,
    "review_quality": null,
    "pre_optimization_commit": "5a8fee33e5b6a00d403a325d55217306c9de4e64",
    "resolution_method": "git_parent",
    "source": "git",
    "original_function_code": "    def is_loaded(self, model_id: str) -> bool:\n        with self._models_lock:\n            return model_id in self._models\n",
    "optimized_function_code": "import threading\nfrom collections import deque\nfrom typing import Deque, Dict, List, Optional, Union\n\nimport torch\n\nfrom inference_exp.models.auto_loaders.core import AutoModel, AnyModel\nfrom inference.core import logger\nfrom inference.core.env import MEMORY_FREE_THRESHOLD\n\n\nclass ExperimentalModelManager:\n    \"\"\"Thread-safe in-memory manager for inference-exp models.\n\n    Responsibilities:\n    - Keep a cache of instantiated models keyed by `model_id`.\n    - Ensure only one instantiation per `model_id` via per-model locks.\n    - Return existing instances without re-loading when available.\n    - Provide removal and clearing utilities (best-effort GPU memory release).\n    - expose a basic GPU memory availability heuristic.\n\n    Notes:\n    - File download and on-disk locking are already handled by `AutoModel`.\n    - This manager focuses solely on in-memory instance management.\n    - Cross-process deduplication is out of scope for now; rely on `AutoModel` file locks.\n    \"\"\"\n\n    _instance: Optional[\"ExperimentalModelManager\"] = None\n    _instance_lock = threading.Lock()\n\n    def __init__(self) -> None:\n        self._models: Dict[str, AnyModel] = {}\n        self._models_lock = threading.Lock()\n        # Per-model instantiation locks to avoid concurrent in-memory loads\n        self._model_locks: Dict[str, threading.Lock] = {}\n        # LRU queue of model_ids; right side is most recently used\n        self._lru_queue: Deque[str] = deque()\n\n    @classmethod\n    def get_instance(cls) -> \"ExperimentalModelManager\":\n        # Double-checked locking for singleton instance\n        if cls._instance is None:\n            with cls._instance_lock:\n                if cls._instance is None:\n                    cls._instance = ExperimentalModelManager()\n        return cls._instance\n\n    def is_loaded(self, model_id: str) -> bool:\n        return model_id in self._models\n\n    def list_models(self) -> List[str]:\n        with self._models_lock:\n            return list(self._models.keys())\n\n    def _get_model_lock(self, model_id: str) -> threading.Lock:\n        # Ensure a stable per-model lock exists\n        with self._models_lock:\n            lock = self._model_locks.get(model_id)\n            if lock is None:\n                lock = threading.Lock()\n                self._model_locks[model_id] = lock\n            return lock\n\n    def _mark_as_used(self, model_id: str) -> None:\n        with self._models_lock:\n            try:\n                self._lru_queue.remove(model_id)\n            except ValueError:\n                pass\n            self._lru_queue.append(model_id)\n\n    def _evict_if_needed(\n        self,\n        *,\n        min_free_ratio: Optional[float] = None,\n        estimated_bytes: Optional[int] = None,\n    ) -> None:\n        \"\"\"Evict least-recently used models under memory pressure only.\n\n        If `min_free_ratio` is None, use MEMORY_FREE_THRESHOLD when valid.\n        If `estimated_bytes` is provided, ensure free >= estimated_bytes.\n        \"\"\"\n        if min_free_ratio is None:\n            if (\n                isinstance(MEMORY_FREE_THRESHOLD, float)\n                and 0.0 < MEMORY_FREE_THRESHOLD < 1.0\n            ):\n                min_free_ratio = MEMORY_FREE_THRESHOLD\n        self.evict_until_memory(\n            min_free_ratio=min_free_ratio, estimated_bytes=estimated_bytes\n        )\n\n    def get_or_load_model(\n        self,\n        model_id: str,\n        *,\n        api_key: Optional[str] = None,\n        device: Optional[torch.device] = None,\n        backends: Optional[Union[str, List[str]]] = None,\n        batch_size: Optional[Union[int, tuple]] = None,\n        quantization: Optional[Union[str, List[str]]] = None,\n        onnx_execution_providers: Optional[List[Union[str, tuple]]] = None,\n        verbose: bool = False,\n        min_free_gpu_memory_ratio: Optional[float] = None,\n        estimated_gpu_memory_bytes: Optional[int] = None,\n        **kwargs,\n    ) -> AnyModel:\n        # Fast path: return cached without global lock if present (benign race acceptable)\n        with self._models_lock:\n            cached = self._models.get(model_id)\n        if cached is not None:\n            # mark as most recently used (must be outside _models_lock to avoid deadlock)\n            self._mark_as_used(model_id)\n            return cached\n\n        # Serialize instantiation per model_id\n        model_lock = self._get_model_lock(model_id)\n        with model_lock:\n            # Re-check after acquiring the lock\n            with self._models_lock:\n                cached = self._models.get(model_id)\n            if cached is not None:\n                # mark as most recently used (must be outside _models_lock to avoid deadlock)\n                self._mark_as_used(model_id)\n                return cached\n\n            # Optionally check GPU memory before attempting load\n            # (heuristic; proceed if unknown)\n            if device is None and torch.cuda.is_available():\n                device = torch.device(\"cuda\")\n\n            # Proactively evict before loading if needed (memory-only policy for now)\n            self._evict_if_needed(\n                min_free_ratio=min_free_gpu_memory_ratio,\n                estimated_bytes=estimated_gpu_memory_bytes,\n            )\n\n            model = AutoModel.from_pretrained(\n                model_name_or_path=model_id,\n                api_key=api_key,\n                backends=backends,\n                batch_size=batch_size,\n                quantization=quantization,\n                onnx_execution_providers=onnx_execution_providers,\n                device=device if device is not None else torch.device(\"cpu\"),\n                verbose=verbose,\n                **kwargs,\n            )\n            with self._models_lock:\n                self._models[model_id] = model\n            # Mark as most recently used outside of _models_lock to avoid deadlock\n            self._mark_as_used(model_id)\n            return model\n\n    def remove_model(self, model_id: str) -> None:\n        with self._models_lock:\n            if model_id in self._models:\n                # Drop strong reference to allow GC; best-effort GPU cache release below\n                del self._models[model_id]\n            try:\n                self._lru_queue.remove(model_id)\n            except ValueError:\n                pass\n        self._best_effort_gpu_memory_release()\n\n    def clear(self) -> None:\n        with self._models_lock:\n            self._models.clear()\n            self._lru_queue.clear()\n        self._best_effort_gpu_memory_release()\n\n    def _best_effort_gpu_memory_release(self) -> None:\n        # Attempt to free CUDA cache if available\n        try:\n            if torch.cuda.is_available():\n                torch.cuda.empty_cache()\n        except Exception:\n            # Ignore any CUDA context errors; memory will be reclaimed by GC\n            pass\n\n    def gpu_memory_info(self) -> Optional[Dict[str, int]]:\n        \"\"\"Return basic GPU memory info in bytes if available, otherwise None.\n\n        Returns a dict with keys: total, free, used.\n        \"\"\"\n        try:\n            if torch.cuda.is_available():\n                free, total = torch.cuda.mem_get_info()  # type: ignore[attr-defined]\n                used = total - free\n                return {\"total\": int(total), \"free\": int(free), \"used\": int(used)}\n        except Exception:\n            return None\n        return None\n\n    def has_sufficient_memory(\n        self,\n        *,\n        estimated_bytes: Optional[int] = None,\n        min_free_ratio: Optional[float] = None,\n    ) -> bool:\n        \"\"\"Check if current device memory appears sufficient.\n\n        - If CUDA not available, return True.\n        - If memory info unavailable, return True.\n        - If `estimated_bytes` provided, require free >= estimated_bytes.\n        - Else require free/total >= min_free_ratio (or MEMORY_FREE_THRESHOLD if not provided and valid).\n        \"\"\"\n        try:\n            if not torch.cuda.is_available():\n                return True\n            mem = self.gpu_memory_info()\n            if not mem or mem[\"total\"] <= 0:\n                return True\n            if estimated_bytes is not None:\n                return mem[\"free\"] >= estimated_bytes\n            if min_free_ratio is None:\n                if (\n                    isinstance(MEMORY_FREE_THRESHOLD, float)\n                    and 0.0 < MEMORY_FREE_THRESHOLD < 1.0\n                ):\n                    min_free_ratio = MEMORY_FREE_THRESHOLD\n            if min_free_ratio is None:\n                return True\n            return (mem[\"free\"] / mem[\"total\"]) >= float(min_free_ratio)\n        except Exception:\n            return True\n\n    # Backwards-compatible alias\n    def can_load_model(\n        self,\n        *,\n        estimated_bytes: Optional[int] = None,\n        min_free_ratio: float = 0.1,\n    ) -> bool:\n        return self.has_sufficient_memory(\n            estimated_bytes=estimated_bytes, min_free_ratio=min_free_ratio\n        )\n\n    def evict_until_memory(\n        self,\n        *,\n        min_free_ratio: Optional[float] = None,\n        estimated_bytes: Optional[int] = None,\n    ) -> None:\n        \"\"\"Evict LRU models until memory constraint is satisfied (GPU only).\n\n        No-op if CUDA unavailable or memory metrics cannot be obtained.\n        \"\"\"\n        try:\n            if not torch.cuda.is_available():\n                return None\n            if min_free_ratio is None:\n                if (\n                    isinstance(MEMORY_FREE_THRESHOLD, float)\n                    and 0.0 < MEMORY_FREE_THRESHOLD < 1.0\n                ):\n                    min_free_ratio = MEMORY_FREE_THRESHOLD\n            # quick check: if already sufficient, return\n            if self.has_sufficient_memory(\n                estimated_bytes=estimated_bytes, min_free_ratio=min_free_ratio\n            ):\n                return None\n            with self._models_lock:\n                free, total = torch.cuda.mem_get_info()  # type: ignore[attr-defined]\n                while self._lru_queue:\n                    # stop if satisfied\n                    if estimated_bytes is not None and free >= estimated_bytes:\n                        break\n                    if (\n                        min_free_ratio is not None\n                        and total > 0\n                        and float(free) / float(total) >= float(min_free_ratio)\n                    ):\n                        break\n                    to_remove = self._lru_queue.popleft()\n                    if to_remove in self._models:\n                        logger.debug(\n                            f\"ExperimentalModelManager: Evicting LRU model: {to_remove}\"\n                        )\n                        del self._models[to_remove]\n                        try:\n                            torch.cuda.empty_cache()\n                        except Exception:\n                            pass\n                    # refresh memory\n                    free, total = torch.cuda.mem_get_info()  # type: ignore[attr-defined]\n        except Exception as e:\n            logger.debug(\n                f\"ExperimentalModelManager: evict_until_memory skipped due to error: {e}\"\n            )\n",
    "optimized_raw_markdown": "",
    "optimized_function_only": "    def is_loaded(self, model_id: str) -> bool:\n        return model_id in self._models\n",
    "original_file_content": "import threading\nfrom collections import deque\nfrom typing import Deque, Dict, List, Optional, Union\n\nimport torch\n\nfrom inference_exp.models.auto_loaders.core import AutoModel, AnyModel\nfrom inference.core import logger\nfrom inference.core.env import MEMORY_FREE_THRESHOLD\n\n\nclass ExperimentalModelManager:\n    \"\"\"Thread-safe in-memory manager for inference-exp models.\n\n    Responsibilities:\n    - Keep a cache of instantiated models keyed by `model_id`.\n    - Ensure only one instantiation per `model_id` via per-model locks.\n    - Return existing instances without re-loading when available.\n    - Provide removal and clearing utilities (best-effort GPU memory release).\n    - expose a basic GPU memory availability heuristic.\n\n    Notes:\n    - File download and on-disk locking are already handled by `AutoModel`.\n    - This manager focuses solely on in-memory instance management.\n    - Cross-process deduplication is out of scope for now; rely on `AutoModel` file locks.\n    \"\"\"\n\n    _instance: Optional[\"ExperimentalModelManager\"] = None\n    _instance_lock = threading.Lock()\n\n    def __init__(self) -> None:\n        self._models: Dict[str, AnyModel] = {}\n        self._models_lock = threading.Lock()\n        # Per-model instantiation locks to avoid concurrent in-memory loads\n        self._model_locks: Dict[str, threading.Lock] = {}\n        # LRU queue of model_ids; right side is most recently used\n        self._lru_queue: Deque[str] = deque()\n\n    @classmethod\n    def get_instance(cls) -> \"ExperimentalModelManager\":\n        # Double-checked locking for singleton instance\n        if cls._instance is None:\n            with cls._instance_lock:\n                if cls._instance is None:\n                    cls._instance = ExperimentalModelManager()\n        return cls._instance\n\n    def is_loaded(self, model_id: str) -> bool:\n        with self._models_lock:\n            return model_id in self._models\n\n    def list_models(self) -> List[str]:\n        with self._models_lock:\n            return list(self._models.keys())\n\n    def _get_model_lock(self, model_id: str) -> threading.Lock:\n        # Ensure a stable per-model lock exists\n        with self._models_lock:\n            lock = self._model_locks.get(model_id)\n            if lock is None:\n                lock = threading.Lock()\n                self._model_locks[model_id] = lock\n            return lock\n\n    def _mark_as_used(self, model_id: str) -> None:\n        with self._models_lock:\n            try:\n                self._lru_queue.remove(model_id)\n            except ValueError:\n                pass\n            self._lru_queue.append(model_id)\n\n    def _evict_if_needed(\n        self,\n        *,\n        min_free_ratio: Optional[float] = None,\n        estimated_bytes: Optional[int] = None,\n    ) -> None:\n        \"\"\"Evict least-recently used models under memory pressure only.\n\n        If `min_free_ratio` is None, use MEMORY_FREE_THRESHOLD when valid.\n        If `estimated_bytes` is provided, ensure free >= estimated_bytes.\n        \"\"\"\n        if min_free_ratio is None:\n            if (\n                isinstance(MEMORY_FREE_THRESHOLD, float)\n                and 0.0 < MEMORY_FREE_THRESHOLD < 1.0\n            ):\n                min_free_ratio = MEMORY_FREE_THRESHOLD\n        self.evict_until_memory(\n            min_free_ratio=min_free_ratio, estimated_bytes=estimated_bytes\n        )\n\n    def get_or_load_model(\n        self,\n        model_id: str,\n        *,\n        api_key: Optional[str] = None,\n        device: Optional[torch.device] = None,\n        backends: Optional[Union[str, List[str]]] = None,\n        batch_size: Optional[Union[int, tuple]] = None,\n        quantization: Optional[Union[str, List[str]]] = None,\n        onnx_execution_providers: Optional[List[Union[str, tuple]]] = None,\n        verbose: bool = False,\n        min_free_gpu_memory_ratio: Optional[float] = None,\n        estimated_gpu_memory_bytes: Optional[int] = None,\n        **kwargs,\n    ) -> AnyModel:\n        # Fast path: return cached without global lock if present (benign race acceptable)\n        with self._models_lock:\n            cached = self._models.get(model_id)\n        if cached is not None:\n            # mark as most recently used (must be outside _models_lock to avoid deadlock)\n            self._mark_as_used(model_id)\n            return cached\n\n        # Serialize instantiation per model_id\n        model_lock = self._get_model_lock(model_id)\n        with model_lock:\n            # Re-check after acquiring the lock\n            with self._models_lock:\n                cached = self._models.get(model_id)\n            if cached is not None:\n                # mark as most recently used (must be outside _models_lock to avoid deadlock)\n                self._mark_as_used(model_id)\n                return cached\n\n            # Optionally check GPU memory before attempting load\n            # (heuristic; proceed if unknown)\n            if device is None and torch.cuda.is_available():\n                device = torch.device(\"cuda\")\n\n            # Proactively evict before loading if needed (memory-only policy for now)\n            self._evict_if_needed(\n                min_free_ratio=min_free_gpu_memory_ratio,\n                estimated_bytes=estimated_gpu_memory_bytes,\n            )\n\n            model = AutoModel.from_pretrained(\n                model_name_or_path=model_id,\n                api_key=api_key,\n                backends=backends,\n                batch_size=batch_size,\n                quantization=quantization,\n                onnx_execution_providers=onnx_execution_providers,\n                device=device if device is not None else torch.device(\"cpu\"),\n                verbose=verbose,\n                **kwargs,\n            )\n            with self._models_lock:\n                self._models[model_id] = model\n            # Mark as most recently used outside of _models_lock to avoid deadlock\n            self._mark_as_used(model_id)\n            return model\n\n    def remove_model(self, model_id: str) -> None:\n        with self._models_lock:\n            if model_id in self._models:\n                # Drop strong reference to allow GC; best-effort GPU cache release below\n                del self._models[model_id]\n            try:\n                self._lru_queue.remove(model_id)\n            except ValueError:\n                pass\n        self._best_effort_gpu_memory_release()\n\n    def clear(self) -> None:\n        with self._models_lock:\n            self._models.clear()\n            self._lru_queue.clear()\n        self._best_effort_gpu_memory_release()\n\n    def _best_effort_gpu_memory_release(self) -> None:\n        # Attempt to free CUDA cache if available\n        try:\n            if torch.cuda.is_available():\n                torch.cuda.empty_cache()\n        except Exception:\n            # Ignore any CUDA context errors; memory will be reclaimed by GC\n            pass\n\n    def gpu_memory_info(self) -> Optional[Dict[str, int]]:\n        \"\"\"Return basic GPU memory info in bytes if available, otherwise None.\n\n        Returns a dict with keys: total, free, used.\n        \"\"\"\n        try:\n            if torch.cuda.is_available():\n                free, total = torch.cuda.mem_get_info()  # type: ignore[attr-defined]\n                used = total - free\n                return {\"total\": int(total), \"free\": int(free), \"used\": int(used)}\n        except Exception:\n            return None\n        return None\n\n    def has_sufficient_memory(\n        self,\n        *,\n        estimated_bytes: Optional[int] = None,\n        min_free_ratio: Optional[float] = None,\n    ) -> bool:\n        \"\"\"Check if current device memory appears sufficient.\n\n        - If CUDA not available, return True.\n        - If memory info unavailable, return True.\n        - If `estimated_bytes` provided, require free >= estimated_bytes.\n        - Else require free/total >= min_free_ratio (or MEMORY_FREE_THRESHOLD if not provided and valid).\n        \"\"\"\n        try:\n            if not torch.cuda.is_available():\n                return True\n            mem = self.gpu_memory_info()\n            if not mem or mem[\"total\"] <= 0:\n                return True\n            if estimated_bytes is not None:\n                return mem[\"free\"] >= estimated_bytes\n            if min_free_ratio is None:\n                if (\n                    isinstance(MEMORY_FREE_THRESHOLD, float)\n                    and 0.0 < MEMORY_FREE_THRESHOLD < 1.0\n                ):\n                    min_free_ratio = MEMORY_FREE_THRESHOLD\n            if min_free_ratio is None:\n                return True\n            return (mem[\"free\"] / mem[\"total\"]) >= float(min_free_ratio)\n        except Exception:\n            return True\n\n    # Backwards-compatible alias\n    def can_load_model(\n        self,\n        *,\n        estimated_bytes: Optional[int] = None,\n        min_free_ratio: float = 0.1,\n    ) -> bool:\n        return self.has_sufficient_memory(\n            estimated_bytes=estimated_bytes, min_free_ratio=min_free_ratio\n        )\n\n    def evict_until_memory(\n        self,\n        *,\n        min_free_ratio: Optional[float] = None,\n        estimated_bytes: Optional[int] = None,\n    ) -> None:\n        \"\"\"Evict LRU models until memory constraint is satisfied (GPU only).\n\n        No-op if CUDA unavailable or memory metrics cannot be obtained.\n        \"\"\"\n        try:\n            if not torch.cuda.is_available():\n                return None\n            if min_free_ratio is None:\n                if (\n                    isinstance(MEMORY_FREE_THRESHOLD, float)\n                    and 0.0 < MEMORY_FREE_THRESHOLD < 1.0\n                ):\n                    min_free_ratio = MEMORY_FREE_THRESHOLD\n            # quick check: if already sufficient, return\n            if self.has_sufficient_memory(\n                estimated_bytes=estimated_bytes, min_free_ratio=min_free_ratio\n            ):\n                return None\n            with self._models_lock:\n                free, total = torch.cuda.mem_get_info()  # type: ignore[attr-defined]\n                while self._lru_queue:\n                    # stop if satisfied\n                    if estimated_bytes is not None and free >= estimated_bytes:\n                        break\n                    if (\n                        min_free_ratio is not None\n                        and total > 0\n                        and float(free) / float(total) >= float(min_free_ratio)\n                    ):\n                        break\n                    to_remove = self._lru_queue.popleft()\n                    if to_remove in self._models:\n                        logger.debug(\n                            f\"ExperimentalModelManager: Evicting LRU model: {to_remove}\"\n                        )\n                        del self._models[to_remove]\n                        try:\n                            torch.cuda.empty_cache()\n                        except Exception:\n                            pass\n                    # refresh memory\n                    free, total = torch.cuda.mem_get_info()  # type: ignore[attr-defined]\n        except Exception as e:\n            logger.debug(\n                f\"ExperimentalModelManager: evict_until_memory skipped due to error: {e}\"\n            )\n",
    "patch": "diff --git a/inference/core/managers/experimental_model_manager.py b/inference/core/managers/experimental_model_manager.py\nindex 2508f68ae..95afffe0e 100644\n--- a/inference/core/managers/experimental_model_manager.py\n+++ b/inference/core/managers/experimental_model_manager.py\n@@ -46,8 +46,7 @@ class ExperimentalModelManager:\n         return cls._instance\n \n     def is_loaded(self, model_id: str) -> bool:\n-        with self._models_lock:\n-            return model_id in self._models\n+        return model_id in self._models\n \n     def list_models(self) -> List[str]:\n         with self._models_lock:\n"
  },
  {
    "trace_id": "12b5bd5f-45cc-4f7e-ac07-d0d7624fc71a",
    "function_name": "ModelManager._dispose_model_lock",
    "file_path": "inference/core/managers/base.py",
    "speedup_x": 2.24,
    "review_quality": null,
    "pre_optimization_commit": "1e3077455f0c992cee3f41a15a254a0af1b6a67e",
    "resolution_method": "git_parent",
    "source": "git",
    "original_function_code": "    def _dispose_model_lock(self, model_id: str) -> None:\n        with acquire_with_timeout(lock=self._state_lock) as acquired:\n            if not acquired:\n                raise ModelManagerLockAcquisitionError(\n                    \"Could not acquire lock on Model Manager state to dispose model lock.\"\n                )\n            if model_id not in self._models_state_locks:\n                return None\n            del self._models_state_locks[model_id]\n",
    "optimized_function_code": "import time\nfrom contextlib import contextmanager\nfrom threading import Lock\nfrom typing import Dict, Generator, List, Optional, Tuple, Union\n\nimport numpy as np\nfrom fastapi.encoders import jsonable_encoder\n\nfrom inference.core.cache import cache\nfrom inference.core.cache.serializers import to_cachable_inference_item\nfrom inference.core.devices.utils import GLOBAL_INFERENCE_SERVER_ID\nfrom inference.core.entities.requests.inference import InferenceRequest\nfrom inference.core.entities.responses.inference import InferenceResponse\nfrom inference.core.env import (\n    DISABLE_INFERENCE_CACHE,\n    INTERNAL_WEIGHTS_URL_SUFFIX,\n    METRICS_ENABLED,\n    METRICS_INTERVAL,\n    MODEL_LOCK_ACQUIRE_TIMEOUT,\n    MODELS_CACHE_AUTH_ENABLED,\n    ROBOFLOW_SERVER_UUID,\n)\nfrom inference.core.exceptions import (\n    InferenceModelNotFound,\n    ModelManagerLockAcquisitionError,\n    RoboflowAPINotAuthorizedError,\n)\nfrom inference.core.logger import logger\nfrom inference.core.managers.entities import ModelDescription\nfrom inference.core.managers.pingback import PingbackInfo\nfrom inference.core.models.base import Model, PreprocessReturnMetadata\nfrom inference.core.registries.base import ModelRegistry\nfrom inference.core.registries.roboflow import (\n    ModelEndpointType,\n    _check_if_api_key_has_access_to_model,\n)\n\n\nclass ModelManager:\n    \"\"\"Model managers keep track of a dictionary of Model objects and is responsible for passing requests to the right model using the infer method.\"\"\"\n\n    def __init__(self, model_registry: ModelRegistry, models: Optional[dict] = None):\n        self.model_registry = model_registry\n        self._models: Dict[str, Model] = models if models is not None else {}\n        self.pingback = None\n        self._state_lock = Lock()\n        self._models_state_locks: Dict[str, Lock] = {}\n\n    def init_pingback(self):\n        \"\"\"Initializes pingback mechanism.\"\"\"\n        self.num_errors = 0  # in the device\n        self.uuid = ROBOFLOW_SERVER_UUID\n        if METRICS_ENABLED:\n            self.pingback = PingbackInfo(self)\n            self.pingback.start()\n\n    def add_model(\n        self,\n        model_id: str,\n        api_key: str,\n        model_id_alias: Optional[str] = None,\n        endpoint_type: ModelEndpointType = ModelEndpointType.ORT,\n        countinference: Optional[bool] = None,\n        service_secret: Optional[str] = None,\n    ) -> None:\n        \"\"\"Adds a new model to the manager.\n\n        Args:\n            model_id (str): The identifier of the model.\n            model (Model): The model instance.\n            endpoint_type (ModelEndpointType, optional): The endpoint type to use for the model.\n        \"\"\"\n        if MODELS_CACHE_AUTH_ENABLED:\n            if not _check_if_api_key_has_access_to_model(\n                api_key=api_key,\n                model_id=model_id,\n                endpoint_type=endpoint_type,\n                countinference=countinference,\n                service_secret=service_secret,\n            ):\n                raise RoboflowAPINotAuthorizedError(\n                    f\"API key {api_key} does not have access to model {model_id}\"\n                )\n\n        logger.debug(\n            f\"ModelManager - Adding model with model_id={model_id}, model_id_alias={model_id_alias}\"\n        )\n        resolved_identifier = model_id if model_id_alias is None else model_id_alias\n        model_lock = self._get_lock_for_a_model(model_id=resolved_identifier)\n        with acquire_with_timeout(lock=model_lock) as acquired:\n            if not acquired:\n                # if failed to acquire - then in use, no need to purge lock\n                raise ModelManagerLockAcquisitionError(\n                    f\"Could not acquire lock for model with id={resolved_identifier}.\"\n                )\n            if resolved_identifier in self._models:\n                logger.debug(\n                    f\"ModelManager - model with model_id={resolved_identifier} is already loaded.\"\n                )\n                return\n            try:\n                logger.debug(\"ModelManager - model initialisation...\")\n                model_class = self.model_registry.get_model(\n                    resolved_identifier,\n                    api_key,\n                    countinference=countinference,\n                    service_secret=service_secret,\n                )\n                model = model_class(\n                    model_id=model_id,\n                    api_key=api_key,\n                )\n\n                # Pass countinference and service_secret to download_model_artifacts_from_roboflow_api if available\n                if (\n                    hasattr(model, \"download_model_artifacts_from_roboflow_api\")\n                    and INTERNAL_WEIGHTS_URL_SUFFIX == \"serverless\"\n                ):\n                    # Only pass these parameters if INTERNAL_WEIGHTS_URL_SUFFIX is \"serverless\"\n                    if (\n                        hasattr(model, \"cache_model_artefacts\")\n                        and not model.has_model_metadata\n                    ):\n                        # Override the download_model_artifacts_from_roboflow_api method with parameters\n                        original_method = (\n                            model.download_model_artifacts_from_roboflow_api\n                        )\n                        model.download_model_artifacts_from_roboflow_api = (\n                            lambda: original_method(\n                                countinference=countinference,\n                                service_secret=service_secret,\n                            )\n                        )\n\n                logger.debug(\"ModelManager - model successfully loaded.\")\n                self._models[resolved_identifier] = model\n            except Exception as error:\n                self._dispose_model_lock(model_id=resolved_identifier)\n                raise error\n\n    def check_for_model(self, model_id: str) -> None:\n        \"\"\"Checks whether the model with the given ID is in the manager.\n\n        Args:\n            model_id (str): The identifier of the model.\n\n        Raises:\n            InferenceModelNotFound: If the model is not found in the manager.\n        \"\"\"\n        if model_id not in self:\n            raise InferenceModelNotFound(f\"Model with id {model_id} not loaded.\")\n\n    async def infer_from_request(\n        self, model_id: str, request: InferenceRequest, **kwargs\n    ) -> InferenceResponse:\n        \"\"\"Runs inference on the specified model with the given request.\n\n        Args:\n            model_id (str): The identifier of the model.\n            request (InferenceRequest): The request to process.\n\n        Returns:\n            InferenceResponse: The response from the inference.\n        \"\"\"\n        logger.debug(\n            f\"ModelManager - inference from request started for model_id={model_id}.\"\n        )\n        if METRICS_ENABLED and self.pingback:\n            logger.debug(\"ModelManager - setting pingback fallback api key...\")\n            self.pingback.fallback_api_key = request.api_key\n        try:\n            rtn_val = await self.model_infer(\n                model_id=model_id, request=request, **kwargs\n            )\n            logger.debug(\n                f\"ModelManager - inference from request finished for model_id={model_id}.\"\n            )\n            finish_time = time.time()\n            if not DISABLE_INFERENCE_CACHE:\n                try:\n                    logger.debug(\n                        f\"ModelManager - caching inference request started for model_id={model_id}\"\n                    )\n                    cache.zadd(\n                        f\"models\",\n                        value=f\"{GLOBAL_INFERENCE_SERVER_ID}:{request.api_key}:{model_id}\",\n                        score=finish_time,\n                        expire=METRICS_INTERVAL * 2,\n                    )\n                    if (\n                        hasattr(request, \"image\")\n                        and hasattr(request.image, \"type\")\n                        and request.image.type == \"numpy\"\n                    ):\n                        request.image.value = str(request.image.value)\n                    cache.zadd(\n                        f\"inference:{GLOBAL_INFERENCE_SERVER_ID}:{model_id}\",\n                        value=to_cachable_inference_item(request, rtn_val),\n                        score=finish_time,\n                        expire=METRICS_INTERVAL * 2,\n                    )\n                    logger.debug(\n                        f\"ModelManager - caching inference request finished for model_id={model_id}\"\n                    )\n                except Exception as cache_error:\n                    logger.warning(\n                        f\"Failed to cache inference data for model {model_id}: {cache_error}\"\n                    )\n            return rtn_val\n        except Exception as e:\n            finish_time = time.time()\n            if not DISABLE_INFERENCE_CACHE:\n                try:\n                    cache.zadd(\n                        f\"models\",\n                        value=f\"{GLOBAL_INFERENCE_SERVER_ID}:{request.api_key}:{model_id}\",\n                        score=finish_time,\n                        expire=METRICS_INTERVAL * 2,\n                    )\n                    cache.zadd(\n                        f\"error:{GLOBAL_INFERENCE_SERVER_ID}:{model_id}\",\n                        value={\n                            \"request\": jsonable_encoder(\n                                request.dict(exclude={\"image\", \"subject\", \"prompt\"})\n                            ),\n                            \"error\": str(e),\n                        },\n                        score=finish_time,\n                        expire=METRICS_INTERVAL * 2,\n                    )\n                except Exception as cache_error:\n                    logger.warning(\n                        f\"Failed to cache error data for model {model_id}: {cache_error}\"\n                    )\n            raise\n\n    def infer_from_request_sync(\n        self, model_id: str, request: InferenceRequest, **kwargs\n    ) -> InferenceResponse:\n        \"\"\"Runs inference on the specified model with the given request.\n\n        Args:\n            model_id (str): The identifier of the model.\n            request (InferenceRequest): The request to process.\n\n        Returns:\n            InferenceResponse: The response from the inference.\n        \"\"\"\n        logger.debug(\n            f\"ModelManager - inference from request started for model_id={model_id}.\"\n        )\n        if METRICS_ENABLED and self.pingback:\n            logger.debug(\"ModelManager - setting pingback fallback api key...\")\n            self.pingback.fallback_api_key = request.api_key\n        try:\n            rtn_val = self.model_infer_sync(\n                model_id=model_id, request=request, **kwargs\n            )\n            logger.debug(\n                f\"ModelManager - inference from request finished for model_id={model_id}.\"\n            )\n            finish_time = time.time()\n            if not DISABLE_INFERENCE_CACHE:\n                try:\n                    logger.debug(\n                        f\"ModelManager - caching inference request started for model_id={model_id}\"\n                    )\n                    cache.zadd(\n                        f\"models\",\n                        value=f\"{GLOBAL_INFERENCE_SERVER_ID}:{request.api_key}:{model_id}\",\n                        score=finish_time,\n                        expire=METRICS_INTERVAL * 2,\n                    )\n                    if (\n                        hasattr(request, \"image\")\n                        and hasattr(request.image, \"type\")\n                        and request.image.type == \"numpy\"\n                    ):\n                        request.image.value = str(request.image.value)\n                    cache.zadd(\n                        f\"inference:{GLOBAL_INFERENCE_SERVER_ID}:{model_id}\",\n                        value=to_cachable_inference_item(request, rtn_val),\n                        score=finish_time,\n                        expire=METRICS_INTERVAL * 2,\n                    )\n                    logger.debug(\n                        f\"ModelManager - caching inference request finished for model_id={model_id}\"\n                    )\n                except Exception as cache_error:\n                    logger.warning(\n                        f\"Failed to cache inference data for model {model_id}: {cache_error}\"\n                    )\n            return rtn_val\n        except Exception as e:\n            finish_time = time.time()\n            if not DISABLE_INFERENCE_CACHE:\n                try:\n                    cache.zadd(\n                        f\"models\",\n                        value=f\"{GLOBAL_INFERENCE_SERVER_ID}:{request.api_key}:{model_id}\",\n                        score=finish_time,\n                        expire=METRICS_INTERVAL * 2,\n                    )\n                    cache.zadd(\n                        f\"error:{GLOBAL_INFERENCE_SERVER_ID}:{model_id}\",\n                        value={\n                            \"request\": jsonable_encoder(\n                                request.dict(exclude={\"image\", \"subject\", \"prompt\"})\n                            ),\n                            \"error\": str(e),\n                        },\n                        score=finish_time,\n                        expire=METRICS_INTERVAL * 2,\n                    )\n                except Exception as cache_error:\n                    logger.warning(\n                        f\"Failed to cache error data for model {model_id}: {cache_error}\"\n                    )\n            raise\n\n    async def model_infer(self, model_id: str, request: InferenceRequest, **kwargs):\n        self.check_for_model(model_id)\n        return self._models[model_id].infer_from_request(request)\n\n    def model_infer_sync(\n        self, model_id: str, request: InferenceRequest, **kwargs\n    ) -> Union[List[InferenceResponse], InferenceResponse]:\n        self.check_for_model(model_id)\n        return self._models[model_id].infer_from_request(request)\n\n    def make_response(\n        self, model_id: str, predictions: List[List[float]], *args, **kwargs\n    ) -> InferenceResponse:\n        \"\"\"Creates a response object from the model's predictions.\n\n        Args:\n            model_id (str): The identifier of the model.\n            predictions (List[List[float]]): The model's predictions.\n\n        Returns:\n            InferenceResponse: The created response object.\n        \"\"\"\n        self.check_for_model(model_id)\n        return self._models[model_id].make_response(predictions, *args, **kwargs)\n\n    def postprocess(\n        self,\n        model_id: str,\n        predictions: Tuple[np.ndarray, ...],\n        preprocess_return_metadata: PreprocessReturnMetadata,\n        *args,\n        **kwargs,\n    ) -> List[List[float]]:\n        \"\"\"Processes the model's predictions after inference.\n\n        Args:\n            model_id (str): The identifier of the model.\n            predictions (np.ndarray): The model's predictions.\n\n        Returns:\n            List[List[float]]: The post-processed predictions.\n        \"\"\"\n        self.check_for_model(model_id)\n        return self._models[model_id].postprocess(\n            predictions, preprocess_return_metadata, *args, **kwargs\n        )\n\n    def predict(self, model_id: str, *args, **kwargs) -> Tuple[np.ndarray, ...]:\n        \"\"\"Runs prediction on the specified model.\n\n        Args:\n            model_id (str): The identifier of the model.\n\n        Returns:\n            np.ndarray: The predictions from the model.\n        \"\"\"\n        self.check_for_model(model_id)\n        self._models[model_id].metrics[\"num_inferences\"] += 1\n        tic = time.perf_counter()\n        res = self._models[model_id].predict(*args, **kwargs)\n        toc = time.perf_counter()\n        self._models[model_id].metrics[\"avg_inference_time\"] += toc - tic\n        return res\n\n    def preprocess(\n        self, model_id: str, request: InferenceRequest\n    ) -> Tuple[np.ndarray, PreprocessReturnMetadata]:\n        \"\"\"Preprocesses the request before inference.\n\n        Args:\n            model_id (str): The identifier of the model.\n            request (InferenceRequest): The request to preprocess.\n\n        Returns:\n            Tuple[np.ndarray, List[Tuple[int, int]]]: The preprocessed data.\n        \"\"\"\n        self.check_for_model(model_id)\n        return self._models[model_id].preprocess(**request.dict())\n\n    def get_class_names(self, model_id):\n        \"\"\"Retrieves the class names for a given model.\n\n        Args:\n            model_id (str): The identifier of the model.\n\n        Returns:\n            List[str]: The class names of the model.\n        \"\"\"\n        self.check_for_model(model_id)\n        return self._models[model_id].class_names\n\n    def get_task_type(self, model_id: str, api_key: str = None) -> str:\n        \"\"\"Retrieves the task type for a given model.\n\n        Args:\n            model_id (str): The identifier of the model.\n\n        Returns:\n            str: The task type of the model.\n        \"\"\"\n        self.check_for_model(model_id)\n        return self._models[model_id].task_type\n\n    def remove(self, model_id: str, delete_from_disk: bool = True) -> None:\n        \"\"\"Removes a model from the manager.\n\n        Args:\n            model_id (str): The identifier of the model.\n        \"\"\"\n        try:\n            logger.debug(f\"Removing model {model_id} from base model manager\")\n            model_lock = self._get_lock_for_a_model(model_id=model_id)\n            with acquire_with_timeout(lock=model_lock) as acquired:\n                if not acquired:\n                    raise ModelManagerLockAcquisitionError(\n                        f\"Could not acquire lock for model with id={model_id}.\"\n                    )\n                self.check_for_model(model_id)\n                self._models[model_id].clear_cache(delete_from_disk=delete_from_disk)\n                del self._models[model_id]\n            self._dispose_model_lock(model_id=model_id)\n        except InferenceModelNotFound:\n            logger.warning(\n                f\"Attempted to remove model with id {model_id}, but it is not loaded. Skipping...\"\n            )\n\n    def clear(self) -> None:\n        \"\"\"Removes all models from the manager.\"\"\"\n        for model_id in list(self.keys()):\n            self.remove(model_id)\n\n    def __contains__(self, model_id: str) -> bool:\n        \"\"\"Checks if the model is contained in the manager.\n\n        Args:\n            model_id (str): The identifier of the model.\n\n        Returns:\n            bool: Whether the model is in the manager.\n        \"\"\"\n        return model_id in self._models\n\n    def __getitem__(self, key: str) -> Model:\n        \"\"\"Retrieve a model from the manager by key.\n\n        Args:\n            key (str): The identifier of the model.\n\n        Returns:\n            Model: The model corresponding to the key.\n        \"\"\"\n        self.check_for_model(model_id=key)\n        return self._models[key]\n\n    def __len__(self) -> int:\n        \"\"\"Retrieve the number of models in the manager.\n\n        Returns:\n            int: The number of models in the manager.\n        \"\"\"\n        return len(self._models)\n\n    def keys(self):\n        \"\"\"Retrieve the keys (model identifiers) from the manager.\n\n        Returns:\n            List[str]: The keys of the models in the manager.\n        \"\"\"\n        return self._models.keys()\n\n    def models(self) -> Dict[str, Model]:\n        \"\"\"Retrieve the models dictionary from the manager.\n\n        Returns:\n            Dict[str, Model]: The keys of the models in the manager.\n        \"\"\"\n        return self._models\n\n    def describe_models(self) -> List[ModelDescription]:\n        return [\n            ModelDescription(\n                model_id=model_id,\n                task_type=model.task_type,\n                batch_size=getattr(model, \"batch_size\", None),\n                input_width=getattr(model, \"img_size_w\", None),\n                input_height=getattr(model, \"img_size_h\", None),\n            )\n            for model_id, model in self._models.items()\n        ]\n\n    def _get_lock_for_a_model(self, model_id: str) -> Lock:\n        # Manual lock management instead of contextlib/contextmanager overhead, for much faster hot path\n        acquired = self._state_lock.acquire(timeout=MODEL_LOCK_ACQUIRE_TIMEOUT)\n        if not acquired:\n            raise ModelManagerLockAcquisitionError(\n                \"Could not acquire lock on Model Manager state to retrieve model lock.\"\n            )\n        try:\n            lock = self._models_state_locks.get(model_id)\n            if lock is None:\n                lock = Lock()\n                self._models_state_locks[model_id] = lock\n            return lock\n        finally:\n            self._state_lock.release()\n\n    def _dispose_model_lock(self, model_id: str) -> None:\n        acquired = self._state_lock.acquire(timeout=MODEL_LOCK_ACQUIRE_TIMEOUT)\n        if not acquired:\n            raise ModelManagerLockAcquisitionError(\n                \"Could not acquire lock on Model Manager state to dispose model lock.\"\n            )\n        try:\n            self._models_state_locks.pop(model_id, None)\n        finally:\n            self._state_lock.release()\n\n\n@contextmanager\ndef acquire_with_timeout(\n    lock: Lock, timeout: float = MODEL_LOCK_ACQUIRE_TIMEOUT\n) -> Generator[bool, None, None]:\n    acquired = lock.acquire(timeout=timeout)\n    try:\n        yield acquired\n    finally:\n        if acquired:\n            lock.release()\n",
    "optimized_raw_markdown": "",
    "optimized_function_only": "    def _dispose_model_lock(self, model_id: str) -> None:\n        acquired = self._state_lock.acquire(timeout=MODEL_LOCK_ACQUIRE_TIMEOUT)\n        if not acquired:\n            raise ModelManagerLockAcquisitionError(\n                \"Could not acquire lock on Model Manager state to dispose model lock.\"\n            )\n        try:\n            self._models_state_locks.pop(model_id, None)\n        finally:\n            self._state_lock.release()\n",
    "original_file_content": "import time\nfrom contextlib import contextmanager\nfrom threading import Lock\nfrom typing import Dict, Generator, List, Optional, Tuple, Union\n\nimport numpy as np\nfrom fastapi.encoders import jsonable_encoder\n\nfrom inference.core.cache import cache\nfrom inference.core.cache.serializers import to_cachable_inference_item\nfrom inference.core.devices.utils import GLOBAL_INFERENCE_SERVER_ID\nfrom inference.core.entities.requests.inference import InferenceRequest\nfrom inference.core.entities.responses.inference import InferenceResponse\nfrom inference.core.env import (\n    DISABLE_INFERENCE_CACHE,\n    INTERNAL_WEIGHTS_URL_SUFFIX,\n    METRICS_ENABLED,\n    METRICS_INTERVAL,\n    MODEL_LOCK_ACQUIRE_TIMEOUT,\n    MODELS_CACHE_AUTH_ENABLED,\n    ROBOFLOW_SERVER_UUID,\n)\nfrom inference.core.exceptions import (\n    InferenceModelNotFound,\n    ModelManagerLockAcquisitionError,\n    RoboflowAPINotAuthorizedError,\n)\nfrom inference.core.logger import logger\nfrom inference.core.managers.entities import ModelDescription\nfrom inference.core.managers.pingback import PingbackInfo\nfrom inference.core.models.base import Model, PreprocessReturnMetadata\nfrom inference.core.registries.base import ModelRegistry\nfrom inference.core.registries.roboflow import (\n    ModelEndpointType,\n    _check_if_api_key_has_access_to_model,\n)\n\n\nclass ModelManager:\n    \"\"\"Model managers keep track of a dictionary of Model objects and is responsible for passing requests to the right model using the infer method.\"\"\"\n\n    def __init__(self, model_registry: ModelRegistry, models: Optional[dict] = None):\n        self.model_registry = model_registry\n        self._models: Dict[str, Model] = models if models is not None else {}\n        self.pingback = None\n        self._state_lock = Lock()\n        self._models_state_locks: Dict[str, Lock] = {}\n\n    def init_pingback(self):\n        \"\"\"Initializes pingback mechanism.\"\"\"\n        self.num_errors = 0  # in the device\n        self.uuid = ROBOFLOW_SERVER_UUID\n        if METRICS_ENABLED:\n            self.pingback = PingbackInfo(self)\n            self.pingback.start()\n\n    def add_model(\n        self,\n        model_id: str,\n        api_key: str,\n        model_id_alias: Optional[str] = None,\n        endpoint_type: ModelEndpointType = ModelEndpointType.ORT,\n        countinference: Optional[bool] = None,\n        service_secret: Optional[str] = None,\n    ) -> None:\n        \"\"\"Adds a new model to the manager.\n\n        Args:\n            model_id (str): The identifier of the model.\n            model (Model): The model instance.\n            endpoint_type (ModelEndpointType, optional): The endpoint type to use for the model.\n        \"\"\"\n        if MODELS_CACHE_AUTH_ENABLED:\n            if not _check_if_api_key_has_access_to_model(\n                api_key=api_key,\n                model_id=model_id,\n                endpoint_type=endpoint_type,\n                countinference=countinference,\n                service_secret=service_secret,\n            ):\n                raise RoboflowAPINotAuthorizedError(\n                    f\"API key {api_key} does not have access to model {model_id}\"\n                )\n\n        logger.debug(\n            f\"ModelManager - Adding model with model_id={model_id}, model_id_alias={model_id_alias}\"\n        )\n        resolved_identifier = model_id if model_id_alias is None else model_id_alias\n        model_lock = self._get_lock_for_a_model(model_id=resolved_identifier)\n        with acquire_with_timeout(lock=model_lock) as acquired:\n            if not acquired:\n                # if failed to acquire - then in use, no need to purge lock\n                raise ModelManagerLockAcquisitionError(\n                    f\"Could not acquire lock for model with id={resolved_identifier}.\"\n                )\n            if resolved_identifier in self._models:\n                logger.debug(\n                    f\"ModelManager - model with model_id={resolved_identifier} is already loaded.\"\n                )\n                return\n            try:\n                logger.debug(\"ModelManager - model initialisation...\")\n                model_class = self.model_registry.get_model(\n                    resolved_identifier,\n                    api_key,\n                    countinference=countinference,\n                    service_secret=service_secret,\n                )\n                model = model_class(\n                    model_id=model_id,\n                    api_key=api_key,\n                )\n\n                # Pass countinference and service_secret to download_model_artifacts_from_roboflow_api if available\n                if (\n                    hasattr(model, \"download_model_artifacts_from_roboflow_api\")\n                    and INTERNAL_WEIGHTS_URL_SUFFIX == \"serverless\"\n                ):\n                    # Only pass these parameters if INTERNAL_WEIGHTS_URL_SUFFIX is \"serverless\"\n                    if (\n                        hasattr(model, \"cache_model_artefacts\")\n                        and not model.has_model_metadata\n                    ):\n                        # Override the download_model_artifacts_from_roboflow_api method with parameters\n                        original_method = (\n                            model.download_model_artifacts_from_roboflow_api\n                        )\n                        model.download_model_artifacts_from_roboflow_api = (\n                            lambda: original_method(\n                                countinference=countinference,\n                                service_secret=service_secret,\n                            )\n                        )\n\n                logger.debug(\"ModelManager - model successfully loaded.\")\n                self._models[resolved_identifier] = model\n            except Exception as error:\n                self._dispose_model_lock(model_id=resolved_identifier)\n                raise error\n\n    def check_for_model(self, model_id: str) -> None:\n        \"\"\"Checks whether the model with the given ID is in the manager.\n\n        Args:\n            model_id (str): The identifier of the model.\n\n        Raises:\n            InferenceModelNotFound: If the model is not found in the manager.\n        \"\"\"\n        if model_id not in self:\n            raise InferenceModelNotFound(f\"Model with id {model_id} not loaded.\")\n\n    async def infer_from_request(\n        self, model_id: str, request: InferenceRequest, **kwargs\n    ) -> InferenceResponse:\n        \"\"\"Runs inference on the specified model with the given request.\n\n        Args:\n            model_id (str): The identifier of the model.\n            request (InferenceRequest): The request to process.\n\n        Returns:\n            InferenceResponse: The response from the inference.\n        \"\"\"\n        logger.debug(\n            f\"ModelManager - inference from request started for model_id={model_id}.\"\n        )\n        if METRICS_ENABLED and self.pingback:\n            logger.debug(\"ModelManager - setting pingback fallback api key...\")\n            self.pingback.fallback_api_key = request.api_key\n        try:\n            rtn_val = await self.model_infer(\n                model_id=model_id, request=request, **kwargs\n            )\n            logger.debug(\n                f\"ModelManager - inference from request finished for model_id={model_id}.\"\n            )\n            finish_time = time.time()\n            if not DISABLE_INFERENCE_CACHE:\n                try:\n                    logger.debug(\n                        f\"ModelManager - caching inference request started for model_id={model_id}\"\n                    )\n                    cache.zadd(\n                        f\"models\",\n                        value=f\"{GLOBAL_INFERENCE_SERVER_ID}:{request.api_key}:{model_id}\",\n                        score=finish_time,\n                        expire=METRICS_INTERVAL * 2,\n                    )\n                    if (\n                        hasattr(request, \"image\")\n                        and hasattr(request.image, \"type\")\n                        and request.image.type == \"numpy\"\n                    ):\n                        request.image.value = str(request.image.value)\n                    cache.zadd(\n                        f\"inference:{GLOBAL_INFERENCE_SERVER_ID}:{model_id}\",\n                        value=to_cachable_inference_item(request, rtn_val),\n                        score=finish_time,\n                        expire=METRICS_INTERVAL * 2,\n                    )\n                    logger.debug(\n                        f\"ModelManager - caching inference request finished for model_id={model_id}\"\n                    )\n                except Exception as cache_error:\n                    logger.warning(\n                        f\"Failed to cache inference data for model {model_id}: {cache_error}\"\n                    )\n            return rtn_val\n        except Exception as e:\n            finish_time = time.time()\n            if not DISABLE_INFERENCE_CACHE:\n                try:\n                    cache.zadd(\n                        f\"models\",\n                        value=f\"{GLOBAL_INFERENCE_SERVER_ID}:{request.api_key}:{model_id}\",\n                        score=finish_time,\n                        expire=METRICS_INTERVAL * 2,\n                    )\n                    cache.zadd(\n                        f\"error:{GLOBAL_INFERENCE_SERVER_ID}:{model_id}\",\n                        value={\n                            \"request\": jsonable_encoder(\n                                request.dict(exclude={\"image\", \"subject\", \"prompt\"})\n                            ),\n                            \"error\": str(e),\n                        },\n                        score=finish_time,\n                        expire=METRICS_INTERVAL * 2,\n                    )\n                except Exception as cache_error:\n                    logger.warning(\n                        f\"Failed to cache error data for model {model_id}: {cache_error}\"\n                    )\n            raise\n\n    def infer_from_request_sync(\n        self, model_id: str, request: InferenceRequest, **kwargs\n    ) -> InferenceResponse:\n        \"\"\"Runs inference on the specified model with the given request.\n\n        Args:\n            model_id (str): The identifier of the model.\n            request (InferenceRequest): The request to process.\n\n        Returns:\n            InferenceResponse: The response from the inference.\n        \"\"\"\n        logger.debug(\n            f\"ModelManager - inference from request started for model_id={model_id}.\"\n        )\n        if METRICS_ENABLED and self.pingback:\n            logger.debug(\"ModelManager - setting pingback fallback api key...\")\n            self.pingback.fallback_api_key = request.api_key\n        try:\n            rtn_val = self.model_infer_sync(\n                model_id=model_id, request=request, **kwargs\n            )\n            logger.debug(\n                f\"ModelManager - inference from request finished for model_id={model_id}.\"\n            )\n            finish_time = time.time()\n            if not DISABLE_INFERENCE_CACHE:\n                try:\n                    logger.debug(\n                        f\"ModelManager - caching inference request started for model_id={model_id}\"\n                    )\n                    cache.zadd(\n                        f\"models\",\n                        value=f\"{GLOBAL_INFERENCE_SERVER_ID}:{request.api_key}:{model_id}\",\n                        score=finish_time,\n                        expire=METRICS_INTERVAL * 2,\n                    )\n                    if (\n                        hasattr(request, \"image\")\n                        and hasattr(request.image, \"type\")\n                        and request.image.type == \"numpy\"\n                    ):\n                        request.image.value = str(request.image.value)\n                    cache.zadd(\n                        f\"inference:{GLOBAL_INFERENCE_SERVER_ID}:{model_id}\",\n                        value=to_cachable_inference_item(request, rtn_val),\n                        score=finish_time,\n                        expire=METRICS_INTERVAL * 2,\n                    )\n                    logger.debug(\n                        f\"ModelManager - caching inference request finished for model_id={model_id}\"\n                    )\n                except Exception as cache_error:\n                    logger.warning(\n                        f\"Failed to cache inference data for model {model_id}: {cache_error}\"\n                    )\n            return rtn_val\n        except Exception as e:\n            finish_time = time.time()\n            if not DISABLE_INFERENCE_CACHE:\n                try:\n                    cache.zadd(\n                        f\"models\",\n                        value=f\"{GLOBAL_INFERENCE_SERVER_ID}:{request.api_key}:{model_id}\",\n                        score=finish_time,\n                        expire=METRICS_INTERVAL * 2,\n                    )\n                    cache.zadd(\n                        f\"error:{GLOBAL_INFERENCE_SERVER_ID}:{model_id}\",\n                        value={\n                            \"request\": jsonable_encoder(\n                                request.dict(exclude={\"image\", \"subject\", \"prompt\"})\n                            ),\n                            \"error\": str(e),\n                        },\n                        score=finish_time,\n                        expire=METRICS_INTERVAL * 2,\n                    )\n                except Exception as cache_error:\n                    logger.warning(\n                        f\"Failed to cache error data for model {model_id}: {cache_error}\"\n                    )\n            raise\n\n    async def model_infer(self, model_id: str, request: InferenceRequest, **kwargs):\n        self.check_for_model(model_id)\n        return self._models[model_id].infer_from_request(request)\n\n    def model_infer_sync(\n        self, model_id: str, request: InferenceRequest, **kwargs\n    ) -> Union[List[InferenceResponse], InferenceResponse]:\n        self.check_for_model(model_id)\n        return self._models[model_id].infer_from_request(request)\n\n    def make_response(\n        self, model_id: str, predictions: List[List[float]], *args, **kwargs\n    ) -> InferenceResponse:\n        \"\"\"Creates a response object from the model's predictions.\n\n        Args:\n            model_id (str): The identifier of the model.\n            predictions (List[List[float]]): The model's predictions.\n\n        Returns:\n            InferenceResponse: The created response object.\n        \"\"\"\n        self.check_for_model(model_id)\n        return self._models[model_id].make_response(predictions, *args, **kwargs)\n\n    def postprocess(\n        self,\n        model_id: str,\n        predictions: Tuple[np.ndarray, ...],\n        preprocess_return_metadata: PreprocessReturnMetadata,\n        *args,\n        **kwargs,\n    ) -> List[List[float]]:\n        \"\"\"Processes the model's predictions after inference.\n\n        Args:\n            model_id (str): The identifier of the model.\n            predictions (np.ndarray): The model's predictions.\n\n        Returns:\n            List[List[float]]: The post-processed predictions.\n        \"\"\"\n        self.check_for_model(model_id)\n        return self._models[model_id].postprocess(\n            predictions, preprocess_return_metadata, *args, **kwargs\n        )\n\n    def predict(self, model_id: str, *args, **kwargs) -> Tuple[np.ndarray, ...]:\n        \"\"\"Runs prediction on the specified model.\n\n        Args:\n            model_id (str): The identifier of the model.\n\n        Returns:\n            np.ndarray: The predictions from the model.\n        \"\"\"\n        self.check_for_model(model_id)\n        self._models[model_id].metrics[\"num_inferences\"] += 1\n        tic = time.perf_counter()\n        res = self._models[model_id].predict(*args, **kwargs)\n        toc = time.perf_counter()\n        self._models[model_id].metrics[\"avg_inference_time\"] += toc - tic\n        return res\n\n    def preprocess(\n        self, model_id: str, request: InferenceRequest\n    ) -> Tuple[np.ndarray, PreprocessReturnMetadata]:\n        \"\"\"Preprocesses the request before inference.\n\n        Args:\n            model_id (str): The identifier of the model.\n            request (InferenceRequest): The request to preprocess.\n\n        Returns:\n            Tuple[np.ndarray, List[Tuple[int, int]]]: The preprocessed data.\n        \"\"\"\n        self.check_for_model(model_id)\n        return self._models[model_id].preprocess(**request.dict())\n\n    def get_class_names(self, model_id):\n        \"\"\"Retrieves the class names for a given model.\n\n        Args:\n            model_id (str): The identifier of the model.\n\n        Returns:\n            List[str]: The class names of the model.\n        \"\"\"\n        self.check_for_model(model_id)\n        return self._models[model_id].class_names\n\n    def get_task_type(self, model_id: str, api_key: str = None) -> str:\n        \"\"\"Retrieves the task type for a given model.\n\n        Args:\n            model_id (str): The identifier of the model.\n\n        Returns:\n            str: The task type of the model.\n        \"\"\"\n        self.check_for_model(model_id)\n        return self._models[model_id].task_type\n\n    def remove(self, model_id: str, delete_from_disk: bool = True) -> None:\n        \"\"\"Removes a model from the manager.\n\n        Args:\n            model_id (str): The identifier of the model.\n        \"\"\"\n        try:\n            logger.debug(f\"Removing model {model_id} from base model manager\")\n            model_lock = self._get_lock_for_a_model(model_id=model_id)\n            with acquire_with_timeout(lock=model_lock) as acquired:\n                if not acquired:\n                    raise ModelManagerLockAcquisitionError(\n                        f\"Could not acquire lock for model with id={model_id}.\"\n                    )\n                self.check_for_model(model_id)\n                self._models[model_id].clear_cache(delete_from_disk=delete_from_disk)\n                del self._models[model_id]\n            self._dispose_model_lock(model_id=model_id)\n        except InferenceModelNotFound:\n            logger.warning(\n                f\"Attempted to remove model with id {model_id}, but it is not loaded. Skipping...\"\n            )\n\n    def clear(self) -> None:\n        \"\"\"Removes all models from the manager.\"\"\"\n        for model_id in list(self.keys()):\n            self.remove(model_id)\n\n    def __contains__(self, model_id: str) -> bool:\n        \"\"\"Checks if the model is contained in the manager.\n\n        Args:\n            model_id (str): The identifier of the model.\n\n        Returns:\n            bool: Whether the model is in the manager.\n        \"\"\"\n        return model_id in self._models\n\n    def __getitem__(self, key: str) -> Model:\n        \"\"\"Retrieve a model from the manager by key.\n\n        Args:\n            key (str): The identifier of the model.\n\n        Returns:\n            Model: The model corresponding to the key.\n        \"\"\"\n        self.check_for_model(model_id=key)\n        return self._models[key]\n\n    def __len__(self) -> int:\n        \"\"\"Retrieve the number of models in the manager.\n\n        Returns:\n            int: The number of models in the manager.\n        \"\"\"\n        return len(self._models)\n\n    def keys(self):\n        \"\"\"Retrieve the keys (model identifiers) from the manager.\n\n        Returns:\n            List[str]: The keys of the models in the manager.\n        \"\"\"\n        return self._models.keys()\n\n    def models(self) -> Dict[str, Model]:\n        \"\"\"Retrieve the models dictionary from the manager.\n\n        Returns:\n            Dict[str, Model]: The keys of the models in the manager.\n        \"\"\"\n        return self._models\n\n    def describe_models(self) -> List[ModelDescription]:\n        return [\n            ModelDescription(\n                model_id=model_id,\n                task_type=model.task_type,\n                batch_size=getattr(model, \"batch_size\", None),\n                input_width=getattr(model, \"img_size_w\", None),\n                input_height=getattr(model, \"img_size_h\", None),\n            )\n            for model_id, model in self._models.items()\n        ]\n\n    def _get_lock_for_a_model(self, model_id: str) -> Lock:\n        with acquire_with_timeout(lock=self._state_lock) as acquired:\n            if not acquired:\n                raise ModelManagerLockAcquisitionError(\n                    \"Could not acquire lock on Model Manager state to retrieve model lock.\"\n                )\n            if model_id not in self._models_state_locks:\n                self._models_state_locks[model_id] = Lock()\n            return self._models_state_locks[model_id]\n\n    def _dispose_model_lock(self, model_id: str) -> None:\n        with acquire_with_timeout(lock=self._state_lock) as acquired:\n            if not acquired:\n                raise ModelManagerLockAcquisitionError(\n                    \"Could not acquire lock on Model Manager state to dispose model lock.\"\n                )\n            if model_id not in self._models_state_locks:\n                return None\n            del self._models_state_locks[model_id]\n\n\n@contextmanager\ndef acquire_with_timeout(\n    lock: Lock, timeout: float = MODEL_LOCK_ACQUIRE_TIMEOUT\n) -> Generator[bool, None, None]:\n    acquired = lock.acquire(timeout=timeout)\n    try:\n        yield acquired\n    finally:\n        if acquired:\n            lock.release()\n",
    "patch": "diff --git a/inference/core/managers/base.py b/inference/core/managers/base.py\nindex 94aa1fc0b..2af10774f 100644\n--- a/inference/core/managers/base.py\n+++ b/inference/core/managers/base.py\n@@ -509,24 +509,31 @@ class ModelManager:\n         ]\n \n     def _get_lock_for_a_model(self, model_id: str) -> Lock:\n-        with acquire_with_timeout(lock=self._state_lock) as acquired:\n-            if not acquired:\n-                raise ModelManagerLockAcquisitionError(\n-                    \"Could not acquire lock on Model Manager state to retrieve model lock.\"\n-                )\n-            if model_id not in self._models_state_locks:\n-                self._models_state_locks[model_id] = Lock()\n-            return self._models_state_locks[model_id]\n+        # Manual lock management instead of contextlib/contextmanager overhead, for much faster hot path\n+        acquired = self._state_lock.acquire(timeout=MODEL_LOCK_ACQUIRE_TIMEOUT)\n+        if not acquired:\n+            raise ModelManagerLockAcquisitionError(\n+                \"Could not acquire lock on Model Manager state to retrieve model lock.\"\n+            )\n+        try:\n+            lock = self._models_state_locks.get(model_id)\n+            if lock is None:\n+                lock = Lock()\n+                self._models_state_locks[model_id] = lock\n+            return lock\n+        finally:\n+            self._state_lock.release()\n \n     def _dispose_model_lock(self, model_id: str) -> None:\n-        with acquire_with_timeout(lock=self._state_lock) as acquired:\n-            if not acquired:\n-                raise ModelManagerLockAcquisitionError(\n-                    \"Could not acquire lock on Model Manager state to dispose model lock.\"\n-                )\n-            if model_id not in self._models_state_locks:\n-                return None\n-            del self._models_state_locks[model_id]\n+        acquired = self._state_lock.acquire(timeout=MODEL_LOCK_ACQUIRE_TIMEOUT)\n+        if not acquired:\n+            raise ModelManagerLockAcquisitionError(\n+                \"Could not acquire lock on Model Manager state to dispose model lock.\"\n+            )\n+        try:\n+            self._models_state_locks.pop(model_id, None)\n+        finally:\n+            self._state_lock.release()\n \n \n @contextmanager\n"
  },
  {
    "trace_id": "adbc2044-ec0e-4d35-81a9-18cf19b653ea",
    "function_name": "construct_simd_step_input",
    "file_path": "inference/core/workflows/execution_engine/v1/executor/execution_data_manager/step_input_assembler.py",
    "speedup_x": 0.37,
    "review_quality": null,
    "pre_optimization_commit": "714d88cdd217d04c5d5c7235e87efbcb1837e230",
    "resolution_method": "git_parent",
    "source": "git",
    "original_function_code": "def construct_simd_step_input(\n    step_node: StepNode,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    dynamic_batches_manager: DynamicBatchesManager,\n    branching_manager: BranchingManager,\n) -> BatchModeSIMDStepInput:\n    masks, scalars_discarded = construct_mask_for_all_inputs_dimensionalities(\n        step_node=step_node,\n        branching_manager=branching_manager,\n    )\n    return prepare_parameters(\n        step_node=step_node,\n        dynamic_batches_manager=dynamic_batches_manager,\n        masks=masks,\n        scalars_discarded=scalars_discarded,\n        runtime_parameters=runtime_parameters,\n        execution_cache=execution_cache,\n    )\n",
    "optimized_function_code": "from dataclasses import dataclass\nfrom typing import Any, Dict, Generator, List, Optional, Set, Tuple, TypeVar, Union\n\nfrom inference.core.workflows.errors import AssumptionError, ExecutionEngineRuntimeError\nfrom inference.core.workflows.execution_engine.entities.base import Batch\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import (\n    AutoBatchCastingConfig,\n    CompoundStepInputDefinition,\n    DynamicStepInputDefinition,\n    StaticStepInputDefinition,\n    StepInputDefinition,\n    StepNode,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import (\n    get_last_chunk_of_selector,\n)\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.branching_manager import (\n    BranchingManager,\n)\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.dynamic_batches_manager import (\n    DynamicBatchesManager,\n    DynamicBatchIndex,\n)\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.execution_cache import (\n    ExecutionCache,\n)\n\nT = TypeVar(\"T\")\n\n\n@dataclass(frozen=True)\nclass BatchModeSIMDStepInput:\n    indices: List[DynamicBatchIndex]\n    parameters: Dict[str, Any]\n\n\n@dataclass(frozen=True)\nclass NonBatchModeSIMDStepInput:\n    index: DynamicBatchIndex\n    parameters: Dict[str, Any]\n\n\ndef construct_non_simd_step_input(\n    step_node: StepNode,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    branching_manager: BranchingManager,\n) -> Optional[Dict[str, Any]]:\n    if step_node.batch_oriented_parameters:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Attempted to get non-SIMD input for SIMD step: {step_node.name}.\"\n            f\"This is most likely a bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    masks = set()\n    for execution_branch in step_node.execution_branches_impacting_inputs:\n        if not branching_manager.is_execution_branch_registered(\n            execution_branch=execution_branch\n        ):\n            masks.add(False)\n            continue\n        if branching_manager.is_execution_branch_batch_oriented(\n            execution_branch=execution_branch\n        ):\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"For step: {step_node.name}, detected batch-oriented condition statements \"\n                f\"impacting non-SIMD step, which should be prevented by Workflows Compiler. \"\n                f\"This is most likely a bug. Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n        else:\n            mask = branching_manager.get_mask(execution_branch=execution_branch)\n            masks.add(mask)\n    if False in masks:\n        return None\n    result = {}\n    detected_empty_step_output_selector = False\n    for parameter_name, parameter_spec in step_node.input_data.items():\n        if parameter_spec.is_compound_input():\n            result[parameter_name], contains_empty_step_output_selector = (\n                construct_non_simd_step_compound_input(\n                    step_node=step_node,\n                    parameter_spec=parameter_spec,\n                    runtime_parameters=runtime_parameters,\n                    execution_cache=execution_cache,\n                )\n            )\n        else:\n            result[parameter_name], contains_empty_step_output_selector = (\n                construct_non_simd_step_non_compound_input(\n                    step_node=step_node,\n                    parameter_spec=parameter_spec,\n                    runtime_parameters=runtime_parameters,\n                    execution_cache=execution_cache,\n                )\n            )\n        detected_empty_step_output_selector = (\n            detected_empty_step_output_selector or contains_empty_step_output_selector\n        )\n    if (\n        detected_empty_step_output_selector\n        and not step_node.step_manifest.accepts_empty_values()\n    ):\n        return None\n    return result\n\n\ndef construct_non_simd_step_compound_input(\n    step_node: StepNode,\n    parameter_spec: CompoundStepInputDefinition,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> Tuple[Any, bool]:\n    if parameter_spec.represents_list_of_inputs():\n        return construct_non_simd_step_compound_list_input(\n            step_node=step_node,\n            parameter_spec=parameter_spec,\n            runtime_parameters=runtime_parameters,\n            execution_cache=execution_cache,\n        )\n    return construct_non_simd_step_compound_dict_input(\n        step_node=step_node,\n        parameter_spec=parameter_spec,\n        runtime_parameters=runtime_parameters,\n        execution_cache=execution_cache,\n    )\n\n\ndef construct_non_simd_step_compound_list_input(\n    step_node: StepNode,\n    parameter_spec: CompoundStepInputDefinition,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> Tuple[List[Any], bool]:\n    result = []\n    contains_empty_step_output_selector = False\n    for nested_definition in parameter_spec.iterate_through_definitions():\n        nested_value, value_contains_empty_selector = (\n            construct_non_simd_step_non_compound_input(\n                step_node=step_node,\n                parameter_spec=nested_definition,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n            )\n        )\n        result.append(nested_value)\n        contains_empty_step_output_selector = (\n            contains_empty_step_output_selector or value_contains_empty_selector\n        )\n    return result, contains_empty_step_output_selector\n\n\ndef construct_non_simd_step_compound_dict_input(\n    step_node: StepNode,\n    parameter_spec: CompoundStepInputDefinition,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> Tuple[Dict[str, Any], bool]:\n    result = {}\n    contains_empty_step_output_selector = False\n    for nested_definition in parameter_spec.iterate_through_definitions():\n        (\n            result[nested_definition.parameter_specification.nested_element_key],\n            value_contains_empty_selector,\n        ) = construct_non_simd_step_non_compound_input(\n            step_node=step_node,\n            parameter_spec=nested_definition,\n            runtime_parameters=runtime_parameters,\n            execution_cache=execution_cache,\n        )\n        contains_empty_step_output_selector = (\n            contains_empty_step_output_selector or value_contains_empty_selector\n        )\n    return result, contains_empty_step_output_selector\n\n\ndef construct_non_simd_step_non_compound_input(\n    step_node: StepNode,\n    parameter_spec: StepInputDefinition,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> Tuple[Any, bool]:\n    if parameter_spec.is_compound_input():\n        raise AssumptionError(\n            public_message=f\"Workflows Execution Error encountered unexpected state probably related to the fact \"\n            f\"that Workflows Compiler allowed for multi-level nesting of inputs selectors which \"\n            f\"is not supported. This is most likely the bug. Contact Roboflow team \"\n            f\"through github issues (https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if parameter_spec.is_batch_oriented():\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Encountered batch-oriented input for non-SIMD step: {step_node.name}.\"\n            f\"This is most likely a bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if parameter_spec.points_to_input():\n        parameter_spec: DynamicStepInputDefinition = parameter_spec  # type: ignore\n        input_name = get_last_chunk_of_selector(selector=parameter_spec.selector)\n        return runtime_parameters[input_name], False\n    if parameter_spec.points_to_step_output():\n        parameter_spec: DynamicStepInputDefinition = parameter_spec  # type: ignore\n        step_output = execution_cache.get_non_batch_output(\n            selector=parameter_spec.selector\n        )\n        return step_output, step_output is None\n    parameter_spec: StaticStepInputDefinition = parameter_spec  # type: ignore\n    return parameter_spec.value, False\n\n\ndef iterate_over_simd_step_input(\n    step_node: StepNode,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    dynamic_batches_manager: DynamicBatchesManager,\n    branching_manager: BranchingManager,\n) -> Generator[NonBatchModeSIMDStepInput, None, None]:\n    simd_step_input = construct_simd_step_input(\n        step_node=step_node,\n        runtime_parameters=runtime_parameters,\n        execution_cache=execution_cache,\n        dynamic_batches_manager=dynamic_batches_manager,\n        branching_manager=branching_manager,\n    )\n    parameters_generator = unfold_parameters(parameters=simd_step_input.parameters)\n    for index, single_parameters_set in zip(\n        simd_step_input.indices, parameters_generator\n    ):\n        yield NonBatchModeSIMDStepInput(\n            index=index,\n            parameters=single_parameters_set,\n        )\n\n\ndef construct_simd_step_input(\n    step_node: StepNode,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    dynamic_batches_manager: DynamicBatchesManager,\n    branching_manager: BranchingManager,\n) -> BatchModeSIMDStepInput:\n    masks, scalars_discarded = construct_mask_for_all_inputs_dimensionalities(\n        step_node=step_node,\n        branching_manager=branching_manager,\n    )\n    return prepare_parameters(\n        step_node=step_node,\n        dynamic_batches_manager=dynamic_batches_manager,\n        masks=masks,\n        scalars_discarded=scalars_discarded,\n        runtime_parameters=runtime_parameters,\n        execution_cache=execution_cache,\n    )\n\n\ndef construct_mask_for_all_inputs_dimensionalities(\n    step_node: StepNode,\n    branching_manager: BranchingManager,\n) -> Tuple[Any, bool]:\n    inputs_dimensionalities = collect_inputs_dimensionalities(step_node=step_node)\n    all_dimensionalities = {dim for dim in inputs_dimensionalities.values() if dim > 0}\n    batch_masks, non_batch_masks = [], set()\n    for execution_branch in step_node.execution_branches_impacting_inputs:\n        if not branching_manager.is_execution_branch_registered(\n            execution_branch=execution_branch\n        ):\n            non_batch_masks.add(False)\n            continue\n        if branching_manager.is_execution_branch_batch_oriented(\n            execution_branch=execution_branch\n        ):\n            mask = branching_manager.get_mask(execution_branch=execution_branch)\n            batch_masks.append(mask)\n        else:\n            mask = branching_manager.get_mask(execution_branch=execution_branch)\n            non_batch_masks.add(mask)\n    scalar_mask_contains_false = False in non_batch_masks\n    if scalar_mask_contains_false:\n        return {\n            dimension: set() for dimension in all_dimensionalities\n        }, scalar_mask_contains_false\n    return {\n        dimension: get_masks_intersection_up_to_dimension(\n            batch_masks=batch_masks,\n            dimension=dimension,\n        )\n        for dimension in all_dimensionalities\n    }, scalar_mask_contains_false\n\n\ndef collect_inputs_dimensionalities(\n    step_node: StepNode,\n) -> Dict[str, int]:\n    result = {}\n    for parameter_name, parameter_specs in step_node.input_data.items():\n        if parameter_specs.is_compound_input():\n            dimensionalities = [\n                nested_definition.get_dimensionality()\n                for nested_definition in parameter_specs.iterate_through_definitions()\n            ]\n            # to help for empty values\n            dimensionalities.append(0)\n            result[parameter_name] = max(dimensionalities)\n        else:\n            result[parameter_name] = parameter_specs.get_dimensionality()\n    return result\n\n\ndef get_masks_intersection_up_to_dimension(\n    batch_masks: List[Set[DynamicBatchIndex]],\n    dimension: int,\n) -> Optional[Set[DynamicBatchIndex]]:\n    if not batch_masks:\n        return None\n\n    # Initialize intersection with the first batch mask transformed up to the given dimension\n    intersection = {mask_element[:dimension] for mask_element in batch_masks[0]}\n\n    # Perform the intersection with the transformed sets of subsequent batch masks\n    for batch_mask in batch_masks[1:]:\n        intersection &= {mask_element[:dimension] for mask_element in batch_mask}\n\n        # Early exit if intersection becomes empty\n        if not intersection:\n            return set()\n\n    return intersection\n\n\nclass GuardForIndicesWrapping:\n\n    def __init__(self):\n        self._registered_wrapping: Optional[List[DynamicBatchIndex]] = None\n\n    def register_wrapping(\n        self, indices_before_wrapping: List[DynamicBatchIndex]\n    ) -> None:\n        if self._registered_wrapping is None:\n            self._registered_wrapping = indices_before_wrapping\n        elif self._registered_wrapping != indices_before_wrapping:\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Detected a situation when step requires dimensionality wrapping, but\"\n                f\"different inputs register different elements indices to wrap which is illegal \"\n                f\"and should be detected earlier by Workflows compiler. This is most likely a bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n\n\ndef prepare_parameters(\n    step_node: StepNode,\n    dynamic_batches_manager: DynamicBatchesManager,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> BatchModeSIMDStepInput:\n    step_requests_batch_input = step_node.step_manifest.accepts_batch_input()\n    result = {}\n    indices_for_parameter = {}\n    guard_of_indices_wrapping = GuardForIndicesWrapping()\n    compound_inputs = set()\n    contains_empty_scalar_step_output_selector = False\n    for parameter_name, parameter_specs in step_node.input_data.items():\n        if parameter_specs.is_compound_input():\n            (\n                result[parameter_name],\n                indices_for_parameter[parameter_name],\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_compound_parameter_value(\n                parameter=parameter_specs,\n                step_execution_dimensionality=step_node.step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=step_node.auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n            compound_inputs.add(parameter_name)\n        else:\n            (\n                result[parameter_name],\n                indices_for_parameter[parameter_name],\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=parameter_specs,\n                step_execution_dimensionality=step_node.step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=step_node.auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n        contains_empty_scalar_step_output_selector = (\n            contains_empty_scalar_step_output_selector\n            or value_contains_empty_scalar_step_output_selector\n        )\n    batch_parameters_indices = [\n        i for i in indices_for_parameter.values() if i is not None\n    ]\n    ensure_compound_input_indices_match(indices=batch_parameters_indices)\n    if not batch_parameters_indices:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"For step: {step_node.name} which is assessed by Workflows Compiler as \"\n            f\"SIMD step Execution Engine cannot detect batch inputs. \"\n            f\"This is most likely a bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    indices = batch_parameters_indices[0]\n    if not step_node.step_manifest.accepts_empty_values():\n        if contains_empty_scalar_step_output_selector:\n            return BatchModeSIMDStepInput(\n                indices=[],\n                parameters={},\n            )\n        empty_indices = get_empty_batch_elements_indices(value=result)\n        if empty_indices:\n            indices = [e for e in indices if e not in empty_indices]\n            result = remove_indices(value=result, indices=empty_indices)\n    return BatchModeSIMDStepInput(\n        indices=indices,\n        parameters=result,\n    )\n\n\ndef get_compound_parameter_value(\n    parameter: CompoundStepInputDefinition,\n    step_execution_dimensionality: int,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n    dynamic_batches_manager: DynamicBatchesManager,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n    auto_batch_casting_lineage_supports: Dict[str, AutoBatchCastingConfig],\n    step_requests_batch_input: bool,\n) -> Tuple[Union[list, Dict[str, Any]], Optional[List[DynamicBatchIndex]], bool]:\n    contains_empty_scalar_step_output_selector = False\n    batch_indices = []\n    if parameter.represents_list_of_inputs():\n        result = []\n        for nested_element in parameter.iterate_through_definitions():\n            (\n                non_compound_parameter_value,\n                non_compound_indices,\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=nested_element,\n                step_execution_dimensionality=step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n            result.append(non_compound_parameter_value)\n            contains_empty_scalar_step_output_selector = (\n                contains_empty_scalar_step_output_selector\n                or value_contains_empty_scalar_step_output_selector\n            )\n            if non_compound_indices is not None:\n                batch_indices.append(non_compound_indices)\n    else:\n        result = {}\n        for nested_element in parameter.iterate_through_definitions():\n            (\n                non_compound_parameter_value,\n                non_compound_indices,\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=nested_element,\n                step_execution_dimensionality=step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n            result[nested_element.parameter_specification.nested_element_key] = (\n                non_compound_parameter_value\n            )\n            contains_empty_scalar_step_output_selector = (\n                contains_empty_scalar_step_output_selector\n                or value_contains_empty_scalar_step_output_selector\n            )\n            if non_compound_indices is not None:\n                batch_indices.append(non_compound_indices)\n    ensure_compound_input_indices_match(indices=batch_indices)\n    result_indices = None\n    if len(batch_indices) > 0:\n        result_indices = batch_indices[0]\n    return result, result_indices, contains_empty_scalar_step_output_selector\n\n\ndef get_non_compound_parameter_value(\n    parameter: StepInputDefinition,\n    step_execution_dimensionality: int,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n    dynamic_batches_manager: DynamicBatchesManager,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n    auto_batch_casting_lineage_supports: Dict[str, AutoBatchCastingConfig],\n    step_requests_batch_input: bool,\n) -> Tuple[Any, Optional[List[DynamicBatchIndex]], bool]:\n    if not parameter.is_batch_oriented():\n        requested_as_batch = (\n            parameter.parameter_specification.parameter_name\n            in auto_batch_casting_lineage_supports\n        )\n        if parameter.points_to_input():\n            input_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n            parameter_name = get_last_chunk_of_selector(\n                selector=input_parameter.selector\n            )\n            if not requested_as_batch:\n                return runtime_parameters[parameter_name], None, False\n            else:\n                return apply_auto_batch_casting(\n                    parameter_name=parameter_name,\n                    value=runtime_parameters[parameter_name],\n                    auto_batch_casting_config=auto_batch_casting_lineage_supports[\n                        parameter.parameter_specification.parameter_name\n                    ],\n                    contains_empty_scalar_step_output_selector=False,\n                    dynamic_batches_manager=dynamic_batches_manager,\n                    step_execution_dimensionality=step_execution_dimensionality,\n                    guard_of_indices_wrapping=guard_of_indices_wrapping,\n                    step_requests_batch_input=step_requests_batch_input,\n                    masks=masks,\n                    scalars_discarded=False,\n                )\n        elif parameter.points_to_step_output():\n            input_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n            value = execution_cache.get_non_batch_output(\n                selector=input_parameter.selector\n            )\n            if not requested_as_batch:\n                return value, None, value is None\n            else:\n                return apply_auto_batch_casting(\n                    parameter_name=parameter.parameter_specification.parameter_name,\n                    value=value,\n                    auto_batch_casting_config=auto_batch_casting_lineage_supports[\n                        parameter.parameter_specification.parameter_name\n                    ],\n                    contains_empty_scalar_step_output_selector=value is None,\n                    dynamic_batches_manager=dynamic_batches_manager,\n                    step_execution_dimensionality=step_execution_dimensionality,\n                    guard_of_indices_wrapping=guard_of_indices_wrapping,\n                    step_requests_batch_input=step_requests_batch_input,\n                    masks=masks,\n                    scalars_discarded=scalars_discarded,\n                )\n        else:\n            static_input: StaticStepInputDefinition = parameter  # type: ignore\n            return static_input.value, None, False\n    dynamic_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n    parameter_dimensionality = dynamic_parameter.get_dimensionality()\n    lineage_indices = dynamic_batches_manager.get_indices_for_data_lineage(\n        lineage=dynamic_parameter.data_lineage,\n    )\n    mask_for_dimension = masks[parameter_dimensionality]\n    if dynamic_parameter.points_to_input():\n        input_name = get_last_chunk_of_selector(selector=dynamic_parameter.selector)\n        batch_input = _flatten_batch_oriented_inputs(\n            runtime_parameters[input_name],\n            dimensionality=parameter_dimensionality,\n        )\n        if mask_for_dimension is not None:\n            if len(lineage_indices) != len(batch_input):\n                raise ExecutionEngineRuntimeError(\n                    public_message=f\"Detected a situation when input parameter: \"\n                    f\"{input_name}\"\n                    f\"size is mismatched compared to mask requested for that input. \"\n                    f\"Input length: {len(batch_input)}, mask size: {len(lineage_indices)}. \"\n                    f\"This is most likely a bug. \"\n                    f\"Contact Roboflow team through github issues \"\n                    f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                    f\"the problem - including workflow definition you use.\",\n                    context=\"workflow_execution | step_input_assembling\",\n                )\n            batch_input = [\n                input_element if element_index in mask_for_dimension else None\n                for element_index, input_element in zip(lineage_indices, batch_input)\n            ]\n    else:\n        batch_input = execution_cache.get_batch_output(\n            selector=dynamic_parameter.selector,\n            batch_elements_indices=lineage_indices,\n            mask=mask_for_dimension,\n        )\n    if step_execution_dimensionality == parameter_dimensionality:\n        return Batch(batch_input, lineage_indices), lineage_indices, False\n    if step_execution_dimensionality > parameter_dimensionality:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter.parameter_specification.parameter_name}\"\n            f\"has a dimensionality {parameter_dimensionality} larger \"\n            f\"than step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if abs(parameter_dimensionality - step_execution_dimensionality) > 1:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter.parameter_specification.parameter_name}\"\n            f\"has a dimensionality {parameter_dimensionality} differing more than one level \"\n            f\"from step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if step_execution_dimensionality == 0 and not step_requests_batch_input:\n        return Batch(batch_input, lineage_indices), lineage_indices, False\n    upper_lineage = dynamic_parameter.data_lineage[:-1]\n    if len(upper_lineage) == 0:\n        if not step_requests_batch_input:\n            raise AssumptionError(\n                public_message=f\"Parameter: {parameter.parameter_specification.parameter_name} \"\n                f\"requires dimensionality wrapping, but registered lineage support is incompatible \"\n                f\"which should be detected by the compiler. This is most likely a bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n        upper_level_indices = [()]\n    else:\n        upper_level_indices = dynamic_batches_manager.get_indices_for_data_lineage(\n            lineage=dynamic_parameter.data_lineage[:-1],\n        )\n    result = reduce_batch_dimensionality(\n        indices=lineage_indices,\n        upper_level_index=upper_level_indices,\n        data=batch_input,\n        guard_of_indices_wrapping=guard_of_indices_wrapping,\n    )\n    return result, result.indices, False\n\n\ndef apply_auto_batch_casting(\n    parameter_name: str,\n    value: Any,\n    auto_batch_casting_config: AutoBatchCastingConfig,\n    contains_empty_scalar_step_output_selector: bool,\n    dynamic_batches_manager: DynamicBatchesManager,\n    step_execution_dimensionality: int,\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n    step_requests_batch_input: bool,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n) -> Tuple[Any, List[DynamicBatchIndex], bool]:\n    if auto_batch_casting_config.lineage_support is None:\n        indices = [(0,) * auto_batch_casting_config.casted_dimensionality]\n    else:\n        indices = dynamic_batches_manager.get_indices_for_data_lineage(\n            lineage=auto_batch_casting_config.lineage_support,\n        )\n        missing_dimensions = auto_batch_casting_config.casted_dimensionality - len(\n            auto_batch_casting_config.lineage_support\n        )\n        if missing_dimensions > 0:\n            padding = (0,) * missing_dimensions\n            indices = [i + padding for i in indices]\n    if scalars_discarded:\n        batch_content = [None] * len(indices)\n    elif auto_batch_casting_config.lineage_support is None:\n        batch_content = [value] * len(indices)\n    else:\n        support_dimensionality = len(auto_batch_casting_config.lineage_support)\n        mask_for_support_dimensionality = masks[support_dimensionality]\n        if mask_for_support_dimensionality is None:\n            batch_content = [value] * len(indices)\n        else:\n            batch_content = []\n            for index in indices:\n                if index[:support_dimensionality] in mask_for_support_dimensionality:\n                    batch_content.append(value)\n                else:\n                    batch_content.append(None)\n    created_batch = Batch(content=batch_content, indices=indices)\n    if step_execution_dimensionality == auto_batch_casting_config.casted_dimensionality:\n        return (\n            created_batch,\n            indices,\n            contains_empty_scalar_step_output_selector or scalars_discarded,\n        )\n    if step_execution_dimensionality > auto_batch_casting_config.casted_dimensionality:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter_name}\"\n            f\"has auto-batch casted dimensionality {auto_batch_casting_config.casted_dimensionality} larger \"\n            f\"than step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if (\n        abs(\n            auto_batch_casting_config.casted_dimensionality\n            - step_execution_dimensionality\n        )\n        > 1\n    ):\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter_name} has auto batch casted \"\n            f\"dimensionality {auto_batch_casting_config.casted_dimensionality} differing more than one level \"\n            f\"from step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    upper_level_lineage_dimensionality = (\n        auto_batch_casting_config.casted_dimensionality - 1\n    )\n    if upper_level_lineage_dimensionality == 0 and not step_requests_batch_input:\n        # for batch collapse into scalar\n        return (\n            created_batch,\n            indices,\n            contains_empty_scalar_step_output_selector or scalars_discarded,\n        )\n    if auto_batch_casting_config.lineage_support is None:\n        upper_level_indices = [indices[0][:-1]]\n    else:\n        upper_level_lineage = auto_batch_casting_config.lineage_support[\n            :upper_level_lineage_dimensionality\n        ]\n        if (\n            upper_level_lineage_dimensionality < 1\n            or len(upper_level_lineage) < upper_level_lineage_dimensionality\n        ):\n            if not step_requests_batch_input:\n                raise AssumptionError(\n                    public_message=f\"Detected a situation when parameter: {parameter_name} requires dimensionality \"\n                    f\"wrapping, but registered lineage support is incompatible which should be detected \"\n                    f\"by the compiler. This is most likely a bug. \"\n                    f\"Contact Roboflow team through github issues \"\n                    f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                    f\"the problem - including workflow definition you use.\",\n                    context=\"workflow_execution | step_input_assembling\",\n                )\n            upper_level_indices = [()]\n        else:\n            upper_level_indices = dynamic_batches_manager.get_indices_for_data_lineage(\n                lineage=upper_level_lineage,\n            )\n    result = reduce_batch_dimensionality(\n        indices=indices,\n        upper_level_index=upper_level_indices,\n        data=batch_content,\n        guard_of_indices_wrapping=guard_of_indices_wrapping,\n    )\n    return (\n        result,\n        result.indices,\n        contains_empty_scalar_step_output_selector or scalars_discarded,\n    )\n\n\ndef _flatten_batch_oriented_inputs(\n    inputs: list,\n    dimensionality: int,\n) -> List[Any]:\n    if dimensionality == 0 or not isinstance(inputs, list):\n        raise AssumptionError(\n            public_message=f\"Could not prepare batch-oriented input data. This is most likely the bug. Contact \"\n            f\"Roboflow team through github issues (https://github.com/roboflow/inference/issues) \"\n            f\"providing full context of the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if dimensionality == 1:\n        return inputs\n    result = []\n    for element in inputs:\n        result.extend(\n            _flatten_batch_oriented_inputs(\n                inputs=element, dimensionality=dimensionality - 1\n            )\n        )\n    return result\n\n\ndef reduce_batch_dimensionality(\n    indices: List[DynamicBatchIndex],\n    upper_level_index: List[DynamicBatchIndex],\n    data: List[T],\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n) -> Batch[Optional[Batch[T]]]:\n    guard_of_indices_wrapping.register_wrapping(indices_before_wrapping=indices)\n    already_spotted_downgraded_indices = set()\n    wrapped_batch_index, wrapped_batch_content = [], []\n    upper_level_indices_data = {index: None for index in upper_level_index}\n    for index, data in zip(indices, data):\n        downgraded_index = index[:-1]\n        if downgraded_index in already_spotted_downgraded_indices:\n            wrapped_batch_index.append(index)\n            wrapped_batch_content.append(data)\n        else:\n            if wrapped_batch_index:\n                upper_level_indices_data[wrapped_batch_index[-1][:-1]] = Batch(\n                    content=wrapped_batch_content, indices=wrapped_batch_index\n                )\n            already_spotted_downgraded_indices.add(downgraded_index)\n            wrapped_batch_index = [index]\n            wrapped_batch_content = [data]\n    if wrapped_batch_index:\n        upper_level_indices_data[wrapped_batch_index[-1][:-1]] = Batch(\n            content=wrapped_batch_content, indices=wrapped_batch_index\n        )\n    return Batch(\n        content=[upper_level_indices_data[index] for index in upper_level_index],\n        indices=upper_level_index,\n    )\n\n\ndef ensure_compound_input_indices_match(indices: List[List[DynamicBatchIndex]]) -> None:\n    if len(indices) < 2:\n        return None\n    reference_set = set(indices[0])\n    for index in indices[1:]:\n        other_set = set(index)\n        if reference_set != other_set:\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Detected a situation when step input parameters cannot be created \"\n                f\"due to missmatch in batch element indices. This is most likely a bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n\n\ndef get_empty_batch_elements_indices(value: Any) -> Set[DynamicBatchIndex]:\n    result = set()\n    if isinstance(value, dict):\n        for v in value.values():\n            value_result = get_empty_batch_elements_indices(v)\n            result = result.union(value_result)\n    if isinstance(value, list):\n        for v in value:\n            value_result = get_empty_batch_elements_indices(v)\n            result = result.union(value_result)\n    if isinstance(value, Batch):\n        for index, value_element in value.iter_with_indices():\n            if isinstance(value_element, Batch):\n                value_result = get_empty_batch_elements_indices(value=value_element)\n                result = result.union(value_result)\n            elif value_element is None:\n                result.add(index)\n    return result\n\n\ndef remove_indices(value: Any, indices: Set[DynamicBatchIndex]) -> Any:\n    if isinstance(value, dict):\n        return {k: remove_indices(value=v, indices=indices) for k, v in value.items()}\n    if isinstance(value, list):\n        return [remove_indices(value=v, indices=indices) for v in value]\n    if isinstance(value, Batch):\n        return value.remove_by_indices(indices_to_remove=indices)\n    return value\n\n\ndef unfold_parameters(\n    parameters: Dict[str, Any],\n) -> Generator[Dict[str, Any], None, None]:\n    batch_parameters = get_batch_parameters(parameters=parameters)\n    non_batch_parameters = {\n        k: v for k, v in parameters.items() if k not in batch_parameters\n    }\n    if not batch_parameters:\n        if not non_batch_parameters:\n            return None\n        yield non_batch_parameters\n        return None\n    for unfolded_batch_parameters in iterate_over_batches(\n        batch_parameters=batch_parameters\n    ):\n        yield {**unfolded_batch_parameters, **non_batch_parameters}\n\n\ndef get_batch_parameters(parameters: Dict[str, Any]) -> Dict[str, Any]:\n    result = {}\n    for name, value in parameters.items():\n        if isinstance(value, Batch):\n            result[name] = value\n        elif isinstance(value, list) and any(isinstance(v, Batch) for v in value):\n            result[name] = value\n        elif isinstance(value, dict) and any(\n            isinstance(v, Batch) for v in value.values()\n        ):\n            result[name] = value\n    return result\n\n\ndef iterate_over_batches(\n    batch_parameters: Dict[str, Any],\n) -> Generator[Dict[str, Any], None, None]:\n    index = 0\n    end = False\n    while not end:\n        result = {}\n        for name, value in batch_parameters.items():\n            if isinstance(value, Batch):\n                if len(value) <= index:\n                    end = True\n                    break\n                result[name] = value[index]\n            elif isinstance(value, list):\n                to_yield = []\n                for element in value:\n                    if isinstance(element, Batch):\n                        if len(element) <= index:\n                            end = True\n                            break\n                        to_yield.append(element[index])\n                    else:\n                        to_yield.append(element)\n                result[name] = to_yield\n            elif isinstance(value, dict):\n                to_yield = {}\n                for key, key_value in value.items():\n                    if not isinstance(key_value, Batch):\n                        to_yield[key] = key_value\n                    else:\n                        if len(key_value) <= index:\n                            end = True\n                            break\n                        else:\n                            to_yield[key] = key_value[index]\n                result[name] = to_yield\n        index += 1\n        if not end:\n            yield result\n",
    "optimized_raw_markdown": "",
    "optimized_function_only": "def construct_simd_step_input(\n    step_node: StepNode,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    dynamic_batches_manager: DynamicBatchesManager,\n    branching_manager: BranchingManager,\n) -> BatchModeSIMDStepInput:\n    masks, scalars_discarded = construct_mask_for_all_inputs_dimensionalities(\n        step_node=step_node,\n        branching_manager=branching_manager,\n    )\n    return prepare_parameters(\n        step_node=step_node,\n        dynamic_batches_manager=dynamic_batches_manager,\n        masks=masks,\n        scalars_discarded=scalars_discarded,\n        runtime_parameters=runtime_parameters,\n        execution_cache=execution_cache,\n    )\n",
    "original_file_content": "from dataclasses import dataclass\nfrom typing import Any, Dict, Generator, List, Optional, Set, Tuple, TypeVar, Union\n\nfrom inference.core.workflows.errors import AssumptionError, ExecutionEngineRuntimeError\nfrom inference.core.workflows.execution_engine.entities.base import Batch\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import (\n    AutoBatchCastingConfig,\n    CompoundStepInputDefinition,\n    DynamicStepInputDefinition,\n    StaticStepInputDefinition,\n    StepInputDefinition,\n    StepNode,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import (\n    get_last_chunk_of_selector,\n)\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.branching_manager import (\n    BranchingManager,\n)\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.dynamic_batches_manager import (\n    DynamicBatchesManager,\n    DynamicBatchIndex,\n)\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.execution_cache import (\n    ExecutionCache,\n)\n\nT = TypeVar(\"T\")\n\n\n@dataclass(frozen=True)\nclass BatchModeSIMDStepInput:\n    indices: List[DynamicBatchIndex]\n    parameters: Dict[str, Any]\n\n\n@dataclass(frozen=True)\nclass NonBatchModeSIMDStepInput:\n    index: DynamicBatchIndex\n    parameters: Dict[str, Any]\n\n\ndef construct_non_simd_step_input(\n    step_node: StepNode,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    branching_manager: BranchingManager,\n) -> Optional[Dict[str, Any]]:\n    if step_node.batch_oriented_parameters:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Attempted to get non-SIMD input for SIMD step: {step_node.name}.\"\n            f\"This is most likely a bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    masks = set()\n    for execution_branch in step_node.execution_branches_impacting_inputs:\n        if not branching_manager.is_execution_branch_registered(\n            execution_branch=execution_branch\n        ):\n            masks.add(False)\n            continue\n        if branching_manager.is_execution_branch_batch_oriented(\n            execution_branch=execution_branch\n        ):\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"For step: {step_node.name}, detected batch-oriented condition statements \"\n                f\"impacting non-SIMD step, which should be prevented by Workflows Compiler. \"\n                f\"This is most likely a bug. Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n        else:\n            mask = branching_manager.get_mask(execution_branch=execution_branch)\n            masks.add(mask)\n    if False in masks:\n        return None\n    result = {}\n    detected_empty_step_output_selector = False\n    for parameter_name, parameter_spec in step_node.input_data.items():\n        if parameter_spec.is_compound_input():\n            result[parameter_name], contains_empty_step_output_selector = (\n                construct_non_simd_step_compound_input(\n                    step_node=step_node,\n                    parameter_spec=parameter_spec,\n                    runtime_parameters=runtime_parameters,\n                    execution_cache=execution_cache,\n                )\n            )\n        else:\n            result[parameter_name], contains_empty_step_output_selector = (\n                construct_non_simd_step_non_compound_input(\n                    step_node=step_node,\n                    parameter_spec=parameter_spec,\n                    runtime_parameters=runtime_parameters,\n                    execution_cache=execution_cache,\n                )\n            )\n        detected_empty_step_output_selector = (\n            detected_empty_step_output_selector or contains_empty_step_output_selector\n        )\n    if (\n        detected_empty_step_output_selector\n        and not step_node.step_manifest.accepts_empty_values()\n    ):\n        return None\n    return result\n\n\ndef construct_non_simd_step_compound_input(\n    step_node: StepNode,\n    parameter_spec: CompoundStepInputDefinition,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> Tuple[Any, bool]:\n    if parameter_spec.represents_list_of_inputs():\n        return construct_non_simd_step_compound_list_input(\n            step_node=step_node,\n            parameter_spec=parameter_spec,\n            runtime_parameters=runtime_parameters,\n            execution_cache=execution_cache,\n        )\n    return construct_non_simd_step_compound_dict_input(\n        step_node=step_node,\n        parameter_spec=parameter_spec,\n        runtime_parameters=runtime_parameters,\n        execution_cache=execution_cache,\n    )\n\n\ndef construct_non_simd_step_compound_list_input(\n    step_node: StepNode,\n    parameter_spec: CompoundStepInputDefinition,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> Tuple[List[Any], bool]:\n    result = []\n    contains_empty_step_output_selector = False\n    for nested_definition in parameter_spec.iterate_through_definitions():\n        nested_value, value_contains_empty_selector = (\n            construct_non_simd_step_non_compound_input(\n                step_node=step_node,\n                parameter_spec=nested_definition,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n            )\n        )\n        result.append(nested_value)\n        contains_empty_step_output_selector = (\n            contains_empty_step_output_selector or value_contains_empty_selector\n        )\n    return result, contains_empty_step_output_selector\n\n\ndef construct_non_simd_step_compound_dict_input(\n    step_node: StepNode,\n    parameter_spec: CompoundStepInputDefinition,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> Tuple[Dict[str, Any], bool]:\n    result = {}\n    contains_empty_step_output_selector = False\n    for nested_definition in parameter_spec.iterate_through_definitions():\n        (\n            result[nested_definition.parameter_specification.nested_element_key],\n            value_contains_empty_selector,\n        ) = construct_non_simd_step_non_compound_input(\n            step_node=step_node,\n            parameter_spec=nested_definition,\n            runtime_parameters=runtime_parameters,\n            execution_cache=execution_cache,\n        )\n        contains_empty_step_output_selector = (\n            contains_empty_step_output_selector or value_contains_empty_selector\n        )\n    return result, contains_empty_step_output_selector\n\n\ndef construct_non_simd_step_non_compound_input(\n    step_node: StepNode,\n    parameter_spec: StepInputDefinition,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> Tuple[Any, bool]:\n    if parameter_spec.is_compound_input():\n        raise AssumptionError(\n            public_message=f\"Workflows Execution Error encountered unexpected state probably related to the fact \"\n            f\"that Workflows Compiler allowed for multi-level nesting of inputs selectors which \"\n            f\"is not supported. This is most likely the bug. Contact Roboflow team \"\n            f\"through github issues (https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if parameter_spec.is_batch_oriented():\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Encountered batch-oriented input for non-SIMD step: {step_node.name}.\"\n            f\"This is most likely a bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if parameter_spec.points_to_input():\n        parameter_spec: DynamicStepInputDefinition = parameter_spec  # type: ignore\n        input_name = get_last_chunk_of_selector(selector=parameter_spec.selector)\n        return runtime_parameters[input_name], False\n    if parameter_spec.points_to_step_output():\n        parameter_spec: DynamicStepInputDefinition = parameter_spec  # type: ignore\n        step_output = execution_cache.get_non_batch_output(\n            selector=parameter_spec.selector\n        )\n        return step_output, step_output is None\n    parameter_spec: StaticStepInputDefinition = parameter_spec  # type: ignore\n    return parameter_spec.value, False\n\n\ndef iterate_over_simd_step_input(\n    step_node: StepNode,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    dynamic_batches_manager: DynamicBatchesManager,\n    branching_manager: BranchingManager,\n) -> Generator[NonBatchModeSIMDStepInput, None, None]:\n    simd_step_input = construct_simd_step_input(\n        step_node=step_node,\n        runtime_parameters=runtime_parameters,\n        execution_cache=execution_cache,\n        dynamic_batches_manager=dynamic_batches_manager,\n        branching_manager=branching_manager,\n    )\n    parameters_generator = unfold_parameters(parameters=simd_step_input.parameters)\n    for index, single_parameters_set in zip(\n        simd_step_input.indices, parameters_generator\n    ):\n        yield NonBatchModeSIMDStepInput(\n            index=index,\n            parameters=single_parameters_set,\n        )\n\n\ndef construct_simd_step_input(\n    step_node: StepNode,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    dynamic_batches_manager: DynamicBatchesManager,\n    branching_manager: BranchingManager,\n) -> BatchModeSIMDStepInput:\n    masks, scalars_discarded = construct_mask_for_all_inputs_dimensionalities(\n        step_node=step_node,\n        branching_manager=branching_manager,\n    )\n    return prepare_parameters(\n        step_node=step_node,\n        dynamic_batches_manager=dynamic_batches_manager,\n        masks=masks,\n        scalars_discarded=scalars_discarded,\n        runtime_parameters=runtime_parameters,\n        execution_cache=execution_cache,\n    )\n\n\ndef construct_mask_for_all_inputs_dimensionalities(\n    step_node: StepNode,\n    branching_manager: BranchingManager,\n) -> Tuple[Any, bool]:\n    inputs_dimensionalities = collect_inputs_dimensionalities(step_node=step_node)\n    all_dimensionalities = {dim for dim in inputs_dimensionalities.values() if dim > 0}\n    batch_masks, non_batch_masks = [], set()\n    for execution_branch in step_node.execution_branches_impacting_inputs:\n        if not branching_manager.is_execution_branch_registered(\n            execution_branch=execution_branch\n        ):\n            non_batch_masks.add(False)\n            continue\n        if branching_manager.is_execution_branch_batch_oriented(\n            execution_branch=execution_branch\n        ):\n            mask = branching_manager.get_mask(execution_branch=execution_branch)\n            batch_masks.append(mask)\n        else:\n            mask = branching_manager.get_mask(execution_branch=execution_branch)\n            non_batch_masks.add(mask)\n    scalar_mask_contains_false = False in non_batch_masks\n    if scalar_mask_contains_false:\n        return {\n            dimension: set() for dimension in all_dimensionalities\n        }, scalar_mask_contains_false\n    return {\n        dimension: get_masks_intersection_up_to_dimension(\n            batch_masks=batch_masks,\n            dimension=dimension,\n        )\n        for dimension in all_dimensionalities\n    }, scalar_mask_contains_false\n\n\ndef collect_inputs_dimensionalities(\n    step_node: StepNode,\n) -> Dict[str, int]:\n    result = {}\n    for parameter_name, parameter_specs in step_node.input_data.items():\n        if parameter_specs.is_compound_input():\n            dimensionalities = [\n                nested_definition.get_dimensionality()\n                for nested_definition in parameter_specs.iterate_through_definitions()\n            ]\n            # to help for empty values\n            dimensionalities.append(0)\n            result[parameter_name] = max(dimensionalities)\n        else:\n            result[parameter_name] = parameter_specs.get_dimensionality()\n    return result\n\n\ndef get_masks_intersection_up_to_dimension(\n    batch_masks: List[Set[DynamicBatchIndex]],\n    dimension: int,\n) -> Optional[Set[DynamicBatchIndex]]:\n    if not batch_masks:\n        return None\n\n    # Initialize intersection with the first batch mask transformed up to the given dimension\n    intersection = {mask_element[:dimension] for mask_element in batch_masks[0]}\n\n    # Perform the intersection with the transformed sets of subsequent batch masks\n    for batch_mask in batch_masks[1:]:\n        intersection &= {mask_element[:dimension] for mask_element in batch_mask}\n\n        # Early exit if intersection becomes empty\n        if not intersection:\n            return set()\n\n    return intersection\n\n\nclass GuardForIndicesWrapping:\n\n    def __init__(self):\n        self._registered_wrapping: Optional[List[DynamicBatchIndex]] = None\n\n    def register_wrapping(\n        self, indices_before_wrapping: List[DynamicBatchIndex]\n    ) -> None:\n        if self._registered_wrapping is None:\n            self._registered_wrapping = indices_before_wrapping\n        elif self._registered_wrapping != indices_before_wrapping:\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Detected a situation when step requires dimensionality wrapping, but\"\n                f\"different inputs register different elements indices to wrap which is illegal \"\n                f\"and should be detected earlier by Workflows compiler. This is most likely a bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n\n\ndef prepare_parameters(\n    step_node: StepNode,\n    dynamic_batches_manager: DynamicBatchesManager,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> BatchModeSIMDStepInput:\n    step_requests_batch_input = step_node.step_manifest.accepts_batch_input()\n    result = {}\n    indices_for_parameter = {}\n    guard_of_indices_wrapping = GuardForIndicesWrapping()\n    compound_inputs = set()\n    contains_empty_scalar_step_output_selector = False\n    for parameter_name, parameter_specs in step_node.input_data.items():\n        if parameter_specs.is_compound_input():\n            (\n                result[parameter_name],\n                indices_for_parameter[parameter_name],\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_compound_parameter_value(\n                parameter=parameter_specs,\n                step_execution_dimensionality=step_node.step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=step_node.auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n            compound_inputs.add(parameter_name)\n        else:\n            (\n                result[parameter_name],\n                indices_for_parameter[parameter_name],\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=parameter_specs,\n                step_execution_dimensionality=step_node.step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=step_node.auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n        contains_empty_scalar_step_output_selector = (\n            contains_empty_scalar_step_output_selector\n            or value_contains_empty_scalar_step_output_selector\n        )\n    batch_parameters_indices = [\n        i for i in indices_for_parameter.values() if i is not None\n    ]\n    ensure_compound_input_indices_match(indices=batch_parameters_indices)\n    if not batch_parameters_indices:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"For step: {step_node.name} which is assessed by Workflows Compiler as \"\n            f\"SIMD step Execution Engine cannot detect batch inputs. \"\n            f\"This is most likely a bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    indices = batch_parameters_indices[0]\n    if not step_node.step_manifest.accepts_empty_values():\n        if contains_empty_scalar_step_output_selector:\n            return BatchModeSIMDStepInput(\n                indices=[],\n                parameters={},\n            )\n        empty_indices = get_empty_batch_elements_indices(value=result)\n        indices = [e for e in indices if e not in empty_indices]\n        result = remove_indices(value=result, indices=empty_indices)\n    return BatchModeSIMDStepInput(\n        indices=indices,\n        parameters=result,\n    )\n\n\ndef get_compound_parameter_value(\n    parameter: CompoundStepInputDefinition,\n    step_execution_dimensionality: int,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n    dynamic_batches_manager: DynamicBatchesManager,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n    auto_batch_casting_lineage_supports: Dict[str, AutoBatchCastingConfig],\n    step_requests_batch_input: bool,\n) -> Tuple[Union[list, Dict[str, Any]], Optional[List[DynamicBatchIndex]], bool]:\n    contains_empty_scalar_step_output_selector = False\n    batch_indices = []\n    if parameter.represents_list_of_inputs():\n        result = []\n        for nested_element in parameter.iterate_through_definitions():\n            (\n                non_compound_parameter_value,\n                non_compound_indices,\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=nested_element,\n                step_execution_dimensionality=step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n            result.append(non_compound_parameter_value)\n            contains_empty_scalar_step_output_selector = (\n                contains_empty_scalar_step_output_selector\n                or value_contains_empty_scalar_step_output_selector\n            )\n            if non_compound_indices is not None:\n                batch_indices.append(non_compound_indices)\n    else:\n        result = {}\n        for nested_element in parameter.iterate_through_definitions():\n            (\n                non_compound_parameter_value,\n                non_compound_indices,\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=nested_element,\n                step_execution_dimensionality=step_execution_dimensionality,\n                masks=masks,\n                scalars_discarded=scalars_discarded,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n                auto_batch_casting_lineage_supports=auto_batch_casting_lineage_supports,\n                step_requests_batch_input=step_requests_batch_input,\n            )\n            result[nested_element.parameter_specification.nested_element_key] = (\n                non_compound_parameter_value\n            )\n            contains_empty_scalar_step_output_selector = (\n                contains_empty_scalar_step_output_selector\n                or value_contains_empty_scalar_step_output_selector\n            )\n            if non_compound_indices is not None:\n                batch_indices.append(non_compound_indices)\n    ensure_compound_input_indices_match(indices=batch_indices)\n    result_indices = None\n    if len(batch_indices) > 0:\n        result_indices = batch_indices[0]\n    return result, result_indices, contains_empty_scalar_step_output_selector\n\n\ndef get_non_compound_parameter_value(\n    parameter: StepInputDefinition,\n    step_execution_dimensionality: int,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n    dynamic_batches_manager: DynamicBatchesManager,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n    auto_batch_casting_lineage_supports: Dict[str, AutoBatchCastingConfig],\n    step_requests_batch_input: bool,\n) -> Tuple[Any, Optional[List[DynamicBatchIndex]], bool]:\n    if not parameter.is_batch_oriented():\n        requested_as_batch = (\n            parameter.parameter_specification.parameter_name\n            in auto_batch_casting_lineage_supports\n        )\n        if parameter.points_to_input():\n            input_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n            parameter_name = get_last_chunk_of_selector(\n                selector=input_parameter.selector\n            )\n            if not requested_as_batch:\n                return runtime_parameters[parameter_name], None, False\n            else:\n                return apply_auto_batch_casting(\n                    parameter_name=parameter_name,\n                    value=runtime_parameters[parameter_name],\n                    auto_batch_casting_config=auto_batch_casting_lineage_supports[\n                        parameter.parameter_specification.parameter_name\n                    ],\n                    contains_empty_scalar_step_output_selector=False,\n                    dynamic_batches_manager=dynamic_batches_manager,\n                    step_execution_dimensionality=step_execution_dimensionality,\n                    guard_of_indices_wrapping=guard_of_indices_wrapping,\n                    step_requests_batch_input=step_requests_batch_input,\n                    masks=masks,\n                    scalars_discarded=False,\n                )\n        elif parameter.points_to_step_output():\n            input_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n            value = execution_cache.get_non_batch_output(\n                selector=input_parameter.selector\n            )\n            if not requested_as_batch:\n                return value, None, value is None\n            else:\n                return apply_auto_batch_casting(\n                    parameter_name=parameter.parameter_specification.parameter_name,\n                    value=value,\n                    auto_batch_casting_config=auto_batch_casting_lineage_supports[\n                        parameter.parameter_specification.parameter_name\n                    ],\n                    contains_empty_scalar_step_output_selector=value is None,\n                    dynamic_batches_manager=dynamic_batches_manager,\n                    step_execution_dimensionality=step_execution_dimensionality,\n                    guard_of_indices_wrapping=guard_of_indices_wrapping,\n                    step_requests_batch_input=step_requests_batch_input,\n                    masks=masks,\n                    scalars_discarded=scalars_discarded,\n                )\n        else:\n            static_input: StaticStepInputDefinition = parameter  # type: ignore\n            return static_input.value, None, False\n    dynamic_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n    parameter_dimensionality = dynamic_parameter.get_dimensionality()\n    lineage_indices = dynamic_batches_manager.get_indices_for_data_lineage(\n        lineage=dynamic_parameter.data_lineage,\n    )\n    mask_for_dimension = masks[parameter_dimensionality]\n    if dynamic_parameter.points_to_input():\n        input_name = get_last_chunk_of_selector(selector=dynamic_parameter.selector)\n        batch_input = _flatten_batch_oriented_inputs(\n            runtime_parameters[input_name],\n            dimensionality=parameter_dimensionality,\n        )\n        if mask_for_dimension is not None:\n            if len(lineage_indices) != len(batch_input):\n                raise ExecutionEngineRuntimeError(\n                    public_message=f\"Detected a situation when input parameter: \"\n                    f\"{input_name}\"\n                    f\"size is mismatched compared to mask requested for that input. \"\n                    f\"Input length: {len(batch_input)}, mask size: {len(lineage_indices)}. \"\n                    f\"This is most likely a bug. \"\n                    f\"Contact Roboflow team through github issues \"\n                    f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                    f\"the problem - including workflow definition you use.\",\n                    context=\"workflow_execution | step_input_assembling\",\n                )\n            batch_input = [\n                input_element if element_index in mask_for_dimension else None\n                for element_index, input_element in zip(lineage_indices, batch_input)\n            ]\n    else:\n        batch_input = execution_cache.get_batch_output(\n            selector=dynamic_parameter.selector,\n            batch_elements_indices=lineage_indices,\n            mask=mask_for_dimension,\n        )\n    if step_execution_dimensionality == parameter_dimensionality:\n        return Batch(batch_input, lineage_indices), lineage_indices, False\n    if step_execution_dimensionality > parameter_dimensionality:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter.parameter_specification.parameter_name}\"\n            f\"has a dimensionality {parameter_dimensionality} larger \"\n            f\"than step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if abs(parameter_dimensionality - step_execution_dimensionality) > 1:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter.parameter_specification.parameter_name}\"\n            f\"has a dimensionality {parameter_dimensionality} differing more than one level \"\n            f\"from step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if step_execution_dimensionality == 0 and not step_requests_batch_input:\n        return Batch(batch_input, lineage_indices), lineage_indices, False\n    upper_lineage = dynamic_parameter.data_lineage[:-1]\n    if len(upper_lineage) == 0:\n        if not step_requests_batch_input:\n            raise AssumptionError(\n                public_message=f\"Parameter: {parameter.parameter_specification.parameter_name} \"\n                f\"requires dimensionality wrapping, but registered lineage support is incompatible \"\n                f\"which should be detected by the compiler. This is most likely a bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n        upper_level_indices = [()]\n    else:\n        upper_level_indices = dynamic_batches_manager.get_indices_for_data_lineage(\n            lineage=dynamic_parameter.data_lineage[:-1],\n        )\n    result = reduce_batch_dimensionality(\n        indices=lineage_indices,\n        upper_level_index=upper_level_indices,\n        data=batch_input,\n        guard_of_indices_wrapping=guard_of_indices_wrapping,\n    )\n    return result, result.indices, False\n\n\ndef apply_auto_batch_casting(\n    parameter_name: str,\n    value: Any,\n    auto_batch_casting_config: AutoBatchCastingConfig,\n    contains_empty_scalar_step_output_selector: bool,\n    dynamic_batches_manager: DynamicBatchesManager,\n    step_execution_dimensionality: int,\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n    step_requests_batch_input: bool,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    scalars_discarded: bool,\n) -> Tuple[Any, List[DynamicBatchIndex], bool]:\n    if auto_batch_casting_config.lineage_support is None:\n        indices = [(0,) * auto_batch_casting_config.casted_dimensionality]\n    else:\n        indices = dynamic_batches_manager.get_indices_for_data_lineage(\n            lineage=auto_batch_casting_config.lineage_support,\n        )\n        missing_dimensions = auto_batch_casting_config.casted_dimensionality - len(\n            auto_batch_casting_config.lineage_support\n        )\n        if missing_dimensions > 0:\n            padding = (0,) * missing_dimensions\n            indices = [i + padding for i in indices]\n    if scalars_discarded:\n        batch_content = [None] * len(indices)\n    elif auto_batch_casting_config.lineage_support is None:\n        batch_content = [value] * len(indices)\n    else:\n        support_dimensionality = len(auto_batch_casting_config.lineage_support)\n        mask_for_support_dimensionality = masks[support_dimensionality]\n        if mask_for_support_dimensionality is None:\n            batch_content = [value] * len(indices)\n        else:\n            batch_content = []\n            for index in indices:\n                if index[:support_dimensionality] in mask_for_support_dimensionality:\n                    batch_content.append(value)\n                else:\n                    batch_content.append(None)\n    created_batch = Batch(content=batch_content, indices=indices)\n    if step_execution_dimensionality == auto_batch_casting_config.casted_dimensionality:\n        return (\n            created_batch,\n            indices,\n            contains_empty_scalar_step_output_selector or scalars_discarded,\n        )\n    if step_execution_dimensionality > auto_batch_casting_config.casted_dimensionality:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter_name}\"\n            f\"has auto-batch casted dimensionality {auto_batch_casting_config.casted_dimensionality} larger \"\n            f\"than step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if (\n        abs(\n            auto_batch_casting_config.casted_dimensionality\n            - step_execution_dimensionality\n        )\n        > 1\n    ):\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter_name} has auto batch casted \"\n            f\"dimensionality {auto_batch_casting_config.casted_dimensionality} differing more than one level \"\n            f\"from step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    upper_level_lineage_dimensionality = (\n        auto_batch_casting_config.casted_dimensionality - 1\n    )\n    if upper_level_lineage_dimensionality == 0 and not step_requests_batch_input:\n        # for batch collapse into scalar\n        return (\n            created_batch,\n            indices,\n            contains_empty_scalar_step_output_selector or scalars_discarded,\n        )\n    if auto_batch_casting_config.lineage_support is None:\n        upper_level_indices = [indices[0][:-1]]\n    else:\n        upper_level_lineage = auto_batch_casting_config.lineage_support[\n            :upper_level_lineage_dimensionality\n        ]\n        if (\n            upper_level_lineage_dimensionality < 1\n            or len(upper_level_lineage) < upper_level_lineage_dimensionality\n        ):\n            if not step_requests_batch_input:\n                raise AssumptionError(\n                    public_message=f\"Detected a situation when parameter: {parameter_name} requires dimensionality \"\n                    f\"wrapping, but registered lineage support is incompatible which should be detected \"\n                    f\"by the compiler. This is most likely a bug. \"\n                    f\"Contact Roboflow team through github issues \"\n                    f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                    f\"the problem - including workflow definition you use.\",\n                    context=\"workflow_execution | step_input_assembling\",\n                )\n            upper_level_indices = [()]\n        else:\n            upper_level_indices = dynamic_batches_manager.get_indices_for_data_lineage(\n                lineage=upper_level_lineage,\n            )\n    result = reduce_batch_dimensionality(\n        indices=indices,\n        upper_level_index=upper_level_indices,\n        data=batch_content,\n        guard_of_indices_wrapping=guard_of_indices_wrapping,\n    )\n    return (\n        result,\n        result.indices,\n        contains_empty_scalar_step_output_selector or scalars_discarded,\n    )\n\n\ndef _flatten_batch_oriented_inputs(\n    inputs: list,\n    dimensionality: int,\n) -> List[Any]:\n    if dimensionality == 0 or not isinstance(inputs, list):\n        raise AssumptionError(\n            public_message=f\"Could not prepare batch-oriented input data. This is most likely the bug. Contact \"\n            f\"Roboflow team through github issues (https://github.com/roboflow/inference/issues) \"\n            f\"providing full context of the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if dimensionality == 1:\n        return inputs\n    result = []\n    for element in inputs:\n        result.extend(\n            _flatten_batch_oriented_inputs(\n                inputs=element, dimensionality=dimensionality - 1\n            )\n        )\n    return result\n\n\ndef reduce_batch_dimensionality(\n    indices: List[DynamicBatchIndex],\n    upper_level_index: List[DynamicBatchIndex],\n    data: List[T],\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n) -> Batch[Optional[Batch[T]]]:\n    guard_of_indices_wrapping.register_wrapping(indices_before_wrapping=indices)\n    already_spotted_downgraded_indices = set()\n    wrapped_batch_index, wrapped_batch_content = [], []\n    upper_level_indices_data = {index: None for index in upper_level_index}\n    for index, data in zip(indices, data):\n        downgraded_index = index[:-1]\n        if downgraded_index in already_spotted_downgraded_indices:\n            wrapped_batch_index.append(index)\n            wrapped_batch_content.append(data)\n        else:\n            if wrapped_batch_index:\n                upper_level_indices_data[wrapped_batch_index[-1][:-1]] = Batch(\n                    content=wrapped_batch_content, indices=wrapped_batch_index\n                )\n            already_spotted_downgraded_indices.add(downgraded_index)\n            wrapped_batch_index = [index]\n            wrapped_batch_content = [data]\n    if wrapped_batch_index:\n        upper_level_indices_data[wrapped_batch_index[-1][:-1]] = Batch(\n            content=wrapped_batch_content, indices=wrapped_batch_index\n        )\n    return Batch(\n        content=[upper_level_indices_data[index] for index in upper_level_index],\n        indices=upper_level_index,\n    )\n\n\ndef ensure_compound_input_indices_match(indices: List[List[DynamicBatchIndex]]) -> None:\n    if len(indices) < 2:\n        return None\n    reference_set = set(indices[0])\n    for index in indices[1:]:\n        other_set = set(index)\n        if reference_set != other_set:\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Detected a situation when step input parameters cannot be created \"\n                f\"due to missmatch in batch element indices. This is most likely a bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n\n\ndef get_empty_batch_elements_indices(value: Any) -> Set[DynamicBatchIndex]:\n    result = set()\n    if isinstance(value, dict):\n        for v in value.values():\n            value_result = get_empty_batch_elements_indices(v)\n            result = result.union(value_result)\n    if isinstance(value, list):\n        for v in value:\n            value_result = get_empty_batch_elements_indices(v)\n            result = result.union(value_result)\n    if isinstance(value, Batch):\n        for index, value_element in value.iter_with_indices():\n            if isinstance(value_element, Batch):\n                value_result = get_empty_batch_elements_indices(value=value_element)\n                result = result.union(value_result)\n            elif value_element is None:\n                result.add(index)\n    return result\n\n\ndef remove_indices(value: Any, indices: Set[DynamicBatchIndex]) -> Any:\n    if isinstance(value, dict):\n        return {k: remove_indices(value=v, indices=indices) for k, v in value.items()}\n    if isinstance(value, list):\n        return [remove_indices(value=v, indices=indices) for v in value]\n    if isinstance(value, Batch):\n        return value.remove_by_indices(indices_to_remove=indices)\n    return value\n\n\ndef unfold_parameters(\n    parameters: Dict[str, Any],\n) -> Generator[Dict[str, Any], None, None]:\n    batch_parameters = get_batch_parameters(parameters=parameters)\n    non_batch_parameters = {\n        k: v for k, v in parameters.items() if k not in batch_parameters\n    }\n    if not batch_parameters:\n        if not non_batch_parameters:\n            return None\n        yield non_batch_parameters\n        return None\n    for unfolded_batch_parameters in iterate_over_batches(\n        batch_parameters=batch_parameters\n    ):\n        yield {**unfolded_batch_parameters, **non_batch_parameters}\n\n\ndef get_batch_parameters(parameters: Dict[str, Any]) -> Dict[str, Any]:\n    result = {}\n    for name, value in parameters.items():\n        if isinstance(value, Batch):\n            result[name] = value\n        elif isinstance(value, list) and any(isinstance(v, Batch) for v in value):\n            result[name] = value\n        elif isinstance(value, dict) and any(\n            isinstance(v, Batch) for v in value.values()\n        ):\n            result[name] = value\n    return result\n\n\ndef iterate_over_batches(\n    batch_parameters: Dict[str, Any],\n) -> Generator[Dict[str, Any], None, None]:\n    index = 0\n    end = False\n    while not end:\n        result = {}\n        for name, value in batch_parameters.items():\n            if isinstance(value, Batch):\n                if len(value) <= index:\n                    end = True\n                    break\n                result[name] = value[index]\n            elif isinstance(value, list):\n                to_yield = []\n                for element in value:\n                    if isinstance(element, Batch):\n                        if len(element) <= index:\n                            end = True\n                            break\n                        to_yield.append(element[index])\n                    else:\n                        to_yield.append(element)\n                result[name] = to_yield\n            elif isinstance(value, dict):\n                to_yield = {}\n                for key, key_value in value.items():\n                    if not isinstance(key_value, Batch):\n                        to_yield[key] = key_value\n                    else:\n                        if len(key_value) <= index:\n                            end = True\n                            break\n                        else:\n                            to_yield[key] = key_value[index]\n                result[name] = to_yield\n        index += 1\n        if not end:\n            yield result\n",
    "patch": "diff --git a/inference/core/workflows/execution_engine/v1/executor/execution_data_manager/step_input_assembler.py b/inference/core/workflows/execution_engine/v1/executor/execution_data_manager/step_input_assembler.py\nindex 89fc07427..05faf9277 100644\n--- a/inference/core/workflows/execution_engine/v1/executor/execution_data_manager/step_input_assembler.py\n+++ b/inference/core/workflows/execution_engine/v1/executor/execution_data_manager/step_input_assembler.py\n@@ -431,8 +431,9 @@ def prepare_parameters(\n                 parameters={},\n             )\n         empty_indices = get_empty_batch_elements_indices(value=result)\n-        indices = [e for e in indices if e not in empty_indices]\n-        result = remove_indices(value=result, indices=empty_indices)\n+        if empty_indices:\n+            indices = [e for e in indices if e not in empty_indices]\n+            result = remove_indices(value=result, indices=empty_indices)\n     return BatchModeSIMDStepInput(\n         indices=indices,\n         parameters=result,\n"
  },
  {
    "trace_id": "de7c36bb-eeeb-48c6-9345-41e851be9185",
    "function_name": "find_longest_lineage_support",
    "file_path": "inference/core/workflows/execution_engine/v1/compiler/graph_constructor.py",
    "speedup_x": 0.26,
    "review_quality": null,
    "pre_optimization_commit": "9e7765a4485365e457db24f37888bacfa3e5a40b",
    "resolution_method": "git_parent",
    "source": "git",
    "original_function_code": "def find_longest_lineage_support(\n    all_lineages_of_batch_parameters: List[List[str]],\n) -> Optional[List[str]]:\n    longest_longest_lineage_support = []\n    for lineage in all_lineages_of_batch_parameters:\n        if len(lineage) > len(longest_longest_lineage_support):\n            longest_longest_lineage_support = lineage\n    if len(longest_longest_lineage_support) == 0:\n        return None\n    return longest_longest_lineage_support\n",
    "optimized_function_code": "import itertools\nfrom collections import defaultdict\nfrom copy import copy, deepcopy\nfrom typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union\nfrom uuid import uuid4\n\nimport networkx as nx\nfrom networkx import DiGraph\n\nfrom inference.core import logger\nfrom inference.core.workflows.errors import (\n    AssumptionError,\n    BlockInterfaceError,\n    ControlFlowDefinitionError,\n    ExecutionGraphStructureError,\n    InvalidReferenceTargetError,\n    StepInputDimensionalityError,\n    StepInputLineageError,\n    StepOutputLineageError,\n    WorkflowBlockError,\n)\nfrom inference.core.workflows.execution_engine.constants import (\n    NODE_COMPILATION_OUTPUT_PROPERTY,\n    PARSED_NODE_INPUT_SELECTORS_PROPERTY,\n    TOP_LEVEL_LINEAGE_KEY,\n    WORKFLOW_INPUT_BATCH_LINEAGE_ID,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    InputType,\n    JsonField,\n    OutputDefinition,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    STEP_AS_SELECTED_ELEMENT,\n    Kind,\n)\nfrom inference.core.workflows.execution_engine.introspection.entities import (\n    ParsedSelector,\n)\nfrom inference.core.workflows.execution_engine.introspection.selectors_parser import (\n    get_step_selectors,\n)\nfrom inference.core.workflows.execution_engine.profiling.core import (\n    WorkflowsProfiler,\n    execution_phase,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import (\n    AutoBatchCastingConfig,\n    CompoundStepInputDefinition,\n    DictOfStepInputDefinitions,\n    DynamicStepInputDefinition,\n    ExecutionGraphNode,\n    InputDimensionalitySpecification,\n    InputNode,\n    ListOfStepInputDefinitions,\n    NodeCategory,\n    NodeInputCategory,\n    OutputNode,\n    ParameterSpecification,\n    ParsedWorkflowDefinition,\n    PropertyPredecessorDefinition,\n    StaticStepInputDefinition,\n    StepInputData,\n    StepInputDefinition,\n    StepNode,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.graph_traversal import (\n    traverse_graph_ensuring_parents_are_reached_first,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.reference_type_checker import (\n    validate_reference_kinds,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import (\n    construct_input_selector,\n    construct_output_selector,\n    construct_step_selector,\n    get_last_chunk_of_selector,\n    get_nodes_of_specific_category,\n    get_step_selector_from_its_output,\n    identify_lineage,\n    is_flow_control_step,\n    is_input_node,\n    is_input_selector,\n    is_output_node,\n    is_step_node,\n    is_step_output_selector,\n    is_step_selector,\n    node_as,\n)\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nNODE_DEFINITION_KEY = \"definition\"\nSTEP_INPUT_SELECTORS_PROPERTY = \"step_input_selectors\"\nEXCLUDED_FIELDS = {\"type\", \"name\"}\n\n\n@execution_phase(\n    name=\"execution_graph_creation\",\n    categories=[\"execution_engine_operation\"],\n)\ndef prepare_execution_graph(\n    workflow_definition: ParsedWorkflowDefinition,\n    profiler: Optional[WorkflowsProfiler] = None,\n) -> DiGraph:\n    execution_graph = construct_graph(\n        workflow_definition=workflow_definition,\n    )\n    if not nx.is_directed_acyclic_graph(execution_graph):\n        raise ExecutionGraphStructureError(\n            public_message=f\"Detected cycle in execution graph. This means that there is output from one \"\n            f\"step that is connected to input of other step creating loop in the graph that would \"\n            f\"never end if executed.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    return denote_data_flow_in_workflow(\n        execution_graph=execution_graph,\n        parsed_workflow_definition=workflow_definition,\n    )\n\n\ndef construct_graph(\n    workflow_definition: ParsedWorkflowDefinition,\n) -> DiGraph:\n    execution_graph = nx.DiGraph()\n    execution_graph = add_input_nodes_for_graph(\n        inputs=workflow_definition.inputs,\n        execution_graph=execution_graph,\n    )\n    execution_graph = add_steps_nodes_for_graph(\n        steps=workflow_definition.steps,\n        execution_graph=execution_graph,\n    )\n    execution_graph = add_output_nodes_for_graph(\n        outputs=workflow_definition.outputs,\n        execution_graph=execution_graph,\n    )\n    execution_graph = add_steps_edges(\n        workflow_definition=workflow_definition,\n        execution_graph=execution_graph,\n    )\n    return add_edges_for_outputs(\n        workflow_definition=workflow_definition,\n        execution_graph=execution_graph,\n    )\n\n\ndef add_input_nodes_for_graph(\n    inputs: List[InputType],\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for input_spec in inputs:\n        input_selector = construct_input_selector(input_name=input_spec.name)\n        if input_spec.is_batch_oriented():\n            if input_spec.dimensionality < 1:\n                raise ExecutionGraphStructureError(\n                    public_message=f\"Detected batch oriented input `{input_spec.name}` with \"\n                    f\"declared dimensionality `{input_spec.dimensionality}` which is below \"\n                    f\"one (one is minimum dimensionality of the batch). Fix input definition in\"\n                    f\"your Workflow.\",\n                    context=\"workflow_compilation | execution_graph_construction\",\n                )\n            data_lineage = [WORKFLOW_INPUT_BATCH_LINEAGE_ID]\n            for _ in range(input_spec.dimensionality - 1):\n                # TODO: this may end up being a bug - with ability for multi-step debugging, if we will\n                #  ever have a situation that there will be multiple step outputs with nested\n                #  dimensionality with the same lineage, this re-construction method will\n                #  assign a different lineage identifier, causing the inputs being non-composable in\n                #  a single execution branch\n                data_lineage.append(f\"{uuid4()}\")\n        else:\n            data_lineage = []\n        compilation_output = InputNode(\n            node_category=NodeCategory.INPUT_NODE,\n            name=input_spec.name,\n            selector=input_selector,\n            data_lineage=data_lineage,\n            input_manifest=input_spec,\n        )\n        execution_graph.add_node(\n            input_selector,\n            **{\n                NODE_COMPILATION_OUTPUT_PROPERTY: compilation_output,\n            },\n        )\n    return execution_graph\n\n\ndef add_steps_nodes_for_graph(\n    steps: List[WorkflowBlockManifest],\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for step in steps:\n        step_selector = construct_step_selector(step_name=step.name)\n        compilation_output = StepNode(\n            node_category=NodeCategory.STEP_NODE,\n            name=step.name,\n            selector=step_selector,\n            data_lineage=[],\n            step_manifest=step,\n        )\n        execution_graph.add_node(\n            step_selector,\n            **{\n                NODE_COMPILATION_OUTPUT_PROPERTY: compilation_output,\n            },\n        )\n    return execution_graph\n\n\ndef add_output_nodes_for_graph(\n    outputs: List[JsonField],\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for output_spec in outputs:\n        output_selector = construct_output_selector(name=output_spec.name)\n        compilation_output = OutputNode(\n            node_category=NodeCategory.OUTPUT_NODE,\n            name=output_spec.name,\n            selector=output_selector,\n            data_lineage=[],\n            output_manifest=output_spec,\n        )\n        execution_graph.add_node(\n            output_selector,\n            **{\n                NODE_COMPILATION_OUTPUT_PROPERTY: compilation_output,\n            },\n        )\n    return execution_graph\n\n\ndef add_steps_edges(\n    workflow_definition: ParsedWorkflowDefinition,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for step in workflow_definition.steps:\n        source_step_selector = construct_step_selector(step_name=step.name)\n        step_selectors = get_step_selectors(step_manifest=step)\n        execution_graph.nodes[source_step_selector][\n            PARSED_NODE_INPUT_SELECTORS_PROPERTY\n        ] = step_selectors\n        execution_graph = add_edges_for_step(\n            execution_graph=execution_graph,\n            source_step_selector=source_step_selector,\n            target_step_parsed_selectors=step_selectors,\n        )\n    return execution_graph\n\n\ndef add_edges_for_step(\n    execution_graph: DiGraph,\n    source_step_selector: str,\n    target_step_parsed_selectors: List[ParsedSelector],\n) -> DiGraph:\n    for target_step_parsed_selector in target_step_parsed_selectors:\n        execution_graph = add_edge_for_step(\n            execution_graph=execution_graph,\n            source_step_selector=source_step_selector,\n            target_step_parsed_selector=target_step_parsed_selector,\n        )\n    return execution_graph\n\n\ndef add_edge_for_step(\n    execution_graph: DiGraph,\n    source_step_selector: str,\n    target_step_parsed_selector: ParsedSelector,\n) -> DiGraph:\n    target_step_selector = get_step_selector_from_its_output(\n        step_output_selector=target_step_parsed_selector.value\n    )\n    verify_edge_is_created_between_existing_nodes(\n        execution_graph=execution_graph,\n        start=source_step_selector,\n        end=target_step_selector,\n    )\n    if is_step_selector(target_step_parsed_selector.value):\n        return establish_flow_control_edge(\n            source_step_selector=source_step_selector,\n            target_step_parsed_selector=target_step_parsed_selector,\n            execution_graph=execution_graph,\n        )\n    if is_input_selector(target_step_parsed_selector.value):\n        input_node_compilation_data = node_as(\n            execution_graph=execution_graph,\n            node=target_step_parsed_selector.value,\n            expected_type=InputNode,\n        )\n        actual_input_kind = input_node_compilation_data.input_manifest.kind\n    else:\n        other_step_compilation_data = node_as(\n            execution_graph=execution_graph,\n            node=target_step_selector,\n            expected_type=StepNode,\n        )\n        source_step_compilation_data = node_as(\n            execution_graph=execution_graph,\n            node=source_step_selector,\n            expected_type=StepNode,\n        )\n        actual_input_kind = get_kind_of_value_provided_in_step_output(\n            step_manifest=other_step_compilation_data.step_manifest,\n            step_property=get_last_chunk_of_selector(\n                selector=target_step_parsed_selector.value\n            ),\n            source_step_manifest=source_step_compilation_data.step_manifest,\n        )\n    expected_input_kind = list(\n        itertools.chain.from_iterable(\n            ref.kind\n            for ref in target_step_parsed_selector.definition.allowed_references\n        )\n    )\n    error_message = (\n        f\"Failed to validate reference provided for step: {source_step_selector} regarding property: \"\n        f\"{target_step_parsed_selector.definition.property_name} with value: {target_step_parsed_selector.value}. \"\n        f\"Allowed kinds of references for this property: {list(set(e.name for e in expected_input_kind))}. \"\n        f\"Types of output for referred property: \"\n        f\"{list(set(a.name if isinstance(a, Kind) else a for a in actual_input_kind))}\"\n    )\n    validate_reference_kinds(\n        expected=expected_input_kind,\n        actual=actual_input_kind,\n        error_message=error_message,\n    )\n    if execution_graph.has_edge(target_step_selector, source_step_selector):\n        edge_data = execution_graph.edges[(target_step_selector, source_step_selector)]\n        if STEP_INPUT_SELECTORS_PROPERTY not in edge_data:\n            edge_data[STEP_INPUT_SELECTORS_PROPERTY] = []\n        edge_data[STEP_INPUT_SELECTORS_PROPERTY].append(\n            target_step_parsed_selector,\n        )\n    else:\n        execution_graph.add_edge(\n            target_step_selector,\n            source_step_selector,\n            **{STEP_INPUT_SELECTORS_PROPERTY: [target_step_parsed_selector]},\n        )\n    return execution_graph\n\n\ndef establish_flow_control_edge(\n    source_step_selector: str,\n    target_step_parsed_selector: ParsedSelector,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    if not step_definition_allows_flow_control_references(\n        parsed_selector=target_step_parsed_selector\n    ):\n        raise ExecutionGraphStructureError(\n            public_message=f\"Detected reference to other step in manifest of step {source_step_selector}. \"\n            f\"This is not allowed, as step manifest does not define any properties of type `StepSelector` \"\n            f\"allowing for defining connections between steps that represent flow control in `workflows`.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    target_step_selector = get_step_selector_from_its_output(\n        step_output_selector=target_step_parsed_selector.value\n    )\n    source_compilation_data = node_as(\n        execution_graph=execution_graph,\n        node=source_step_selector,\n        expected_type=StepNode,\n    )\n    target_compilation_data = node_as(\n        execution_graph=execution_graph,\n        node=target_step_selector,\n        expected_type=StepNode,\n    )\n    nodes_categories = {\n        source_compilation_data.node_category,\n        target_compilation_data.node_category,\n    }\n    if nodes_categories != {NodeCategory.STEP_NODE}:\n        raise ExecutionGraphStructureError(\n            public_message=f\"Attempted to create flow-control connection between workflow nodes: \"\n            f\"{source_step_selector} and {target_step_selector}, one of which is not denoted\"\n            f\"as step node.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    execution_graph.add_edge(\n        source_step_selector,\n        target_step_selector,\n    )\n    if target_step_selector in source_compilation_data.child_execution_branches:\n        raise ExecutionGraphStructureError(\n            public_message=f\"While establishing flow-control connection between source `{source_step_selector}` \"\n            f\"and target `{target_step_selector}` it was discovered that source step defines\"\n            f\"control flow transition into target one more than once, which is not allowed as \"\n            f\"that situation creates ambiguity in selecting execution branch.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    execution_branch_name = f\"Branch[{source_step_selector} -> {target_step_parsed_selector.definition.property_name}]\"\n    source_compilation_data.child_execution_branches[target_step_selector] = (\n        execution_branch_name\n    )\n    target_compilation_data.execution_branches_impacting_inputs.add(\n        execution_branch_name\n    )\n    return execution_graph\n\n\ndef step_definition_allows_flow_control_references(\n    parsed_selector: ParsedSelector,\n) -> bool:\n    return any(\n        definition.selected_element == STEP_AS_SELECTED_ELEMENT\n        for definition in parsed_selector.definition.allowed_references\n    )\n\n\ndef get_kind_of_value_provided_in_step_output(\n    step_manifest: WorkflowBlockManifest,\n    step_property: str,\n    source_step_manifest: WorkflowBlockManifest,\n) -> List[Kind]:\n    referred_node_outputs = step_manifest.get_actual_outputs()\n    actual_kind = []\n    matched_property = False\n    for output in referred_node_outputs:\n        if output.name != step_property:\n            continue\n        matched_property = True\n        actual_kind.extend(output.kind)\n    if not matched_property:\n        property_name = get_property_with_invalid_selector(\n            manifest=source_step_manifest,\n            step_property=step_property,\n        )\n        raise ExecutionGraphStructureError(\n            public_message=f\"Found reference to non-existing property `{step_property}` of step `{step_manifest.name}`.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=source_step_manifest.name,\n                    block_type=source_step_manifest.type,\n                    property_name=property_name,\n                    property_details=f\"'{step_manifest.name}.{step_property}' is an invalid reference\",\n                )\n            ],\n        )\n    return actual_kind\n\n\ndef add_edges_for_step_inputs(\n    execution_graph: DiGraph,\n    input_selectors: Set[str],\n    step_selector: str,\n) -> DiGraph:\n    for input_selector in input_selectors:\n        if is_step_output_selector(selector_or_value=input_selector):\n            input_selector = get_step_selector_from_its_output(\n                step_output_selector=input_selector\n            )\n        verify_edge_is_created_between_existing_nodes(\n            execution_graph=execution_graph,\n            start=input_selector,\n            end=step_selector,\n        )\n        execution_graph.add_edge(input_selector, step_selector)\n    return execution_graph\n\n\ndef add_edges_for_outputs(\n    workflow_definition: ParsedWorkflowDefinition,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for output in workflow_definition.outputs:\n        node_selector = output.selector\n        if is_step_output_selector(selector_or_value=node_selector):\n            node_selector = get_step_selector_from_its_output(\n                step_output_selector=node_selector\n            )\n        output_selector = construct_output_selector(name=output.name)\n        verify_edge_is_created_between_existing_nodes(\n            execution_graph=execution_graph,\n            start=node_selector,\n            end=output_selector,\n        )\n        output_node_manifest = node_as(\n            execution_graph=execution_graph,\n            node=output_selector,\n            expected_type=OutputNode,\n        )\n        if is_step_output_selector(selector_or_value=output.selector):\n            step_manifest = execution_graph.nodes[node_selector][\n                NODE_COMPILATION_OUTPUT_PROPERTY\n            ].step_manifest\n            step_outputs = step_manifest.get_actual_outputs()\n            denote_output_node_kind_based_on_step_outputs(\n                output_selector=output.selector,\n                step_outputs=step_outputs,\n                output_node_manifest=output_node_manifest,\n            )\n        else:\n            input_manifest = node_as(\n                execution_graph=execution_graph,\n                node=node_selector,\n                expected_type=InputNode,\n            ).input_manifest\n            output_node_manifest.kind = copy(input_manifest.kind)\n        execution_graph.add_edge(node_selector, output_selector)\n    return execution_graph\n\n\ndef verify_edge_is_created_between_existing_nodes(\n    execution_graph: DiGraph,\n    start: str,\n    end: str,\n) -> None:\n    if not execution_graph.has_node(start) or not execution_graph.has_node(end):\n        invalid_block = start if not execution_graph.has_node(start) else end\n        referencing_block = end if invalid_block == start else start\n\n        step_type = None\n        property_name = None\n        if execution_graph.has_node(referencing_block):\n            if is_step_node(execution_graph, referencing_block):\n                step_manifest = node_as(\n                    execution_graph=execution_graph,\n                    node=referencing_block,\n                    expected_type=StepNode,\n                ).step_manifest\n                step_type = step_manifest.type\n                property_name = get_property_with_invalid_selector(\n                    manifest=step_manifest,\n                    step_property=invalid_block,\n                )\n\n        block_id = (\n            \"$outputs\"\n            if referencing_block.startswith(\"$outputs.\")\n            else get_last_chunk_of_selector(selector=referencing_block)\n        )\n        property_name = (\n            get_last_chunk_of_selector(selector=referencing_block)\n            if referencing_block.startswith(\"$outputs.\")\n            else property_name\n        )\n\n        is_input = is_input_selector(selector_or_value=invalid_block)\n        raise InvalidReferenceTargetError(\n            public_message=f\"Workflow references '{invalid_block}' which points to a non-existent {is_input and 'input parameter' or 'block'}.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=block_id,\n                    block_type=step_type,\n                    property_name=property_name,\n                    property_details=f\"Invalid reference to {invalid_block}\",\n                ),\n            ],\n        )\n\n\ndef denote_output_node_kind_based_on_step_outputs(\n    output_selector: str,\n    step_outputs: List[OutputDefinition],\n    output_node_manifest: OutputNode,\n) -> None:\n    selected_output_name = get_last_chunk_of_selector(selector=output_selector)\n    kinds_for_outputs = {output.name: output.kind for output in step_outputs}\n\n    if selected_output_name == \"*\":\n        output_node_manifest.kind = deepcopy(kinds_for_outputs)\n        return None\n    if selected_output_name not in kinds_for_outputs:\n        output_name = output_node_manifest.output_manifest.name\n\n        raise InvalidReferenceTargetError(\n            public_message=f\"Workflow output references '{output_selector}' which points to a non-existent block property.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=\"$outputs\",\n                    property_name=output_name,\n                    property_details=f\"Invalid reference to {output_selector}\",\n                ),\n            ],\n        )\n    output_node_manifest.kind = copy(kinds_for_outputs[selected_output_name])\n    return None\n\n\ndef denote_data_flow_in_workflow(\n    execution_graph: DiGraph,\n    parsed_workflow_definition: ParsedWorkflowDefinition,\n) -> nx.DiGraph:\n    block_manifest_by_step_name = {\n        step.name: step for step in parsed_workflow_definition.steps\n    }\n    super_input_node = \"<super-input>\"\n    execution_graph = add_super_input_node_in_execution_graph(\n        execution_graph=execution_graph,\n        super_input_node=super_input_node,\n    )\n    execution_graph.nodes[super_input_node][NODE_COMPILATION_OUTPUT_PROPERTY] = (\n        InputNode(\n            node_category=NodeCategory.INPUT_NODE,\n            name=super_input_node,\n            selector=f\"$inputs.{super_input_node}\",\n            data_lineage=[],\n            input_manifest=None,  # this is expected never to be reached\n        )\n    )\n    top_level_data_lineage = set()\n    for node in traverse_graph_ensuring_parents_are_reached_first(\n        graph=execution_graph,\n        start_node=super_input_node,\n    ):\n        execution_graph = denote_data_flow_for_node(\n            execution_graph=execution_graph,\n            node=node,\n            block_manifest_by_step_name=block_manifest_by_step_name,\n            on_top_level_lineage_denoted=lambda element: top_level_data_lineage.add(\n                element\n            ),\n        )\n    execution_graph.remove_node(super_input_node)\n    if len(top_level_data_lineage) > 1:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler detected that the workflow contains multiple elements which create \"\n            f\"top-level data batches - for instance inputs and blocks that create batched outputs from \"\n            f\"scalar parameters. We know it sounds convoluted, but the bottom line is that this \"\n            f\"situation is known limitation of Workflows Compiler. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_batches_sources\",\n        )\n    if len(top_level_data_lineage) > 0:\n        top_level_data_lineage_marker = top_level_data_lineage.pop()\n    else:\n        top_level_data_lineage_marker = None\n    execution_graph.graph[TOP_LEVEL_LINEAGE_KEY] = top_level_data_lineage_marker\n    return execution_graph\n\n\ndef denote_data_flow_for_node(\n    execution_graph: DiGraph,\n    node: str,\n    block_manifest_by_step_name: Dict[str, WorkflowBlockManifest],\n    on_top_level_lineage_denoted: Callable[[str], None],\n) -> DiGraph:\n    if is_input_node(execution_graph=execution_graph, node=node):\n        # everything already set there, in the previous stage of compilation\n        return execution_graph\n    if is_step_node(execution_graph=execution_graph, node=node):\n        step_name = get_last_chunk_of_selector(selector=node)\n        if step_name not in block_manifest_by_step_name:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler expected manifest for the step: {step_name} to be registered \"\n                f\"but this condition is not met. This is most likely the bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | retrieving_predecessors_for_output\",\n            )\n        manifest = block_manifest_by_step_name[step_name]\n        return denote_data_flow_for_step(\n            execution_graph=execution_graph,\n            node=node,\n            manifest=manifest,\n            on_top_level_lineage_denoted=on_top_level_lineage_denoted,\n        )\n    if is_output_node(execution_graph=execution_graph, node=node):\n        # output is allowed to have exactly one predecessor\n        output_predecessors = list(execution_graph.predecessors(node))\n        if len(output_predecessors) != 1:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler expected each output in compiled graph to have one predecessor, \"\n                f\"but this condition is not met for node {node}. This is most likely the bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | retrieving_predecessors_for_output\",\n            )\n        predecessor_node = output_predecessors[0]\n        predecessor_node_data = node_as(\n            execution_graph=execution_graph,\n            node=predecessor_node,\n            expected_type=ExecutionGraphNode,\n        )\n        predecessor_node_lineage = predecessor_node_data.data_lineage\n        output_node_data = node_as(\n            execution_graph=execution_graph,\n            node=node,\n            expected_type=OutputNode,\n        )\n        output_node_data.data_lineage = predecessor_node_lineage\n        return execution_graph\n    raise AssumptionError(\n        f\"Workflow Compiler encountered node: {node} which cannot be classified as known node type. \"\n        f\"This is most likely the bug. Contact Roboflow team through github issues \"\n        f\"(https://github.com/roboflow/inference/issues) providing full \"\n        f\"context of the problem - including workflow definition you use.\",\n        context=\"workflow_compilation | execution_graph_construction | denoting_data_flow_for_step\",\n    )\n\n\ndef denote_data_flow_for_step(\n    execution_graph: DiGraph,\n    node: str,\n    manifest: WorkflowBlockManifest,\n    on_top_level_lineage_denoted: Callable[[str], None],\n) -> DiGraph:\n    all_control_flow_predecessors, all_non_control_flow_predecessors = (\n        separate_flow_control_predecessors_from_data_providers(\n            execution_graph=execution_graph, node=node\n        )\n    )\n    input_data = build_input_data_for_step(\n        manifest=manifest,\n        step_node=node,\n        data_providing_predecessors=all_non_control_flow_predecessors,\n        execution_graph=execution_graph,\n    )\n    step_name = get_last_chunk_of_selector(node)\n    step_node_data = node_as(\n        execution_graph=execution_graph,\n        node=node,\n        expected_type=StepNode,\n    )\n    parsed_step_input_selectors: List[ParsedSelector] = execution_graph.nodes[node][\n        PARSED_NODE_INPUT_SELECTORS_PROPERTY\n    ]\n    batch_compatibility_of_properties = retrieve_batch_compatibility_of_input_selectors(\n        input_selectors=parsed_step_input_selectors\n    )\n    scalar_parameters_to_be_batched = (\n        verify_declared_batch_compatibility_against_actual_inputs(\n            node=node,\n            step_node_data=step_node_data,\n            input_data=input_data,\n            batch_compatibility_of_properties=batch_compatibility_of_properties,\n        )\n    )\n    input_dimensionality_offsets = manifest.get_input_dimensionality_offsets()\n    print(\"input_dimensionality_offsets\", input_dimensionality_offsets)\n    verify_step_input_dimensionality_offsets(\n        step_name=step_name,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n    )\n    print(\"scalar_parameters_to_be_batched\", scalar_parameters_to_be_batched)\n    inputs_dimensionalities = get_inputs_dimensionalities(\n        step_name=step_name,\n        step_type=manifest.type,\n        input_data=input_data,\n        scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n    )\n    print(\"inputs_dimensionalities\", inputs_dimensionalities)\n    logger.debug(\n        f\"For step: {node}, detected the following input dimensionalities: {inputs_dimensionalities}\"\n    )\n    parameters_with_batch_inputs = grab_parameters_defining_batch_inputs(\n        inputs_dimensionalities=inputs_dimensionalities,\n    )\n    print(\"parameters_with_batch_inputs\", parameters_with_batch_inputs)\n    dimensionality_reference_property = manifest.get_dimensionality_reference_property()\n    print(\"dimensionality_reference_property\", dimensionality_reference_property)\n    output_dimensionality_offset = manifest.get_output_dimensionality_offset()\n    print(\"output_dimensionality_offset\", output_dimensionality_offset)\n    verify_step_input_dimensionality_offsets(\n        step_name=step_name,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n    )\n    verify_output_offset(\n        step_name=step_name,\n        parameters_with_batch_inputs=parameters_with_batch_inputs,\n        dimensionality_reference_property=dimensionality_reference_property,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n        output_dimensionality_offset=output_dimensionality_offset,\n    )\n    verify_input_data_dimensionality(\n        step_name=step_name,\n        step_type=manifest.type,\n        dimensionality_reference_property=dimensionality_reference_property,\n        inputs_dimensionalities=inputs_dimensionalities,\n        dimensionality_offstes=input_dimensionality_offsets,\n    )\n    all_lineages = get_input_data_lineage_excluding_auto_batch_casting(\n        step_name=step_name,\n        input_data=input_data,\n        scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n    )\n    verify_compatibility_of_input_data_lineage_with_control_flow_lineage(\n        step_name=step_name,\n        inputs_lineage=all_lineages,\n        flow_control_steps_selectors=all_control_flow_predecessors,\n        execution_graph=execution_graph,\n    )\n    step_node_data.input_data = input_data\n    step_node_data.dimensionality_reference_property = dimensionality_reference_property\n    step_node_data.batch_oriented_parameters = parameters_with_batch_inputs\n    step_node_data.step_execution_dimensionality = (\n        establish_step_execution_dimensionality(\n            inputs_dimensionalities=inputs_dimensionalities,\n            output_dimensionality_offset=output_dimensionality_offset,\n        )\n    )\n    truly_batch_parameters = parameters_with_batch_inputs.difference(\n        scalar_parameters_to_be_batched\n    )\n    if not truly_batch_parameters:\n        if manifest.get_output_dimensionality_offset() > 0:\n            # brave decision to open a Pandora box\n            data_lineage = [node]\n        else:\n            data_lineage = []\n    else:\n        data_lineage = establish_batch_oriented_step_lineage(\n            step_selector=node,\n            all_lineages=all_lineages,\n            input_data=input_data,\n            dimensionality_reference_property=dimensionality_reference_property,\n            output_dimensionality_offset=output_dimensionality_offset,\n        )\n    lineage_supports = get_lineage_support_for_auto_batch_casted_parameters(\n        input_dimensionalities=inputs_dimensionalities,\n        all_lineages_of_batch_parameters=all_lineages,\n        scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n    )\n    step_node_data.auto_batch_casting_lineage_supports = lineage_supports\n    print(\"lineage_supports\", lineage_supports)\n    print(\"Data lineage of block output\", data_lineage)\n    if data_lineage:\n        on_top_level_lineage_denoted(data_lineage[0])\n    step_node_data.data_lineage = data_lineage\n    return execution_graph\n\n\ndef separate_flow_control_predecessors_from_data_providers(\n    execution_graph: DiGraph,\n    node: str,\n) -> Tuple[List[str], List[str]]:\n    all_predecessors = list(execution_graph.predecessors(node))\n    all_control_flow_predecessors = [\n        predecessor\n        for predecessor in all_predecessors\n        if is_flow_control_step(execution_graph=execution_graph, node=predecessor)\n    ]\n    all_non_control_flow_predecessors = [\n        predecessor\n        for predecessor in all_predecessors\n        if not is_flow_control_step(execution_graph=execution_graph, node=predecessor)\n    ]\n    return all_control_flow_predecessors, all_non_control_flow_predecessors\n\n\ndef build_input_data_for_step(\n    manifest: WorkflowBlockManifest,\n    step_node: str,\n    data_providing_predecessors: List[str],\n    execution_graph: DiGraph,\n) -> StepInputData:\n    predecessors_by_property_name = get_predecessors_for_step_manifest_properties(\n        execution_graph=execution_graph,\n        step_node=step_node,\n        data_providing_predecessors=data_providing_predecessors,\n    )\n    manifest_fields_values = get_manifest_fields_values(step_manifest=manifest)\n    result = {}\n    for name, value in manifest_fields_values.items():\n        result[name] = build_input_property(\n            step_node=step_node,\n            manifest_property_name=name,\n            manifest_property_value=value,\n            predecessors_by_property_name=predecessors_by_property_name,\n            execution_graph=execution_graph,\n        )\n    return result\n\n\ndef get_predecessors_for_step_manifest_properties(\n    execution_graph: DiGraph, step_node: str, data_providing_predecessors: List[str]\n) -> Dict[str, List[PropertyPredecessorDefinition]]:\n    predecessors_by_property_name = defaultdict(list)\n    for predecessor in data_providing_predecessors:\n        edge_data = execution_graph.edges[(predecessor, step_node)]\n        # STEP_INPUT_SELECTORS_PROPERTY is optional, as special <super-input> node may be directly\n        # connected to step\n        selectors_associated_to_edge: List[ParsedSelector] = edge_data.get(\n            STEP_INPUT_SELECTORS_PROPERTY, []\n        )\n        for selector_associated_to_edge in selectors_associated_to_edge:\n            definition = PropertyPredecessorDefinition(\n                predecessor_selector=predecessor,\n                parsed_selector=selector_associated_to_edge,\n            )\n            predecessors_by_property_name[\n                selector_associated_to_edge.definition.property_name\n            ].append(definition)\n    return predecessors_by_property_name\n\n\ndef build_input_property(\n    step_node: str,\n    manifest_property_name: str,\n    manifest_property_value: Any,\n    predecessors_by_property_name: Dict[str, List[PropertyPredecessorDefinition]],\n    execution_graph: DiGraph,\n) -> Union[StepInputDefinition, CompoundStepInputDefinition]:\n    if manifest_property_name not in predecessors_by_property_name:\n        return StaticStepInputDefinition(\n            parameter_specification=ParameterSpecification(\n                parameter_name=manifest_property_name,\n            ),\n            category=NodeInputCategory.STATIC_VALUE,\n            value=manifest_property_value,\n        )\n    if isinstance(manifest_property_value, dict):\n        return build_nested_dictionary_for_input_property(\n            step_node=step_node,\n            manifest_property_name=manifest_property_name,\n            manifest_property_value=manifest_property_value,\n            predecessors_definitions=predecessors_by_property_name[\n                manifest_property_name\n            ],\n            execution_graph=execution_graph,\n        )\n    if isinstance(manifest_property_value, list):\n        return build_nested_list_for_input_property(\n            step_node=step_node,\n            manifest_property_name=manifest_property_name,\n            manifest_property_value=manifest_property_value,\n            predecessors_definitions=predecessors_by_property_name[\n                manifest_property_name\n            ],\n            execution_graph=execution_graph,\n        )\n    matching_predecessors_data = predecessors_by_property_name[manifest_property_name]\n    if len(matching_predecessors_data) != 1:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler deduced that property `{manifest_property_name}` of step `{step_node}` \"\n            f\"should be fed with data coming from exactly one execution graph node, but found \"\n            f\"{len(matching_predecessors_data)} data sources. This is most likely the bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n        )\n    predecessor_selector, predecessor_parsed_selector = (\n        matching_predecessors_data[0].predecessor_selector,\n        matching_predecessors_data[0].parsed_selector,\n    )\n    if is_input_node(execution_graph=execution_graph, node=predecessor_selector):\n        predecessor_node_data = node_as(\n            execution_graph=execution_graph,\n            node=matching_predecessors_data[0].predecessor_selector,\n            expected_type=InputNode,\n        )\n        category = (\n            NodeInputCategory.BATCH_INPUT_PARAMETER\n            if predecessor_node_data.is_batch_oriented()\n            else NodeInputCategory.NON_BATCH_INPUT_PARAMETER\n        )\n        return DynamicStepInputDefinition(\n            parameter_specification=ParameterSpecification(\n                parameter_name=manifest_property_name,\n            ),\n            category=category,\n            data_lineage=predecessor_node_data.data_lineage,\n            selector=predecessor_node_data.selector,\n        )\n    if is_step_node(execution_graph=execution_graph, node=predecessor_selector):\n        predecessor_node_data = node_as(\n            execution_graph=execution_graph,\n            node=matching_predecessors_data[0].predecessor_selector,\n            expected_type=StepNode,\n        )\n        category = (\n            NodeInputCategory.BATCH_STEP_OUTPUT\n            if predecessor_node_data.output_dimensionality > 0\n            else NodeInputCategory.NON_BATCH_STEP_OUTPUT\n        )\n        return DynamicStepInputDefinition(\n            parameter_specification=ParameterSpecification(\n                parameter_name=manifest_property_name,\n            ),\n            category=category,\n            data_lineage=predecessor_node_data.data_lineage,\n            selector=predecessor_parsed_selector.value,\n        )\n    raise AssumptionError(\n        public_message=f\"Workflow Compiler for property `{manifest_property_name}` of step `{step_node}` \"\n        f\"found data providing predecessor `{predecessor_selector}` which has unsupported step type.\"\n        f\"This is most likely the bug. \"\n        f\"Contact Roboflow team through github issues \"\n        f\"(https://github.com/roboflow/inference/issues) providing full \"\n        f\"context of the problem - including workflow definition you use.\",\n        context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n    )\n\n\ndef build_nested_dictionary_for_input_property(\n    step_node: str,\n    manifest_property_name: str,\n    manifest_property_value: dict,\n    predecessors_definitions: List[PropertyPredecessorDefinition],\n    execution_graph: DiGraph,\n) -> DictOfStepInputDefinitions:\n    nested_property_name2data: Dict[Optional[str], PropertyPredecessorDefinition] = {\n        predecessor_definition.parsed_selector.key: predecessor_definition\n        for predecessor_definition in predecessors_definitions\n    }\n    result = {}\n    for nested_dict_key, nested_dict_value in manifest_property_value.items():\n        if nested_dict_key not in nested_property_name2data:\n            result[nested_dict_key] = StaticStepInputDefinition(\n                parameter_specification=ParameterSpecification(\n                    parameter_name=manifest_property_name,\n                    nested_element_key=nested_dict_key,\n                ),\n                category=NodeInputCategory.STATIC_VALUE,\n                value=nested_dict_value,\n            )\n            continue\n        referred_node_selector = nested_property_name2data[\n            nested_dict_key\n        ].predecessor_selector\n        referred_node_parsed_selector = nested_property_name2data[\n            nested_dict_key\n        ].parsed_selector\n        if is_input_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=InputNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_INPUT_PARAMETER\n                if predecessor_node_data.is_batch_oriented()\n                else NodeInputCategory.NON_BATCH_INPUT_PARAMETER\n            )\n            result[nested_dict_key] = DynamicStepInputDefinition(\n                parameter_specification=ParameterSpecification(\n                    parameter_name=manifest_property_name,\n                    nested_element_key=nested_dict_key,\n                ),\n                category=category,\n                data_lineage=predecessor_node_data.data_lineage,\n                selector=predecessor_node_data.selector,\n            )\n            continue\n        if is_step_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=StepNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_STEP_OUTPUT\n                if predecessor_node_data.output_dimensionality > 0\n                else NodeInputCategory.NON_BATCH_STEP_OUTPUT\n            )\n            result[nested_dict_key] = DynamicStepInputDefinition(\n                parameter_specification=ParameterSpecification(\n                    parameter_name=manifest_property_name,\n                    nested_element_key=nested_dict_key,\n                ),\n                category=category,\n                data_lineage=predecessor_node_data.data_lineage,\n                selector=referred_node_parsed_selector.value,\n            )\n            continue\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for property `{manifest_property_name}` of step `{step_node}` \"\n            f\"found data providing predecessor `{referred_node_selector}` which has \"\n            f\"unsupported step type (key: {nested_dict_key} of nested data dictionary). \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n        )\n    return DictOfStepInputDefinitions(\n        name=manifest_property_name,\n        nested_definitions=result,\n    )\n\n\ndef get_manifest_fields_values(step_manifest: WorkflowBlockManifest) -> Dict[str, Any]:\n    result = {}\n    for field in step_manifest.model_fields:\n        if field in EXCLUDED_FIELDS:\n            continue\n        result[field] = getattr(step_manifest, field)\n    return result\n\n\ndef build_nested_list_for_input_property(\n    step_node: str,\n    manifest_property_name: str,\n    manifest_property_value: list,\n    predecessors_definitions: List[PropertyPredecessorDefinition],\n    execution_graph: DiGraph,\n) -> ListOfStepInputDefinitions:\n    nested_index2data: Dict[Optional[int], PropertyPredecessorDefinition] = {\n        e.parsed_selector.index: e for e in predecessors_definitions\n    }\n    result = []\n    for index, element in enumerate(manifest_property_value):\n        if index not in nested_index2data:\n            result.append(\n                StaticStepInputDefinition(\n                    parameter_specification=ParameterSpecification(\n                        parameter_name=manifest_property_name,\n                        nested_element_index=index,\n                    ),\n                    category=NodeInputCategory.STATIC_VALUE,\n                    value=element,\n                )\n            )\n            continue\n        referred_node_selector = nested_index2data[index].predecessor_selector\n        referred_node_parsed_selector = nested_index2data[index].parsed_selector\n        if is_input_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=InputNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_INPUT_PARAMETER\n                if predecessor_node_data.is_batch_oriented()\n                else NodeInputCategory.NON_BATCH_INPUT_PARAMETER\n            )\n            result.append(\n                DynamicStepInputDefinition(\n                    parameter_specification=ParameterSpecification(\n                        parameter_name=manifest_property_name,\n                        nested_element_index=index,\n                    ),\n                    category=category,\n                    data_lineage=predecessor_node_data.data_lineage,\n                    selector=predecessor_node_data.selector,\n                )\n            )\n            continue\n        if is_step_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=StepNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_STEP_OUTPUT\n                if predecessor_node_data.output_dimensionality > 0\n                else NodeInputCategory.NON_BATCH_STEP_OUTPUT\n            )\n            result.append(\n                DynamicStepInputDefinition(\n                    parameter_specification=ParameterSpecification(\n                        parameter_name=manifest_property_name,\n                        nested_element_index=index,\n                    ),\n                    category=category,\n                    data_lineage=predecessor_node_data.data_lineage,\n                    selector=referred_node_parsed_selector.value,\n                )\n            )\n            continue\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for property `{manifest_property_name}` of step `{step_node}` \"\n            f\"found data providing predecessor `{referred_node_selector}` which has \"\n            f\"unsupported step type (index: {index} of nested data list). \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n        )\n    return ListOfStepInputDefinitions(\n        name=manifest_property_name,\n        nested_definitions=result,\n    )\n\n\ndef verify_step_input_dimensionality_offsets(\n    step_name: str,\n    input_dimensionality_offsets: Dict[str, int],\n) -> None:\n    min_offset, max_offset = None, None\n    for offset in input_dimensionality_offsets.values():\n        if min_offset is None or offset < min_offset:\n            min_offset = offset\n        if max_offset is None or offset > max_offset:\n            max_offset = offset\n    if min_offset is None or max_offset is None:\n        return None\n    if min_offset < 0 or max_offset < 0:\n        raise BlockInterfaceError(\n            public_message=f\"Offsets could not be negative, but block defining step: {step_name} defines that values.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_input_offset_definitions\",\n        )\n    if abs(max_offset - min_offset) > 1:\n        raise BlockInterfaceError(\n            public_message=\"Offsets of input parameters could not differ more than 1, but block defining step {step_name} \"\n            f\"violates that rule.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_input_offset_definitions\",\n        )\n\n\ndef verify_output_offset(\n    step_name: str,\n    parameters_with_batch_inputs: Set[str],\n    input_dimensionality_offsets: Dict[str, int],\n    dimensionality_reference_property: Optional[str],\n    output_dimensionality_offset: int,\n) -> None:\n    if not parameters_with_batch_inputs and output_dimensionality_offset < 0:\n        raise StepInputDimensionalityError(\n            public_message=f\"Block defining step {step_name} defines negative dimensionality offset while only \"\n            f\"scalar inputs being provided - the block cannot run as there is no dimension to collapse.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if (\n        dimensionality_reference_property is not None\n        and dimensionality_reference_property not in parameters_with_batch_inputs\n    ):\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} defines dimensionality reference property \"\n            f\"which is not in scope of parameters bring batch-oriented input, which makes it impossible \"\n            f\"to use as reference for output dimensionality.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if output_dimensionality_offset not in {-1, 0, 1}:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} defines output dimensionality offset \"\n            f\"being {output_dimensionality_offset}, whereas it is only possible for that offset being \"\n            f\"in set [-1, 0, 1].\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    different_offsets = {o for o in input_dimensionality_offsets.values()}\n    if len(parameters_with_batch_inputs) != len(input_dimensionality_offsets):\n        # assumption of default offset being zero - and this one does not need to be manifested\n        # by block\n        different_offsets.add(0)\n    if 0 not in different_offsets and parameters_with_batch_inputs:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} explicitly defines input dimensionalities offsets\"\n            f\"with {input_dimensionality_offsets}, but the definition lack 0-level input, which is \"\n            f\"not allowed, as in this scenario offsets could be adjusted to include 0\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if len(different_offsets) > 1 and dimensionality_reference_property is None:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} explicitly defines input dimensionality \"\n            f\"offsets {input_dimensionality_offsets}. In this scenario it is required to provide dimensionality \"\n            f\"reference property.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if len(different_offsets) > 1 and output_dimensionality_offset != 0:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} explicitly defines input dimensionality \"\n            f\"offsets {input_dimensionality_offsets} and output dimensionality offset {output_dimensionality_offset} \"\n            f\"where the latter is not 0, but for inputs differing with dimensionality it is only possible to keep \"\n            f\"output dimensionality the same and point reference parameter.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n\n\ndef verify_input_data_dimensionality(\n    step_name: str,\n    step_type: str,\n    dimensionality_reference_property: Optional[str],\n    inputs_dimensionalities: Dict[str, Set[int]],\n    dimensionality_offstes: Dict[str, int],\n) -> None:\n    parameter_name2dimensionality_specification = (\n        grab_input_data_dimensionality_specifications(\n            step_name=step_name,\n            inputs_dimensionalities=inputs_dimensionalities,\n            dimensionality_offstes=dimensionality_offstes,\n        )\n    )\n    if not parameter_name2dimensionality_specification:\n        # nothing to check if no batch-oriented inputs\n        return None\n    different_dimensionalities_of_parameters = {\n        specification.actual_dimensionality\n        for specification in parameter_name2dimensionality_specification.values()\n    }\n    if dimensionality_reference_property is None:\n        if len(different_dimensionalities_of_parameters) > 1:\n            parameter2dimensionality = {\n                k: e.actual_dimensionality\n                for k, e in parameter_name2dimensionality_specification.items()\n            }\n            raise StepInputDimensionalityError(\n                public_message=f\"Block defining step {step_name} does not define dimensionality reference property, \"\n                f\"which means that all batch-oriented parameters must be at the same dimensionality level, \"\n                f\"but detected the following dimensionalities for parameters {parameter2dimensionality}\",\n                context=\"workflow_compilation | execution_graph_construction | denoting_step_inputs_dimensionality\",\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=step_name,\n                        block_type=step_type,\n                        block_details=f\"Dimensionality of input parameters doesn't match: {parameter2dimensionality}\",\n                    )\n                ],\n            )\n        return None\n    reference_specification = parameter_name2dimensionality_specification[\n        dimensionality_reference_property\n    ]\n    expected_dimensionalities = {\n        property_name: (e.expected_offset - reference_specification.expected_offset)\n        + reference_specification.actual_dimensionality\n        for property_name, e in parameter_name2dimensionality_specification.items()\n    }\n    if any(dim <= 0 for dim in expected_dimensionalities.values()):\n        raise StepInputDimensionalityError(\n            public_message=f\"Given the definition of block defining step {step_name} and data provided, \"\n            f\"the block would expect batch input dimensionality to be 0 or below, which is invalid.\",\n            context=\"workflow_compilation | execution_graph_construction | denoting_step_inputs_dimensionality\",\n        )\n    for property_name, expected_dimensionality in expected_dimensionalities.items():\n        actual_dimensionality = parameter_name2dimensionality_specification[\n            property_name\n        ].actual_dimensionality\n        if actual_dimensionality != expected_dimensionality:\n            raise StepInputDimensionalityError(\n                public_message=f\"Data fed into step `{step_name}` property `{property_name}` has \"\n                f\"actual dimensionality {actual_dimensionality}, \"\n                f\"when expected was {expected_dimensionality}\",\n                context=\"workflow_compilation | execution_graph_construction | denoting_step_inputs_dimensionality\",\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=step_name,\n                        block_type=step_type,\n                        property_name=property_name,\n                        property_details=f\"Expected dimensionality {expected_dimensionality}, but received dimensionality {actual_dimensionality}\",\n                    )\n                ],\n            )\n    return None\n\n\ndef grab_input_data_dimensionality_specifications(\n    step_name: str,\n    inputs_dimensionalities: Dict[str, Set[int]],\n    dimensionality_offstes: Dict[str, int],\n) -> Dict[str, InputDimensionalitySpecification]:\n    result = {}\n    for parameter_name, dimensionality in inputs_dimensionalities.items():\n        parameter_offset = dimensionality_offstes.get(parameter_name, 0)\n        non_zero_dimensionalities_for_parameter = {d for d in dimensionality if d > 0}\n        if len(non_zero_dimensionalities_for_parameter) > 1:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler for step: `{step_name}` and parameter: {parameter_name}\"\n                f\"found multiple different values of actual input dimensionalities: \"\n                f\"`{non_zero_dimensionalities_for_parameter}` which should be detected and addresses \"\n                f\"at earlier stages of compilation.\"\n                f\"This is most likely the bug. Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n            )\n        if non_zero_dimensionalities_for_parameter:\n            actual_dimensionality = next(iter(non_zero_dimensionalities_for_parameter))\n            result[parameter_name] = InputDimensionalitySpecification(\n                actual_dimensionality=actual_dimensionality,\n                expected_offset=parameter_offset,\n            )\n    return result\n\n\ndef verify_compatibility_of_input_data_lineage_with_control_flow_lineage(\n    step_name: str,\n    inputs_lineage: List[List[str]],\n    flow_control_steps_selectors: List[str],\n    execution_graph: DiGraph,\n) -> None:\n    already_spotted_input_lineages = set()\n    lineage_id2control_flow_steps = defaultdict(list)\n    batch_oriented_control_flow_lineages = []\n    for flow_control_steps_selector in flow_control_steps_selectors:\n        flow_control_step_data = node_as(\n            execution_graph=execution_graph,\n            node=flow_control_steps_selector,\n            expected_type=StepNode,\n        )\n        lineage = flow_control_step_data.data_lineage\n        lineage_id = identify_lineage(lineage=lineage)\n        if lineage_id not in already_spotted_input_lineages and lineage:\n            already_spotted_input_lineages.add(lineage_id)\n            batch_oriented_control_flow_lineages.append(lineage)\n        lineage_id2control_flow_steps[lineage_id].append(flow_control_steps_selector)\n    all_input_lineage_prefixes = get_all_batch_lineage_prefixes(lineages=inputs_lineage)\n    all_input_lineage_prefixes_hashes = {\n        identify_lineage(lineage=lineage) for lineage in all_input_lineage_prefixes\n    }\n    for control_flow_lineage in batch_oriented_control_flow_lineages:\n        control_flow_lineage_id = identify_lineage(lineage=control_flow_lineage)\n        if control_flow_lineage_id not in all_input_lineage_prefixes_hashes:\n            problematic_flow_control_steps = lineage_id2control_flow_steps[\n                control_flow_lineage_id\n            ]\n            raise ControlFlowDefinitionError(\n                public_message=f\"Step {step_name} execution is impacted by control flow outcome of the following \"\n                f\"steps {problematic_flow_control_steps} which make decision based on data that is \"\n                f\"not compatible with data fed to the step {step_name} - which would cause the step \"\n                f\"to never execute. This behaviour is invalid and prevented upfront by Workflows compiler.\",\n                context=\"workflow_compilation | execution_graph_construction | verification_of_flow_control_lineage\",\n            )\n\n\ndef get_all_batch_lineage_prefixes(lineages: List[List[str]]) -> List[List[str]]:\n    result = []\n    already_spotted = set()\n    for lineage in lineages:\n        lineage_prefixes = get_batch_lineage_prefixes(lineage=lineage)\n        for lineage_prefix in lineage_prefixes:\n            lineage_prefix_id = identify_lineage(lineage=lineage_prefix)\n            if lineage_prefix_id not in already_spotted:\n                already_spotted.add(lineage_prefix_id)\n                result.append(lineage_prefix)\n    return result\n\n\ndef get_batch_lineage_prefixes(lineage: List[str]) -> List[List[str]]:\n    if not lineage:\n        return []\n    result = []\n    prefix = []\n    for i in range(len(lineage)):\n        prefix.append(lineage[i])\n        result.append(copy(prefix))\n    return result\n\n\ndef get_inputs_dimensionalities(\n    step_name: str,\n    step_type: str,\n    input_data: StepInputData,\n    scalar_parameters_to_be_batched: Set[str],\n    input_dimensionality_offsets: Dict[str, int],\n) -> Dict[str, Set[int]]:\n    result = defaultdict(set)\n    dimensionalities_spotted = set()\n    offset_parameters = {\n        parameter: value\n        for parameter, value in input_dimensionality_offsets.items()\n        if value > 0\n    }\n    non_offset_parameters_dimensionality_values = set()\n    for property_name, input_definition in input_data.items():\n        if property_name in offset_parameters:\n            continue\n        if input_definition.is_compound_input():\n            for value in input_definition.iterate_through_definitions():\n                if value.is_batch_oriented():\n                    non_offset_parameters_dimensionality_values.add(\n                        value.get_dimensionality()\n                    )\n        elif input_definition.is_batch_oriented():\n            non_offset_parameters_dimensionality_values.add(\n                input_definition.get_dimensionality()\n            )\n    if len(non_offset_parameters_dimensionality_values) > 1:\n        raise StepInputDimensionalityError(\n            public_message=f\"For step {step_name} attempted to plug input data that are in different dimensions, \"\n            f\"whereas block defines the inputs to be equal in that terms.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_input_data\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=step_name,\n                    block_type=step_type,\n                    block_details=f\"Dimensionality of input parameters differs by more than 1. Detected dimensions: {dict(result)}\",\n                )\n            ],\n        )\n    non_offset_parameters_dimensionality_value = (\n        non_offset_parameters_dimensionality_values.pop()\n        if len(non_offset_parameters_dimensionality_values) > 0\n        else 1\n    )\n    for property_name, input_definition in input_data.items():\n        if input_definition.is_compound_input():\n            result[property_name] = get_compound_input_dimensionality(\n                step_name=step_name,\n                step_type=step_type,\n                property_name=property_name,\n                input_definition=input_definition,\n                scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n                non_offset_parameters_dimensionality_value=non_offset_parameters_dimensionality_value,\n                offset_parameters=offset_parameters,\n            )\n        else:\n            if property_name in scalar_parameters_to_be_batched:\n                if property_name not in offset_parameters:\n                    result[property_name] = {non_offset_parameters_dimensionality_value}\n                else:\n                    result[property_name] = (\n                        non_offset_parameters_dimensionality_value\n                        + offset_parameters[property_name]\n                    )\n            else:\n                result[property_name] = {input_definition.get_dimensionality()}\n        dimensionalities_spotted.update(result[property_name])\n    non_zero_dimensionalities_spotted = {d for d in dimensionalities_spotted if d != 0}\n    if len(non_zero_dimensionalities_spotted) > 0:\n        min_dim, max_dim = min(non_zero_dimensionalities_spotted), max(\n            non_zero_dimensionalities_spotted\n        )\n        if abs(max_dim - min_dim) > 1:\n            raise StepInputDimensionalityError(\n                public_message=f\"For step {step_name} attempted to plug input data differing in dimensionality more than 1\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_input_data\",\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=step_name,\n                        block_type=step_type,\n                        block_details=f\"Dimensionality of input parameters differs by more than 1. Detected dimensions: {dict(result)}\",\n                    )\n                ],\n            )\n    return result\n\n\ndef get_compound_input_dimensionality(\n    step_name: str,\n    property_name: str,\n    step_type: str,\n    input_definition: CompoundStepInputDefinition,\n    scalar_parameters_to_be_batched: Set[str],\n    offset_parameters: Dict[str, int],\n    non_offset_parameters_dimensionality_value: int,\n) -> Set[int]:\n    dimensionalities_spotted = set()\n    for definition in input_definition.iterate_through_definitions():\n        if (\n            property_name not in scalar_parameters_to_be_batched\n            or definition.is_batch_oriented()\n        ):\n            dimensionalities_spotted.add(definition.get_dimensionality())\n        elif property_name not in offset_parameters:\n            dimensionalities_spotted.add(non_offset_parameters_dimensionality_value)\n        else:\n            dimensionalities_spotted.add(\n                non_offset_parameters_dimensionality_value\n                + offset_parameters[property_name]\n            )\n    non_zero_dimensionalities = {e for e in dimensionalities_spotted if e != 0}\n    if len(non_zero_dimensionalities) > 1:\n        raise StepInputDimensionalityError(\n            public_message=f\"While evaluating compound property {property_name} of step {step_name}, \"\n            f\"detected multiple inputs of differing batch dimensionalities: {non_zero_dimensionalities}\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_input_data\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=step_name,\n                    block_type=step_type,\n                    property_name=property_name,\n                    property_details=f\"Detected multiple inputs of differing batch dimensionalities: {non_zero_dimensionalities}\",\n                )\n            ],\n        )\n    return dimensionalities_spotted\n\n\ndef grab_parameters_defining_batch_inputs(\n    inputs_dimensionalities: Dict[str, Set[int]],\n) -> Set[str]:\n    result = set()\n    for paremeter, dimensionalities in inputs_dimensionalities.items():\n        batch_dimensionalities = {d for d in dimensionalities if d > 0}\n        if len(batch_dimensionalities):\n            result.add(paremeter)\n    return result\n\n\ndef retrieve_batch_compatibility_of_input_selectors(\n    input_selectors: List[ParsedSelector],\n) -> Dict[str, Set[bool]]:\n    batch_compatibility_of_properties = defaultdict(set)\n    for parsed_selector in input_selectors:\n        for reference in parsed_selector.definition.allowed_references:\n            batch_compatibility_of_properties[\n                parsed_selector.definition.property_name\n            ].update(reference.points_to_batch)\n    return batch_compatibility_of_properties\n\n\ndef verify_declared_batch_compatibility_against_actual_inputs(\n    node: str,\n    step_node_data: StepNode,\n    input_data: StepInputData,\n    batch_compatibility_of_properties: Dict[str, Set[bool]],\n) -> Set[str]:\n    scalar_parameters_to_be_batched = set()\n    for property_name, input_definition in input_data.items():\n        if property_name not in batch_compatibility_of_properties:\n            # only values plugged via selectors are to be validated\n            continue\n        if input_definition.is_compound_input():\n            actual_input_is_batch = {\n                element.is_batch_oriented()\n                for element in input_definition.iterate_through_definitions()\n            }\n        else:\n            actual_input_is_batch = {input_definition.is_batch_oriented()}\n        batch_compatibility = batch_compatibility_of_properties[property_name]\n        step_accepts_batch_input = step_node_data.step_manifest.accepts_batch_input()\n        if (\n            step_accepts_batch_input\n            and batch_compatibility == {False}\n            and True in actual_input_is_batch\n        ):\n            raise ExecutionGraphStructureError(\n                public_message=f\"Detected invalid reference plugged \"\n                f\"into property `{property_name}` of step `{node}` - the step \"\n                f\"property do not accept batch-oriented inputs, yet the input selector \"\n                f\"holds one - this indicates the problem with \"\n                f\"construction of your Workflow - usually the problem occurs when non-batch oriented \"\n                f\"step inputs are filled with outputs of batch-oriented steps or batch-oriented inputs.\",\n                context=\"workflow_compilation | execution_graph_construction\",\n            )\n        if batch_compatibility == {True} and False in actual_input_is_batch:\n            scalar_parameters_to_be_batched.add(property_name)\n        print(\n            f\"property_name: {property_name}, batch_compatibility={batch_compatibility}, actual_input_is_batch={actual_input_is_batch}, step_accepts_batch_input={step_accepts_batch_input}\"\n        )\n    return scalar_parameters_to_be_batched\n\n\ndef get_input_data_lineage_excluding_auto_batch_casting(\n    step_name: str,\n    input_data: StepInputData,\n    scalar_parameters_to_be_batched: Set[str],\n) -> List[List[str]]:\n    lineage_deduplication_set = set()\n    lineages = []\n    for property_name, input_definition in input_data.items():\n        if property_name in scalar_parameters_to_be_batched:\n            continue\n        new_lineages_detected_within_property_data = get_lineage_for_input_property(\n            step_name=step_name,\n            property_name=property_name,\n            input_definition=input_definition,\n            lineage_deduplication_set=lineage_deduplication_set,\n        )\n        lineages.extend(new_lineages_detected_within_property_data)\n    if not lineages:\n        return lineages\n    verify_lineages(step_name=step_name, detected_lineages=lineages)\n    return lineages\n\n\ndef get_lineage_support_for_auto_batch_casted_parameters(\n    input_dimensionalities: Dict[str, Set[int]],\n    scalar_parameters_to_be_batched: Set[str],\n    all_lineages_of_batch_parameters: List[List[str]],\n) -> Dict[str, AutoBatchCastingConfig]:\n    longest_lineage_support = find_longest_lineage_support(\n        all_lineages_of_batch_parameters=all_lineages_of_batch_parameters,\n    )\n    result = {}\n    for parameter_name in scalar_parameters_to_be_batched:\n        parameter_dimensionality = max(input_dimensionalities[parameter_name])\n        if longest_lineage_support is None:\n            lineage_support = None\n        else:\n            lineage_support = longest_lineage_support[:parameter_dimensionality]\n        result[parameter_name] = AutoBatchCastingConfig(\n            casted_dimensionality=parameter_dimensionality,\n            lineage_support=lineage_support,\n        )\n    print(\"DUMMY\", result)\n    return result\n\n\ndef find_longest_lineage_support(\n    all_lineages_of_batch_parameters: List[List[str]],\n) -> Optional[List[str]]:\n    result = max(all_lineages_of_batch_parameters, key=len, default=[])\n    if len(result) == 0:\n        return None\n    return result\n\n\ndef get_lineage_for_input_property(\n    step_name: str,\n    property_name: str,\n    input_definition: Union[StepInputDefinition, CompoundStepInputDefinition],\n    lineage_deduplication_set: Set[int],\n) -> List[List[str]]:\n    if input_definition.is_compound_input():\n        return get_lineage_from_compound_input(\n            step_name=step_name,\n            property_name=property_name,\n            input_definition=input_definition,\n            lineage_deduplication_set=lineage_deduplication_set,\n        )\n    lineages = []\n    if input_definition.is_batch_oriented():\n        lineage = input_definition.data_lineage\n        lineage_id = identify_lineage(lineage=lineage)\n        if lineage_id not in lineage_deduplication_set:\n            lineage_deduplication_set.add(lineage_id)\n            lineages.append(lineage)\n    return lineages\n\n\ndef get_lineage_from_compound_input(\n    step_name: str,\n    property_name: str,\n    input_definition: Union[StepInputDefinition, CompoundStepInputDefinition],\n    lineage_deduplication_set: Set[int],\n) -> List[List[str]]:\n    lineages = []\n    for nested_element in input_definition.iterate_through_definitions():\n        if nested_element.is_batch_oriented():\n            lineage = nested_element.data_lineage\n            lineage_id = identify_lineage(lineage=lineage)\n            if lineage_id not in lineage_deduplication_set:\n                lineage_deduplication_set.add(lineage_id)\n                lineages.append(lineage)\n    if len(lineages) > 1:\n        raise StepInputLineageError(\n            public_message=f\"Input data provided for step: `{step_name}` comes with multiple different lineages \"\n            f\"{lineages} for property `{property_name}` accepting \"\n            f\"multiple selectors, which is not allowed.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    return lineages\n\n\ndef verify_lineages(step_name: str, detected_lineages: List[List[str]]) -> None:\n    lineages_by_length = defaultdict(list)\n    for lineage in detected_lineages:\n        lineages_by_length[len(lineage)].append(lineage)\n    if len(lineages_by_length) > 2:\n        raise StepInputLineageError(\n            public_message=f\"Input data provided for step: `{step_name}` comes with lineages at more than two \"\n            f\"dimensionality levels, which should not be possible.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    lineage_lengths = sorted(lineages_by_length.keys())\n    for lineage_length in lineage_lengths:\n        if len(lineages_by_length[lineage_length]) > 1:\n            raise StepInputLineageError(\n                public_message=f\"Among step `{step_name}` inputs found different lineages at the same  \"\n                f\"dimensionality levels dimensionality.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if len(lineages_by_length[lineage_lengths[-1]]) > 1 and len(lineage_lengths) < 2:\n        raise StepInputLineageError(\n            public_message=f\"If lineage differ at the last level, then Execution Engine requires at least one \"\n            f\"higher-dimension  input that will come with common lineage, but this is not the \"\n            f\"case for step {step_name}.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    if len(lineage_lengths) == 2:\n        reference_lineage = lineages_by_length[lineage_lengths[0]][0]\n        if reference_lineage != lineages_by_length[lineage_lengths[1]][0][:-1]:\n            raise StepInputLineageError(\n                public_message=f\"Step `{step_name}` inputs does not share common lineage. Differing element: \"\n                f\"{lineages_by_length[lineage_lengths[1]][0]}, \"\n                f\"reference lineage prefix: {reference_lineage}\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n\n\ndef establish_step_execution_dimensionality(\n    inputs_dimensionalities: Dict[str, Set[int]],\n    output_dimensionality_offset: int,\n) -> int:\n    step_execution_dimensionality = 0\n    non_zero_dimensionalities = {\n        dimensionality\n        for dimensionalities in inputs_dimensionalities.values()\n        for dimensionality in dimensionalities\n        if dimensionality > 0\n    }\n    if len(non_zero_dimensionalities) > 0:\n        step_execution_dimensionality = min(non_zero_dimensionalities)\n        if output_dimensionality_offset < 0:\n            step_execution_dimensionality -= 1\n    return step_execution_dimensionality\n\n\ndef establish_batch_oriented_step_lineage(\n    step_selector: str,\n    all_lineages: List[List[str]],\n    input_data: StepInputData,\n    dimensionality_reference_property: Optional[str],\n    output_dimensionality_offset: int,\n) -> List[str]:\n    reference_lineage = get_reference_lineage(\n        step_selector=step_selector,\n        all_lineages=all_lineages,\n        input_data=input_data,\n        dimensionality_reference_property=dimensionality_reference_property,\n    )\n    if output_dimensionality_offset < 0:\n        result_dimensionality = reference_lineage[:output_dimensionality_offset]\n        # if len(result_dimensionality) == 0:\n        #     raise StepOutputLineageError(\n        #         public_message=f\"Step {step_selector} is to decrease dimensionality, but it is not possible if \"\n        #         f\"input dimensionality is not greater or equal 2, otherwise output would not \"\n        #         f\"be batch-oriented.\",\n        #         context=\"workflow_compilation | execution_graph_construction | establishing_step_output_lineage\",\n        #     )\n        return result_dimensionality\n    if output_dimensionality_offset == 0:\n        return reference_lineage\n    reference_lineage.append(step_selector)\n    return reference_lineage\n\n\ndef get_reference_lineage(\n    step_selector: str,\n    all_lineages: List[List[str]],\n    input_data: StepInputData,\n    dimensionality_reference_property: Optional[str],\n) -> List[str]:\n    if len(all_lineages) == 1:\n        return copy(all_lineages[0])\n    if dimensionality_reference_property not in input_data:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` expected dimensionality_reference_property \"\n            f\"presence to be verified at earlier stages, which did not happen as expected. \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    property_data = input_data[dimensionality_reference_property]\n    if property_data.is_compound_input():\n        lineage = None\n        for nested_element in property_data.iterate_through_definitions():\n            if nested_element.is_batch_oriented():\n                lineage = copy(nested_element.data_lineage)\n                return lineage\n        if lineage is None:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n                f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if not property_data.is_batch_oriented():\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n            f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    return copy(property_data.data_lineage)\n\n\ndef get_property_with_invalid_selector(\n    manifest: WorkflowBlockManifest, step_property: str\n) -> Optional[str]:\n    property_name = None\n    for key, value in manifest.__dict__.items():\n        if isinstance(value, str) and step_property in value:\n            property_name = key\n            break\n    return property_name\n\n\ndef add_super_input_node_in_execution_graph(\n    execution_graph: DiGraph,\n    super_input_node: str,\n) -> DiGraph:\n    nodes_to_attach_super_input_into = get_nodes_of_specific_category(\n        execution_graph=execution_graph,\n        category=NodeCategory.INPUT_NODE,\n    )\n    step_nodes_without_predecessors = [\n        node\n        for node in execution_graph.nodes\n        if not list(execution_graph.predecessors(node))\n    ]\n    nodes_to_attach_super_input_into.update(step_nodes_without_predecessors)\n    execution_graph.add_node(super_input_node)\n    for node in nodes_to_attach_super_input_into:\n        execution_graph.add_edge(super_input_node, node)\n    return execution_graph\n",
    "optimized_raw_markdown": "",
    "optimized_function_only": "def find_longest_lineage_support(\n    all_lineages_of_batch_parameters: List[List[str]],\n) -> Optional[List[str]]:\n    result = max(all_lineages_of_batch_parameters, key=len, default=[])\n    if len(result) == 0:\n        return None\n    return result\n",
    "original_file_content": "import itertools\nfrom collections import defaultdict\nfrom copy import copy, deepcopy\nfrom typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union\nfrom uuid import uuid4\n\nimport networkx as nx\nfrom networkx import DiGraph\n\nfrom inference.core import logger\nfrom inference.core.workflows.errors import (\n    AssumptionError,\n    BlockInterfaceError,\n    ControlFlowDefinitionError,\n    ExecutionGraphStructureError,\n    InvalidReferenceTargetError,\n    StepInputDimensionalityError,\n    StepInputLineageError,\n    StepOutputLineageError,\n    WorkflowBlockError,\n)\nfrom inference.core.workflows.execution_engine.constants import (\n    NODE_COMPILATION_OUTPUT_PROPERTY,\n    PARSED_NODE_INPUT_SELECTORS_PROPERTY,\n    TOP_LEVEL_LINEAGE_KEY,\n    WORKFLOW_INPUT_BATCH_LINEAGE_ID,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    InputType,\n    JsonField,\n    OutputDefinition,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    STEP_AS_SELECTED_ELEMENT,\n    Kind,\n)\nfrom inference.core.workflows.execution_engine.introspection.entities import (\n    ParsedSelector,\n)\nfrom inference.core.workflows.execution_engine.introspection.selectors_parser import (\n    get_step_selectors,\n)\nfrom inference.core.workflows.execution_engine.profiling.core import (\n    WorkflowsProfiler,\n    execution_phase,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import (\n    AutoBatchCastingConfig,\n    CompoundStepInputDefinition,\n    DictOfStepInputDefinitions,\n    DynamicStepInputDefinition,\n    ExecutionGraphNode,\n    InputDimensionalitySpecification,\n    InputNode,\n    ListOfStepInputDefinitions,\n    NodeCategory,\n    NodeInputCategory,\n    OutputNode,\n    ParameterSpecification,\n    ParsedWorkflowDefinition,\n    PropertyPredecessorDefinition,\n    StaticStepInputDefinition,\n    StepInputData,\n    StepInputDefinition,\n    StepNode,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.graph_traversal import (\n    traverse_graph_ensuring_parents_are_reached_first,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.reference_type_checker import (\n    validate_reference_kinds,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import (\n    construct_input_selector,\n    construct_output_selector,\n    construct_step_selector,\n    get_last_chunk_of_selector,\n    get_nodes_of_specific_category,\n    get_step_selector_from_its_output,\n    identify_lineage,\n    is_flow_control_step,\n    is_input_node,\n    is_input_selector,\n    is_output_node,\n    is_step_node,\n    is_step_output_selector,\n    is_step_selector,\n    node_as,\n)\nfrom inference.core.workflows.prototypes.block import WorkflowBlockManifest\n\nNODE_DEFINITION_KEY = \"definition\"\nSTEP_INPUT_SELECTORS_PROPERTY = \"step_input_selectors\"\nEXCLUDED_FIELDS = {\"type\", \"name\"}\n\n\n@execution_phase(\n    name=\"execution_graph_creation\",\n    categories=[\"execution_engine_operation\"],\n)\ndef prepare_execution_graph(\n    workflow_definition: ParsedWorkflowDefinition,\n    profiler: Optional[WorkflowsProfiler] = None,\n) -> DiGraph:\n    execution_graph = construct_graph(\n        workflow_definition=workflow_definition,\n    )\n    if not nx.is_directed_acyclic_graph(execution_graph):\n        raise ExecutionGraphStructureError(\n            public_message=f\"Detected cycle in execution graph. This means that there is output from one \"\n            f\"step that is connected to input of other step creating loop in the graph that would \"\n            f\"never end if executed.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    return denote_data_flow_in_workflow(\n        execution_graph=execution_graph,\n        parsed_workflow_definition=workflow_definition,\n    )\n\n\ndef construct_graph(\n    workflow_definition: ParsedWorkflowDefinition,\n) -> DiGraph:\n    execution_graph = nx.DiGraph()\n    execution_graph = add_input_nodes_for_graph(\n        inputs=workflow_definition.inputs,\n        execution_graph=execution_graph,\n    )\n    execution_graph = add_steps_nodes_for_graph(\n        steps=workflow_definition.steps,\n        execution_graph=execution_graph,\n    )\n    execution_graph = add_output_nodes_for_graph(\n        outputs=workflow_definition.outputs,\n        execution_graph=execution_graph,\n    )\n    execution_graph = add_steps_edges(\n        workflow_definition=workflow_definition,\n        execution_graph=execution_graph,\n    )\n    return add_edges_for_outputs(\n        workflow_definition=workflow_definition,\n        execution_graph=execution_graph,\n    )\n\n\ndef add_input_nodes_for_graph(\n    inputs: List[InputType],\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for input_spec in inputs:\n        input_selector = construct_input_selector(input_name=input_spec.name)\n        if input_spec.is_batch_oriented():\n            if input_spec.dimensionality < 1:\n                raise ExecutionGraphStructureError(\n                    public_message=f\"Detected batch oriented input `{input_spec.name}` with \"\n                    f\"declared dimensionality `{input_spec.dimensionality}` which is below \"\n                    f\"one (one is minimum dimensionality of the batch). Fix input definition in\"\n                    f\"your Workflow.\",\n                    context=\"workflow_compilation | execution_graph_construction\",\n                )\n            data_lineage = [WORKFLOW_INPUT_BATCH_LINEAGE_ID]\n            for _ in range(input_spec.dimensionality - 1):\n                # TODO: this may end up being a bug - with ability for multi-step debugging, if we will\n                #  ever have a situation that there will be multiple step outputs with nested\n                #  dimensionality with the same lineage, this re-construction method will\n                #  assign a different lineage identifier, causing the inputs being non-composable in\n                #  a single execution branch\n                data_lineage.append(f\"{uuid4()}\")\n        else:\n            data_lineage = []\n        compilation_output = InputNode(\n            node_category=NodeCategory.INPUT_NODE,\n            name=input_spec.name,\n            selector=input_selector,\n            data_lineage=data_lineage,\n            input_manifest=input_spec,\n        )\n        execution_graph.add_node(\n            input_selector,\n            **{\n                NODE_COMPILATION_OUTPUT_PROPERTY: compilation_output,\n            },\n        )\n    return execution_graph\n\n\ndef add_steps_nodes_for_graph(\n    steps: List[WorkflowBlockManifest],\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for step in steps:\n        step_selector = construct_step_selector(step_name=step.name)\n        compilation_output = StepNode(\n            node_category=NodeCategory.STEP_NODE,\n            name=step.name,\n            selector=step_selector,\n            data_lineage=[],\n            step_manifest=step,\n        )\n        execution_graph.add_node(\n            step_selector,\n            **{\n                NODE_COMPILATION_OUTPUT_PROPERTY: compilation_output,\n            },\n        )\n    return execution_graph\n\n\ndef add_output_nodes_for_graph(\n    outputs: List[JsonField],\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for output_spec in outputs:\n        output_selector = construct_output_selector(name=output_spec.name)\n        compilation_output = OutputNode(\n            node_category=NodeCategory.OUTPUT_NODE,\n            name=output_spec.name,\n            selector=output_selector,\n            data_lineage=[],\n            output_manifest=output_spec,\n        )\n        execution_graph.add_node(\n            output_selector,\n            **{\n                NODE_COMPILATION_OUTPUT_PROPERTY: compilation_output,\n            },\n        )\n    return execution_graph\n\n\ndef add_steps_edges(\n    workflow_definition: ParsedWorkflowDefinition,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for step in workflow_definition.steps:\n        source_step_selector = construct_step_selector(step_name=step.name)\n        step_selectors = get_step_selectors(step_manifest=step)\n        execution_graph.nodes[source_step_selector][\n            PARSED_NODE_INPUT_SELECTORS_PROPERTY\n        ] = step_selectors\n        execution_graph = add_edges_for_step(\n            execution_graph=execution_graph,\n            source_step_selector=source_step_selector,\n            target_step_parsed_selectors=step_selectors,\n        )\n    return execution_graph\n\n\ndef add_edges_for_step(\n    execution_graph: DiGraph,\n    source_step_selector: str,\n    target_step_parsed_selectors: List[ParsedSelector],\n) -> DiGraph:\n    for target_step_parsed_selector in target_step_parsed_selectors:\n        execution_graph = add_edge_for_step(\n            execution_graph=execution_graph,\n            source_step_selector=source_step_selector,\n            target_step_parsed_selector=target_step_parsed_selector,\n        )\n    return execution_graph\n\n\ndef add_edge_for_step(\n    execution_graph: DiGraph,\n    source_step_selector: str,\n    target_step_parsed_selector: ParsedSelector,\n) -> DiGraph:\n    target_step_selector = get_step_selector_from_its_output(\n        step_output_selector=target_step_parsed_selector.value\n    )\n    verify_edge_is_created_between_existing_nodes(\n        execution_graph=execution_graph,\n        start=source_step_selector,\n        end=target_step_selector,\n    )\n    if is_step_selector(target_step_parsed_selector.value):\n        return establish_flow_control_edge(\n            source_step_selector=source_step_selector,\n            target_step_parsed_selector=target_step_parsed_selector,\n            execution_graph=execution_graph,\n        )\n    if is_input_selector(target_step_parsed_selector.value):\n        input_node_compilation_data = node_as(\n            execution_graph=execution_graph,\n            node=target_step_parsed_selector.value,\n            expected_type=InputNode,\n        )\n        actual_input_kind = input_node_compilation_data.input_manifest.kind\n    else:\n        other_step_compilation_data = node_as(\n            execution_graph=execution_graph,\n            node=target_step_selector,\n            expected_type=StepNode,\n        )\n        source_step_compilation_data = node_as(\n            execution_graph=execution_graph,\n            node=source_step_selector,\n            expected_type=StepNode,\n        )\n        actual_input_kind = get_kind_of_value_provided_in_step_output(\n            step_manifest=other_step_compilation_data.step_manifest,\n            step_property=get_last_chunk_of_selector(\n                selector=target_step_parsed_selector.value\n            ),\n            source_step_manifest=source_step_compilation_data.step_manifest,\n        )\n    expected_input_kind = list(\n        itertools.chain.from_iterable(\n            ref.kind\n            for ref in target_step_parsed_selector.definition.allowed_references\n        )\n    )\n    error_message = (\n        f\"Failed to validate reference provided for step: {source_step_selector} regarding property: \"\n        f\"{target_step_parsed_selector.definition.property_name} with value: {target_step_parsed_selector.value}. \"\n        f\"Allowed kinds of references for this property: {list(set(e.name for e in expected_input_kind))}. \"\n        f\"Types of output for referred property: \"\n        f\"{list(set(a.name if isinstance(a, Kind) else a for a in actual_input_kind))}\"\n    )\n    validate_reference_kinds(\n        expected=expected_input_kind,\n        actual=actual_input_kind,\n        error_message=error_message,\n    )\n    if execution_graph.has_edge(target_step_selector, source_step_selector):\n        edge_data = execution_graph.edges[(target_step_selector, source_step_selector)]\n        if STEP_INPUT_SELECTORS_PROPERTY not in edge_data:\n            edge_data[STEP_INPUT_SELECTORS_PROPERTY] = []\n        edge_data[STEP_INPUT_SELECTORS_PROPERTY].append(\n            target_step_parsed_selector,\n        )\n    else:\n        execution_graph.add_edge(\n            target_step_selector,\n            source_step_selector,\n            **{STEP_INPUT_SELECTORS_PROPERTY: [target_step_parsed_selector]},\n        )\n    return execution_graph\n\n\ndef establish_flow_control_edge(\n    source_step_selector: str,\n    target_step_parsed_selector: ParsedSelector,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    if not step_definition_allows_flow_control_references(\n        parsed_selector=target_step_parsed_selector\n    ):\n        raise ExecutionGraphStructureError(\n            public_message=f\"Detected reference to other step in manifest of step {source_step_selector}. \"\n            f\"This is not allowed, as step manifest does not define any properties of type `StepSelector` \"\n            f\"allowing for defining connections between steps that represent flow control in `workflows`.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    target_step_selector = get_step_selector_from_its_output(\n        step_output_selector=target_step_parsed_selector.value\n    )\n    source_compilation_data = node_as(\n        execution_graph=execution_graph,\n        node=source_step_selector,\n        expected_type=StepNode,\n    )\n    target_compilation_data = node_as(\n        execution_graph=execution_graph,\n        node=target_step_selector,\n        expected_type=StepNode,\n    )\n    nodes_categories = {\n        source_compilation_data.node_category,\n        target_compilation_data.node_category,\n    }\n    if nodes_categories != {NodeCategory.STEP_NODE}:\n        raise ExecutionGraphStructureError(\n            public_message=f\"Attempted to create flow-control connection between workflow nodes: \"\n            f\"{source_step_selector} and {target_step_selector}, one of which is not denoted\"\n            f\"as step node.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    execution_graph.add_edge(\n        source_step_selector,\n        target_step_selector,\n    )\n    if target_step_selector in source_compilation_data.child_execution_branches:\n        raise ExecutionGraphStructureError(\n            public_message=f\"While establishing flow-control connection between source `{source_step_selector}` \"\n            f\"and target `{target_step_selector}` it was discovered that source step defines\"\n            f\"control flow transition into target one more than once, which is not allowed as \"\n            f\"that situation creates ambiguity in selecting execution branch.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n        )\n    execution_branch_name = f\"Branch[{source_step_selector} -> {target_step_parsed_selector.definition.property_name}]\"\n    source_compilation_data.child_execution_branches[target_step_selector] = (\n        execution_branch_name\n    )\n    target_compilation_data.execution_branches_impacting_inputs.add(\n        execution_branch_name\n    )\n    return execution_graph\n\n\ndef step_definition_allows_flow_control_references(\n    parsed_selector: ParsedSelector,\n) -> bool:\n    return any(\n        definition.selected_element == STEP_AS_SELECTED_ELEMENT\n        for definition in parsed_selector.definition.allowed_references\n    )\n\n\ndef get_kind_of_value_provided_in_step_output(\n    step_manifest: WorkflowBlockManifest,\n    step_property: str,\n    source_step_manifest: WorkflowBlockManifest,\n) -> List[Kind]:\n    referred_node_outputs = step_manifest.get_actual_outputs()\n    actual_kind = []\n    matched_property = False\n    for output in referred_node_outputs:\n        if output.name != step_property:\n            continue\n        matched_property = True\n        actual_kind.extend(output.kind)\n    if not matched_property:\n        property_name = get_property_with_invalid_selector(\n            manifest=source_step_manifest,\n            step_property=step_property,\n        )\n        raise ExecutionGraphStructureError(\n            public_message=f\"Found reference to non-existing property `{step_property}` of step `{step_manifest.name}`.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=source_step_manifest.name,\n                    block_type=source_step_manifest.type,\n                    property_name=property_name,\n                    property_details=f\"'{step_manifest.name}.{step_property}' is an invalid reference\",\n                )\n            ],\n        )\n    return actual_kind\n\n\ndef add_edges_for_step_inputs(\n    execution_graph: DiGraph,\n    input_selectors: Set[str],\n    step_selector: str,\n) -> DiGraph:\n    for input_selector in input_selectors:\n        if is_step_output_selector(selector_or_value=input_selector):\n            input_selector = get_step_selector_from_its_output(\n                step_output_selector=input_selector\n            )\n        verify_edge_is_created_between_existing_nodes(\n            execution_graph=execution_graph,\n            start=input_selector,\n            end=step_selector,\n        )\n        execution_graph.add_edge(input_selector, step_selector)\n    return execution_graph\n\n\ndef add_edges_for_outputs(\n    workflow_definition: ParsedWorkflowDefinition,\n    execution_graph: DiGraph,\n) -> DiGraph:\n    for output in workflow_definition.outputs:\n        node_selector = output.selector\n        if is_step_output_selector(selector_or_value=node_selector):\n            node_selector = get_step_selector_from_its_output(\n                step_output_selector=node_selector\n            )\n        output_selector = construct_output_selector(name=output.name)\n        verify_edge_is_created_between_existing_nodes(\n            execution_graph=execution_graph,\n            start=node_selector,\n            end=output_selector,\n        )\n        output_node_manifest = node_as(\n            execution_graph=execution_graph,\n            node=output_selector,\n            expected_type=OutputNode,\n        )\n        if is_step_output_selector(selector_or_value=output.selector):\n            step_manifest = execution_graph.nodes[node_selector][\n                NODE_COMPILATION_OUTPUT_PROPERTY\n            ].step_manifest\n            step_outputs = step_manifest.get_actual_outputs()\n            denote_output_node_kind_based_on_step_outputs(\n                output_selector=output.selector,\n                step_outputs=step_outputs,\n                output_node_manifest=output_node_manifest,\n            )\n        else:\n            input_manifest = node_as(\n                execution_graph=execution_graph,\n                node=node_selector,\n                expected_type=InputNode,\n            ).input_manifest\n            output_node_manifest.kind = copy(input_manifest.kind)\n        execution_graph.add_edge(node_selector, output_selector)\n    return execution_graph\n\n\ndef verify_edge_is_created_between_existing_nodes(\n    execution_graph: DiGraph,\n    start: str,\n    end: str,\n) -> None:\n    if not execution_graph.has_node(start) or not execution_graph.has_node(end):\n        invalid_block = start if not execution_graph.has_node(start) else end\n        referencing_block = end if invalid_block == start else start\n\n        step_type = None\n        property_name = None\n        if execution_graph.has_node(referencing_block):\n            if is_step_node(execution_graph, referencing_block):\n                step_manifest = node_as(\n                    execution_graph=execution_graph,\n                    node=referencing_block,\n                    expected_type=StepNode,\n                ).step_manifest\n                step_type = step_manifest.type\n                property_name = get_property_with_invalid_selector(\n                    manifest=step_manifest,\n                    step_property=invalid_block,\n                )\n\n        block_id = (\n            \"$outputs\"\n            if referencing_block.startswith(\"$outputs.\")\n            else get_last_chunk_of_selector(selector=referencing_block)\n        )\n        property_name = (\n            get_last_chunk_of_selector(selector=referencing_block)\n            if referencing_block.startswith(\"$outputs.\")\n            else property_name\n        )\n\n        is_input = is_input_selector(selector_or_value=invalid_block)\n        raise InvalidReferenceTargetError(\n            public_message=f\"Workflow references '{invalid_block}' which points to a non-existent {is_input and 'input parameter' or 'block'}.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=block_id,\n                    block_type=step_type,\n                    property_name=property_name,\n                    property_details=f\"Invalid reference to {invalid_block}\",\n                ),\n            ],\n        )\n\n\ndef denote_output_node_kind_based_on_step_outputs(\n    output_selector: str,\n    step_outputs: List[OutputDefinition],\n    output_node_manifest: OutputNode,\n) -> None:\n    selected_output_name = get_last_chunk_of_selector(selector=output_selector)\n    kinds_for_outputs = {output.name: output.kind for output in step_outputs}\n\n    if selected_output_name == \"*\":\n        output_node_manifest.kind = deepcopy(kinds_for_outputs)\n        return None\n    if selected_output_name not in kinds_for_outputs:\n        output_name = output_node_manifest.output_manifest.name\n\n        raise InvalidReferenceTargetError(\n            public_message=f\"Workflow output references '{output_selector}' which points to a non-existent block property.\",\n            context=\"workflow_compilation | execution_graph_construction\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=\"$outputs\",\n                    property_name=output_name,\n                    property_details=f\"Invalid reference to {output_selector}\",\n                ),\n            ],\n        )\n    output_node_manifest.kind = copy(kinds_for_outputs[selected_output_name])\n    return None\n\n\ndef denote_data_flow_in_workflow(\n    execution_graph: DiGraph,\n    parsed_workflow_definition: ParsedWorkflowDefinition,\n) -> nx.DiGraph:\n    block_manifest_by_step_name = {\n        step.name: step for step in parsed_workflow_definition.steps\n    }\n    super_input_node = \"<super-input>\"\n    execution_graph = add_super_input_node_in_execution_graph(\n        execution_graph=execution_graph,\n        super_input_node=super_input_node,\n    )\n    execution_graph.nodes[super_input_node][NODE_COMPILATION_OUTPUT_PROPERTY] = (\n        InputNode(\n            node_category=NodeCategory.INPUT_NODE,\n            name=super_input_node,\n            selector=f\"$inputs.{super_input_node}\",\n            data_lineage=[],\n            input_manifest=None,  # this is expected never to be reached\n        )\n    )\n    top_level_data_lineage = set()\n    for node in traverse_graph_ensuring_parents_are_reached_first(\n        graph=execution_graph,\n        start_node=super_input_node,\n    ):\n        execution_graph = denote_data_flow_for_node(\n            execution_graph=execution_graph,\n            node=node,\n            block_manifest_by_step_name=block_manifest_by_step_name,\n            on_top_level_lineage_denoted=lambda element: top_level_data_lineage.add(\n                element\n            ),\n        )\n    execution_graph.remove_node(super_input_node)\n    if len(top_level_data_lineage) > 1:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler detected that the workflow contains multiple elements which create \"\n            f\"top-level data batches - for instance inputs and blocks that create batched outputs from \"\n            f\"scalar parameters. We know it sounds convoluted, but the bottom line is that this \"\n            f\"situation is known limitation of Workflows Compiler. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_batches_sources\",\n        )\n    if len(top_level_data_lineage) > 0:\n        top_level_data_lineage_marker = top_level_data_lineage.pop()\n    else:\n        top_level_data_lineage_marker = None\n    execution_graph.graph[TOP_LEVEL_LINEAGE_KEY] = top_level_data_lineage_marker\n    return execution_graph\n\n\ndef denote_data_flow_for_node(\n    execution_graph: DiGraph,\n    node: str,\n    block_manifest_by_step_name: Dict[str, WorkflowBlockManifest],\n    on_top_level_lineage_denoted: Callable[[str], None],\n) -> DiGraph:\n    if is_input_node(execution_graph=execution_graph, node=node):\n        # everything already set there, in the previous stage of compilation\n        return execution_graph\n    if is_step_node(execution_graph=execution_graph, node=node):\n        step_name = get_last_chunk_of_selector(selector=node)\n        if step_name not in block_manifest_by_step_name:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler expected manifest for the step: {step_name} to be registered \"\n                f\"but this condition is not met. This is most likely the bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | retrieving_predecessors_for_output\",\n            )\n        manifest = block_manifest_by_step_name[step_name]\n        return denote_data_flow_for_step(\n            execution_graph=execution_graph,\n            node=node,\n            manifest=manifest,\n            on_top_level_lineage_denoted=on_top_level_lineage_denoted,\n        )\n    if is_output_node(execution_graph=execution_graph, node=node):\n        # output is allowed to have exactly one predecessor\n        output_predecessors = list(execution_graph.predecessors(node))\n        if len(output_predecessors) != 1:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler expected each output in compiled graph to have one predecessor, \"\n                f\"but this condition is not met for node {node}. This is most likely the bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | retrieving_predecessors_for_output\",\n            )\n        predecessor_node = output_predecessors[0]\n        predecessor_node_data = node_as(\n            execution_graph=execution_graph,\n            node=predecessor_node,\n            expected_type=ExecutionGraphNode,\n        )\n        predecessor_node_lineage = predecessor_node_data.data_lineage\n        output_node_data = node_as(\n            execution_graph=execution_graph,\n            node=node,\n            expected_type=OutputNode,\n        )\n        output_node_data.data_lineage = predecessor_node_lineage\n        return execution_graph\n    raise AssumptionError(\n        f\"Workflow Compiler encountered node: {node} which cannot be classified as known node type. \"\n        f\"This is most likely the bug. Contact Roboflow team through github issues \"\n        f\"(https://github.com/roboflow/inference/issues) providing full \"\n        f\"context of the problem - including workflow definition you use.\",\n        context=\"workflow_compilation | execution_graph_construction | denoting_data_flow_for_step\",\n    )\n\n\ndef denote_data_flow_for_step(\n    execution_graph: DiGraph,\n    node: str,\n    manifest: WorkflowBlockManifest,\n    on_top_level_lineage_denoted: Callable[[str], None],\n) -> DiGraph:\n    all_control_flow_predecessors, all_non_control_flow_predecessors = (\n        separate_flow_control_predecessors_from_data_providers(\n            execution_graph=execution_graph, node=node\n        )\n    )\n    input_data = build_input_data_for_step(\n        manifest=manifest,\n        step_node=node,\n        data_providing_predecessors=all_non_control_flow_predecessors,\n        execution_graph=execution_graph,\n    )\n    step_name = get_last_chunk_of_selector(node)\n    step_node_data = node_as(\n        execution_graph=execution_graph,\n        node=node,\n        expected_type=StepNode,\n    )\n    parsed_step_input_selectors: List[ParsedSelector] = execution_graph.nodes[node][\n        PARSED_NODE_INPUT_SELECTORS_PROPERTY\n    ]\n    batch_compatibility_of_properties = retrieve_batch_compatibility_of_input_selectors(\n        input_selectors=parsed_step_input_selectors\n    )\n    scalar_parameters_to_be_batched = (\n        verify_declared_batch_compatibility_against_actual_inputs(\n            node=node,\n            step_node_data=step_node_data,\n            input_data=input_data,\n            batch_compatibility_of_properties=batch_compatibility_of_properties,\n        )\n    )\n    input_dimensionality_offsets = manifest.get_input_dimensionality_offsets()\n    print(\"input_dimensionality_offsets\", input_dimensionality_offsets)\n    verify_step_input_dimensionality_offsets(\n        step_name=step_name,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n    )\n    print(\"scalar_parameters_to_be_batched\", scalar_parameters_to_be_batched)\n    inputs_dimensionalities = get_inputs_dimensionalities(\n        step_name=step_name,\n        step_type=manifest.type,\n        input_data=input_data,\n        scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n    )\n    print(\"inputs_dimensionalities\", inputs_dimensionalities)\n    logger.debug(\n        f\"For step: {node}, detected the following input dimensionalities: {inputs_dimensionalities}\"\n    )\n    parameters_with_batch_inputs = grab_parameters_defining_batch_inputs(\n        inputs_dimensionalities=inputs_dimensionalities,\n    )\n    print(\"parameters_with_batch_inputs\", parameters_with_batch_inputs)\n    dimensionality_reference_property = manifest.get_dimensionality_reference_property()\n    print(\"dimensionality_reference_property\", dimensionality_reference_property)\n    output_dimensionality_offset = manifest.get_output_dimensionality_offset()\n    print(\"output_dimensionality_offset\", output_dimensionality_offset)\n    verify_step_input_dimensionality_offsets(\n        step_name=step_name,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n    )\n    verify_output_offset(\n        step_name=step_name,\n        parameters_with_batch_inputs=parameters_with_batch_inputs,\n        dimensionality_reference_property=dimensionality_reference_property,\n        input_dimensionality_offsets=input_dimensionality_offsets,\n        output_dimensionality_offset=output_dimensionality_offset,\n    )\n    verify_input_data_dimensionality(\n        step_name=step_name,\n        step_type=manifest.type,\n        dimensionality_reference_property=dimensionality_reference_property,\n        inputs_dimensionalities=inputs_dimensionalities,\n        dimensionality_offstes=input_dimensionality_offsets,\n    )\n    all_lineages = get_input_data_lineage_excluding_auto_batch_casting(\n        step_name=step_name,\n        input_data=input_data,\n        scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n    )\n    verify_compatibility_of_input_data_lineage_with_control_flow_lineage(\n        step_name=step_name,\n        inputs_lineage=all_lineages,\n        flow_control_steps_selectors=all_control_flow_predecessors,\n        execution_graph=execution_graph,\n    )\n    step_node_data.input_data = input_data\n    step_node_data.dimensionality_reference_property = dimensionality_reference_property\n    step_node_data.batch_oriented_parameters = parameters_with_batch_inputs\n    step_node_data.step_execution_dimensionality = (\n        establish_step_execution_dimensionality(\n            inputs_dimensionalities=inputs_dimensionalities,\n            output_dimensionality_offset=output_dimensionality_offset,\n        )\n    )\n    truly_batch_parameters = parameters_with_batch_inputs.difference(\n        scalar_parameters_to_be_batched\n    )\n    if not truly_batch_parameters:\n        if manifest.get_output_dimensionality_offset() > 0:\n            # brave decision to open a Pandora box\n            data_lineage = [node]\n        else:\n            data_lineage = []\n    else:\n        data_lineage = establish_batch_oriented_step_lineage(\n            step_selector=node,\n            all_lineages=all_lineages,\n            input_data=input_data,\n            dimensionality_reference_property=dimensionality_reference_property,\n            output_dimensionality_offset=output_dimensionality_offset,\n        )\n    lineage_supports = get_lineage_support_for_auto_batch_casted_parameters(\n        input_dimensionalities=inputs_dimensionalities,\n        all_lineages_of_batch_parameters=all_lineages,\n        scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n    )\n    step_node_data.auto_batch_casting_lineage_supports = lineage_supports\n    print(\"lineage_supports\", lineage_supports)\n    print(\"Data lineage of block output\", data_lineage)\n    if data_lineage:\n        on_top_level_lineage_denoted(data_lineage[0])\n    step_node_data.data_lineage = data_lineage\n    return execution_graph\n\n\ndef separate_flow_control_predecessors_from_data_providers(\n    execution_graph: DiGraph,\n    node: str,\n) -> Tuple[List[str], List[str]]:\n    all_predecessors = list(execution_graph.predecessors(node))\n    all_control_flow_predecessors = [\n        predecessor\n        for predecessor in all_predecessors\n        if is_flow_control_step(execution_graph=execution_graph, node=predecessor)\n    ]\n    all_non_control_flow_predecessors = [\n        predecessor\n        for predecessor in all_predecessors\n        if not is_flow_control_step(execution_graph=execution_graph, node=predecessor)\n    ]\n    return all_control_flow_predecessors, all_non_control_flow_predecessors\n\n\ndef build_input_data_for_step(\n    manifest: WorkflowBlockManifest,\n    step_node: str,\n    data_providing_predecessors: List[str],\n    execution_graph: DiGraph,\n) -> StepInputData:\n    predecessors_by_property_name = get_predecessors_for_step_manifest_properties(\n        execution_graph=execution_graph,\n        step_node=step_node,\n        data_providing_predecessors=data_providing_predecessors,\n    )\n    manifest_fields_values = get_manifest_fields_values(step_manifest=manifest)\n    result = {}\n    for name, value in manifest_fields_values.items():\n        result[name] = build_input_property(\n            step_node=step_node,\n            manifest_property_name=name,\n            manifest_property_value=value,\n            predecessors_by_property_name=predecessors_by_property_name,\n            execution_graph=execution_graph,\n        )\n    return result\n\n\ndef get_predecessors_for_step_manifest_properties(\n    execution_graph: DiGraph, step_node: str, data_providing_predecessors: List[str]\n) -> Dict[str, List[PropertyPredecessorDefinition]]:\n    predecessors_by_property_name = defaultdict(list)\n    for predecessor in data_providing_predecessors:\n        edge_data = execution_graph.edges[(predecessor, step_node)]\n        # STEP_INPUT_SELECTORS_PROPERTY is optional, as special <super-input> node may be directly\n        # connected to step\n        selectors_associated_to_edge: List[ParsedSelector] = edge_data.get(\n            STEP_INPUT_SELECTORS_PROPERTY, []\n        )\n        for selector_associated_to_edge in selectors_associated_to_edge:\n            definition = PropertyPredecessorDefinition(\n                predecessor_selector=predecessor,\n                parsed_selector=selector_associated_to_edge,\n            )\n            predecessors_by_property_name[\n                selector_associated_to_edge.definition.property_name\n            ].append(definition)\n    return predecessors_by_property_name\n\n\ndef build_input_property(\n    step_node: str,\n    manifest_property_name: str,\n    manifest_property_value: Any,\n    predecessors_by_property_name: Dict[str, List[PropertyPredecessorDefinition]],\n    execution_graph: DiGraph,\n) -> Union[StepInputDefinition, CompoundStepInputDefinition]:\n    if manifest_property_name not in predecessors_by_property_name:\n        return StaticStepInputDefinition(\n            parameter_specification=ParameterSpecification(\n                parameter_name=manifest_property_name,\n            ),\n            category=NodeInputCategory.STATIC_VALUE,\n            value=manifest_property_value,\n        )\n    if isinstance(manifest_property_value, dict):\n        return build_nested_dictionary_for_input_property(\n            step_node=step_node,\n            manifest_property_name=manifest_property_name,\n            manifest_property_value=manifest_property_value,\n            predecessors_definitions=predecessors_by_property_name[\n                manifest_property_name\n            ],\n            execution_graph=execution_graph,\n        )\n    if isinstance(manifest_property_value, list):\n        return build_nested_list_for_input_property(\n            step_node=step_node,\n            manifest_property_name=manifest_property_name,\n            manifest_property_value=manifest_property_value,\n            predecessors_definitions=predecessors_by_property_name[\n                manifest_property_name\n            ],\n            execution_graph=execution_graph,\n        )\n    matching_predecessors_data = predecessors_by_property_name[manifest_property_name]\n    if len(matching_predecessors_data) != 1:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler deduced that property `{manifest_property_name}` of step `{step_node}` \"\n            f\"should be fed with data coming from exactly one execution graph node, but found \"\n            f\"{len(matching_predecessors_data)} data sources. This is most likely the bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n        )\n    predecessor_selector, predecessor_parsed_selector = (\n        matching_predecessors_data[0].predecessor_selector,\n        matching_predecessors_data[0].parsed_selector,\n    )\n    if is_input_node(execution_graph=execution_graph, node=predecessor_selector):\n        predecessor_node_data = node_as(\n            execution_graph=execution_graph,\n            node=matching_predecessors_data[0].predecessor_selector,\n            expected_type=InputNode,\n        )\n        category = (\n            NodeInputCategory.BATCH_INPUT_PARAMETER\n            if predecessor_node_data.is_batch_oriented()\n            else NodeInputCategory.NON_BATCH_INPUT_PARAMETER\n        )\n        return DynamicStepInputDefinition(\n            parameter_specification=ParameterSpecification(\n                parameter_name=manifest_property_name,\n            ),\n            category=category,\n            data_lineage=predecessor_node_data.data_lineage,\n            selector=predecessor_node_data.selector,\n        )\n    if is_step_node(execution_graph=execution_graph, node=predecessor_selector):\n        predecessor_node_data = node_as(\n            execution_graph=execution_graph,\n            node=matching_predecessors_data[0].predecessor_selector,\n            expected_type=StepNode,\n        )\n        category = (\n            NodeInputCategory.BATCH_STEP_OUTPUT\n            if predecessor_node_data.output_dimensionality > 0\n            else NodeInputCategory.NON_BATCH_STEP_OUTPUT\n        )\n        return DynamicStepInputDefinition(\n            parameter_specification=ParameterSpecification(\n                parameter_name=manifest_property_name,\n            ),\n            category=category,\n            data_lineage=predecessor_node_data.data_lineage,\n            selector=predecessor_parsed_selector.value,\n        )\n    raise AssumptionError(\n        public_message=f\"Workflow Compiler for property `{manifest_property_name}` of step `{step_node}` \"\n        f\"found data providing predecessor `{predecessor_selector}` which has unsupported step type.\"\n        f\"This is most likely the bug. \"\n        f\"Contact Roboflow team through github issues \"\n        f\"(https://github.com/roboflow/inference/issues) providing full \"\n        f\"context of the problem - including workflow definition you use.\",\n        context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n    )\n\n\ndef build_nested_dictionary_for_input_property(\n    step_node: str,\n    manifest_property_name: str,\n    manifest_property_value: dict,\n    predecessors_definitions: List[PropertyPredecessorDefinition],\n    execution_graph: DiGraph,\n) -> DictOfStepInputDefinitions:\n    nested_property_name2data: Dict[Optional[str], PropertyPredecessorDefinition] = {\n        predecessor_definition.parsed_selector.key: predecessor_definition\n        for predecessor_definition in predecessors_definitions\n    }\n    result = {}\n    for nested_dict_key, nested_dict_value in manifest_property_value.items():\n        if nested_dict_key not in nested_property_name2data:\n            result[nested_dict_key] = StaticStepInputDefinition(\n                parameter_specification=ParameterSpecification(\n                    parameter_name=manifest_property_name,\n                    nested_element_key=nested_dict_key,\n                ),\n                category=NodeInputCategory.STATIC_VALUE,\n                value=nested_dict_value,\n            )\n            continue\n        referred_node_selector = nested_property_name2data[\n            nested_dict_key\n        ].predecessor_selector\n        referred_node_parsed_selector = nested_property_name2data[\n            nested_dict_key\n        ].parsed_selector\n        if is_input_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=InputNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_INPUT_PARAMETER\n                if predecessor_node_data.is_batch_oriented()\n                else NodeInputCategory.NON_BATCH_INPUT_PARAMETER\n            )\n            result[nested_dict_key] = DynamicStepInputDefinition(\n                parameter_specification=ParameterSpecification(\n                    parameter_name=manifest_property_name,\n                    nested_element_key=nested_dict_key,\n                ),\n                category=category,\n                data_lineage=predecessor_node_data.data_lineage,\n                selector=predecessor_node_data.selector,\n            )\n            continue\n        if is_step_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=StepNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_STEP_OUTPUT\n                if predecessor_node_data.output_dimensionality > 0\n                else NodeInputCategory.NON_BATCH_STEP_OUTPUT\n            )\n            result[nested_dict_key] = DynamicStepInputDefinition(\n                parameter_specification=ParameterSpecification(\n                    parameter_name=manifest_property_name,\n                    nested_element_key=nested_dict_key,\n                ),\n                category=category,\n                data_lineage=predecessor_node_data.data_lineage,\n                selector=referred_node_parsed_selector.value,\n            )\n            continue\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for property `{manifest_property_name}` of step `{step_node}` \"\n            f\"found data providing predecessor `{referred_node_selector}` which has \"\n            f\"unsupported step type (key: {nested_dict_key} of nested data dictionary). \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n        )\n    return DictOfStepInputDefinitions(\n        name=manifest_property_name,\n        nested_definitions=result,\n    )\n\n\ndef get_manifest_fields_values(step_manifest: WorkflowBlockManifest) -> Dict[str, Any]:\n    result = {}\n    for field in step_manifest.model_fields:\n        if field in EXCLUDED_FIELDS:\n            continue\n        result[field] = getattr(step_manifest, field)\n    return result\n\n\ndef build_nested_list_for_input_property(\n    step_node: str,\n    manifest_property_name: str,\n    manifest_property_value: list,\n    predecessors_definitions: List[PropertyPredecessorDefinition],\n    execution_graph: DiGraph,\n) -> ListOfStepInputDefinitions:\n    nested_index2data: Dict[Optional[int], PropertyPredecessorDefinition] = {\n        e.parsed_selector.index: e for e in predecessors_definitions\n    }\n    result = []\n    for index, element in enumerate(manifest_property_value):\n        if index not in nested_index2data:\n            result.append(\n                StaticStepInputDefinition(\n                    parameter_specification=ParameterSpecification(\n                        parameter_name=manifest_property_name,\n                        nested_element_index=index,\n                    ),\n                    category=NodeInputCategory.STATIC_VALUE,\n                    value=element,\n                )\n            )\n            continue\n        referred_node_selector = nested_index2data[index].predecessor_selector\n        referred_node_parsed_selector = nested_index2data[index].parsed_selector\n        if is_input_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=InputNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_INPUT_PARAMETER\n                if predecessor_node_data.is_batch_oriented()\n                else NodeInputCategory.NON_BATCH_INPUT_PARAMETER\n            )\n            result.append(\n                DynamicStepInputDefinition(\n                    parameter_specification=ParameterSpecification(\n                        parameter_name=manifest_property_name,\n                        nested_element_index=index,\n                    ),\n                    category=category,\n                    data_lineage=predecessor_node_data.data_lineage,\n                    selector=predecessor_node_data.selector,\n                )\n            )\n            continue\n        if is_step_node(execution_graph=execution_graph, node=referred_node_selector):\n            predecessor_node_data = node_as(\n                execution_graph=execution_graph,\n                node=referred_node_selector,\n                expected_type=StepNode,\n            )\n            category = (\n                NodeInputCategory.BATCH_STEP_OUTPUT\n                if predecessor_node_data.output_dimensionality > 0\n                else NodeInputCategory.NON_BATCH_STEP_OUTPUT\n            )\n            result.append(\n                DynamicStepInputDefinition(\n                    parameter_specification=ParameterSpecification(\n                        parameter_name=manifest_property_name,\n                        nested_element_index=index,\n                    ),\n                    category=category,\n                    data_lineage=predecessor_node_data.data_lineage,\n                    selector=referred_node_parsed_selector.value,\n                )\n            )\n            continue\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for property `{manifest_property_name}` of step `{step_node}` \"\n            f\"found data providing predecessor `{referred_node_selector}` which has \"\n            f\"unsupported step type (index: {index} of nested data list). \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n        )\n    return ListOfStepInputDefinitions(\n        name=manifest_property_name,\n        nested_definitions=result,\n    )\n\n\ndef verify_step_input_dimensionality_offsets(\n    step_name: str,\n    input_dimensionality_offsets: Dict[str, int],\n) -> None:\n    min_offset, max_offset = None, None\n    for offset in input_dimensionality_offsets.values():\n        if min_offset is None or offset < min_offset:\n            min_offset = offset\n        if max_offset is None or offset > max_offset:\n            max_offset = offset\n    if min_offset is None or max_offset is None:\n        return None\n    if min_offset < 0 or max_offset < 0:\n        raise BlockInterfaceError(\n            public_message=f\"Offsets could not be negative, but block defining step: {step_name} defines that values.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_input_offset_definitions\",\n        )\n    if abs(max_offset - min_offset) > 1:\n        raise BlockInterfaceError(\n            public_message=\"Offsets of input parameters could not differ more than 1, but block defining step {step_name} \"\n            f\"violates that rule.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_input_offset_definitions\",\n        )\n\n\ndef verify_output_offset(\n    step_name: str,\n    parameters_with_batch_inputs: Set[str],\n    input_dimensionality_offsets: Dict[str, int],\n    dimensionality_reference_property: Optional[str],\n    output_dimensionality_offset: int,\n) -> None:\n    if not parameters_with_batch_inputs and output_dimensionality_offset < 0:\n        raise StepInputDimensionalityError(\n            public_message=f\"Block defining step {step_name} defines negative dimensionality offset while only \"\n            f\"scalar inputs being provided - the block cannot run as there is no dimension to collapse.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if (\n        dimensionality_reference_property is not None\n        and dimensionality_reference_property not in parameters_with_batch_inputs\n    ):\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} defines dimensionality reference property \"\n            f\"which is not in scope of parameters bring batch-oriented input, which makes it impossible \"\n            f\"to use as reference for output dimensionality.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if output_dimensionality_offset not in {-1, 0, 1}:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} defines output dimensionality offset \"\n            f\"being {output_dimensionality_offset}, whereas it is only possible for that offset being \"\n            f\"in set [-1, 0, 1].\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    different_offsets = {o for o in input_dimensionality_offsets.values()}\n    if len(parameters_with_batch_inputs) != len(input_dimensionality_offsets):\n        # assumption of default offset being zero - and this one does not need to be manifested\n        # by block\n        different_offsets.add(0)\n    if 0 not in different_offsets and parameters_with_batch_inputs:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} explicitly defines input dimensionalities offsets\"\n            f\"with {input_dimensionality_offsets}, but the definition lack 0-level input, which is \"\n            f\"not allowed, as in this scenario offsets could be adjusted to include 0\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if len(different_offsets) > 1 and dimensionality_reference_property is None:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} explicitly defines input dimensionality \"\n            f\"offsets {input_dimensionality_offsets}. In this scenario it is required to provide dimensionality \"\n            f\"reference property.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n    if len(different_offsets) > 1 and output_dimensionality_offset != 0:\n        raise BlockInterfaceError(\n            public_message=f\"Block defining step {step_name} explicitly defines input dimensionality \"\n            f\"offsets {input_dimensionality_offsets} and output dimensionality offset {output_dimensionality_offset} \"\n            f\"where the latter is not 0, but for inputs differing with dimensionality it is only possible to keep \"\n            f\"output dimensionality the same and point reference parameter.\",\n            context=\"workflow_compilation | execution_graph_construction | verification_of_output_offset\",\n        )\n\n\ndef verify_input_data_dimensionality(\n    step_name: str,\n    step_type: str,\n    dimensionality_reference_property: Optional[str],\n    inputs_dimensionalities: Dict[str, Set[int]],\n    dimensionality_offstes: Dict[str, int],\n) -> None:\n    parameter_name2dimensionality_specification = (\n        grab_input_data_dimensionality_specifications(\n            step_name=step_name,\n            inputs_dimensionalities=inputs_dimensionalities,\n            dimensionality_offstes=dimensionality_offstes,\n        )\n    )\n    if not parameter_name2dimensionality_specification:\n        # nothing to check if no batch-oriented inputs\n        return None\n    different_dimensionalities_of_parameters = {\n        specification.actual_dimensionality\n        for specification in parameter_name2dimensionality_specification.values()\n    }\n    if dimensionality_reference_property is None:\n        if len(different_dimensionalities_of_parameters) > 1:\n            parameter2dimensionality = {\n                k: e.actual_dimensionality\n                for k, e in parameter_name2dimensionality_specification.items()\n            }\n            raise StepInputDimensionalityError(\n                public_message=f\"Block defining step {step_name} does not define dimensionality reference property, \"\n                f\"which means that all batch-oriented parameters must be at the same dimensionality level, \"\n                f\"but detected the following dimensionalities for parameters {parameter2dimensionality}\",\n                context=\"workflow_compilation | execution_graph_construction | denoting_step_inputs_dimensionality\",\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=step_name,\n                        block_type=step_type,\n                        block_details=f\"Dimensionality of input parameters doesn't match: {parameter2dimensionality}\",\n                    )\n                ],\n            )\n        return None\n    reference_specification = parameter_name2dimensionality_specification[\n        dimensionality_reference_property\n    ]\n    expected_dimensionalities = {\n        property_name: (e.expected_offset - reference_specification.expected_offset)\n        + reference_specification.actual_dimensionality\n        for property_name, e in parameter_name2dimensionality_specification.items()\n    }\n    if any(dim <= 0 for dim in expected_dimensionalities.values()):\n        raise StepInputDimensionalityError(\n            public_message=f\"Given the definition of block defining step {step_name} and data provided, \"\n            f\"the block would expect batch input dimensionality to be 0 or below, which is invalid.\",\n            context=\"workflow_compilation | execution_graph_construction | denoting_step_inputs_dimensionality\",\n        )\n    for property_name, expected_dimensionality in expected_dimensionalities.items():\n        actual_dimensionality = parameter_name2dimensionality_specification[\n            property_name\n        ].actual_dimensionality\n        if actual_dimensionality != expected_dimensionality:\n            raise StepInputDimensionalityError(\n                public_message=f\"Data fed into step `{step_name}` property `{property_name}` has \"\n                f\"actual dimensionality {actual_dimensionality}, \"\n                f\"when expected was {expected_dimensionality}\",\n                context=\"workflow_compilation | execution_graph_construction | denoting_step_inputs_dimensionality\",\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=step_name,\n                        block_type=step_type,\n                        property_name=property_name,\n                        property_details=f\"Expected dimensionality {expected_dimensionality}, but received dimensionality {actual_dimensionality}\",\n                    )\n                ],\n            )\n    return None\n\n\ndef grab_input_data_dimensionality_specifications(\n    step_name: str,\n    inputs_dimensionalities: Dict[str, Set[int]],\n    dimensionality_offstes: Dict[str, int],\n) -> Dict[str, InputDimensionalitySpecification]:\n    result = {}\n    for parameter_name, dimensionality in inputs_dimensionalities.items():\n        parameter_offset = dimensionality_offstes.get(parameter_name, 0)\n        non_zero_dimensionalities_for_parameter = {d for d in dimensionality if d > 0}\n        if len(non_zero_dimensionalities_for_parameter) > 1:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler for step: `{step_name}` and parameter: {parameter_name}\"\n                f\"found multiple different values of actual input dimensionalities: \"\n                f\"`{non_zero_dimensionalities_for_parameter}` which should be detected and addresses \"\n                f\"at earlier stages of compilation.\"\n                f\"This is most likely the bug. Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs\",\n            )\n        if non_zero_dimensionalities_for_parameter:\n            actual_dimensionality = next(iter(non_zero_dimensionalities_for_parameter))\n            result[parameter_name] = InputDimensionalitySpecification(\n                actual_dimensionality=actual_dimensionality,\n                expected_offset=parameter_offset,\n            )\n    return result\n\n\ndef verify_compatibility_of_input_data_lineage_with_control_flow_lineage(\n    step_name: str,\n    inputs_lineage: List[List[str]],\n    flow_control_steps_selectors: List[str],\n    execution_graph: DiGraph,\n) -> None:\n    already_spotted_input_lineages = set()\n    lineage_id2control_flow_steps = defaultdict(list)\n    batch_oriented_control_flow_lineages = []\n    for flow_control_steps_selector in flow_control_steps_selectors:\n        flow_control_step_data = node_as(\n            execution_graph=execution_graph,\n            node=flow_control_steps_selector,\n            expected_type=StepNode,\n        )\n        lineage = flow_control_step_data.data_lineage\n        lineage_id = identify_lineage(lineage=lineage)\n        if lineage_id not in already_spotted_input_lineages and lineage:\n            already_spotted_input_lineages.add(lineage_id)\n            batch_oriented_control_flow_lineages.append(lineage)\n        lineage_id2control_flow_steps[lineage_id].append(flow_control_steps_selector)\n    all_input_lineage_prefixes = get_all_batch_lineage_prefixes(lineages=inputs_lineage)\n    all_input_lineage_prefixes_hashes = {\n        identify_lineage(lineage=lineage) for lineage in all_input_lineage_prefixes\n    }\n    for control_flow_lineage in batch_oriented_control_flow_lineages:\n        control_flow_lineage_id = identify_lineage(lineage=control_flow_lineage)\n        if control_flow_lineage_id not in all_input_lineage_prefixes_hashes:\n            problematic_flow_control_steps = lineage_id2control_flow_steps[\n                control_flow_lineage_id\n            ]\n            raise ControlFlowDefinitionError(\n                public_message=f\"Step {step_name} execution is impacted by control flow outcome of the following \"\n                f\"steps {problematic_flow_control_steps} which make decision based on data that is \"\n                f\"not compatible with data fed to the step {step_name} - which would cause the step \"\n                f\"to never execute. This behaviour is invalid and prevented upfront by Workflows compiler.\",\n                context=\"workflow_compilation | execution_graph_construction | verification_of_flow_control_lineage\",\n            )\n\n\ndef get_all_batch_lineage_prefixes(lineages: List[List[str]]) -> List[List[str]]:\n    result = []\n    already_spotted = set()\n    for lineage in lineages:\n        lineage_prefixes = get_batch_lineage_prefixes(lineage=lineage)\n        for lineage_prefix in lineage_prefixes:\n            lineage_prefix_id = identify_lineage(lineage=lineage_prefix)\n            if lineage_prefix_id not in already_spotted:\n                already_spotted.add(lineage_prefix_id)\n                result.append(lineage_prefix)\n    return result\n\n\ndef get_batch_lineage_prefixes(lineage: List[str]) -> List[List[str]]:\n    if not lineage:\n        return []\n    result = []\n    prefix = []\n    for i in range(len(lineage)):\n        prefix.append(lineage[i])\n        result.append(copy(prefix))\n    return result\n\n\ndef get_inputs_dimensionalities(\n    step_name: str,\n    step_type: str,\n    input_data: StepInputData,\n    scalar_parameters_to_be_batched: Set[str],\n    input_dimensionality_offsets: Dict[str, int],\n) -> Dict[str, Set[int]]:\n    result = defaultdict(set)\n    dimensionalities_spotted = set()\n    offset_parameters = {\n        parameter: value\n        for parameter, value in input_dimensionality_offsets.items()\n        if value > 0\n    }\n    non_offset_parameters_dimensionality_values = set()\n    for property_name, input_definition in input_data.items():\n        if property_name in offset_parameters:\n            continue\n        if input_definition.is_compound_input():\n            for value in input_definition.iterate_through_definitions():\n                if value.is_batch_oriented():\n                    non_offset_parameters_dimensionality_values.add(\n                        value.get_dimensionality()\n                    )\n        elif input_definition.is_batch_oriented():\n            non_offset_parameters_dimensionality_values.add(\n                input_definition.get_dimensionality()\n            )\n    if len(non_offset_parameters_dimensionality_values) > 1:\n        raise StepInputDimensionalityError(\n            public_message=f\"For step {step_name} attempted to plug input data that are in different dimensions, \"\n            f\"whereas block defines the inputs to be equal in that terms.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_input_data\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=step_name,\n                    block_type=step_type,\n                    block_details=f\"Dimensionality of input parameters differs by more than 1. Detected dimensions: {dict(result)}\",\n                )\n            ],\n        )\n    non_offset_parameters_dimensionality_value = (\n        non_offset_parameters_dimensionality_values.pop()\n        if len(non_offset_parameters_dimensionality_values) > 0\n        else 1\n    )\n    for property_name, input_definition in input_data.items():\n        if input_definition.is_compound_input():\n            result[property_name] = get_compound_input_dimensionality(\n                step_name=step_name,\n                step_type=step_type,\n                property_name=property_name,\n                input_definition=input_definition,\n                scalar_parameters_to_be_batched=scalar_parameters_to_be_batched,\n                non_offset_parameters_dimensionality_value=non_offset_parameters_dimensionality_value,\n                offset_parameters=offset_parameters,\n            )\n        else:\n            if property_name in scalar_parameters_to_be_batched:\n                if property_name not in offset_parameters:\n                    result[property_name] = {non_offset_parameters_dimensionality_value}\n                else:\n                    result[property_name] = (\n                        non_offset_parameters_dimensionality_value\n                        + offset_parameters[property_name]\n                    )\n            else:\n                result[property_name] = {input_definition.get_dimensionality()}\n        dimensionalities_spotted.update(result[property_name])\n    non_zero_dimensionalities_spotted = {d for d in dimensionalities_spotted if d != 0}\n    if len(non_zero_dimensionalities_spotted) > 0:\n        min_dim, max_dim = min(non_zero_dimensionalities_spotted), max(\n            non_zero_dimensionalities_spotted\n        )\n        if abs(max_dim - min_dim) > 1:\n            raise StepInputDimensionalityError(\n                public_message=f\"For step {step_name} attempted to plug input data differing in dimensionality more than 1\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_input_data\",\n                blocks_errors=[\n                    WorkflowBlockError(\n                        block_id=step_name,\n                        block_type=step_type,\n                        block_details=f\"Dimensionality of input parameters differs by more than 1. Detected dimensions: {dict(result)}\",\n                    )\n                ],\n            )\n    return result\n\n\ndef get_compound_input_dimensionality(\n    step_name: str,\n    property_name: str,\n    step_type: str,\n    input_definition: CompoundStepInputDefinition,\n    scalar_parameters_to_be_batched: Set[str],\n    offset_parameters: Dict[str, int],\n    non_offset_parameters_dimensionality_value: int,\n) -> Set[int]:\n    dimensionalities_spotted = set()\n    for definition in input_definition.iterate_through_definitions():\n        if (\n            property_name not in scalar_parameters_to_be_batched\n            or definition.is_batch_oriented()\n        ):\n            dimensionalities_spotted.add(definition.get_dimensionality())\n        elif property_name not in offset_parameters:\n            dimensionalities_spotted.add(non_offset_parameters_dimensionality_value)\n        else:\n            dimensionalities_spotted.add(\n                non_offset_parameters_dimensionality_value\n                + offset_parameters[property_name]\n            )\n    non_zero_dimensionalities = {e for e in dimensionalities_spotted if e != 0}\n    if len(non_zero_dimensionalities) > 1:\n        raise StepInputDimensionalityError(\n            public_message=f\"While evaluating compound property {property_name} of step {step_name}, \"\n            f\"detected multiple inputs of differing batch dimensionalities: {non_zero_dimensionalities}\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_input_data\",\n            blocks_errors=[\n                WorkflowBlockError(\n                    block_id=step_name,\n                    block_type=step_type,\n                    property_name=property_name,\n                    property_details=f\"Detected multiple inputs of differing batch dimensionalities: {non_zero_dimensionalities}\",\n                )\n            ],\n        )\n    return dimensionalities_spotted\n\n\ndef grab_parameters_defining_batch_inputs(\n    inputs_dimensionalities: Dict[str, Set[int]],\n) -> Set[str]:\n    result = set()\n    for paremeter, dimensionalities in inputs_dimensionalities.items():\n        batch_dimensionalities = {d for d in dimensionalities if d > 0}\n        if len(batch_dimensionalities):\n            result.add(paremeter)\n    return result\n\n\ndef retrieve_batch_compatibility_of_input_selectors(\n    input_selectors: List[ParsedSelector],\n) -> Dict[str, Set[bool]]:\n    batch_compatibility_of_properties = defaultdict(set)\n    for parsed_selector in input_selectors:\n        for reference in parsed_selector.definition.allowed_references:\n            batch_compatibility_of_properties[\n                parsed_selector.definition.property_name\n            ].update(reference.points_to_batch)\n    return batch_compatibility_of_properties\n\n\ndef verify_declared_batch_compatibility_against_actual_inputs(\n    node: str,\n    step_node_data: StepNode,\n    input_data: StepInputData,\n    batch_compatibility_of_properties: Dict[str, Set[bool]],\n) -> Set[str]:\n    scalar_parameters_to_be_batched = set()\n    for property_name, input_definition in input_data.items():\n        if property_name not in batch_compatibility_of_properties:\n            # only values plugged via selectors are to be validated\n            continue\n        if input_definition.is_compound_input():\n            actual_input_is_batch = {\n                element.is_batch_oriented()\n                for element in input_definition.iterate_through_definitions()\n            }\n        else:\n            actual_input_is_batch = {input_definition.is_batch_oriented()}\n        batch_compatibility = batch_compatibility_of_properties[property_name]\n        step_accepts_batch_input = step_node_data.step_manifest.accepts_batch_input()\n        if (\n            step_accepts_batch_input\n            and batch_compatibility == {False}\n            and True in actual_input_is_batch\n        ):\n            raise ExecutionGraphStructureError(\n                public_message=f\"Detected invalid reference plugged \"\n                f\"into property `{property_name}` of step `{node}` - the step \"\n                f\"property do not accept batch-oriented inputs, yet the input selector \"\n                f\"holds one - this indicates the problem with \"\n                f\"construction of your Workflow - usually the problem occurs when non-batch oriented \"\n                f\"step inputs are filled with outputs of batch-oriented steps or batch-oriented inputs.\",\n                context=\"workflow_compilation | execution_graph_construction\",\n            )\n        if batch_compatibility == {True} and False in actual_input_is_batch:\n            scalar_parameters_to_be_batched.add(property_name)\n        print(\n            f\"property_name: {property_name}, batch_compatibility={batch_compatibility}, actual_input_is_batch={actual_input_is_batch}, step_accepts_batch_input={step_accepts_batch_input}\"\n        )\n    return scalar_parameters_to_be_batched\n\n\ndef get_input_data_lineage_excluding_auto_batch_casting(\n    step_name: str,\n    input_data: StepInputData,\n    scalar_parameters_to_be_batched: Set[str],\n) -> List[List[str]]:\n    lineage_deduplication_set = set()\n    lineages = []\n    for property_name, input_definition in input_data.items():\n        if property_name in scalar_parameters_to_be_batched:\n            continue\n        new_lineages_detected_within_property_data = get_lineage_for_input_property(\n            step_name=step_name,\n            property_name=property_name,\n            input_definition=input_definition,\n            lineage_deduplication_set=lineage_deduplication_set,\n        )\n        lineages.extend(new_lineages_detected_within_property_data)\n    if not lineages:\n        return lineages\n    verify_lineages(step_name=step_name, detected_lineages=lineages)\n    return lineages\n\n\ndef get_lineage_support_for_auto_batch_casted_parameters(\n    input_dimensionalities: Dict[str, Set[int]],\n    scalar_parameters_to_be_batched: Set[str],\n    all_lineages_of_batch_parameters: List[List[str]],\n) -> Dict[str, AutoBatchCastingConfig]:\n    longest_lineage_support = find_longest_lineage_support(\n        all_lineages_of_batch_parameters=all_lineages_of_batch_parameters,\n    )\n    result = {}\n    for parameter_name in scalar_parameters_to_be_batched:\n        parameter_dimensionality = max(input_dimensionalities[parameter_name])\n        if longest_lineage_support is None:\n            lineage_support = None\n        else:\n            lineage_support = longest_lineage_support[:parameter_dimensionality]\n        result[parameter_name] = AutoBatchCastingConfig(\n            casted_dimensionality=parameter_dimensionality,\n            lineage_support=lineage_support,\n        )\n    print(\"DUMMY\", result)\n    return result\n\n\ndef find_longest_lineage_support(\n    all_lineages_of_batch_parameters: List[List[str]],\n) -> Optional[List[str]]:\n    longest_longest_lineage_support = []\n    for lineage in all_lineages_of_batch_parameters:\n        if len(lineage) > len(longest_longest_lineage_support):\n            longest_longest_lineage_support = lineage\n    if len(longest_longest_lineage_support) == 0:\n        return None\n    return longest_longest_lineage_support\n\n\ndef get_lineage_for_input_property(\n    step_name: str,\n    property_name: str,\n    input_definition: Union[StepInputDefinition, CompoundStepInputDefinition],\n    lineage_deduplication_set: Set[int],\n) -> List[List[str]]:\n    if input_definition.is_compound_input():\n        return get_lineage_from_compound_input(\n            step_name=step_name,\n            property_name=property_name,\n            input_definition=input_definition,\n            lineage_deduplication_set=lineage_deduplication_set,\n        )\n    lineages = []\n    if input_definition.is_batch_oriented():\n        lineage = input_definition.data_lineage\n        lineage_id = identify_lineage(lineage=lineage)\n        if lineage_id not in lineage_deduplication_set:\n            lineage_deduplication_set.add(lineage_id)\n            lineages.append(lineage)\n    return lineages\n\n\ndef get_lineage_from_compound_input(\n    step_name: str,\n    property_name: str,\n    input_definition: Union[StepInputDefinition, CompoundStepInputDefinition],\n    lineage_deduplication_set: Set[int],\n) -> List[List[str]]:\n    lineages = []\n    for nested_element in input_definition.iterate_through_definitions():\n        if nested_element.is_batch_oriented():\n            lineage = nested_element.data_lineage\n            lineage_id = identify_lineage(lineage=lineage)\n            if lineage_id not in lineage_deduplication_set:\n                lineage_deduplication_set.add(lineage_id)\n                lineages.append(lineage)\n    if len(lineages) > 1:\n        raise StepInputLineageError(\n            public_message=f\"Input data provided for step: `{step_name}` comes with multiple different lineages \"\n            f\"{lineages} for property `{property_name}` accepting \"\n            f\"multiple selectors, which is not allowed.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    return lineages\n\n\ndef verify_lineages(step_name: str, detected_lineages: List[List[str]]) -> None:\n    lineages_by_length = defaultdict(list)\n    for lineage in detected_lineages:\n        lineages_by_length[len(lineage)].append(lineage)\n    if len(lineages_by_length) > 2:\n        raise StepInputLineageError(\n            public_message=f\"Input data provided for step: `{step_name}` comes with lineages at more than two \"\n            f\"dimensionality levels, which should not be possible.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    lineage_lengths = sorted(lineages_by_length.keys())\n    for lineage_length in lineage_lengths:\n        if len(lineages_by_length[lineage_length]) > 1:\n            raise StepInputLineageError(\n                public_message=f\"Among step `{step_name}` inputs found different lineages at the same  \"\n                f\"dimensionality levels dimensionality.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if len(lineages_by_length[lineage_lengths[-1]]) > 1 and len(lineage_lengths) < 2:\n        raise StepInputLineageError(\n            public_message=f\"If lineage differ at the last level, then Execution Engine requires at least one \"\n            f\"higher-dimension  input that will come with common lineage, but this is not the \"\n            f\"case for step {step_name}.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    if len(lineage_lengths) == 2:\n        reference_lineage = lineages_by_length[lineage_lengths[0]][0]\n        if reference_lineage != lineages_by_length[lineage_lengths[1]][0][:-1]:\n            raise StepInputLineageError(\n                public_message=f\"Step `{step_name}` inputs does not share common lineage. Differing element: \"\n                f\"{lineages_by_length[lineage_lengths[1]][0]}, \"\n                f\"reference lineage prefix: {reference_lineage}\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n\n\ndef establish_step_execution_dimensionality(\n    inputs_dimensionalities: Dict[str, Set[int]],\n    output_dimensionality_offset: int,\n) -> int:\n    step_execution_dimensionality = 0\n    non_zero_dimensionalities = {\n        dimensionality\n        for dimensionalities in inputs_dimensionalities.values()\n        for dimensionality in dimensionalities\n        if dimensionality > 0\n    }\n    if len(non_zero_dimensionalities) > 0:\n        step_execution_dimensionality = min(non_zero_dimensionalities)\n        if output_dimensionality_offset < 0:\n            step_execution_dimensionality -= 1\n    return step_execution_dimensionality\n\n\ndef establish_batch_oriented_step_lineage(\n    step_selector: str,\n    all_lineages: List[List[str]],\n    input_data: StepInputData,\n    dimensionality_reference_property: Optional[str],\n    output_dimensionality_offset: int,\n) -> List[str]:\n    reference_lineage = get_reference_lineage(\n        step_selector=step_selector,\n        all_lineages=all_lineages,\n        input_data=input_data,\n        dimensionality_reference_property=dimensionality_reference_property,\n    )\n    if output_dimensionality_offset < 0:\n        result_dimensionality = reference_lineage[:output_dimensionality_offset]\n        # if len(result_dimensionality) == 0:\n        #     raise StepOutputLineageError(\n        #         public_message=f\"Step {step_selector} is to decrease dimensionality, but it is not possible if \"\n        #         f\"input dimensionality is not greater or equal 2, otherwise output would not \"\n        #         f\"be batch-oriented.\",\n        #         context=\"workflow_compilation | execution_graph_construction | establishing_step_output_lineage\",\n        #     )\n        return result_dimensionality\n    if output_dimensionality_offset == 0:\n        return reference_lineage\n    reference_lineage.append(step_selector)\n    return reference_lineage\n\n\ndef get_reference_lineage(\n    step_selector: str,\n    all_lineages: List[List[str]],\n    input_data: StepInputData,\n    dimensionality_reference_property: Optional[str],\n) -> List[str]:\n    if len(all_lineages) == 1:\n        return copy(all_lineages[0])\n    if dimensionality_reference_property not in input_data:\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` expected dimensionality_reference_property \"\n            f\"presence to be verified at earlier stages, which did not happen as expected. \"\n            f\"This is most likely the bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    property_data = input_data[dimensionality_reference_property]\n    if property_data.is_compound_input():\n        lineage = None\n        for nested_element in property_data.iterate_through_definitions():\n            if nested_element.is_batch_oriented():\n                lineage = copy(nested_element.data_lineage)\n                return lineage\n        if lineage is None:\n            raise AssumptionError(\n                public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n                f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full \"\n                f\"context of the problem - including workflow definition you use.\",\n                context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n            )\n    if not property_data.is_batch_oriented():\n        raise AssumptionError(\n            public_message=f\"Workflow Compiler for step: `{step_selector}` cannot establish output lineage. \"\n            f\"At this stage it is expected to succeed - lack of success indicates bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_compilation | execution_graph_construction | collecting_step_inputs_lineage\",\n        )\n    return copy(property_data.data_lineage)\n\n\ndef get_property_with_invalid_selector(\n    manifest: WorkflowBlockManifest, step_property: str\n) -> Optional[str]:\n    property_name = None\n    for key, value in manifest.__dict__.items():\n        if isinstance(value, str) and step_property in value:\n            property_name = key\n            break\n    return property_name\n\n\ndef add_super_input_node_in_execution_graph(\n    execution_graph: DiGraph,\n    super_input_node: str,\n) -> DiGraph:\n    nodes_to_attach_super_input_into = get_nodes_of_specific_category(\n        execution_graph=execution_graph,\n        category=NodeCategory.INPUT_NODE,\n    )\n    step_nodes_without_predecessors = [\n        node\n        for node in execution_graph.nodes\n        if not list(execution_graph.predecessors(node))\n    ]\n    nodes_to_attach_super_input_into.update(step_nodes_without_predecessors)\n    execution_graph.add_node(super_input_node)\n    for node in nodes_to_attach_super_input_into:\n        execution_graph.add_edge(super_input_node, node)\n    return execution_graph\n",
    "patch": "diff --git a/inference/core/workflows/execution_engine/v1/compiler/graph_constructor.py b/inference/core/workflows/execution_engine/v1/compiler/graph_constructor.py\nindex 8308a62cb..85ae24be2 100644\n--- a/inference/core/workflows/execution_engine/v1/compiler/graph_constructor.py\n+++ b/inference/core/workflows/execution_engine/v1/compiler/graph_constructor.py\n@@ -1672,13 +1672,10 @@ def get_lineage_support_for_auto_batch_casted_parameters(\n def find_longest_lineage_support(\n     all_lineages_of_batch_parameters: List[List[str]],\n ) -> Optional[List[str]]:\n-    longest_longest_lineage_support = []\n-    for lineage in all_lineages_of_batch_parameters:\n-        if len(lineage) > len(longest_longest_lineage_support):\n-            longest_longest_lineage_support = lineage\n-    if len(longest_longest_lineage_support) == 0:\n+    result = max(all_lineages_of_batch_parameters, key=len, default=[])\n+    if len(result) == 0:\n         return None\n-    return longest_longest_lineage_support\n+    return result\n \n \n def get_lineage_for_input_property(\n"
  },
  {
    "trace_id": "a4faf7da-e81e-4e04-9b78-6bc874d82ca1",
    "function_name": "execute_gpt_4v_request",
    "file_path": "inference/core/workflows/core_steps/models/foundation/openai/v3.py",
    "speedup_x": 1.0,
    "review_quality": null,
    "pre_optimization_commit": "eb6046f90a5ad05d02ad11cd55ed89d8e32cec7a",
    "resolution_method": "git_parent",
    "source": "git",
    "original_function_code": "def execute_gpt_4v_request(\n    roboflow_api_key: str,\n    openai_api_key: str,\n    prompt: List[dict],\n    gpt_model_version: str,\n    max_tokens: int,\n    temperature: Optional[float],\n) -> str:\n    if openai_api_key.startswith(\"rf_key:account\") or openai_api_key.startswith(\n        \"rf_key:user:\"\n    ):\n        return _execute_proxied_openai_request(\n            roboflow_api_key=roboflow_api_key,\n            openai_api_key=openai_api_key,\n            prompt=prompt,\n            gpt_model_version=gpt_model_version,\n            max_tokens=max_tokens,\n            temperature=temperature,\n        )\n    else:\n        return _execute_openai_request(\n            openai_api_key=openai_api_key,\n            prompt=prompt,\n            gpt_model_version=gpt_model_version,\n            max_tokens=max_tokens,\n            temperature=temperature,\n        )\n",
    "optimized_function_code": "import base64\nimport json\nfrom functools import partial\nfrom typing import Any, Dict, List, Literal, Optional, Type, Union\nimport requests\n\nfrom openai import OpenAI\nfrom openai._types import NOT_GIVEN\nfrom pydantic import ConfigDict, Field, model_validator\n\nfrom inference.core.env import (\n    WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS,\n    API_BASE_URL,\n)\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.utils.image_utils import encode_image_to_jpeg_bytes, load_image\nfrom inference.core.workflows.core_steps.common.utils import run_in_parallel\nfrom inference.core.workflows.core_steps.common.vlms import VLM_TASKS_METADATA\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    FLOAT_KIND,\n    IMAGE_KIND,\n    LANGUAGE_MODEL_OUTPUT_KIND,\n    LIST_OF_VALUES_KIND,\n    SECRET_KIND,\n    STRING_KIND,\n    ImageInputField,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nSUPPORTED_TASK_TYPES_LIST = [\n    \"unconstrained\",\n    \"ocr\",\n    \"structured-answering\",\n    \"classification\",\n    \"multi-label-classification\",\n    \"visual-question-answering\",\n    \"caption\",\n    \"detailed-caption\",\n]\nSUPPORTED_TASK_TYPES = set(SUPPORTED_TASK_TYPES_LIST)\n\nRELEVANT_TASKS_METADATA = {\n    k: v for k, v in VLM_TASKS_METADATA.items() if k in SUPPORTED_TASK_TYPES\n}\nRELEVANT_TASKS_DOCS_DESCRIPTION = \"\\n\\n\".join(\n    f\"* **{v['name']}** (`{k}`) - {v['description']}\"\n    for k, v in RELEVANT_TASKS_METADATA.items()\n)\n\n\nLONG_DESCRIPTION = f\"\"\"\nAsk a question to OpenAI's GPT-4 with Vision model.\n\nYou can specify arbitrary text prompts or predefined ones, the block supports the following types of prompt:\n\n{RELEVANT_TASKS_DOCS_DESCRIPTION}\n\nYou need to provide your OpenAI API key to use the GPT-4 with Vision model. \n\"\"\"\n\n\nTaskType = Literal[tuple(SUPPORTED_TASK_TYPES_LIST)]\n\nTASKS_REQUIRING_PROMPT = {\n    \"unconstrained\",\n    \"visual-question-answering\",\n}\n\nTASKS_REQUIRING_CLASSES = {\n    \"classification\",\n    \"multi-label-classification\",\n}\n\nTASKS_REQUIRING_OUTPUT_STRUCTURE = {\n    \"structured-answering\",\n}\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"OpenAI\",\n            \"version\": \"v3\",\n            \"short_description\": \"Run OpenAI's GPT-4 with vision capabilities.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"model\",\n            \"search_keywords\": [\"LMM\", \"VLM\", \"ChatGPT\", \"GPT\", \"OpenAI\"],\n            \"is_vlm_block\": True,\n            \"task_type_property\": \"task_type\",\n            \"ui_manifest\": {\n                \"section\": \"model\",\n                \"icon\": \"fal fa-atom\",\n                \"blockPriority\": 5,\n                \"popular\": True,\n            },\n        },\n        protected_namespaces=(),\n    )\n    type: Literal[\"roboflow_core/open_ai@v3\"]\n    images: Selector(kind=[IMAGE_KIND]) = ImageInputField\n    task_type: TaskType = Field(\n        default=\"unconstrained\",\n        description=\"Task type to be performed by model. Value determines required parameters and output response.\",\n        json_schema_extra={\n            \"values_metadata\": RELEVANT_TASKS_METADATA,\n            \"recommended_parsers\": {\n                \"structured-answering\": \"roboflow_core/json_parser@v1\",\n                \"classification\": \"roboflow_core/vlm_as_classifier@v1\",\n                \"multi-label-classification\": \"roboflow_core/vlm_as_classifier@v1\",\n            },\n            \"always_visible\": True,\n        },\n    )\n    prompt: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Text prompt to the OpenAI model\",\n        examples=[\"my prompt\", \"$inputs.prompt\"],\n        json_schema_extra={\n            \"relevant_for\": {\n                \"task_type\": {\"values\": TASKS_REQUIRING_PROMPT, \"required\": True},\n            },\n            \"multiline\": True,\n        },\n    )\n    output_structure: Optional[Dict[str, str]] = Field(\n        default=None,\n        description=\"Dictionary with structure of expected JSON response\",\n        examples=[{\"my_key\": \"description\"}, \"$inputs.output_structure\"],\n        json_schema_extra={\n            \"relevant_for\": {\n                \"task_type\": {\n                    \"values\": TASKS_REQUIRING_OUTPUT_STRUCTURE,\n                    \"required\": True,\n                },\n            },\n        },\n    )\n    classes: Optional[Union[Selector(kind=[LIST_OF_VALUES_KIND]), List[str]]] = Field(\n        default=None,\n        description=\"List of classes to be used\",\n        examples=[[\"class-a\", \"class-b\"], \"$inputs.classes\"],\n        json_schema_extra={\n            \"relevant_for\": {\n                \"task_type\": {\n                    \"values\": TASKS_REQUIRING_CLASSES,\n                    \"required\": True,\n                },\n            },\n        },\n    )\n    api_key: Union[Selector(kind=[STRING_KIND, SECRET_KIND]), str] = Field(\n        description=\"Your OpenAI API key\",\n        examples=[\"xxx-xxx\", \"$inputs.openai_api_key\"],\n        private=True,\n    )\n    model_version: Union[\n        Selector(kind=[STRING_KIND]), Literal[\"gpt-4o\", \"gpt-4o-mini\"]\n    ] = Field(\n        default=\"gpt-4o\",\n        description=\"Model to be used\",\n        examples=[\"gpt-4o\", \"$inputs.openai_model\"],\n    )\n    image_detail: Union[\n        Selector(kind=[STRING_KIND]), Literal[\"auto\", \"high\", \"low\"]\n    ] = Field(\n        default=\"auto\",\n        description=\"Indicates the image's quality, with 'high' suggesting it is of high resolution and should be processed or displayed with high fidelity.\",\n        examples=[\"auto\", \"high\", \"low\"],\n    )\n    max_tokens: int = Field(\n        default=450,\n        description=\"Maximum number of tokens the model can generate in it's response.\",\n    )\n    temperature: Optional[Union[float, Selector(kind=[FLOAT_KIND])]] = Field(\n        default=None,\n        description=\"Temperature to sample from the model - value in range 0.0-2.0, the higher - the more \"\n        'random / \"creative\" the generations are.',\n        ge=0.0,\n        le=2.0,\n    )\n    max_concurrent_requests: Optional[int] = Field(\n        default=None,\n        description=\"Number of concurrent requests that can be executed by block when batch of input images provided. \"\n        \"If not given - block defaults to value configured globally in Workflows Execution Engine. \"\n        \"Please restrict if you hit OpenAI limits.\",\n    )\n\n    @model_validator(mode=\"after\")\n    def validate(self) -> \"BlockManifest\":\n        if self.task_type in TASKS_REQUIRING_PROMPT and self.prompt is None:\n            raise ValueError(\n                f\"`prompt` parameter required to be set for task `{self.task_type}`\"\n            )\n        if self.task_type in TASKS_REQUIRING_CLASSES and self.classes is None:\n            raise ValueError(\n                f\"`classes` parameter required to be set for task `{self.task_type}`\"\n            )\n        if (\n            self.task_type in TASKS_REQUIRING_OUTPUT_STRUCTURE\n            and self.output_structure is None\n        ):\n            raise ValueError(\n                f\"`output_structure` parameter required to be set for task `{self.task_type}`\"\n            )\n        return self\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return [\"images\"]\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(\n                name=\"output\", kind=[STRING_KIND, LANGUAGE_MODEL_OUTPUT_KIND]\n            ),\n            OutputDefinition(name=\"classes\", kind=[LIST_OF_VALUES_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.4.0,<2.0.0\"\n\n\nclass OpenAIBlockV3(WorkflowBlock):\n\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"model_manager\", \"api_key\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        task_type: TaskType,\n        prompt: Optional[str],\n        output_structure: Optional[Dict[str, str]],\n        classes: Optional[List[str]],\n        api_key: str,\n        model_version: str,\n        image_detail: Literal[\"low\", \"high\", \"auto\"],\n        max_tokens: int,\n        temperature: Optional[float],\n        max_concurrent_requests: Optional[int],\n    ) -> BlockResult:\n        inference_images = [i.to_inference_format() for i in images]\n        raw_outputs = run_gpt_4v_llm_prompting(\n            roboflow_api_key=self._api_key,\n            images=inference_images,\n            task_type=task_type,\n            prompt=prompt,\n            output_structure=output_structure,\n            classes=classes,\n            openai_api_key=api_key,\n            gpt_model_version=model_version,\n            gpt_image_detail=image_detail,\n            max_tokens=max_tokens,\n            temperature=temperature,\n            max_concurrent_requests=max_concurrent_requests,\n        )\n        return [\n            {\"output\": raw_output, \"classes\": classes} for raw_output in raw_outputs\n        ]\n\n\ndef run_gpt_4v_llm_prompting(\n    images: List[Dict[str, Any]],\n    task_type: TaskType,\n    prompt: Optional[str],\n    output_structure: Optional[Dict[str, str]],\n    classes: Optional[List[str]],\n    roboflow_api_key: Optional[str],\n    openai_api_key: Optional[str],\n    gpt_model_version: str,\n    gpt_image_detail: Literal[\"auto\", \"high\", \"low\"],\n    max_tokens: int,\n    temperature: Optional[int],\n    max_concurrent_requests: Optional[int],\n) -> List[str]:\n    if task_type not in PROMPT_BUILDERS:\n        raise ValueError(f\"Task type: {task_type} not supported.\")\n    gpt4_prompts = []\n    for image in images:\n        loaded_image, _ = load_image(image)\n        base64_image = base64.b64encode(\n            encode_image_to_jpeg_bytes(loaded_image)\n        ).decode(\"ascii\")\n        generated_prompt = PROMPT_BUILDERS[task_type](\n            base64_image=base64_image,\n            prompt=prompt,\n            output_structure=output_structure,\n            classes=classes,\n            gpt_image_detail=gpt_image_detail,\n        )\n        gpt4_prompts.append(generated_prompt)\n    return execute_gpt_4v_requests(\n        roboflow_api_key=roboflow_api_key,\n        openai_api_key=openai_api_key,\n        gpt4_prompts=gpt4_prompts,\n        gpt_model_version=gpt_model_version,\n        max_tokens=max_tokens,\n        temperature=temperature,\n        max_concurrent_requests=max_concurrent_requests,\n    )\n\n\ndef execute_gpt_4v_requests(\n    roboflow_api_key: str,\n    openai_api_key: str,\n    gpt4_prompts: List[List[dict]],\n    gpt_model_version: str,\n    max_tokens: int,\n    temperature: Optional[float],\n    max_concurrent_requests: Optional[int],\n) -> List[str]:\n    tasks = [\n        partial(\n            execute_gpt_4v_request,\n            roboflow_api_key=roboflow_api_key,\n            openai_api_key=openai_api_key,\n            prompt=prompt,\n            gpt_model_version=gpt_model_version,\n            max_tokens=max_tokens,\n            temperature=temperature,\n        )\n        for prompt in gpt4_prompts\n    ]\n    max_workers = (\n        max_concurrent_requests\n        or WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS\n    )\n    return run_in_parallel(\n        tasks=tasks,\n        max_workers=max_workers,\n    )\n\n\ndef _execute_proxied_openai_request(\n    roboflow_api_key: str,\n    openai_api_key: str,\n    prompt: List[dict],\n    gpt_model_version: str,\n    max_tokens: int,\n    temperature: Optional[float],\n) -> str:\n    \"\"\"Executes OpenAI request via Roboflow proxy.\"\"\"\n    # Build payload and endpoint outside error handling.\n    payload = {\n        \"model\": gpt_model_version,\n        \"messages\": prompt,\n        \"max_tokens\": max_tokens,\n        \"openai_api_key\": openai_api_key,\n    }\n    if temperature is not None:\n        payload[\"temperature\"] = temperature\n\n    endpoint = f\"{API_BASE_URL}/apiproxy/openai?api_key={roboflow_api_key}\"\n\n    try:\n        response = requests.post(endpoint, json=payload)\n        response.raise_for_status()\n    except requests.exceptions.RequestException as e:\n        raise RuntimeError(f\"Failed to connect to Roboflow proxy: {e}\") from e\n\n    try:\n        response_data = response.json()\n        return response_data[\"choices\"][0][\"message\"][\"content\"]\n    except (KeyError, IndexError) as e:\n        raise RuntimeError(\n            f\"Invalid response structure from Roboflow proxy: {e} - Response: {response.text}\"\n        ) from e\n\n\ndef _execute_openai_request(\n    openai_api_key: str,\n    prompt: List[dict],\n    gpt_model_version: str,\n    max_tokens: int,\n    temperature: Optional[float],\n) -> str:\n    \"\"\"Executes OpenAI request directly.\"\"\"\n    # Use NOT_GIVEN only if needed, right away.\n    temp_value = temperature if temperature is not None else NOT_GIVEN\n\n    try:\n        client = _get_openai_client(openai_api_key)\n        # Required params tight together\n        response = client.chat.completions.create(\n            model=gpt_model_version,\n            messages=prompt,\n            max_tokens=max_tokens,\n            temperature=temp_value,\n        )\n        return response.choices[0].message.content\n    except Exception as e:\n        # Don't do any extra logic except what is necessary.\n        raise RuntimeError(f\"OpenAI API request failed: {e}\") from e\n\n\ndef execute_gpt_4v_request(\n    roboflow_api_key: str,\n    openai_api_key: str,\n    prompt: List[dict],\n    gpt_model_version: str,\n    max_tokens: int,\n    temperature: Optional[float],\n) -> str:\n    # Tuple-of-prefixes is faster for multiple startswith checks\n    if openai_api_key.startswith((\"rf_key:account\", \"rf_key:user:\")):\n        return _execute_proxied_openai_request(\n            roboflow_api_key=roboflow_api_key,\n            openai_api_key=openai_api_key,\n            prompt=prompt,\n            gpt_model_version=gpt_model_version,\n            max_tokens=max_tokens,\n            temperature=temperature,\n        )\n    else:\n        return _execute_openai_request(\n            openai_api_key=openai_api_key,\n            prompt=prompt,\n            gpt_model_version=gpt_model_version,\n            max_tokens=max_tokens,\n            temperature=temperature,\n        )\n\n\ndef prepare_unconstrained_prompt(\n    base64_image: str,\n    prompt: str,\n    gpt_image_detail: str,\n    **kwargs,\n) -> List[dict]:\n    return [\n        {\n            \"role\": \"user\",\n            \"content\": [\n                {\"type\": \"text\", \"text\": prompt},\n                {\n                    \"type\": \"image_url\",\n                    \"image_url\": {\n                        \"url\": f\"data:image/jpeg;base64,{base64_image}\",\n                        \"detail\": gpt_image_detail,\n                    },\n                },\n            ],\n        }\n    ]\n\n\ndef prepare_classification_prompt(\n    base64_image: str, classes: List[str], gpt_image_detail: str, **kwargs\n) -> List[dict]:\n    serialised_classes = \", \".join(classes)\n    return [\n        {\n            \"role\": \"system\",\n            \"content\": \"You act as single-class classification model. You must provide reasonable predictions. \"\n            \"You are only allowed to produce JSON document in Markdown ```json [...]``` markers. \"\n            'Expected structure of json: {\"class_name\": \"class-name\", \"confidence\": 0.4}. '\n            \"`class-name` must be one of the class names defined by user. You are only allowed to return \"\n            \"single JSON document, even if there are potentially multiple classes. You are not allowed to return list.\",\n        },\n        {\n            \"role\": \"user\",\n            \"content\": [\n                {\n                    \"type\": \"text\",\n                    \"text\": f\"List of all classes to be recognised by model: {serialised_classes}\",\n                },\n                {\n                    \"type\": \"image_url\",\n                    \"image_url\": {\n                        \"url\": f\"data:image/jpeg;base64,{base64_image}\",\n                        \"detail\": gpt_image_detail,\n                    },\n                },\n            ],\n        },\n    ]\n\n\ndef prepare_multi_label_classification_prompt(\n    base64_image: str, classes: List[str], gpt_image_detail: str, **kwargs\n) -> List[dict]:\n    serialised_classes = \", \".join(classes)\n    return [\n        {\n            \"role\": \"system\",\n            \"content\": \"You act as multi-label classification model. You must provide reasonable predictions. \"\n            \"You are only allowed to produce JSON document in Markdown ```json``` markers. \"\n            'Expected structure of json: {\"predicted_classes\": [{\"class\": \"class-name-1\", \"confidence\": 0.9}, '\n            '{\"class\": \"class-name-2\", \"confidence\": 0.7}]}. '\n            \"`class-name-X` must be one of the class names defined by user and `confidence` is a float value in range \"\n            \"0.0-1.0 that represent how sure you are that the class is present in the image. Only return class names \"\n            \"that are visible.\",\n        },\n        {\n            \"role\": \"user\",\n            \"content\": [\n                {\n                    \"type\": \"text\",\n                    \"text\": f\"List of all classes to be recognised by model: {serialised_classes}\",\n                },\n                {\n                    \"type\": \"image_url\",\n                    \"image_url\": {\n                        \"url\": f\"data:image/jpeg;base64,{base64_image}\",\n                        \"detail\": gpt_image_detail,\n                    },\n                },\n            ],\n        },\n    ]\n\n\ndef prepare_vqa_prompt(\n    base64_image: str, prompt: str, gpt_image_detail: str, **kwargs\n) -> List[dict]:\n    return [\n        {\n            \"role\": \"system\",\n            \"content\": \"You act as Visual Question Answering model. Your task is to provide answer to question\"\n            \"submitted by user. If this is open-question - answer with few sentences, for ABCD question, \"\n            \"return only the indicator of the answer.\",\n        },\n        {\n            \"role\": \"user\",\n            \"content\": [\n                {\"type\": \"text\", \"text\": f\"Question: {prompt}\"},\n                {\n                    \"type\": \"image_url\",\n                    \"image_url\": {\n                        \"url\": f\"data:image/jpeg;base64,{base64_image}\",\n                        \"detail\": gpt_image_detail,\n                    },\n                },\n            ],\n        },\n    ]\n\n\ndef prepare_ocr_prompt(\n    base64_image: str, gpt_image_detail: str, **kwargs\n) -> List[dict]:\n    return [\n        {\n            \"role\": \"system\",\n            \"content\": \"You act as OCR model. Your task is to read text from the image and return it in \"\n            \"paragraphs representing the structure of texts in the image. You should only return \"\n            \"recognised text, nothing else.\",\n        },\n        {\n            \"role\": \"user\",\n            \"content\": [\n                {\n                    \"type\": \"image_url\",\n                    \"image_url\": {\n                        \"url\": f\"data:image/jpeg;base64,{base64_image}\",\n                        \"detail\": gpt_image_detail,\n                    },\n                },\n            ],\n        },\n    ]\n\n\ndef prepare_caption_prompt(\n    base64_image: str, gpt_image_detail: str, short_description: bool, **kwargs\n) -> List[dict]:\n    caption_detail_level = \"Caption should be short.\"\n    if not short_description:\n        caption_detail_level = \"Caption should be extensive.\"\n    return [\n        {\n            \"role\": \"system\",\n            \"content\": f\"You act as image caption model. Your task is to provide description of the image. \"\n            f\"{caption_detail_level}\",\n        },\n        {\n            \"role\": \"user\",\n            \"content\": [\n                {\n                    \"type\": \"image_url\",\n                    \"image_url\": {\n                        \"url\": f\"data:image/jpeg;base64,{base64_image}\",\n                        \"detail\": gpt_image_detail,\n                    },\n                },\n            ],\n        },\n    ]\n\n\ndef prepare_structured_answering_prompt(\n    base64_image: str, output_structure: Dict[str, str], gpt_image_detail: str, **kwargs\n) -> List[dict]:\n    output_structure_serialised = json.dumps(output_structure, indent=4)\n    return [\n        {\n            \"role\": \"system\",\n            \"content\": \"You are supposed to produce responses in JSON wrapped in Markdown markers: \"\n            \"```json\\nyour-response\\n```. User is to provide you dictionary with keys and values. \"\n            \"Each key must be present in your response. Values in user dictionary represent \"\n            \"descriptions for JSON fields to be generated. Provide only JSON Markdown in response.\",\n        },\n        {\n            \"role\": \"user\",\n            \"content\": [\n                {\n                    \"type\": \"text\",\n                    \"text\": f\"Specification of requirements regarding output fields: \\n\"\n                    f\"{output_structure_serialised}\",\n                },\n                {\n                    \"type\": \"image_url\",\n                    \"image_url\": {\n                        \"url\": f\"data:image/jpeg;base64,{base64_image}\",\n                        \"detail\": gpt_image_detail,\n                    },\n                },\n            ],\n        },\n    ]\n\n\ndef _get_openai_client(api_key: str):\n    client = _openai_client_cache.get(api_key)\n    if client is None:\n        client = OpenAI(api_key=api_key)\n        _openai_client_cache[api_key] = client\n    return client\n\n\nPROMPT_BUILDERS = {\n    \"unconstrained\": prepare_unconstrained_prompt,\n    \"ocr\": prepare_ocr_prompt,\n    \"visual-question-answering\": prepare_vqa_prompt,\n    \"caption\": partial(prepare_caption_prompt, short_description=True),\n    \"detailed-caption\": partial(prepare_caption_prompt, short_description=False),\n    \"classification\": prepare_classification_prompt,\n    \"multi-label-classification\": prepare_multi_label_classification_prompt,\n    \"structured-answering\": prepare_structured_answering_prompt,\n}\n\n_openai_client_cache = {}\n",
    "optimized_raw_markdown": "",
    "optimized_function_only": "def execute_gpt_4v_request(\n    roboflow_api_key: str,\n    openai_api_key: str,\n    prompt: List[dict],\n    gpt_model_version: str,\n    max_tokens: int,\n    temperature: Optional[float],\n) -> str:\n    # Tuple-of-prefixes is faster for multiple startswith checks\n    if openai_api_key.startswith((\"rf_key:account\", \"rf_key:user:\")):\n        return _execute_proxied_openai_request(\n            roboflow_api_key=roboflow_api_key,\n            openai_api_key=openai_api_key,\n            prompt=prompt,\n            gpt_model_version=gpt_model_version,\n            max_tokens=max_tokens,\n            temperature=temperature,\n        )\n    else:\n        return _execute_openai_request(\n            openai_api_key=openai_api_key,\n            prompt=prompt,\n            gpt_model_version=gpt_model_version,\n            max_tokens=max_tokens,\n            temperature=temperature,\n        )\n",
    "original_file_content": "import base64\nimport json\nfrom functools import partial\nfrom typing import Any, Dict, List, Literal, Optional, Type, Union\nimport requests\n\nfrom openai import OpenAI\nfrom openai._types import NOT_GIVEN\nfrom pydantic import ConfigDict, Field, model_validator\n\nfrom inference.core.env import WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS, API_BASE_URL\nfrom inference.core.managers.base import ModelManager\nfrom inference.core.utils.image_utils import encode_image_to_jpeg_bytes, load_image\nfrom inference.core.workflows.core_steps.common.utils import run_in_parallel\nfrom inference.core.workflows.core_steps.common.vlms import VLM_TASKS_METADATA\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    FLOAT_KIND,\n    IMAGE_KIND,\n    LANGUAGE_MODEL_OUTPUT_KIND,\n    LIST_OF_VALUES_KIND,\n    SECRET_KIND,\n    STRING_KIND,\n    ImageInputField,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nSUPPORTED_TASK_TYPES_LIST = [\n    \"unconstrained\",\n    \"ocr\",\n    \"structured-answering\",\n    \"classification\",\n    \"multi-label-classification\",\n    \"visual-question-answering\",\n    \"caption\",\n    \"detailed-caption\",\n]\nSUPPORTED_TASK_TYPES = set(SUPPORTED_TASK_TYPES_LIST)\n\nRELEVANT_TASKS_METADATA = {\n    k: v for k, v in VLM_TASKS_METADATA.items() if k in SUPPORTED_TASK_TYPES\n}\nRELEVANT_TASKS_DOCS_DESCRIPTION = \"\\n\\n\".join(\n    f\"* **{v['name']}** (`{k}`) - {v['description']}\"\n    for k, v in RELEVANT_TASKS_METADATA.items()\n)\n\n\nLONG_DESCRIPTION = f\"\"\"\nAsk a question to OpenAI's GPT-4 with Vision model.\n\nYou can specify arbitrary text prompts or predefined ones, the block supports the following types of prompt:\n\n{RELEVANT_TASKS_DOCS_DESCRIPTION}\n\nYou need to provide your OpenAI API key to use the GPT-4 with Vision model. \n\"\"\"\n\n\nTaskType = Literal[tuple(SUPPORTED_TASK_TYPES_LIST)]\n\nTASKS_REQUIRING_PROMPT = {\n    \"unconstrained\",\n    \"visual-question-answering\",\n}\n\nTASKS_REQUIRING_CLASSES = {\n    \"classification\",\n    \"multi-label-classification\",\n}\n\nTASKS_REQUIRING_OUTPUT_STRUCTURE = {\n    \"structured-answering\",\n}\n\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"OpenAI\",\n            \"version\": \"v3\",\n            \"short_description\": \"Run OpenAI's GPT-4 with vision capabilities.\",\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"model\",\n            \"search_keywords\": [\"LMM\", \"VLM\", \"ChatGPT\", \"GPT\", \"OpenAI\"],\n            \"is_vlm_block\": True,\n            \"task_type_property\": \"task_type\",\n            \"ui_manifest\": {\n                \"section\": \"model\",\n                \"icon\": \"fal fa-atom\",\n                \"blockPriority\": 5,\n                \"popular\": True,\n            },\n        },\n        protected_namespaces=(),\n    )\n    type: Literal[\"roboflow_core/open_ai@v3\"]\n    images: Selector(kind=[IMAGE_KIND]) = ImageInputField\n    task_type: TaskType = Field(\n        default=\"unconstrained\",\n        description=\"Task type to be performed by model. Value determines required parameters and output response.\",\n        json_schema_extra={\n            \"values_metadata\": RELEVANT_TASKS_METADATA,\n            \"recommended_parsers\": {\n                \"structured-answering\": \"roboflow_core/json_parser@v1\",\n                \"classification\": \"roboflow_core/vlm_as_classifier@v1\",\n                \"multi-label-classification\": \"roboflow_core/vlm_as_classifier@v1\",\n            },\n            \"always_visible\": True,\n        },\n    )\n    prompt: Optional[Union[Selector(kind=[STRING_KIND]), str]] = Field(\n        default=None,\n        description=\"Text prompt to the OpenAI model\",\n        examples=[\"my prompt\", \"$inputs.prompt\"],\n        json_schema_extra={\n            \"relevant_for\": {\n                \"task_type\": {\"values\": TASKS_REQUIRING_PROMPT, \"required\": True},\n            },\n            \"multiline\": True,\n        },\n    )\n    output_structure: Optional[Dict[str, str]] = Field(\n        default=None,\n        description=\"Dictionary with structure of expected JSON response\",\n        examples=[{\"my_key\": \"description\"}, \"$inputs.output_structure\"],\n        json_schema_extra={\n            \"relevant_for\": {\n                \"task_type\": {\n                    \"values\": TASKS_REQUIRING_OUTPUT_STRUCTURE,\n                    \"required\": True,\n                },\n            },\n        },\n    )\n    classes: Optional[Union[Selector(kind=[LIST_OF_VALUES_KIND]), List[str]]] = Field(\n        default=None,\n        description=\"List of classes to be used\",\n        examples=[[\"class-a\", \"class-b\"], \"$inputs.classes\"],\n        json_schema_extra={\n            \"relevant_for\": {\n                \"task_type\": {\n                    \"values\": TASKS_REQUIRING_CLASSES,\n                    \"required\": True,\n                },\n            },\n        },\n    )\n    api_key: Union[Selector(kind=[STRING_KIND, SECRET_KIND]), str] = Field(\n        description=\"Your OpenAI API key\",\n        examples=[\"xxx-xxx\", \"$inputs.openai_api_key\"],\n        private=True,\n    )\n    model_version: Union[\n        Selector(kind=[STRING_KIND]), Literal[\"gpt-4o\", \"gpt-4o-mini\"]\n    ] = Field(\n        default=\"gpt-4o\",\n        description=\"Model to be used\",\n        examples=[\"gpt-4o\", \"$inputs.openai_model\"],\n    )\n    image_detail: Union[\n        Selector(kind=[STRING_KIND]), Literal[\"auto\", \"high\", \"low\"]\n    ] = Field(\n        default=\"auto\",\n        description=\"Indicates the image's quality, with 'high' suggesting it is of high resolution and should be processed or displayed with high fidelity.\",\n        examples=[\"auto\", \"high\", \"low\"],\n    )\n    max_tokens: int = Field(\n        default=450,\n        description=\"Maximum number of tokens the model can generate in it's response.\",\n    )\n    temperature: Optional[Union[float, Selector(kind=[FLOAT_KIND])]] = Field(\n        default=None,\n        description=\"Temperature to sample from the model - value in range 0.0-2.0, the higher - the more \"\n        'random / \"creative\" the generations are.',\n        ge=0.0,\n        le=2.0,\n    )\n    max_concurrent_requests: Optional[int] = Field(\n        default=None,\n        description=\"Number of concurrent requests that can be executed by block when batch of input images provided. \"\n        \"If not given - block defaults to value configured globally in Workflows Execution Engine. \"\n        \"Please restrict if you hit OpenAI limits.\",\n    )\n\n    @model_validator(mode=\"after\")\n    def validate(self) -> \"BlockManifest\":\n        if self.task_type in TASKS_REQUIRING_PROMPT and self.prompt is None:\n            raise ValueError(\n                f\"`prompt` parameter required to be set for task `{self.task_type}`\"\n            )\n        if self.task_type in TASKS_REQUIRING_CLASSES and self.classes is None:\n            raise ValueError(\n                f\"`classes` parameter required to be set for task `{self.task_type}`\"\n            )\n        if (\n            self.task_type in TASKS_REQUIRING_OUTPUT_STRUCTURE\n            and self.output_structure is None\n        ):\n            raise ValueError(\n                f\"`output_structure` parameter required to be set for task `{self.task_type}`\"\n            )\n        return self\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return [\"images\"]\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(\n                name=\"output\", kind=[STRING_KIND, LANGUAGE_MODEL_OUTPUT_KIND]\n            ),\n            OutputDefinition(name=\"classes\", kind=[LIST_OF_VALUES_KIND]),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.4.0,<2.0.0\"\n\n\nclass OpenAIBlockV3(WorkflowBlock):\n\n    def __init__(\n        self,\n        model_manager: ModelManager,\n        api_key: Optional[str],\n    ):\n        self._model_manager = model_manager\n        self._api_key = api_key\n\n    @classmethod\n    def get_init_parameters(cls) -> List[str]:\n        return [\"model_manager\", \"api_key\"]\n\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n    def run(\n        self,\n        images: Batch[WorkflowImageData],\n        task_type: TaskType,\n        prompt: Optional[str],\n        output_structure: Optional[Dict[str, str]],\n        classes: Optional[List[str]],\n        api_key: str,\n        model_version: str,\n        image_detail: Literal[\"low\", \"high\", \"auto\"],\n        max_tokens: int,\n        temperature: Optional[float],\n        max_concurrent_requests: Optional[int],\n    ) -> BlockResult:\n        inference_images = [i.to_inference_format() for i in images]\n        raw_outputs = run_gpt_4v_llm_prompting(\n            roboflow_api_key=self._api_key,\n            images=inference_images,\n            task_type=task_type,\n            prompt=prompt,\n            output_structure=output_structure,\n            classes=classes,\n            openai_api_key=api_key,\n            gpt_model_version=model_version,\n            gpt_image_detail=image_detail,\n            max_tokens=max_tokens,\n            temperature=temperature,\n            max_concurrent_requests=max_concurrent_requests,\n        )\n        return [\n            {\"output\": raw_output, \"classes\": classes} for raw_output in raw_outputs\n        ]\n\n\ndef run_gpt_4v_llm_prompting(\n    images: List[Dict[str, Any]],\n    task_type: TaskType,\n    prompt: Optional[str],\n    output_structure: Optional[Dict[str, str]],\n    classes: Optional[List[str]],\n    roboflow_api_key: Optional[str],\n    openai_api_key: Optional[str],\n    gpt_model_version: str,\n    gpt_image_detail: Literal[\"auto\", \"high\", \"low\"],\n    max_tokens: int,\n    temperature: Optional[int],\n    max_concurrent_requests: Optional[int],\n) -> List[str]:\n    if task_type not in PROMPT_BUILDERS:\n        raise ValueError(f\"Task type: {task_type} not supported.\")\n    gpt4_prompts = []\n    for image in images:\n        loaded_image, _ = load_image(image)\n        base64_image = base64.b64encode(\n            encode_image_to_jpeg_bytes(loaded_image)\n        ).decode(\"ascii\")\n        generated_prompt = PROMPT_BUILDERS[task_type](\n            base64_image=base64_image,\n            prompt=prompt,\n            output_structure=output_structure,\n            classes=classes,\n            gpt_image_detail=gpt_image_detail,\n        )\n        gpt4_prompts.append(generated_prompt)\n    return execute_gpt_4v_requests(\n        roboflow_api_key=roboflow_api_key,\n        openai_api_key=openai_api_key,\n        gpt4_prompts=gpt4_prompts,\n        gpt_model_version=gpt_model_version,\n        max_tokens=max_tokens,\n        temperature=temperature,\n        max_concurrent_requests=max_concurrent_requests,\n    )\n\n\ndef execute_gpt_4v_requests(\n    roboflow_api_key:str,\n    openai_api_key: str,\n    gpt4_prompts: List[List[dict]],\n    gpt_model_version: str,\n    max_tokens: int,\n    temperature: Optional[float],\n    max_concurrent_requests: Optional[int],\n) -> List[str]:\n    tasks = [\n        partial(\n            execute_gpt_4v_request,\n            roboflow_api_key=roboflow_api_key,\n            openai_api_key=openai_api_key,\n            prompt=prompt,\n            gpt_model_version=gpt_model_version,\n            max_tokens=max_tokens,\n            temperature=temperature,\n        )\n        for prompt in gpt4_prompts\n    ]\n    max_workers = (\n        max_concurrent_requests\n        or WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS\n    )\n    return run_in_parallel(\n        tasks=tasks,\n        max_workers=max_workers,\n    )\n\n\ndef _execute_proxied_openai_request(\n    roboflow_api_key: str,\n    openai_api_key: str,\n    prompt: List[dict],\n    gpt_model_version: str,\n    max_tokens: int,\n    temperature: Optional[float],\n) -> str:\n    \"\"\"Executes OpenAI request via Roboflow proxy.\"\"\"\n    payload = {\n        \"model\": gpt_model_version,\n        \"messages\": prompt,\n        \"max_tokens\": max_tokens,\n        \"openai_api_key\": openai_api_key,\n    }\n    if temperature is not None:\n        payload[\"temperature\"] = temperature\n\n    try:\n        endpoint = f\"{API_BASE_URL}/apiproxy/openai?api_key={roboflow_api_key}\"\n        response = requests.post(endpoint, json=payload)\n        response.raise_for_status()\n        response_data = response.json()\n        return response_data[\"choices\"][0][\"message\"][\"content\"]\n    except requests.exceptions.RequestException as e:\n        raise RuntimeError(f\"Failed to connect to Roboflow proxy: {e}\") from e\n    except (KeyError, IndexError) as e:\n        raise RuntimeError(\n            f\"Invalid response structure from Roboflow proxy: {e} - Response: {response.text}\"\n        ) from e\n\n\ndef _execute_openai_request(\n    openai_api_key: str,\n    prompt: List[dict],\n    gpt_model_version: str,\n    max_tokens: int,\n    temperature: Optional[float],\n) -> str:\n    \"\"\"Executes OpenAI request directly.\"\"\"\n    temp_value = temperature if temperature is not None else NOT_GIVEN\n    try:\n        client = OpenAI(api_key=openai_api_key)\n        response = client.chat.completions.create(\n            model=gpt_model_version,\n            messages=prompt,\n            max_tokens=max_tokens,\n            temperature=temp_value,\n        )\n        return response.choices[0].message.content\n    except Exception as e:\n        raise RuntimeError(f\"OpenAI API request failed: {e}\") from e\n\n\ndef execute_gpt_4v_request(\n    roboflow_api_key: str,\n    openai_api_key: str,\n    prompt: List[dict],\n    gpt_model_version: str,\n    max_tokens: int,\n    temperature: Optional[float],\n) -> str:\n    if openai_api_key.startswith(\"rf_key:account\") or openai_api_key.startswith(\n        \"rf_key:user:\"\n    ):\n        return _execute_proxied_openai_request(\n            roboflow_api_key=roboflow_api_key,\n            openai_api_key=openai_api_key,\n            prompt=prompt,\n            gpt_model_version=gpt_model_version,\n            max_tokens=max_tokens,\n            temperature=temperature,\n        )\n    else:\n        return _execute_openai_request(\n            openai_api_key=openai_api_key,\n            prompt=prompt,\n            gpt_model_version=gpt_model_version,\n            max_tokens=max_tokens,\n            temperature=temperature,\n        )\n\n\ndef prepare_unconstrained_prompt(\n    base64_image: str,\n    prompt: str,\n    gpt_image_detail: str,\n    **kwargs,\n) -> List[dict]:\n    return [\n        {\n            \"role\": \"user\",\n            \"content\": [\n                {\"type\": \"text\", \"text\": prompt},\n                {\n                    \"type\": \"image_url\",\n                    \"image_url\": {\n                        \"url\": f\"data:image/jpeg;base64,{base64_image}\",\n                        \"detail\": gpt_image_detail,\n                    },\n                },\n            ],\n        }\n    ]\n\n\ndef prepare_classification_prompt(\n    base64_image: str, classes: List[str], gpt_image_detail: str, **kwargs\n) -> List[dict]:\n    serialised_classes = \", \".join(classes)\n    return [\n        {\n            \"role\": \"system\",\n            \"content\": \"You act as single-class classification model. You must provide reasonable predictions. \"\n            \"You are only allowed to produce JSON document in Markdown ```json [...]``` markers. \"\n            'Expected structure of json: {\"class_name\": \"class-name\", \"confidence\": 0.4}. '\n            \"`class-name` must be one of the class names defined by user. You are only allowed to return \"\n            \"single JSON document, even if there are potentially multiple classes. You are not allowed to return list.\",\n        },\n        {\n            \"role\": \"user\",\n            \"content\": [\n                {\n                    \"type\": \"text\",\n                    \"text\": f\"List of all classes to be recognised by model: {serialised_classes}\",\n                },\n                {\n                    \"type\": \"image_url\",\n                    \"image_url\": {\n                        \"url\": f\"data:image/jpeg;base64,{base64_image}\",\n                        \"detail\": gpt_image_detail,\n                    },\n                },\n            ],\n        },\n    ]\n\n\ndef prepare_multi_label_classification_prompt(\n    base64_image: str, classes: List[str], gpt_image_detail: str, **kwargs\n) -> List[dict]:\n    serialised_classes = \", \".join(classes)\n    return [\n        {\n            \"role\": \"system\",\n            \"content\": \"You act as multi-label classification model. You must provide reasonable predictions. \"\n            \"You are only allowed to produce JSON document in Markdown ```json``` markers. \"\n            'Expected structure of json: {\"predicted_classes\": [{\"class\": \"class-name-1\", \"confidence\": 0.9}, '\n            '{\"class\": \"class-name-2\", \"confidence\": 0.7}]}. '\n            \"`class-name-X` must be one of the class names defined by user and `confidence` is a float value in range \"\n            \"0.0-1.0 that represent how sure you are that the class is present in the image. Only return class names \"\n            \"that are visible.\",\n        },\n        {\n            \"role\": \"user\",\n            \"content\": [\n                {\n                    \"type\": \"text\",\n                    \"text\": f\"List of all classes to be recognised by model: {serialised_classes}\",\n                },\n                {\n                    \"type\": \"image_url\",\n                    \"image_url\": {\n                        \"url\": f\"data:image/jpeg;base64,{base64_image}\",\n                        \"detail\": gpt_image_detail,\n                    },\n                },\n            ],\n        },\n    ]\n\n\ndef prepare_vqa_prompt(\n    base64_image: str, prompt: str, gpt_image_detail: str, **kwargs\n) -> List[dict]:\n    return [\n        {\n            \"role\": \"system\",\n            \"content\": \"You act as Visual Question Answering model. Your task is to provide answer to question\"\n            \"submitted by user. If this is open-question - answer with few sentences, for ABCD question, \"\n            \"return only the indicator of the answer.\",\n        },\n        {\n            \"role\": \"user\",\n            \"content\": [\n                {\"type\": \"text\", \"text\": f\"Question: {prompt}\"},\n                {\n                    \"type\": \"image_url\",\n                    \"image_url\": {\n                        \"url\": f\"data:image/jpeg;base64,{base64_image}\",\n                        \"detail\": gpt_image_detail,\n                    },\n                },\n            ],\n        },\n    ]\n\n\ndef prepare_ocr_prompt(\n    base64_image: str, gpt_image_detail: str, **kwargs\n) -> List[dict]:\n    return [\n        {\n            \"role\": \"system\",\n            \"content\": \"You act as OCR model. Your task is to read text from the image and return it in \"\n            \"paragraphs representing the structure of texts in the image. You should only return \"\n            \"recognised text, nothing else.\",\n        },\n        {\n            \"role\": \"user\",\n            \"content\": [\n                {\n                    \"type\": \"image_url\",\n                    \"image_url\": {\n                        \"url\": f\"data:image/jpeg;base64,{base64_image}\",\n                        \"detail\": gpt_image_detail,\n                    },\n                },\n            ],\n        },\n    ]\n\n\ndef prepare_caption_prompt(\n    base64_image: str, gpt_image_detail: str, short_description: bool, **kwargs\n) -> List[dict]:\n    caption_detail_level = \"Caption should be short.\"\n    if not short_description:\n        caption_detail_level = \"Caption should be extensive.\"\n    return [\n        {\n            \"role\": \"system\",\n            \"content\": f\"You act as image caption model. Your task is to provide description of the image. \"\n            f\"{caption_detail_level}\",\n        },\n        {\n            \"role\": \"user\",\n            \"content\": [\n                {\n                    \"type\": \"image_url\",\n                    \"image_url\": {\n                        \"url\": f\"data:image/jpeg;base64,{base64_image}\",\n                        \"detail\": gpt_image_detail,\n                    },\n                },\n            ],\n        },\n    ]\n\n\ndef prepare_structured_answering_prompt(\n    base64_image: str, output_structure: Dict[str, str], gpt_image_detail: str, **kwargs\n) -> List[dict]:\n    output_structure_serialised = json.dumps(output_structure, indent=4)\n    return [\n        {\n            \"role\": \"system\",\n            \"content\": \"You are supposed to produce responses in JSON wrapped in Markdown markers: \"\n            \"```json\\nyour-response\\n```. User is to provide you dictionary with keys and values. \"\n            \"Each key must be present in your response. Values in user dictionary represent \"\n            \"descriptions for JSON fields to be generated. Provide only JSON Markdown in response.\",\n        },\n        {\n            \"role\": \"user\",\n            \"content\": [\n                {\n                    \"type\": \"text\",\n                    \"text\": f\"Specification of requirements regarding output fields: \\n\"\n                    f\"{output_structure_serialised}\",\n                },\n                {\n                    \"type\": \"image_url\",\n                    \"image_url\": {\n                        \"url\": f\"data:image/jpeg;base64,{base64_image}\",\n                        \"detail\": gpt_image_detail,\n                    },\n                },\n            ],\n        },\n    ]\n\n\nPROMPT_BUILDERS = {\n    \"unconstrained\": prepare_unconstrained_prompt,\n    \"ocr\": prepare_ocr_prompt,\n    \"visual-question-answering\": prepare_vqa_prompt,\n    \"caption\": partial(prepare_caption_prompt, short_description=True),\n    \"detailed-caption\": partial(prepare_caption_prompt, short_description=False),\n    \"classification\": prepare_classification_prompt,\n    \"multi-label-classification\": prepare_multi_label_classification_prompt,\n    \"structured-answering\": prepare_structured_answering_prompt,\n}\n",
    "patch": "diff --git a/inference/core/workflows/core_steps/models/foundation/openai/v3.py b/inference/core/workflows/core_steps/models/foundation/openai/v3.py\nindex 618094b17..b93b51894 100644\n--- a/inference/core/workflows/core_steps/models/foundation/openai/v3.py\n+++ b/inference/core/workflows/core_steps/models/foundation/openai/v3.py\n@@ -8,7 +8,10 @@ from openai import OpenAI\n from openai._types import NOT_GIVEN\n from pydantic import ConfigDict, Field, model_validator\n \n-from inference.core.env import WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS, API_BASE_URL\n+from inference.core.env import (\n+    WORKFLOWS_REMOTE_EXECUTION_MAX_STEP_CONCURRENT_REQUESTS,\n+    API_BASE_URL,\n+)\n from inference.core.managers.base import ModelManager\n from inference.core.utils.image_utils import encode_image_to_jpeg_bytes, load_image\n from inference.core.workflows.core_steps.common.utils import run_in_parallel\n@@ -83,7 +86,6 @@ TASKS_REQUIRING_OUTPUT_STRUCTURE = {\n }\n \n \n-\n class BlockManifest(WorkflowBlockManifest):\n     model_config = ConfigDict(\n         json_schema_extra={\n@@ -329,7 +331,7 @@ def run_gpt_4v_llm_prompting(\n \n \n def execute_gpt_4v_requests(\n-    roboflow_api_key:str,\n+    roboflow_api_key: str,\n     openai_api_key: str,\n     gpt4_prompts: List[List[dict]],\n     gpt_model_version: str,\n@@ -368,6 +370,7 @@ def _execute_proxied_openai_request(\n     temperature: Optional[float],\n ) -> str:\n     \"\"\"Executes OpenAI request via Roboflow proxy.\"\"\"\n+    # Build payload and endpoint outside error handling.\n     payload = {\n         \"model\": gpt_model_version,\n         \"messages\": prompt,\n@@ -377,14 +380,17 @@ def _execute_proxied_openai_request(\n     if temperature is not None:\n         payload[\"temperature\"] = temperature\n \n+    endpoint = f\"{API_BASE_URL}/apiproxy/openai?api_key={roboflow_api_key}\"\n+\n     try:\n-        endpoint = f\"{API_BASE_URL}/apiproxy/openai?api_key={roboflow_api_key}\"\n         response = requests.post(endpoint, json=payload)\n         response.raise_for_status()\n-        response_data = response.json()\n-        return response_data[\"choices\"][0][\"message\"][\"content\"]\n     except requests.exceptions.RequestException as e:\n         raise RuntimeError(f\"Failed to connect to Roboflow proxy: {e}\") from e\n+\n+    try:\n+        response_data = response.json()\n+        return response_data[\"choices\"][0][\"message\"][\"content\"]\n     except (KeyError, IndexError) as e:\n         raise RuntimeError(\n             f\"Invalid response structure from Roboflow proxy: {e} - Response: {response.text}\"\n@@ -399,9 +405,12 @@ def _execute_openai_request(\n     temperature: Optional[float],\n ) -> str:\n     \"\"\"Executes OpenAI request directly.\"\"\"\n+    # Use NOT_GIVEN only if needed, right away.\n     temp_value = temperature if temperature is not None else NOT_GIVEN\n+\n     try:\n-        client = OpenAI(api_key=openai_api_key)\n+        client = _get_openai_client(openai_api_key)\n+        # Required params tight together\n         response = client.chat.completions.create(\n             model=gpt_model_version,\n             messages=prompt,\n@@ -410,6 +419,7 @@ def _execute_openai_request(\n         )\n         return response.choices[0].message.content\n     except Exception as e:\n+        # Don't do any extra logic except what is necessary.\n         raise RuntimeError(f\"OpenAI API request failed: {e}\") from e\n \n \n@@ -421,9 +431,8 @@ def execute_gpt_4v_request(\n     max_tokens: int,\n     temperature: Optional[float],\n ) -> str:\n-    if openai_api_key.startswith(\"rf_key:account\") or openai_api_key.startswith(\n-        \"rf_key:user:\"\n-    ):\n+    # Tuple-of-prefixes is faster for multiple startswith checks\n+    if openai_api_key.startswith((\"rf_key:account\", \"rf_key:user:\")):\n         return _execute_proxied_openai_request(\n             roboflow_api_key=roboflow_api_key,\n             openai_api_key=openai_api_key,\n@@ -641,6 +650,14 @@ def prepare_structured_answering_prompt(\n     ]\n \n \n+def _get_openai_client(api_key: str):\n+    client = _openai_client_cache.get(api_key)\n+    if client is None:\n+        client = OpenAI(api_key=api_key)\n+        _openai_client_cache[api_key] = client\n+    return client\n+\n+\n PROMPT_BUILDERS = {\n     \"unconstrained\": prepare_unconstrained_prompt,\n     \"ocr\": prepare_ocr_prompt,\n@@ -651,3 +668,5 @@ PROMPT_BUILDERS = {\n     \"multi-label-classification\": prepare_multi_label_classification_prompt,\n     \"structured-answering\": prepare_structured_answering_prompt,\n }\n+\n+_openai_client_cache = {}\n"
  },
  {
    "trace_id": "git_c155e1bccbd9",
    "function_name": "receive_socket_data",
    "file_path": "inference/core/interfaces/stream_manager/manager_app/communication.py",
    "speedup_x": 0.16,
    "review_quality": null,
    "pre_optimization_commit": "faf922980c7603c01683c8b02580a236d8a1c5f4",
    "resolution_method": "git_parent",
    "source": "git",
    "original_function_code": "def receive_socket_data(\n    source: socket.socket, header_size: int, buffer_size: int\n) -> dict:\n    header = source.recv(header_size)\n    if len(header) != header_size:\n        raise MalformedHeaderError(\n            private_message=f\"Expected header size: {header_size}, received: {header}\",\n            public_message=f\"Expected header size: {header_size}, received: {header}\",\n        )\n    payload_size = int.from_bytes(bytes=header, byteorder=\"big\")\n    if payload_size <= 0:\n        raise MalformedHeaderError(\n            private_message=f\"Header is indicating non positive payload size: {payload_size}\",\n            public_message=f\"Header is indicating non positive payload size: {payload_size}\",\n        )\n    received = b\"\"\n    while len(received) < payload_size:\n        chunk = source.recv(buffer_size)\n        if len(chunk) == 0:\n            raise TransmissionChannelClosed(\n                private_message=\"Socket was closed to read before payload was decoded.\",\n                public_message=\"Socket was closed to read before payload was decoded.\",\n            )\n        received += chunk\n    try:\n        return json.loads(received)\n    except ValueError as error:\n        raise MalformedPayloadError(\n            public_message=\"Received payload that is not in a JSON format\",\n            private_message=\"Received payload that is not in a JSON format\",\n            inner_error=error,\n        )\n",
    "optimized_function_code": "import json\nimport socket\nfrom typing import Optional\n\nfrom inference.core import logger\nfrom inference.core.interfaces.stream_manager.manager_app.entities import ErrorType\nfrom inference.core.interfaces.stream_manager.manager_app.errors import (\n    MalformedHeaderError,\n    MalformedPayloadError,\n    TransmissionChannelClosed,\n)\nfrom inference.core.interfaces.stream_manager.manager_app.serialisation import (\n    prepare_error_response,\n)\n\n\ndef receive_socket_data(\n    source: socket.socket, header_size: int, buffer_size: int\n) -> dict:\n    # Read the header part\n    header = source.recv(header_size)\n    if len(header) != header_size:\n        raise MalformedHeaderError(\n            private_message=f\"Expected header size: {header_size}, received: {header}\",\n            public_message=f\"Expected header size: {header_size}, received: {header}\",\n        )\n\n    # Determine payload size from the header\n    try:\n        payload_size = int.from_bytes(header, byteorder=\"big\")\n    except ValueError as e:\n        raise MalformedHeaderError(\n            private_message=\"Header size could not convert to int: \" + str(e),\n            public_message=\"Header size could not convert to int\",\n        )\n\n    if payload_size <= 0:\n        raise MalformedHeaderError(\n            private_message=f\"Header is indicating a non-positive payload size: {payload_size}\",\n            public_message=f\"Header is indicating a non-positive payload size: {payload_size}\",\n        )\n\n    # Efficiently read the payload\n    received = bytearray()\n    remaining_payload_size = payload_size\n\n    while remaining_payload_size > 0:\n        chunk = source.recv(min(buffer_size, remaining_payload_size))\n        if not chunk:\n            raise TransmissionChannelClosed(\n                private_message=\"Socket was closed before the payload was fully received.\",\n                public_message=\"Socket was closed before the payload was fully received.\",\n            )\n        received.extend(chunk)\n        remaining_payload_size -= len(\n            chunk\n        )  # Reduce the remaining size by the chunk size\n\n    # Parse and return the JSON data\n    try:\n        return json.loads(received.decode(\"utf-8\"))\n    except (ValueError, UnicodeDecodeError) as error:\n        raise MalformedPayloadError(\n            public_message=\"Received payload that is not in a JSON format\",\n            private_message=\"Received payload that is not in a JSON format\",\n            inner_error=error,\n        )\n\n\ndef send_data_trough_socket(\n    target: socket.socket,\n    header_size: int,\n    data: bytes,\n    request_id: str,\n    recover_from_overflow: bool = True,\n    pipeline_id: Optional[str] = None,\n) -> None:\n    try:\n        data_size = len(data)\n        header = data_size.to_bytes(length=header_size, byteorder=\"big\")\n        payload = header + data\n        target.sendall(payload)\n    except OverflowError as error:\n        if not recover_from_overflow:\n            logger.error(f\"OverflowError was suppressed. {error}\")\n            return None\n        error_response = prepare_error_response(\n            request_id=request_id,\n            error=error,\n            error_type=ErrorType.INTERNAL_ERROR,\n            pipeline_id=pipeline_id,\n        )\n        send_data_trough_socket(\n            target=target,\n            header_size=header_size,\n            data=error_response,\n            request_id=request_id,\n            recover_from_overflow=False,\n            pipeline_id=pipeline_id,\n        )\n    except Exception as error:\n        logger.error(f\"Could not send the response through socket. Error: {error}\")\n",
    "optimized_raw_markdown": "",
    "optimized_function_only": "def receive_socket_data(\n    source: socket.socket, header_size: int, buffer_size: int\n) -> dict:\n    # Read the header part\n    header = source.recv(header_size)\n    if len(header) != header_size:\n        raise MalformedHeaderError(\n            private_message=f\"Expected header size: {header_size}, received: {header}\",\n            public_message=f\"Expected header size: {header_size}, received: {header}\",\n        )\n\n    # Determine payload size from the header\n    try:\n        payload_size = int.from_bytes(header, byteorder=\"big\")\n    except ValueError as e:\n        raise MalformedHeaderError(\n            private_message=\"Header size could not convert to int: \" + str(e),\n            public_message=\"Header size could not convert to int\",\n        )\n\n    if payload_size <= 0:\n        raise MalformedHeaderError(\n            private_message=f\"Header is indicating a non-positive payload size: {payload_size}\",\n            public_message=f\"Header is indicating a non-positive payload size: {payload_size}\",\n        )\n\n    # Efficiently read the payload\n    received = bytearray()\n    remaining_payload_size = payload_size\n\n    while remaining_payload_size > 0:\n        chunk = source.recv(min(buffer_size, remaining_payload_size))\n        if not chunk:\n            raise TransmissionChannelClosed(\n                private_message=\"Socket was closed before the payload was fully received.\",\n                public_message=\"Socket was closed before the payload was fully received.\",\n            )\n        received.extend(chunk)\n        remaining_payload_size -= len(\n            chunk\n        )  # Reduce the remaining size by the chunk size\n\n    # Parse and return the JSON data\n    try:\n        return json.loads(received.decode(\"utf-8\"))\n    except (ValueError, UnicodeDecodeError) as error:\n        raise MalformedPayloadError(\n            public_message=\"Received payload that is not in a JSON format\",\n            private_message=\"Received payload that is not in a JSON format\",\n            inner_error=error,\n        )\n",
    "original_file_content": "import json\nimport socket\nfrom typing import Optional\n\nfrom inference.core import logger\nfrom inference.core.interfaces.stream_manager.manager_app.entities import ErrorType\nfrom inference.core.interfaces.stream_manager.manager_app.errors import (\n    MalformedHeaderError,\n    MalformedPayloadError,\n    TransmissionChannelClosed,\n)\nfrom inference.core.interfaces.stream_manager.manager_app.serialisation import (\n    prepare_error_response,\n)\n\n\ndef receive_socket_data(\n    source: socket.socket, header_size: int, buffer_size: int\n) -> dict:\n    header = source.recv(header_size)\n    if len(header) != header_size:\n        raise MalformedHeaderError(\n            private_message=f\"Expected header size: {header_size}, received: {header}\",\n            public_message=f\"Expected header size: {header_size}, received: {header}\",\n        )\n    payload_size = int.from_bytes(bytes=header, byteorder=\"big\")\n    if payload_size <= 0:\n        raise MalformedHeaderError(\n            private_message=f\"Header is indicating non positive payload size: {payload_size}\",\n            public_message=f\"Header is indicating non positive payload size: {payload_size}\",\n        )\n    received = b\"\"\n    while len(received) < payload_size:\n        chunk = source.recv(buffer_size)\n        if len(chunk) == 0:\n            raise TransmissionChannelClosed(\n                private_message=\"Socket was closed to read before payload was decoded.\",\n                public_message=\"Socket was closed to read before payload was decoded.\",\n            )\n        received += chunk\n    try:\n        return json.loads(received)\n    except ValueError as error:\n        raise MalformedPayloadError(\n            public_message=\"Received payload that is not in a JSON format\",\n            private_message=\"Received payload that is not in a JSON format\",\n            inner_error=error,\n        )\n\n\ndef send_data_trough_socket(\n    target: socket.socket,\n    header_size: int,\n    data: bytes,\n    request_id: str,\n    recover_from_overflow: bool = True,\n    pipeline_id: Optional[str] = None,\n) -> None:\n    try:\n        data_size = len(data)\n        header = data_size.to_bytes(length=header_size, byteorder=\"big\")\n        payload = header + data\n        target.sendall(payload)\n    except OverflowError as error:\n        if not recover_from_overflow:\n            logger.error(f\"OverflowError was suppressed. {error}\")\n            return None\n        error_response = prepare_error_response(\n            request_id=request_id,\n            error=error,\n            error_type=ErrorType.INTERNAL_ERROR,\n            pipeline_id=pipeline_id,\n        )\n        send_data_trough_socket(\n            target=target,\n            header_size=header_size,\n            data=error_response,\n            request_id=request_id,\n            recover_from_overflow=False,\n            pipeline_id=pipeline_id,\n        )\n    except Exception as error:\n        logger.error(f\"Could not send the response through socket. Error: {error}\")\n",
    "patch": "diff --git a/inference/core/interfaces/stream_manager/manager_app/communication.py b/inference/core/interfaces/stream_manager/manager_app/communication.py\nindex a220a1609..98317427c 100644\n--- a/inference/core/interfaces/stream_manager/manager_app/communication.py\n+++ b/inference/core/interfaces/stream_manager/manager_app/communication.py\n@@ -17,30 +17,49 @@ from inference.core.interfaces.stream_manager.manager_app.serialisation import (\n def receive_socket_data(\n     source: socket.socket, header_size: int, buffer_size: int\n ) -> dict:\n+    # Read the header part\n     header = source.recv(header_size)\n     if len(header) != header_size:\n         raise MalformedHeaderError(\n             private_message=f\"Expected header size: {header_size}, received: {header}\",\n             public_message=f\"Expected header size: {header_size}, received: {header}\",\n         )\n-    payload_size = int.from_bytes(bytes=header, byteorder=\"big\")\n+\n+    # Determine payload size from the header\n+    try:\n+        payload_size = int.from_bytes(header, byteorder=\"big\")\n+    except ValueError as e:\n+        raise MalformedHeaderError(\n+            private_message=\"Header size could not convert to int: \" + str(e),\n+            public_message=\"Header size could not convert to int\",\n+        )\n+\n     if payload_size <= 0:\n         raise MalformedHeaderError(\n-            private_message=f\"Header is indicating non positive payload size: {payload_size}\",\n-            public_message=f\"Header is indicating non positive payload size: {payload_size}\",\n+            private_message=f\"Header is indicating a non-positive payload size: {payload_size}\",\n+            public_message=f\"Header is indicating a non-positive payload size: {payload_size}\",\n         )\n-    received = b\"\"\n-    while len(received) < payload_size:\n-        chunk = source.recv(buffer_size)\n-        if len(chunk) == 0:\n+\n+    # Efficiently read the payload\n+    received = bytearray()\n+    remaining_payload_size = payload_size\n+\n+    while remaining_payload_size > 0:\n+        chunk = source.recv(min(buffer_size, remaining_payload_size))\n+        if not chunk:\n             raise TransmissionChannelClosed(\n-                private_message=\"Socket was closed to read before payload was decoded.\",\n-                public_message=\"Socket was closed to read before payload was decoded.\",\n+                private_message=\"Socket was closed before the payload was fully received.\",\n+                public_message=\"Socket was closed before the payload was fully received.\",\n             )\n-        received += chunk\n+        received.extend(chunk)\n+        remaining_payload_size -= len(\n+            chunk\n+        )  # Reduce the remaining size by the chunk size\n+\n+    # Parse and return the JSON data\n     try:\n-        return json.loads(received)\n-    except ValueError as error:\n+        return json.loads(received.decode(\"utf-8\"))\n+    except (ValueError, UnicodeDecodeError) as error:\n         raise MalformedPayloadError(\n             public_message=\"Received payload that is not in a JSON format\",\n             private_message=\"Received payload that is not in a JSON format\",\n"
  },
  {
    "trace_id": "git_bb7edd0a443f",
    "function_name": "get_masks_intersection_up_to_dimension",
    "file_path": "inference/core/workflows/execution_engine/v1/executor/execution_data_manager/step_input_assembler.py",
    "speedup_x": 0.09,
    "review_quality": null,
    "pre_optimization_commit": "f6289ddfeda5115df3edd38dec2ff6885098a6d8",
    "resolution_method": "git_parent",
    "source": "git",
    "original_function_code": "def get_masks_intersection_up_to_dimension(\n    batch_masks: List[Set[DynamicBatchIndex]],\n    dimension: int,\n) -> Optional[Set[DynamicBatchIndex]]:\n    batch_masks_in_dimension = [\n        {mask_element[:dimension] for mask_element in batch_mask}\n        for batch_mask in batch_masks\n    ]\n    if not batch_masks_in_dimension:\n        return None\n    return set.intersection(*batch_masks_in_dimension)\n",
    "optimized_function_code": "from dataclasses import dataclass\nfrom typing import Any, Dict, Generator, List, Optional, Set, Tuple, TypeVar, Union\n\nfrom inference.core.workflows.errors import AssumptionError, ExecutionEngineRuntimeError\nfrom inference.core.workflows.execution_engine.entities.base import Batch\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import (\n    CompoundStepInputDefinition,\n    DynamicStepInputDefinition,\n    StaticStepInputDefinition,\n    StepInputDefinition,\n    StepNode,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import (\n    get_last_chunk_of_selector,\n)\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.branching_manager import (\n    BranchingManager,\n)\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.dynamic_batches_manager import (\n    DynamicBatchesManager,\n    DynamicBatchIndex,\n)\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.execution_cache import (\n    ExecutionCache,\n)\n\nT = TypeVar(\"T\")\n\n\n@dataclass(frozen=True)\nclass BatchModeSIMDStepInput:\n    indices: List[DynamicBatchIndex]\n    parameters: Dict[str, Any]\n\n\n@dataclass(frozen=True)\nclass NonBatchModeSIMDStepInput:\n    index: DynamicBatchIndex\n    parameters: Dict[str, Any]\n\n\ndef construct_non_simd_step_input(\n    step_node: StepNode,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    branching_manager: BranchingManager,\n) -> Optional[Dict[str, Any]]:\n    if step_node.batch_oriented_parameters:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Attempted to get non-SIMD input for SIMD step: {step_node.name}.\"\n            f\"This is most likely a bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    masks = set()\n    for execution_branch in step_node.execution_branches_impacting_inputs:\n        if not branching_manager.is_execution_branch_registered(\n            execution_branch=execution_branch\n        ):\n            masks.add(False)\n            continue\n        if branching_manager.is_execution_branch_batch_oriented(\n            execution_branch=execution_branch\n        ):\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"For step: {step_node.name}, detected batch-oriented condition statements \"\n                f\"impacting non-SIMD step, which should be prevented by Workflows Compiler. \"\n                f\"This is most likely a bug. Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n        else:\n            mask = branching_manager.get_mask(execution_branch=execution_branch)\n            masks.add(mask)\n    if False in masks:\n        return None\n    result = {}\n    detected_empty_step_output_selector = False\n    for parameter_name, parameter_spec in step_node.input_data.items():\n        if parameter_spec.is_compound_input():\n            result[parameter_name], contains_empty_step_output_selector = (\n                construct_non_simd_step_compound_input(\n                    step_node=step_node,\n                    parameter_spec=parameter_spec,\n                    runtime_parameters=runtime_parameters,\n                    execution_cache=execution_cache,\n                )\n            )\n        else:\n            result[parameter_name], contains_empty_step_output_selector = (\n                construct_non_simd_step_non_compound_input(\n                    step_node=step_node,\n                    parameter_spec=parameter_spec,\n                    runtime_parameters=runtime_parameters,\n                    execution_cache=execution_cache,\n                )\n            )\n        detected_empty_step_output_selector = (\n            detected_empty_step_output_selector or contains_empty_step_output_selector\n        )\n    if (\n        detected_empty_step_output_selector\n        and not step_node.step_manifest.accepts_empty_values()\n    ):\n        return None\n    return result\n\n\ndef construct_non_simd_step_compound_input(\n    step_node: StepNode,\n    parameter_spec: CompoundStepInputDefinition,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> Tuple[Any, bool]:\n    if parameter_spec.represents_list_of_inputs():\n        return construct_non_simd_step_compound_list_input(\n            step_node=step_node,\n            parameter_spec=parameter_spec,\n            runtime_parameters=runtime_parameters,\n            execution_cache=execution_cache,\n        )\n    return construct_non_simd_step_compound_dict_input(\n        step_node=step_node,\n        parameter_spec=parameter_spec,\n        runtime_parameters=runtime_parameters,\n        execution_cache=execution_cache,\n    )\n\n\ndef construct_non_simd_step_compound_list_input(\n    step_node: StepNode,\n    parameter_spec: CompoundStepInputDefinition,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> Tuple[List[Any], bool]:\n    result = []\n    contains_empty_step_output_selector = False\n    for nested_definition in parameter_spec.iterate_through_definitions():\n        nested_value, value_contains_empty_selector = (\n            construct_non_simd_step_non_compound_input(\n                step_node=step_node,\n                parameter_spec=nested_definition,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n            )\n        )\n        result.append(nested_value)\n        contains_empty_step_output_selector = (\n            contains_empty_step_output_selector or value_contains_empty_selector\n        )\n    return result, contains_empty_step_output_selector\n\n\ndef construct_non_simd_step_compound_dict_input(\n    step_node: StepNode,\n    parameter_spec: CompoundStepInputDefinition,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> Tuple[Dict[str, Any], bool]:\n    result = {}\n    contains_empty_step_output_selector = False\n    for nested_definition in parameter_spec.iterate_through_definitions():\n        (\n            result[nested_definition.parameter_specification.nested_element_key],\n            value_contains_empty_selector,\n        ) = construct_non_simd_step_non_compound_input(\n            step_node=step_node,\n            parameter_spec=nested_definition,\n            runtime_parameters=runtime_parameters,\n            execution_cache=execution_cache,\n        )\n        contains_empty_step_output_selector = (\n            contains_empty_step_output_selector or value_contains_empty_selector\n        )\n    return result, contains_empty_step_output_selector\n\n\ndef construct_non_simd_step_non_compound_input(\n    step_node: StepNode,\n    parameter_spec: StepInputDefinition,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> Tuple[Any, bool]:\n    if parameter_spec.is_compound_input():\n        raise AssumptionError(\n            public_message=f\"Workflows Execution Error encountered unexpected state probably related to the fact \"\n            f\"that Workflows Compiler allowed for multi-level nesting of inputs selectors which \"\n            f\"is not supported. This is most likely the bug. Contact Roboflow team \"\n            f\"through github issues (https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if parameter_spec.is_batch_oriented():\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Encountered batch-oriented input for non-SIMD step: {step_node.name}.\"\n            f\"This is most likely a bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if parameter_spec.points_to_input():\n        parameter_spec: DynamicStepInputDefinition = parameter_spec  # type: ignore\n        input_name = get_last_chunk_of_selector(selector=parameter_spec.selector)\n        return runtime_parameters[input_name], False\n    if parameter_spec.points_to_step_output():\n        parameter_spec: DynamicStepInputDefinition = parameter_spec  # type: ignore\n        step_output = execution_cache.get_non_batch_output(\n            selector=parameter_spec.selector\n        )\n        return step_output, step_output is None\n    parameter_spec: StaticStepInputDefinition = parameter_spec  # type: ignore\n    return parameter_spec.value, False\n\n\ndef iterate_over_simd_step_input(\n    step_node: StepNode,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    dynamic_batches_manager: DynamicBatchesManager,\n    branching_manager: BranchingManager,\n) -> Generator[NonBatchModeSIMDStepInput, None, None]:\n    simd_step_input = construct_simd_step_input(\n        step_node=step_node,\n        runtime_parameters=runtime_parameters,\n        execution_cache=execution_cache,\n        dynamic_batches_manager=dynamic_batches_manager,\n        branching_manager=branching_manager,\n    )\n    parameters_generator = unfold_parameters(parameters=simd_step_input.parameters)\n    for index, single_parameters_set in zip(\n        simd_step_input.indices, parameters_generator\n    ):\n        yield NonBatchModeSIMDStepInput(\n            index=index,\n            parameters=single_parameters_set,\n        )\n\n\ndef construct_simd_step_input(\n    step_node: StepNode,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    dynamic_batches_manager: DynamicBatchesManager,\n    branching_manager: BranchingManager,\n) -> BatchModeSIMDStepInput:\n    masks = construct_mask_for_all_inputs_dimensionalities(\n        step_node=step_node,\n        branching_manager=branching_manager,\n    )\n    return prepare_parameters(\n        step_node=step_node,\n        dynamic_batches_manager=dynamic_batches_manager,\n        masks=masks,\n        runtime_parameters=runtime_parameters,\n        execution_cache=execution_cache,\n    )\n\n\ndef construct_mask_for_all_inputs_dimensionalities(\n    step_node: StepNode,\n    branching_manager: BranchingManager,\n) -> Any:\n    inputs_dimensionalities = collect_inputs_dimensionalities(step_node=step_node)\n    all_dimensionalities = {dim for dim in inputs_dimensionalities.values() if dim > 0}\n    batch_masks, non_batch_masks = [], set()\n    for execution_branch in step_node.execution_branches_impacting_inputs:\n        if not branching_manager.is_execution_branch_registered(\n            execution_branch=execution_branch\n        ):\n            non_batch_masks.add(False)\n            continue\n        if branching_manager.is_execution_branch_batch_oriented(\n            execution_branch=execution_branch\n        ):\n            mask = branching_manager.get_mask(execution_branch=execution_branch)\n            batch_masks.append(mask)\n        else:\n            mask = branching_manager.get_mask(execution_branch=execution_branch)\n            non_batch_masks.add(mask)\n    if False in non_batch_masks:\n        return {dimension: set() for dimension in all_dimensionalities}\n    return {\n        dimension: get_masks_intersection_up_to_dimension(\n            batch_masks=batch_masks,\n            dimension=dimension,\n        )\n        for dimension in all_dimensionalities\n    }\n\n\ndef collect_inputs_dimensionalities(\n    step_node: StepNode,\n) -> Dict[str, int]:\n    result = {}\n    for parameter_name, parameter_specs in step_node.input_data.items():\n        if parameter_specs.is_compound_input():\n            dimensionalities = [\n                nested_definition.get_dimensionality()\n                for nested_definition in parameter_specs.iterate_through_definitions()\n            ]\n            # to help for empty values\n            dimensionalities.append(0)\n            result[parameter_name] = max(dimensionalities)\n        else:\n            result[parameter_name] = parameter_specs.get_dimensionality()\n    return result\n\n\ndef get_masks_intersection_up_to_dimension(\n    batch_masks: List[Set[DynamicBatchIndex]],\n    dimension: int,\n) -> Optional[Set[DynamicBatchIndex]]:\n    if not batch_masks:\n        return None\n\n    # Initialize intersection with the first batch mask transformed up to the given dimension\n    intersection = {mask_element[:dimension] for mask_element in batch_masks[0]}\n\n    # Perform the intersection with the transformed sets of subsequent batch masks\n    for batch_mask in batch_masks[1:]:\n        intersection &= {mask_element[:dimension] for mask_element in batch_mask}\n\n        # Early exit if intersection becomes empty\n        if not intersection:\n            return set()\n\n    return intersection\n\n\nclass GuardForIndicesWrapping:\n\n    def __init__(self):\n        self._registered_wrapping: Optional[List[DynamicBatchIndex]] = None\n\n    def register_wrapping(\n        self, indices_before_wrapping: List[DynamicBatchIndex]\n    ) -> None:\n        if self._registered_wrapping is None:\n            self._registered_wrapping = indices_before_wrapping\n        elif self._registered_wrapping != indices_before_wrapping:\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Detected a situation when step requires dimensionality wrapping, but\"\n                f\"different inputs register different elements indices to wrap which is illegal \"\n                f\"and should be detected earlier by Workflows compiler. This is most likely a bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n\n\ndef prepare_parameters(\n    step_node: StepNode,\n    dynamic_batches_manager: DynamicBatchesManager,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> BatchModeSIMDStepInput:\n    result = {}\n    indices_for_parameter = {}\n    guard_of_indices_wrapping = GuardForIndicesWrapping()\n    compound_inputs = set()\n    contains_empty_scalar_step_output_selector = False\n    for parameter_name, parameter_specs in step_node.input_data.items():\n        if parameter_specs.is_compound_input():\n            (\n                result[parameter_name],\n                indices_for_parameter[parameter_name],\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_compound_parameter_value(\n                parameter=parameter_specs,\n                step_execution_dimensionality=step_node.step_execution_dimensionality,\n                masks=masks,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n            )\n            compound_inputs.add(parameter_name)\n        else:\n            (\n                result[parameter_name],\n                indices_for_parameter[parameter_name],\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=parameter_specs,\n                step_execution_dimensionality=step_node.step_execution_dimensionality,\n                masks=masks,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n            )\n        contains_empty_scalar_step_output_selector = (\n            contains_empty_scalar_step_output_selector\n            or value_contains_empty_scalar_step_output_selector\n        )\n    batch_parameters_indices = [\n        i for i in indices_for_parameter.values() if i is not None\n    ]\n    ensure_compound_input_indices_match(indices=batch_parameters_indices)\n    if not batch_parameters_indices:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"For step: {step_node.name} which is assessed by Workflows Compiler as \"\n            f\"SIMD step Execution Engine cannot detect batch inputs. \"\n            f\"This is most likely a bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    indices = batch_parameters_indices[0]\n    if not step_node.step_manifest.accepts_empty_values():\n        if contains_empty_scalar_step_output_selector:\n            return BatchModeSIMDStepInput(\n                indices=[],\n                parameters={},\n            )\n        empty_indices = get_empty_batch_elements_indices(value=result)\n        indices = [e for e in indices if e not in empty_indices]\n        result = remove_indices(value=result, indices=empty_indices)\n    return BatchModeSIMDStepInput(\n        indices=indices,\n        parameters=result,\n    )\n\n\ndef get_compound_parameter_value(\n    parameter: CompoundStepInputDefinition,\n    step_execution_dimensionality: int,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    dynamic_batches_manager: DynamicBatchesManager,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n) -> Tuple[Union[list, Dict[str, Any]], Optional[List[DynamicBatchIndex]], bool]:\n    contains_empty_scalar_step_output_selector = False\n    batch_indices = []\n    if parameter.represents_list_of_inputs():\n        result = []\n        for nested_element in parameter.iterate_through_definitions():\n            (\n                non_compound_parameter_value,\n                non_compound_indices,\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=nested_element,\n                step_execution_dimensionality=step_execution_dimensionality,\n                masks=masks,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n            )\n            result.append(non_compound_parameter_value)\n            contains_empty_scalar_step_output_selector = (\n                contains_empty_scalar_step_output_selector\n                or value_contains_empty_scalar_step_output_selector\n            )\n            if non_compound_indices is not None:\n                batch_indices.append(non_compound_indices)\n    else:\n        result = {}\n        for nested_element in parameter.iterate_through_definitions():\n            (\n                non_compound_parameter_value,\n                non_compound_indices,\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=nested_element,\n                step_execution_dimensionality=step_execution_dimensionality,\n                masks=masks,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n            )\n            result[nested_element.parameter_specification.nested_element_key] = (\n                non_compound_parameter_value\n            )\n            contains_empty_scalar_step_output_selector = (\n                contains_empty_scalar_step_output_selector\n                or value_contains_empty_scalar_step_output_selector\n            )\n            if non_compound_indices is not None:\n                batch_indices.append(non_compound_indices)\n    ensure_compound_input_indices_match(indices=batch_indices)\n    result_indices = None\n    if len(batch_indices) > 0:\n        result_indices = batch_indices[0]\n    return result, result_indices, contains_empty_scalar_step_output_selector\n\n\ndef get_non_compound_parameter_value(\n    parameter: StepInputDefinition,\n    step_execution_dimensionality: int,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    dynamic_batches_manager: DynamicBatchesManager,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n) -> Union[Any, Optional[List[DynamicBatchIndex]], bool]:\n    if not parameter.is_batch_oriented():\n        if parameter.points_to_input():\n            input_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n            parameter_name = get_last_chunk_of_selector(\n                selector=input_parameter.selector\n            )\n            return runtime_parameters[parameter_name], None, False\n        elif parameter.points_to_step_output():\n            input_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n            value = execution_cache.get_non_batch_output(\n                selector=input_parameter.selector\n            )\n            return value, None, value is None\n        else:\n            static_input: StaticStepInputDefinition = parameter  # type: ignore\n            return static_input.value, None, False\n    dynamic_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n    parameter_dimensionality = dynamic_parameter.get_dimensionality()\n    lineage_indices = dynamic_batches_manager.get_indices_for_data_lineage(\n        lineage=dynamic_parameter.data_lineage,\n    )\n    mask_for_dimension = masks[parameter_dimensionality]\n    if dynamic_parameter.points_to_input():\n        input_name = get_last_chunk_of_selector(selector=dynamic_parameter.selector)\n        batch_input = _flatten_batch_oriented_inputs(\n            runtime_parameters[input_name],\n            dimensionality=parameter_dimensionality,\n        )\n        if mask_for_dimension is not None:\n            if len(lineage_indices) != len(batch_input):\n                raise ExecutionEngineRuntimeError(\n                    public_message=f\"Detected a situation when input parameter: \"\n                    f\"{input_name}\"\n                    f\"size is mismatched compared to mask requested for that input. \"\n                    f\"Input length: {len(batch_input)}, mask size: {len(lineage_indices)}. \"\n                    f\"This is most likely a bug. \"\n                    f\"Contact Roboflow team through github issues \"\n                    f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                    f\"the problem - including workflow definition you use.\",\n                    context=\"workflow_execution | step_input_assembling\",\n                )\n            batch_input = [\n                input_element if element_index in mask_for_dimension else None\n                for element_index, input_element in zip(lineage_indices, batch_input)\n            ]\n    else:\n        batch_input = execution_cache.get_batch_output(\n            selector=dynamic_parameter.selector,\n            batch_elements_indices=lineage_indices,\n            mask=mask_for_dimension,\n        )\n    if step_execution_dimensionality == parameter_dimensionality:\n        return Batch(batch_input, lineage_indices), lineage_indices, False\n    if step_execution_dimensionality > parameter_dimensionality:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter.parameter_specification.parameter_name}\"\n            f\"has a dimensionality {parameter_dimensionality} larger \"\n            f\"than step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if abs(parameter_dimensionality - step_execution_dimensionality) > 1:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter.parameter_specification.parameter_name}\"\n            f\"has a dimensionality {parameter_dimensionality} differing more than one level \"\n            f\"from step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    upper_level_indices = dynamic_batches_manager.get_indices_for_data_lineage(\n        lineage=dynamic_parameter.data_lineage[:-1],\n    )\n    result = reduce_batch_dimensionality(\n        indices=lineage_indices,\n        upper_level_index=upper_level_indices,\n        data=batch_input,\n        guard_of_indices_wrapping=guard_of_indices_wrapping,\n    )\n    return result, result.indices, False\n\n\ndef _flatten_batch_oriented_inputs(\n    inputs: list,\n    dimensionality: int,\n) -> List[Any]:\n    if dimensionality == 0 or not isinstance(inputs, list):\n        raise AssumptionError(\n            public_message=f\"Could not prepare batch-oriented input data. This is most likely the bug. Contact \"\n            f\"Roboflow team through github issues (https://github.com/roboflow/inference/issues) \"\n            f\"providing full context of the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if dimensionality == 1:\n        return inputs\n    result = []\n    for element in inputs:\n        result.extend(\n            _flatten_batch_oriented_inputs(\n                inputs=element, dimensionality=dimensionality - 1\n            )\n        )\n    return result\n\n\ndef reduce_batch_dimensionality(\n    indices: List[DynamicBatchIndex],\n    upper_level_index: List[DynamicBatchIndex],\n    data: List[T],\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n) -> Batch[Optional[Batch[T]]]:\n    guard_of_indices_wrapping.register_wrapping(indices_before_wrapping=indices)\n    already_spotted_downgraded_indices = set()\n    wrapped_batch_index, wrapped_batch_content = [], []\n    upper_level_indices_data = {index: None for index in upper_level_index}\n    for index, data in zip(indices, data):\n        downgraded_index = index[:-1]\n        if downgraded_index in already_spotted_downgraded_indices:\n            wrapped_batch_index.append(index)\n            wrapped_batch_content.append(data)\n        else:\n            if wrapped_batch_index:\n                upper_level_indices_data[wrapped_batch_index[-1][:-1]] = Batch(\n                    content=wrapped_batch_content, indices=wrapped_batch_index\n                )\n            already_spotted_downgraded_indices.add(downgraded_index)\n            wrapped_batch_index = [index]\n            wrapped_batch_content = [data]\n    if wrapped_batch_index:\n        upper_level_indices_data[wrapped_batch_index[-1][:-1]] = Batch(\n            content=wrapped_batch_content, indices=wrapped_batch_index\n        )\n    return Batch(\n        content=[upper_level_indices_data[index] for index in upper_level_index],\n        indices=upper_level_index,\n    )\n\n\ndef ensure_compound_input_indices_match(indices: List[List[DynamicBatchIndex]]) -> None:\n    if len(indices) < 2:\n        return None\n    reference_set = set(indices[0])\n    for index in indices[1:]:\n        other_set = set(index)\n        if reference_set != other_set:\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Detected a situation when step input parameters cannot be created \"\n                f\"due to missmatch in batch element indices. This is most likely a bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n\n\ndef get_empty_batch_elements_indices(value: Any) -> Set[DynamicBatchIndex]:\n    result = set()\n    if isinstance(value, dict):\n        for v in value.values():\n            value_result = get_empty_batch_elements_indices(v)\n            result = result.union(value_result)\n    if isinstance(value, list):\n        for v in value:\n            value_result = get_empty_batch_elements_indices(v)\n            result = result.union(value_result)\n    if isinstance(value, Batch):\n        for index, value_element in value.iter_with_indices():\n            if isinstance(value_element, Batch):\n                value_result = get_empty_batch_elements_indices(value=value_element)\n                result = result.union(value_result)\n            elif value_element is None:\n                result.add(index)\n    return result\n\n\ndef remove_indices(value: Any, indices: Set[DynamicBatchIndex]) -> Any:\n    if isinstance(value, dict):\n        return {k: remove_indices(value=v, indices=indices) for k, v in value.items()}\n    if isinstance(value, list):\n        return [remove_indices(value=v, indices=indices) for v in value]\n    if isinstance(value, Batch):\n        return value.remove_by_indices(indices_to_remove=indices)\n    return value\n\n\ndef unfold_parameters(\n    parameters: Dict[str, Any],\n) -> Generator[Dict[str, Any], None, None]:\n    batch_parameters = get_batch_parameters(parameters=parameters)\n    non_batch_parameters = {\n        k: v for k, v in parameters.items() if k not in batch_parameters\n    }\n    if not batch_parameters:\n        if not non_batch_parameters:\n            return None\n        yield non_batch_parameters\n        return None\n    for unfolded_batch_parameters in iterate_over_batches(\n        batch_parameters=batch_parameters\n    ):\n        yield {**unfolded_batch_parameters, **non_batch_parameters}\n\n\ndef get_batch_parameters(parameters: Dict[str, Any]) -> Dict[str, Any]:\n    result = {}\n    for name, value in parameters.items():\n        if isinstance(value, Batch):\n            result[name] = value\n        elif isinstance(value, list) and any(isinstance(v, Batch) for v in value):\n            result[name] = value\n        elif isinstance(value, dict) and any(\n            isinstance(v, Batch) for v in value.values()\n        ):\n            result[name] = value\n    return result\n\n\ndef iterate_over_batches(\n    batch_parameters: Dict[str, Any],\n) -> Generator[Dict[str, Any], None, None]:\n    index = 0\n    end = False\n    while not end:\n        result = {}\n        for name, value in batch_parameters.items():\n            if isinstance(value, Batch):\n                if len(value) <= index:\n                    end = True\n                    break\n                result[name] = value[index]\n            elif isinstance(value, list):\n                to_yield = []\n                for element in value:\n                    if isinstance(element, Batch):\n                        if len(element) <= index:\n                            end = True\n                            break\n                        to_yield.append(element[index])\n                    else:\n                        to_yield.append(element)\n                result[name] = to_yield\n            elif isinstance(value, dict):\n                to_yield = {}\n                for key, key_value in value.items():\n                    if not isinstance(key_value, Batch):\n                        to_yield[key] = key_value\n                    else:\n                        if len(key_value) <= index:\n                            end = True\n                            break\n                        else:\n                            to_yield[key] = key_value[index]\n                result[name] = to_yield\n        index += 1\n        if not end:\n            yield result\n",
    "optimized_raw_markdown": "",
    "optimized_function_only": "def get_masks_intersection_up_to_dimension(\n    batch_masks: List[Set[DynamicBatchIndex]],\n    dimension: int,\n) -> Optional[Set[DynamicBatchIndex]]:\n    if not batch_masks:\n        return None\n\n    # Initialize intersection with the first batch mask transformed up to the given dimension\n    intersection = {mask_element[:dimension] for mask_element in batch_masks[0]}\n\n    # Perform the intersection with the transformed sets of subsequent batch masks\n    for batch_mask in batch_masks[1:]:\n        intersection &= {mask_element[:dimension] for mask_element in batch_mask}\n\n        # Early exit if intersection becomes empty\n        if not intersection:\n            return set()\n\n    return intersection\n",
    "original_file_content": "from dataclasses import dataclass\nfrom typing import Any, Dict, Generator, List, Optional, Set, Tuple, TypeVar, Union\n\nfrom inference.core.workflows.errors import AssumptionError, ExecutionEngineRuntimeError\nfrom inference.core.workflows.execution_engine.entities.base import Batch\nfrom inference.core.workflows.execution_engine.v1.compiler.entities import (\n    CompoundStepInputDefinition,\n    DynamicStepInputDefinition,\n    StaticStepInputDefinition,\n    StepInputDefinition,\n    StepNode,\n)\nfrom inference.core.workflows.execution_engine.v1.compiler.utils import (\n    get_last_chunk_of_selector,\n)\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.branching_manager import (\n    BranchingManager,\n)\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.dynamic_batches_manager import (\n    DynamicBatchesManager,\n    DynamicBatchIndex,\n)\nfrom inference.core.workflows.execution_engine.v1.executor.execution_data_manager.execution_cache import (\n    ExecutionCache,\n)\n\nT = TypeVar(\"T\")\n\n\n@dataclass(frozen=True)\nclass BatchModeSIMDStepInput:\n    indices: List[DynamicBatchIndex]\n    parameters: Dict[str, Any]\n\n\n@dataclass(frozen=True)\nclass NonBatchModeSIMDStepInput:\n    index: DynamicBatchIndex\n    parameters: Dict[str, Any]\n\n\ndef construct_non_simd_step_input(\n    step_node: StepNode,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    branching_manager: BranchingManager,\n) -> Optional[Dict[str, Any]]:\n    if step_node.batch_oriented_parameters:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Attempted to get non-SIMD input for SIMD step: {step_node.name}.\"\n            f\"This is most likely a bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    masks = set()\n    for execution_branch in step_node.execution_branches_impacting_inputs:\n        if not branching_manager.is_execution_branch_registered(\n            execution_branch=execution_branch\n        ):\n            masks.add(False)\n            continue\n        if branching_manager.is_execution_branch_batch_oriented(\n            execution_branch=execution_branch\n        ):\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"For step: {step_node.name}, detected batch-oriented condition statements \"\n                f\"impacting non-SIMD step, which should be prevented by Workflows Compiler. \"\n                f\"This is most likely a bug. Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n        else:\n            mask = branching_manager.get_mask(execution_branch=execution_branch)\n            masks.add(mask)\n    if False in masks:\n        return None\n    result = {}\n    detected_empty_step_output_selector = False\n    for parameter_name, parameter_spec in step_node.input_data.items():\n        if parameter_spec.is_compound_input():\n            result[parameter_name], contains_empty_step_output_selector = (\n                construct_non_simd_step_compound_input(\n                    step_node=step_node,\n                    parameter_spec=parameter_spec,\n                    runtime_parameters=runtime_parameters,\n                    execution_cache=execution_cache,\n                )\n            )\n        else:\n            result[parameter_name], contains_empty_step_output_selector = (\n                construct_non_simd_step_non_compound_input(\n                    step_node=step_node,\n                    parameter_spec=parameter_spec,\n                    runtime_parameters=runtime_parameters,\n                    execution_cache=execution_cache,\n                )\n            )\n        detected_empty_step_output_selector = (\n            detected_empty_step_output_selector or contains_empty_step_output_selector\n        )\n    if (\n        detected_empty_step_output_selector\n        and not step_node.step_manifest.accepts_empty_values()\n    ):\n        return None\n    return result\n\n\ndef construct_non_simd_step_compound_input(\n    step_node: StepNode,\n    parameter_spec: CompoundStepInputDefinition,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> Tuple[Any, bool]:\n    if parameter_spec.represents_list_of_inputs():\n        return construct_non_simd_step_compound_list_input(\n            step_node=step_node,\n            parameter_spec=parameter_spec,\n            runtime_parameters=runtime_parameters,\n            execution_cache=execution_cache,\n        )\n    return construct_non_simd_step_compound_dict_input(\n        step_node=step_node,\n        parameter_spec=parameter_spec,\n        runtime_parameters=runtime_parameters,\n        execution_cache=execution_cache,\n    )\n\n\ndef construct_non_simd_step_compound_list_input(\n    step_node: StepNode,\n    parameter_spec: CompoundStepInputDefinition,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> Tuple[List[Any], bool]:\n    result = []\n    contains_empty_step_output_selector = False\n    for nested_definition in parameter_spec.iterate_through_definitions():\n        nested_value, value_contains_empty_selector = (\n            construct_non_simd_step_non_compound_input(\n                step_node=step_node,\n                parameter_spec=nested_definition,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n            )\n        )\n        result.append(nested_value)\n        contains_empty_step_output_selector = (\n            contains_empty_step_output_selector or value_contains_empty_selector\n        )\n    return result, contains_empty_step_output_selector\n\n\ndef construct_non_simd_step_compound_dict_input(\n    step_node: StepNode,\n    parameter_spec: CompoundStepInputDefinition,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> Tuple[Dict[str, Any], bool]:\n    result = {}\n    contains_empty_step_output_selector = False\n    for nested_definition in parameter_spec.iterate_through_definitions():\n        (\n            result[nested_definition.parameter_specification.nested_element_key],\n            value_contains_empty_selector,\n        ) = construct_non_simd_step_non_compound_input(\n            step_node=step_node,\n            parameter_spec=nested_definition,\n            runtime_parameters=runtime_parameters,\n            execution_cache=execution_cache,\n        )\n        contains_empty_step_output_selector = (\n            contains_empty_step_output_selector or value_contains_empty_selector\n        )\n    return result, contains_empty_step_output_selector\n\n\ndef construct_non_simd_step_non_compound_input(\n    step_node: StepNode,\n    parameter_spec: StepInputDefinition,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> Tuple[Any, bool]:\n    if parameter_spec.is_compound_input():\n        raise AssumptionError(\n            public_message=f\"Workflows Execution Error encountered unexpected state probably related to the fact \"\n            f\"that Workflows Compiler allowed for multi-level nesting of inputs selectors which \"\n            f\"is not supported. This is most likely the bug. Contact Roboflow team \"\n            f\"through github issues (https://github.com/roboflow/inference/issues) providing full \"\n            f\"context of the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if parameter_spec.is_batch_oriented():\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Encountered batch-oriented input for non-SIMD step: {step_node.name}.\"\n            f\"This is most likely a bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if parameter_spec.points_to_input():\n        parameter_spec: DynamicStepInputDefinition = parameter_spec  # type: ignore\n        input_name = get_last_chunk_of_selector(selector=parameter_spec.selector)\n        return runtime_parameters[input_name], False\n    if parameter_spec.points_to_step_output():\n        parameter_spec: DynamicStepInputDefinition = parameter_spec  # type: ignore\n        step_output = execution_cache.get_non_batch_output(\n            selector=parameter_spec.selector\n        )\n        return step_output, step_output is None\n    parameter_spec: StaticStepInputDefinition = parameter_spec  # type: ignore\n    return parameter_spec.value, False\n\n\ndef iterate_over_simd_step_input(\n    step_node: StepNode,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    dynamic_batches_manager: DynamicBatchesManager,\n    branching_manager: BranchingManager,\n) -> Generator[NonBatchModeSIMDStepInput, None, None]:\n    simd_step_input = construct_simd_step_input(\n        step_node=step_node,\n        runtime_parameters=runtime_parameters,\n        execution_cache=execution_cache,\n        dynamic_batches_manager=dynamic_batches_manager,\n        branching_manager=branching_manager,\n    )\n    parameters_generator = unfold_parameters(parameters=simd_step_input.parameters)\n    for index, single_parameters_set in zip(\n        simd_step_input.indices, parameters_generator\n    ):\n        yield NonBatchModeSIMDStepInput(\n            index=index,\n            parameters=single_parameters_set,\n        )\n\n\ndef construct_simd_step_input(\n    step_node: StepNode,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    dynamic_batches_manager: DynamicBatchesManager,\n    branching_manager: BranchingManager,\n) -> BatchModeSIMDStepInput:\n    masks = construct_mask_for_all_inputs_dimensionalities(\n        step_node=step_node,\n        branching_manager=branching_manager,\n    )\n    return prepare_parameters(\n        step_node=step_node,\n        dynamic_batches_manager=dynamic_batches_manager,\n        masks=masks,\n        runtime_parameters=runtime_parameters,\n        execution_cache=execution_cache,\n    )\n\n\ndef construct_mask_for_all_inputs_dimensionalities(\n    step_node: StepNode,\n    branching_manager: BranchingManager,\n) -> Any:\n    inputs_dimensionalities = collect_inputs_dimensionalities(step_node=step_node)\n    all_dimensionalities = {dim for dim in inputs_dimensionalities.values() if dim > 0}\n    batch_masks, non_batch_masks = [], set()\n    for execution_branch in step_node.execution_branches_impacting_inputs:\n        if not branching_manager.is_execution_branch_registered(\n            execution_branch=execution_branch\n        ):\n            non_batch_masks.add(False)\n            continue\n        if branching_manager.is_execution_branch_batch_oriented(\n            execution_branch=execution_branch\n        ):\n            mask = branching_manager.get_mask(execution_branch=execution_branch)\n            batch_masks.append(mask)\n        else:\n            mask = branching_manager.get_mask(execution_branch=execution_branch)\n            non_batch_masks.add(mask)\n    if False in non_batch_masks:\n        return {dimension: set() for dimension in all_dimensionalities}\n    return {\n        dimension: get_masks_intersection_up_to_dimension(\n            batch_masks=batch_masks,\n            dimension=dimension,\n        )\n        for dimension in all_dimensionalities\n    }\n\n\ndef collect_inputs_dimensionalities(\n    step_node: StepNode,\n) -> Dict[str, int]:\n    result = {}\n    for parameter_name, parameter_specs in step_node.input_data.items():\n        if parameter_specs.is_compound_input():\n            dimensionalities = [\n                nested_definition.get_dimensionality()\n                for nested_definition in parameter_specs.iterate_through_definitions()\n            ]\n            # to help for empty values\n            dimensionalities.append(0)\n            result[parameter_name] = max(dimensionalities)\n        else:\n            result[parameter_name] = parameter_specs.get_dimensionality()\n    return result\n\n\ndef get_masks_intersection_up_to_dimension(\n    batch_masks: List[Set[DynamicBatchIndex]],\n    dimension: int,\n) -> Optional[Set[DynamicBatchIndex]]:\n    batch_masks_in_dimension = [\n        {mask_element[:dimension] for mask_element in batch_mask}\n        for batch_mask in batch_masks\n    ]\n    if not batch_masks_in_dimension:\n        return None\n    return set.intersection(*batch_masks_in_dimension)\n\n\nclass GuardForIndicesWrapping:\n\n    def __init__(self):\n        self._registered_wrapping: Optional[List[DynamicBatchIndex]] = None\n\n    def register_wrapping(\n        self, indices_before_wrapping: List[DynamicBatchIndex]\n    ) -> None:\n        if self._registered_wrapping is None:\n            self._registered_wrapping = indices_before_wrapping\n        elif self._registered_wrapping != indices_before_wrapping:\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Detected a situation when step requires dimensionality wrapping, but\"\n                f\"different inputs register different elements indices to wrap which is illegal \"\n                f\"and should be detected earlier by Workflows compiler. This is most likely a bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n\n\ndef prepare_parameters(\n    step_node: StepNode,\n    dynamic_batches_manager: DynamicBatchesManager,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n) -> BatchModeSIMDStepInput:\n    result = {}\n    indices_for_parameter = {}\n    guard_of_indices_wrapping = GuardForIndicesWrapping()\n    compound_inputs = set()\n    contains_empty_scalar_step_output_selector = False\n    for parameter_name, parameter_specs in step_node.input_data.items():\n        if parameter_specs.is_compound_input():\n            (\n                result[parameter_name],\n                indices_for_parameter[parameter_name],\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_compound_parameter_value(\n                parameter=parameter_specs,\n                step_execution_dimensionality=step_node.step_execution_dimensionality,\n                masks=masks,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n            )\n            compound_inputs.add(parameter_name)\n        else:\n            (\n                result[parameter_name],\n                indices_for_parameter[parameter_name],\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=parameter_specs,\n                step_execution_dimensionality=step_node.step_execution_dimensionality,\n                masks=masks,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n            )\n        contains_empty_scalar_step_output_selector = (\n            contains_empty_scalar_step_output_selector\n            or value_contains_empty_scalar_step_output_selector\n        )\n    batch_parameters_indices = [\n        i for i in indices_for_parameter.values() if i is not None\n    ]\n    ensure_compound_input_indices_match(indices=batch_parameters_indices)\n    if not batch_parameters_indices:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"For step: {step_node.name} which is assessed by Workflows Compiler as \"\n            f\"SIMD step Execution Engine cannot detect batch inputs. \"\n            f\"This is most likely a bug. Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    indices = batch_parameters_indices[0]\n    if not step_node.step_manifest.accepts_empty_values():\n        if contains_empty_scalar_step_output_selector:\n            return BatchModeSIMDStepInput(\n                indices=[],\n                parameters={},\n            )\n        empty_indices = get_empty_batch_elements_indices(value=result)\n        indices = [e for e in indices if e not in empty_indices]\n        result = remove_indices(value=result, indices=empty_indices)\n    return BatchModeSIMDStepInput(\n        indices=indices,\n        parameters=result,\n    )\n\n\ndef get_compound_parameter_value(\n    parameter: CompoundStepInputDefinition,\n    step_execution_dimensionality: int,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    dynamic_batches_manager: DynamicBatchesManager,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n) -> Tuple[Union[list, Dict[str, Any]], Optional[List[DynamicBatchIndex]], bool]:\n    contains_empty_scalar_step_output_selector = False\n    batch_indices = []\n    if parameter.represents_list_of_inputs():\n        result = []\n        for nested_element in parameter.iterate_through_definitions():\n            (\n                non_compound_parameter_value,\n                non_compound_indices,\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=nested_element,\n                step_execution_dimensionality=step_execution_dimensionality,\n                masks=masks,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n            )\n            result.append(non_compound_parameter_value)\n            contains_empty_scalar_step_output_selector = (\n                contains_empty_scalar_step_output_selector\n                or value_contains_empty_scalar_step_output_selector\n            )\n            if non_compound_indices is not None:\n                batch_indices.append(non_compound_indices)\n    else:\n        result = {}\n        for nested_element in parameter.iterate_through_definitions():\n            (\n                non_compound_parameter_value,\n                non_compound_indices,\n                value_contains_empty_scalar_step_output_selector,\n            ) = get_non_compound_parameter_value(\n                parameter=nested_element,\n                step_execution_dimensionality=step_execution_dimensionality,\n                masks=masks,\n                dynamic_batches_manager=dynamic_batches_manager,\n                runtime_parameters=runtime_parameters,\n                execution_cache=execution_cache,\n                guard_of_indices_wrapping=guard_of_indices_wrapping,\n            )\n            result[nested_element.parameter_specification.nested_element_key] = (\n                non_compound_parameter_value\n            )\n            contains_empty_scalar_step_output_selector = (\n                contains_empty_scalar_step_output_selector\n                or value_contains_empty_scalar_step_output_selector\n            )\n            if non_compound_indices is not None:\n                batch_indices.append(non_compound_indices)\n    ensure_compound_input_indices_match(indices=batch_indices)\n    result_indices = None\n    if len(batch_indices) > 0:\n        result_indices = batch_indices[0]\n    return result, result_indices, contains_empty_scalar_step_output_selector\n\n\ndef get_non_compound_parameter_value(\n    parameter: StepInputDefinition,\n    step_execution_dimensionality: int,\n    masks: Dict[int, Optional[Set[DynamicBatchIndex]]],\n    dynamic_batches_manager: DynamicBatchesManager,\n    runtime_parameters: Dict[str, Any],\n    execution_cache: ExecutionCache,\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n) -> Union[Any, Optional[List[DynamicBatchIndex]], bool]:\n    if not parameter.is_batch_oriented():\n        if parameter.points_to_input():\n            input_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n            parameter_name = get_last_chunk_of_selector(\n                selector=input_parameter.selector\n            )\n            return runtime_parameters[parameter_name], None, False\n        elif parameter.points_to_step_output():\n            input_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n            value = execution_cache.get_non_batch_output(\n                selector=input_parameter.selector\n            )\n            return value, None, value is None\n        else:\n            static_input: StaticStepInputDefinition = parameter  # type: ignore\n            return static_input.value, None, False\n    dynamic_parameter: DynamicStepInputDefinition = parameter  # type: ignore\n    parameter_dimensionality = dynamic_parameter.get_dimensionality()\n    lineage_indices = dynamic_batches_manager.get_indices_for_data_lineage(\n        lineage=dynamic_parameter.data_lineage,\n    )\n    mask_for_dimension = masks[parameter_dimensionality]\n    if dynamic_parameter.points_to_input():\n        input_name = get_last_chunk_of_selector(selector=dynamic_parameter.selector)\n        batch_input = _flatten_batch_oriented_inputs(\n            runtime_parameters[input_name],\n            dimensionality=parameter_dimensionality,\n        )\n        if mask_for_dimension is not None:\n            if len(lineage_indices) != len(batch_input):\n                raise ExecutionEngineRuntimeError(\n                    public_message=f\"Detected a situation when input parameter: \"\n                    f\"{input_name}\"\n                    f\"size is mismatched compared to mask requested for that input. \"\n                    f\"Input length: {len(batch_input)}, mask size: {len(lineage_indices)}. \"\n                    f\"This is most likely a bug. \"\n                    f\"Contact Roboflow team through github issues \"\n                    f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                    f\"the problem - including workflow definition you use.\",\n                    context=\"workflow_execution | step_input_assembling\",\n                )\n            batch_input = [\n                input_element if element_index in mask_for_dimension else None\n                for element_index, input_element in zip(lineage_indices, batch_input)\n            ]\n    else:\n        batch_input = execution_cache.get_batch_output(\n            selector=dynamic_parameter.selector,\n            batch_elements_indices=lineage_indices,\n            mask=mask_for_dimension,\n        )\n    if step_execution_dimensionality == parameter_dimensionality:\n        return Batch(batch_input, lineage_indices), lineage_indices, False\n    if step_execution_dimensionality > parameter_dimensionality:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter.parameter_specification.parameter_name}\"\n            f\"has a dimensionality {parameter_dimensionality} larger \"\n            f\"than step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if abs(parameter_dimensionality - step_execution_dimensionality) > 1:\n        raise ExecutionEngineRuntimeError(\n            public_message=f\"Detected a situation when parameter: \"\n            f\"{parameter.parameter_specification.parameter_name}\"\n            f\"has a dimensionality {parameter_dimensionality} differing more than one level \"\n            f\"from step execution dimensionality: {step_execution_dimensionality}. \"\n            f\"This is most likely a bug. \"\n            f\"Contact Roboflow team through github issues \"\n            f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n            f\"the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    upper_level_indices = dynamic_batches_manager.get_indices_for_data_lineage(\n        lineage=dynamic_parameter.data_lineage[:-1],\n    )\n    result = reduce_batch_dimensionality(\n        indices=lineage_indices,\n        upper_level_index=upper_level_indices,\n        data=batch_input,\n        guard_of_indices_wrapping=guard_of_indices_wrapping,\n    )\n    return result, result.indices, False\n\n\ndef _flatten_batch_oriented_inputs(\n    inputs: list,\n    dimensionality: int,\n) -> List[Any]:\n    if dimensionality == 0 or not isinstance(inputs, list):\n        raise AssumptionError(\n            public_message=f\"Could not prepare batch-oriented input data. This is most likely the bug. Contact \"\n            f\"Roboflow team through github issues (https://github.com/roboflow/inference/issues) \"\n            f\"providing full context of the problem - including workflow definition you use.\",\n            context=\"workflow_execution | step_input_assembling\",\n        )\n    if dimensionality == 1:\n        return inputs\n    result = []\n    for element in inputs:\n        result.extend(\n            _flatten_batch_oriented_inputs(\n                inputs=element, dimensionality=dimensionality - 1\n            )\n        )\n    return result\n\n\ndef reduce_batch_dimensionality(\n    indices: List[DynamicBatchIndex],\n    upper_level_index: List[DynamicBatchIndex],\n    data: List[T],\n    guard_of_indices_wrapping: GuardForIndicesWrapping,\n) -> Batch[Optional[Batch[T]]]:\n    guard_of_indices_wrapping.register_wrapping(indices_before_wrapping=indices)\n    already_spotted_downgraded_indices = set()\n    wrapped_batch_index, wrapped_batch_content = [], []\n    upper_level_indices_data = {index: None for index in upper_level_index}\n    for index, data in zip(indices, data):\n        downgraded_index = index[:-1]\n        if downgraded_index in already_spotted_downgraded_indices:\n            wrapped_batch_index.append(index)\n            wrapped_batch_content.append(data)\n        else:\n            if wrapped_batch_index:\n                upper_level_indices_data[wrapped_batch_index[-1][:-1]] = Batch(\n                    content=wrapped_batch_content, indices=wrapped_batch_index\n                )\n            already_spotted_downgraded_indices.add(downgraded_index)\n            wrapped_batch_index = [index]\n            wrapped_batch_content = [data]\n    if wrapped_batch_index:\n        upper_level_indices_data[wrapped_batch_index[-1][:-1]] = Batch(\n            content=wrapped_batch_content, indices=wrapped_batch_index\n        )\n    return Batch(\n        content=[upper_level_indices_data[index] for index in upper_level_index],\n        indices=upper_level_index,\n    )\n\n\ndef ensure_compound_input_indices_match(indices: List[List[DynamicBatchIndex]]) -> None:\n    if len(indices) < 2:\n        return None\n    reference_set = set(indices[0])\n    for index in indices[1:]:\n        other_set = set(index)\n        if reference_set != other_set:\n            raise ExecutionEngineRuntimeError(\n                public_message=f\"Detected a situation when step input parameters cannot be created \"\n                f\"due to missmatch in batch element indices. This is most likely a bug. \"\n                f\"Contact Roboflow team through github issues \"\n                f\"(https://github.com/roboflow/inference/issues) providing full context of\"\n                f\"the problem - including workflow definition you use.\",\n                context=\"workflow_execution | step_input_assembling\",\n            )\n\n\ndef get_empty_batch_elements_indices(value: Any) -> Set[DynamicBatchIndex]:\n    result = set()\n    if isinstance(value, dict):\n        for v in value.values():\n            value_result = get_empty_batch_elements_indices(v)\n            result = result.union(value_result)\n    if isinstance(value, list):\n        for v in value:\n            value_result = get_empty_batch_elements_indices(v)\n            result = result.union(value_result)\n    if isinstance(value, Batch):\n        for index, value_element in value.iter_with_indices():\n            if isinstance(value_element, Batch):\n                value_result = get_empty_batch_elements_indices(value=value_element)\n                result = result.union(value_result)\n            elif value_element is None:\n                result.add(index)\n    return result\n\n\ndef remove_indices(value: Any, indices: Set[DynamicBatchIndex]) -> Any:\n    if isinstance(value, dict):\n        return {k: remove_indices(value=v, indices=indices) for k, v in value.items()}\n    if isinstance(value, list):\n        return [remove_indices(value=v, indices=indices) for v in value]\n    if isinstance(value, Batch):\n        return value.remove_by_indices(indices_to_remove=indices)\n    return value\n\n\ndef unfold_parameters(\n    parameters: Dict[str, Any],\n) -> Generator[Dict[str, Any], None, None]:\n    batch_parameters = get_batch_parameters(parameters=parameters)\n    non_batch_parameters = {\n        k: v for k, v in parameters.items() if k not in batch_parameters\n    }\n    if not batch_parameters:\n        if not non_batch_parameters:\n            return None\n        yield non_batch_parameters\n        return None\n    for unfolded_batch_parameters in iterate_over_batches(\n        batch_parameters=batch_parameters\n    ):\n        yield {**unfolded_batch_parameters, **non_batch_parameters}\n\n\ndef get_batch_parameters(parameters: Dict[str, Any]) -> Dict[str, Any]:\n    result = {}\n    for name, value in parameters.items():\n        if isinstance(value, Batch):\n            result[name] = value\n        elif isinstance(value, list) and any(isinstance(v, Batch) for v in value):\n            result[name] = value\n        elif isinstance(value, dict) and any(\n            isinstance(v, Batch) for v in value.values()\n        ):\n            result[name] = value\n    return result\n\n\ndef iterate_over_batches(\n    batch_parameters: Dict[str, Any],\n) -> Generator[Dict[str, Any], None, None]:\n    index = 0\n    end = False\n    while not end:\n        result = {}\n        for name, value in batch_parameters.items():\n            if isinstance(value, Batch):\n                if len(value) <= index:\n                    end = True\n                    break\n                result[name] = value[index]\n            elif isinstance(value, list):\n                to_yield = []\n                for element in value:\n                    if isinstance(element, Batch):\n                        if len(element) <= index:\n                            end = True\n                            break\n                        to_yield.append(element[index])\n                    else:\n                        to_yield.append(element)\n                result[name] = to_yield\n            elif isinstance(value, dict):\n                to_yield = {}\n                for key, key_value in value.items():\n                    if not isinstance(key_value, Batch):\n                        to_yield[key] = key_value\n                    else:\n                        if len(key_value) <= index:\n                            end = True\n                            break\n                        else:\n                            to_yield[key] = key_value[index]\n                result[name] = to_yield\n        index += 1\n        if not end:\n            yield result\n",
    "patch": "diff --git a/inference/core/workflows/execution_engine/v1/executor/execution_data_manager/step_input_assembler.py b/inference/core/workflows/execution_engine/v1/executor/execution_data_manager/step_input_assembler.py\nindex 6bc21c85f..b1b4f0082 100644\n--- a/inference/core/workflows/execution_engine/v1/executor/execution_data_manager/step_input_assembler.py\n+++ b/inference/core/workflows/execution_engine/v1/executor/execution_data_manager/step_input_assembler.py\n@@ -312,13 +312,21 @@ def get_masks_intersection_up_to_dimension(\n     batch_masks: List[Set[DynamicBatchIndex]],\n     dimension: int,\n ) -> Optional[Set[DynamicBatchIndex]]:\n-    batch_masks_in_dimension = [\n-        {mask_element[:dimension] for mask_element in batch_mask}\n-        for batch_mask in batch_masks\n-    ]\n-    if not batch_masks_in_dimension:\n+    if not batch_masks:\n         return None\n-    return set.intersection(*batch_masks_in_dimension)\n+\n+    # Initialize intersection with the first batch mask transformed up to the given dimension\n+    intersection = {mask_element[:dimension] for mask_element in batch_masks[0]}\n+\n+    # Perform the intersection with the transformed sets of subsequent batch masks\n+    for batch_mask in batch_masks[1:]:\n+        intersection &= {mask_element[:dimension] for mask_element in batch_mask}\n+\n+        # Early exit if intersection becomes empty\n+        if not intersection:\n+            return set()\n+\n+    return intersection\n \n \n class GuardForIndicesWrapping:\n"
  },
  {
    "trace_id": "git_818d2e78e36a",
    "function_name": "build_simple_operation",
    "file_path": "inference/core/workflows/core_steps/common/query_language/operations/core.py",
    "speedup_x": 0.68,
    "review_quality": null,
    "pre_optimization_commit": "f6289ddfeda5115df3edd38dec2ff6885098a6d8",
    "resolution_method": "git_parent",
    "source": "git",
    "original_function_code": "def build_simple_operation(\n    operation_definition: OperationDefinition,\n    operation_function: Callable[[T], V],\n    execution_context: str,\n) -> Callable[[T], V]:\n    predefined_arguments_names = [\n        t for t in type(operation_definition).model_fields if t != TYPE_PARAMETER_NAME\n    ]\n    kwargs = {a: getattr(operation_definition, a) for a in predefined_arguments_names}\n    kwargs[\"execution_context\"] = execution_context\n    return partial(operation_function, **kwargs)\n",
    "optimized_function_code": "from functools import partial\nfrom typing import Any, Callable, Dict, List, Optional\n\nfrom inference.core.workflows.core_steps.common.query_language.entities.operations import (\n    TYPE_PARAMETER_NAME,\n    DetectionsFilter,\n    OperationDefinition,\n    OperationsChain,\n    SequenceApply,\n)\nfrom inference.core.workflows.core_steps.common.query_language.entities.types import (\n    T,\n    V,\n)\nfrom inference.core.workflows.core_steps.common.query_language.errors import (\n    OperationTypeNotRecognisedError,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.booleans.base import (\n    to_bool,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.classification_results.base import (\n    extract_classification_property,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.detection.base import (\n    extract_detection_property,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.detections.base import (\n    detections_to_dictionary,\n    extract_detections_property,\n    filter_detections,\n    offset_detections,\n    pick_detections_by_parent_class,\n    rename_detections,\n    select_detections,\n    shift_detections,\n    sort_detections,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.dictionaries.base import (\n    dictionary_to_json,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.generic.base import (\n    apply_lookup,\n    generate_random_number,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.images.base import (\n    encode_image_to_base64,\n    encode_image_to_jpeg,\n    extract_image_property,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.numbers.base import (\n    divide,\n    multiply,\n    number_round,\n    to_number,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.sequences.base import (\n    aggregate_numeric_sequence,\n    aggregate_sequence,\n    get_sequence_elements_count,\n    get_sequence_length,\n    sequence_apply,\n    sequence_map,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.strings.base import (\n    string_matches,\n    string_sub_sequence,\n    string_to_lower,\n    string_to_upper,\n    to_string,\n)\n\n\ndef execute_operations(\n    value: T, operations: List[dict], global_parameters: Optional[Dict[str, Any]] = None\n) -> V:\n    operations_parsed = OperationsChain.model_validate({\"operations\": operations})\n    ops_chain = build_operations_chain(operations_parsed.operations)\n    if global_parameters is None:\n        global_parameters = {}\n    return ops_chain(value, global_parameters=global_parameters)\n\n\ndef identity(value: Any, **kwargs) -> Any:\n    return value\n\n\ndef build_operations_chain(\n    operations: List[OperationDefinition], execution_context: str = \"<root>\"\n) -> Callable[[T, Dict[str, Any]], V]:\n    if not len(operations):\n        return identity  # return identity function\n    operations_functions = []\n    for operation_id, operation_definition in enumerate(operations):\n        operation_context = f\"{execution_context}[{operation_id}]\"\n        operation_function = build_operation(\n            operation_definition=operation_definition,\n            execution_context=operation_context,\n        )\n        operations_functions.append(operation_function)\n    return partial(chain, functions=operations_functions)\n\n\ndef build_operation(\n    operation_definition: OperationDefinition,\n    execution_context: str,\n) -> Callable[[T], V]:\n    if operation_definition.type in REGISTERED_SIMPLE_OPERATIONS:\n        return build_simple_operation(\n            operation_definition=operation_definition,\n            operation_function=REGISTERED_SIMPLE_OPERATIONS[operation_definition.type],\n            execution_context=execution_context,\n        )\n    if operation_definition.type in REGISTERED_COMPOUND_OPERATIONS_BUILDERS:\n        return REGISTERED_COMPOUND_OPERATIONS_BUILDERS[operation_definition.type](\n            operation_definition, execution_context\n        )\n    raise OperationTypeNotRecognisedError(\n        public_message=f\"Attempted to build operation with declared type: {operation_definition.type} \"\n        f\"which was not registered in Roboflow Query Language.\",\n        context=\"step_execution | roboflow_query_language_compilation\",\n    )\n\n\ndef build_simple_operation(\n    operation_definition: OperationDefinition,\n    operation_function: Callable[[T], V],\n    execution_context: str,\n) -> Callable[[T], V]:\n    kwargs = {\n        a: v for a, v in vars(operation_definition).items() if a != TYPE_PARAMETER_NAME\n    }\n    kwargs[\"execution_context\"] = execution_context\n    return partial(operation_function, **kwargs)\n\n\ndef build_sequence_apply_operation(\n    definition: SequenceApply, execution_context: str\n) -> Callable[[T], V]:\n    operations_functions = []\n    for operation in definition.operations:\n        operation_function = build_operation(\n            operation_definition=operation, execution_context=execution_context\n        )\n        operations_functions.append(operation_function)\n    chained_function = partial(chain, functions=operations_functions)\n    return partial(sequence_apply, fun=chained_function)\n\n\ndef chain(\n    value: T, global_parameters: Dict[str, Any], functions: List[Callable[[T], V]]\n) -> Callable[[T, Dict[str, Any]], V]:\n    for function in functions:\n        value = function(value, global_parameters=global_parameters)\n    return value\n\n\ndef build_detections_filter_operation(\n    definition: DetectionsFilter,\n    execution_context: str,\n) -> Callable[[T], V]:\n    # local import to avoid circular dependency of modules with operations and evaluation\n    from inference.core.workflows.core_steps.common.query_language.evaluation_engine.core import (\n        build_eval_function,\n    )\n\n    filtering_fun = build_eval_function(\n        definition=definition.filter_operation,\n        execution_context=execution_context,\n    )\n    return partial(filter_detections, filtering_fun=filtering_fun)\n\n\nREGISTERED_SIMPLE_OPERATIONS = {\n    \"StringToLowerCase\": string_to_lower,\n    \"StringToUpperCase\": string_to_upper,\n    \"LookupTable\": apply_lookup,\n    \"ToNumber\": to_number,\n    \"NumberRound\": number_round,\n    \"SequenceMap\": sequence_map,\n    \"NumericSequenceAggregate\": aggregate_numeric_sequence,\n    \"ToString\": to_string,\n    \"ToBoolean\": to_bool,\n    \"StringSubSequence\": string_sub_sequence,\n    \"DetectionsPropertyExtract\": extract_detections_property,\n    \"SequenceAggregate\": aggregate_sequence,\n    \"ExtractDetectionProperty\": extract_detection_property,\n    \"DetectionsOffset\": offset_detections,\n    \"DetectionsShift\": shift_detections,\n    \"RandomNumber\": generate_random_number,\n    \"StringMatches\": string_matches,\n    \"SequenceLength\": get_sequence_length,\n    \"SequenceElementsCount\": get_sequence_elements_count,\n    \"ExtractImageProperty\": extract_image_property,\n    \"Multiply\": multiply,\n    \"Divide\": divide,\n    \"DetectionsSelection\": select_detections,\n    \"SortDetections\": sort_detections,\n    \"ClassificationPropertyExtract\": extract_classification_property,\n    \"DetectionsRename\": rename_detections,\n    \"ConvertImageToJPEG\": encode_image_to_jpeg,\n    \"ConvertImageToBase64\": encode_image_to_base64,\n    \"DetectionsToDictionary\": detections_to_dictionary,\n    \"ConvertDictionaryToJSON\": dictionary_to_json,\n    \"PickDetectionsByParentClass\": pick_detections_by_parent_class,\n}\n\nREGISTERED_COMPOUND_OPERATIONS_BUILDERS = {\n    \"SequenceApply\": build_sequence_apply_operation,\n    \"DetectionsFilter\": build_detections_filter_operation,\n}\n",
    "optimized_raw_markdown": "",
    "optimized_function_only": "def build_simple_operation(\n    operation_definition: OperationDefinition,\n    operation_function: Callable[[T], V],\n    execution_context: str,\n) -> Callable[[T], V]:\n    kwargs = {\n        a: v for a, v in vars(operation_definition).items() if a != TYPE_PARAMETER_NAME\n    }\n    kwargs[\"execution_context\"] = execution_context\n    return partial(operation_function, **kwargs)\n",
    "original_file_content": "from functools import partial\nfrom typing import Any, Callable, Dict, List, Optional\n\nfrom inference.core.workflows.core_steps.common.query_language.entities.operations import (\n    TYPE_PARAMETER_NAME,\n    DetectionsFilter,\n    OperationDefinition,\n    OperationsChain,\n    SequenceApply,\n)\nfrom inference.core.workflows.core_steps.common.query_language.entities.types import (\n    T,\n    V,\n)\nfrom inference.core.workflows.core_steps.common.query_language.errors import (\n    OperationTypeNotRecognisedError,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.booleans.base import (\n    to_bool,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.classification_results.base import (\n    extract_classification_property,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.detection.base import (\n    extract_detection_property,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.detections.base import (\n    detections_to_dictionary,\n    extract_detections_property,\n    filter_detections,\n    offset_detections,\n    pick_detections_by_parent_class,\n    rename_detections,\n    select_detections,\n    shift_detections,\n    sort_detections,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.dictionaries.base import (\n    dictionary_to_json,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.generic.base import (\n    apply_lookup,\n    generate_random_number,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.images.base import (\n    encode_image_to_base64,\n    encode_image_to_jpeg,\n    extract_image_property,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.numbers.base import (\n    divide,\n    multiply,\n    number_round,\n    to_number,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.sequences.base import (\n    aggregate_numeric_sequence,\n    aggregate_sequence,\n    get_sequence_elements_count,\n    get_sequence_length,\n    sequence_apply,\n    sequence_map,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.strings.base import (\n    string_matches,\n    string_sub_sequence,\n    string_to_lower,\n    string_to_upper,\n    to_string,\n)\n\n\ndef execute_operations(\n    value: T, operations: List[dict], global_parameters: Optional[Dict[str, Any]] = None\n) -> V:\n    operations_parsed = OperationsChain.model_validate({\"operations\": operations})\n    ops_chain = build_operations_chain(operations_parsed.operations)\n    if global_parameters is None:\n        global_parameters = {}\n    return ops_chain(value, global_parameters=global_parameters)\n\n\ndef identity(value: Any, **kwargs) -> Any:\n    return value\n\n\ndef build_operations_chain(\n    operations: List[OperationDefinition], execution_context: str = \"<root>\"\n) -> Callable[[T, Dict[str, Any]], V]:\n    if not len(operations):\n        return identity  # return identity function\n    operations_functions = []\n    for operation_id, operation_definition in enumerate(operations):\n        operation_context = f\"{execution_context}[{operation_id}]\"\n        operation_function = build_operation(\n            operation_definition=operation_definition,\n            execution_context=operation_context,\n        )\n        operations_functions.append(operation_function)\n    return partial(chain, functions=operations_functions)\n\n\ndef build_operation(\n    operation_definition: OperationDefinition,\n    execution_context: str,\n) -> Callable[[T], V]:\n    if operation_definition.type in REGISTERED_SIMPLE_OPERATIONS:\n        return build_simple_operation(\n            operation_definition=operation_definition,\n            operation_function=REGISTERED_SIMPLE_OPERATIONS[operation_definition.type],\n            execution_context=execution_context,\n        )\n    if operation_definition.type in REGISTERED_COMPOUND_OPERATIONS_BUILDERS:\n        return REGISTERED_COMPOUND_OPERATIONS_BUILDERS[operation_definition.type](\n            operation_definition, execution_context\n        )\n    raise OperationTypeNotRecognisedError(\n        public_message=f\"Attempted to build operation with declared type: {operation_definition.type} \"\n        f\"which was not registered in Roboflow Query Language.\",\n        context=\"step_execution | roboflow_query_language_compilation\",\n    )\n\n\ndef build_simple_operation(\n    operation_definition: OperationDefinition,\n    operation_function: Callable[[T], V],\n    execution_context: str,\n) -> Callable[[T], V]:\n    predefined_arguments_names = [\n        t for t in type(operation_definition).model_fields if t != TYPE_PARAMETER_NAME\n    ]\n    kwargs = {a: getattr(operation_definition, a) for a in predefined_arguments_names}\n    kwargs[\"execution_context\"] = execution_context\n    return partial(operation_function, **kwargs)\n\n\ndef build_sequence_apply_operation(\n    definition: SequenceApply, execution_context: str\n) -> Callable[[T], V]:\n    operations_functions = []\n    for operation in definition.operations:\n        operation_function = build_operation(\n            operation_definition=operation, execution_context=execution_context\n        )\n        operations_functions.append(operation_function)\n    chained_function = partial(chain, functions=operations_functions)\n    return partial(sequence_apply, fun=chained_function)\n\n\ndef chain(\n    value: T, global_parameters: Dict[str, Any], functions: List[Callable[[T], V]]\n) -> Callable[[T, Dict[str, Any]], V]:\n    for function in functions:\n        value = function(value, global_parameters=global_parameters)\n    return value\n\n\ndef build_detections_filter_operation(\n    definition: DetectionsFilter,\n    execution_context: str,\n) -> Callable[[T], V]:\n    # local import to avoid circular dependency of modules with operations and evaluation\n    from inference.core.workflows.core_steps.common.query_language.evaluation_engine.core import (\n        build_eval_function,\n    )\n\n    filtering_fun = build_eval_function(\n        definition=definition.filter_operation,\n        execution_context=execution_context,\n    )\n    return partial(filter_detections, filtering_fun=filtering_fun)\n\n\nREGISTERED_SIMPLE_OPERATIONS = {\n    \"StringToLowerCase\": string_to_lower,\n    \"StringToUpperCase\": string_to_upper,\n    \"LookupTable\": apply_lookup,\n    \"ToNumber\": to_number,\n    \"NumberRound\": number_round,\n    \"SequenceMap\": sequence_map,\n    \"NumericSequenceAggregate\": aggregate_numeric_sequence,\n    \"ToString\": to_string,\n    \"ToBoolean\": to_bool,\n    \"StringSubSequence\": string_sub_sequence,\n    \"DetectionsPropertyExtract\": extract_detections_property,\n    \"SequenceAggregate\": aggregate_sequence,\n    \"ExtractDetectionProperty\": extract_detection_property,\n    \"DetectionsOffset\": offset_detections,\n    \"DetectionsShift\": shift_detections,\n    \"RandomNumber\": generate_random_number,\n    \"StringMatches\": string_matches,\n    \"SequenceLength\": get_sequence_length,\n    \"SequenceElementsCount\": get_sequence_elements_count,\n    \"ExtractImageProperty\": extract_image_property,\n    \"Multiply\": multiply,\n    \"Divide\": divide,\n    \"DetectionsSelection\": select_detections,\n    \"SortDetections\": sort_detections,\n    \"ClassificationPropertyExtract\": extract_classification_property,\n    \"DetectionsRename\": rename_detections,\n    \"ConvertImageToJPEG\": encode_image_to_jpeg,\n    \"ConvertImageToBase64\": encode_image_to_base64,\n    \"DetectionsToDictionary\": detections_to_dictionary,\n    \"ConvertDictionaryToJSON\": dictionary_to_json,\n    \"PickDetectionsByParentClass\": pick_detections_by_parent_class,\n}\n\nREGISTERED_COMPOUND_OPERATIONS_BUILDERS = {\n    \"SequenceApply\": build_sequence_apply_operation,\n    \"DetectionsFilter\": build_detections_filter_operation,\n}\n",
    "patch": "diff --git a/inference/core/workflows/core_steps/common/query_language/operations/core.py b/inference/core/workflows/core_steps/common/query_language/operations/core.py\nindex a451be280..06dee039b 100644\n--- a/inference/core/workflows/core_steps/common/query_language/operations/core.py\n+++ b/inference/core/workflows/core_steps/common/query_language/operations/core.py\n@@ -126,10 +126,9 @@ def build_simple_operation(\n     operation_function: Callable[[T], V],\n     execution_context: str,\n ) -> Callable[[T], V]:\n-    predefined_arguments_names = [\n-        t for t in type(operation_definition).model_fields if t != TYPE_PARAMETER_NAME\n-    ]\n-    kwargs = {a: getattr(operation_definition, a) for a in predefined_arguments_names}\n+    kwargs = {\n+        a: v for a, v in vars(operation_definition).items() if a != TYPE_PARAMETER_NAME\n+    }\n     kwargs[\"execution_context\"] = execution_context\n     return partial(operation_function, **kwargs)\n \n"
  },
  {
    "trace_id": "git_009c3a92d058",
    "function_name": "from_keypoints_detection_response",
    "file_path": "inference/core/cache/serializers.py",
    "speedup_x": 0.07,
    "review_quality": null,
    "pre_optimization_commit": "f6289ddfeda5115df3edd38dec2ff6885098a6d8",
    "resolution_method": "git_parent",
    "source": "git",
    "original_function_code": "def from_keypoints_detection_response(response: KeypointsDetectionInferenceResponse):\n    predictions = []\n    for pred in response.predictions:\n        for keypoint in pred.keypoints:\n            predictions.append(\n                {\"class\": keypoint.class_name, \"confidence\": keypoint.confidence}\n            )\n    return predictions\n",
    "optimized_function_code": "from typing import List, Union\n\nfrom fastapi.encoders import jsonable_encoder\n\nfrom inference.core.devices.utils import GLOBAL_INFERENCE_SERVER_ID\nfrom inference.core.entities.requests.inference import InferenceRequest\nfrom inference.core.entities.responses.inference import (\n    ClassificationInferenceResponse,\n    InferenceResponse,\n    InstanceSegmentationInferenceResponse,\n    KeypointsDetectionInferenceResponse,\n    MultiLabelClassificationInferenceResponse,\n    ObjectDetectionInferenceResponse,\n)\nfrom inference.core.env import TINY_CACHE\nfrom inference.core.logger import logger\nfrom inference.core.version import __version__\n\n\ndef to_cachable_inference_item(\n    infer_request: InferenceRequest,\n    infer_response: Union[InferenceResponse, List[InferenceResponse]],\n) -> dict:\n    if not TINY_CACHE:\n        return {\n            \"inference_id\": infer_request.id,\n            \"inference_server_version\": __version__,\n            \"inference_server_id\": GLOBAL_INFERENCE_SERVER_ID,\n            \"request\": jsonable_encoder(infer_request),\n            \"response\": jsonable_encoder(infer_response),\n        }\n\n    included_request_fields = {\n        \"api_key\",\n        \"confidence\",\n        \"model_id\",\n        \"model_type\",\n        \"source\",\n        \"source_info\",\n    }\n    request = infer_request.dict(include=included_request_fields)\n    response = build_condensed_response(infer_response)\n    return {\n        \"inference_id\": infer_request.id,\n        \"inference_server_version\": __version__,\n        \"inference_server_id\": GLOBAL_INFERENCE_SERVER_ID,\n        \"request\": jsonable_encoder(request),\n        \"response\": jsonable_encoder(response),\n    }\n\n\ndef build_condensed_response(responses):\n    if not isinstance(responses, list):\n        responses = [responses]\n\n    response_handlers = {\n        ClassificationInferenceResponse: from_classification_response,\n        MultiLabelClassificationInferenceResponse: from_multilabel_classification_response,\n        ObjectDetectionInferenceResponse: from_object_detection_response,\n        InstanceSegmentationInferenceResponse: from_instance_segmentation_response,\n        KeypointsDetectionInferenceResponse: from_keypoints_detection_response,\n    }\n\n    formatted_responses = []\n    for response in responses:\n        if not getattr(response, \"predictions\", None):\n            continue\n        try:\n            handler = None\n            for cls, h in response_handlers.items():\n                if isinstance(response, cls):\n                    handler = h\n                    break\n            if handler:\n                predictions = handler(response)\n                formatted_responses.append(\n                    {\n                        \"predictions\": predictions,\n                        \"time\": response.time,\n                    }\n                )\n        except Exception as e:\n            logger.warning(f\"Error formatting response, skipping caching: {e}\")\n\n    return formatted_responses\n\n\ndef from_classification_response(response: ClassificationInferenceResponse):\n    return [\n        {\"class\": pred.class_name, \"confidence\": pred.confidence}\n        for pred in response.predictions\n    ]\n\n\ndef from_multilabel_classification_response(\n    response: MultiLabelClassificationInferenceResponse,\n):\n    return [\n        {\"class\": cls, \"confidence\": pred.confidence}\n        for cls, pred in response.predictions.items()\n    ]\n\n\ndef from_object_detection_response(response: ObjectDetectionInferenceResponse):\n    return [\n        {\"class\": pred.class_name, \"confidence\": pred.confidence}\n        for pred in response.predictions\n    ]\n\n\ndef from_instance_segmentation_response(\n    response: InstanceSegmentationInferenceResponse,\n):\n    return [\n        {\"class\": pred.class_name, \"confidence\": pred.confidence}\n        for pred in response.predictions\n    ]\n\n\ndef from_keypoints_detection_response(response: KeypointsDetectionInferenceResponse):\n    return [\n        {\"class\": keypoint.class_name, \"confidence\": keypoint.confidence}\n        for pred in response.predictions\n        for keypoint in pred.keypoints\n    ]\n",
    "optimized_raw_markdown": "",
    "optimized_function_only": "def from_keypoints_detection_response(response: KeypointsDetectionInferenceResponse):\n    return [\n        {\"class\": keypoint.class_name, \"confidence\": keypoint.confidence}\n        for pred in response.predictions\n        for keypoint in pred.keypoints\n    ]\n",
    "original_file_content": "from typing import List, Union\n\nfrom fastapi.encoders import jsonable_encoder\n\nfrom inference.core.devices.utils import GLOBAL_INFERENCE_SERVER_ID\nfrom inference.core.entities.requests.inference import InferenceRequest\nfrom inference.core.entities.responses.inference import (\n    ClassificationInferenceResponse,\n    InferenceResponse,\n    InstanceSegmentationInferenceResponse,\n    KeypointsDetectionInferenceResponse,\n    MultiLabelClassificationInferenceResponse,\n    ObjectDetectionInferenceResponse,\n)\nfrom inference.core.env import TINY_CACHE\nfrom inference.core.logger import logger\nfrom inference.core.version import __version__\n\n\ndef to_cachable_inference_item(\n    infer_request: InferenceRequest,\n    infer_response: Union[InferenceResponse, List[InferenceResponse]],\n) -> dict:\n    if not TINY_CACHE:\n        return {\n            \"inference_id\": infer_request.id,\n            \"inference_server_version\": __version__,\n            \"inference_server_id\": GLOBAL_INFERENCE_SERVER_ID,\n            \"request\": jsonable_encoder(infer_request),\n            \"response\": jsonable_encoder(infer_response),\n        }\n\n    included_request_fields = {\n        \"api_key\",\n        \"confidence\",\n        \"model_id\",\n        \"model_type\",\n        \"source\",\n        \"source_info\",\n    }\n    request = infer_request.dict(include=included_request_fields)\n    response = build_condensed_response(infer_response)\n    return {\n        \"inference_id\": infer_request.id,\n        \"inference_server_version\": __version__,\n        \"inference_server_id\": GLOBAL_INFERENCE_SERVER_ID,\n        \"request\": jsonable_encoder(request),\n        \"response\": jsonable_encoder(response),\n    }\n\n\ndef build_condensed_response(responses):\n    if not isinstance(responses, list):\n        responses = [responses]\n\n    response_handlers = {\n        ClassificationInferenceResponse: from_classification_response,\n        MultiLabelClassificationInferenceResponse: from_multilabel_classification_response,\n        ObjectDetectionInferenceResponse: from_object_detection_response,\n        InstanceSegmentationInferenceResponse: from_instance_segmentation_response,\n        KeypointsDetectionInferenceResponse: from_keypoints_detection_response,\n    }\n\n    formatted_responses = []\n    for response in responses:\n        if not getattr(response, \"predictions\", None):\n            continue\n        try:\n            handler = None\n            for cls, h in response_handlers.items():\n                if isinstance(response, cls):\n                    handler = h\n                    break\n            if handler:\n                predictions = handler(response)\n                formatted_responses.append(\n                    {\n                        \"predictions\": predictions,\n                        \"time\": response.time,\n                    }\n                )\n        except Exception as e:\n            logger.warning(f\"Error formatting response, skipping caching: {e}\")\n\n    return formatted_responses\n\n\ndef from_classification_response(response: ClassificationInferenceResponse):\n    return [\n        {\"class\": pred.class_name, \"confidence\": pred.confidence}\n        for pred in response.predictions\n    ]\n\n\ndef from_multilabel_classification_response(\n    response: MultiLabelClassificationInferenceResponse,\n):\n    return [\n        {\"class\": cls, \"confidence\": pred.confidence}\n        for cls, pred in response.predictions.items()\n    ]\n\n\ndef from_object_detection_response(response: ObjectDetectionInferenceResponse):\n    return [\n        {\"class\": pred.class_name, \"confidence\": pred.confidence}\n        for pred in response.predictions\n    ]\n\n\ndef from_instance_segmentation_response(\n    response: InstanceSegmentationInferenceResponse,\n):\n    return [\n        {\"class\": pred.class_name, \"confidence\": pred.confidence}\n        for pred in response.predictions\n    ]\n\n\ndef from_keypoints_detection_response(response: KeypointsDetectionInferenceResponse):\n    predictions = []\n    for pred in response.predictions:\n        for keypoint in pred.keypoints:\n            predictions.append(\n                {\"class\": keypoint.class_name, \"confidence\": keypoint.confidence}\n            )\n    return predictions\n",
    "patch": "diff --git a/inference/core/cache/serializers.py b/inference/core/cache/serializers.py\nindex 78ca4d3f1..990333711 100644\n--- a/inference/core/cache/serializers.py\n+++ b/inference/core/cache/serializers.py\n@@ -118,10 +118,8 @@ def from_instance_segmentation_response(\n \n \n def from_keypoints_detection_response(response: KeypointsDetectionInferenceResponse):\n-    predictions = []\n-    for pred in response.predictions:\n-        for keypoint in pred.keypoints:\n-            predictions.append(\n-                {\"class\": keypoint.class_name, \"confidence\": keypoint.confidence}\n-            )\n-    return predictions\n+    return [\n+        {\"class\": keypoint.class_name, \"confidence\": keypoint.confidence}\n+        for pred in response.predictions\n+        for keypoint in pred.keypoints\n+    ]\n"
  },
  {
    "trace_id": "git_7988cebce7fd",
    "function_name": "convert_string_color_to_bgr_tuple",
    "file_path": "inference/core/workflows/core_steps/classical_cv/pixel_color_count/v1.py",
    "speedup_x": 0.3,
    "review_quality": null,
    "pre_optimization_commit": "f6289ddfeda5115df3edd38dec2ff6885098a6d8",
    "resolution_method": "git_parent",
    "source": "git",
    "original_function_code": "def convert_string_color_to_bgr_tuple(color: str) -> Tuple[int, int, int]:\n    if color.startswith(\"#\") and len(color) == 7:\n        try:\n            return tuple(int(color[i : i + 2], 16) for i in (5, 3, 1))\n        except ValueError as e:\n            raise ValueError(f\"Invalid hex color format: {color}\") from e\n    if color.startswith(\"#\") and len(color) == 4:\n        try:\n            return tuple(int(color[i] + color[i], 16) for i in (3, 2, 1))\n        except ValueError as e:\n            raise ValueError(f\"Invalid hex color format: {color}\") from e\n    if color.startswith(\"(\") and color.endswith(\")\"):\n        try:\n            return tuple(map(int, color[1:-1].split(\",\")))[::-1]\n        except ValueError as e:\n            raise ValueError(f\"Invalid tuple color format: {color}\") from e\n    raise ValueError(f\"Invalid hex color format: {color}\")\n",
    "optimized_function_code": "from typing import List, Literal, Optional, Tuple, Type, Union\n\nimport cv2\nimport numpy as np\nfrom pydantic import AliasChoices, ConfigDict, Field\n\nfrom inference.core.workflows.execution_engine.entities.base import (\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    IMAGE_KIND,\n    INTEGER_KIND,\n    RGB_COLOR_KIND,\n    STRING_KIND,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nSHORT_DESCRIPTION: str = (\n    \"Count the number of pixels that match a specific color within a given tolerance.\"\n)\n\n\nclass ColorPixelCountManifest(WorkflowBlockManifest):\n    type: Literal[\"roboflow_core/pixel_color_count@v1\"]\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Pixel Color Count\",\n            \"version\": \"v1\",\n            \"short_description\": SHORT_DESCRIPTION,\n            \"long_description\": SHORT_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"classical_computer_vision\",\n            \"ui_manifest\": {\n                \"section\": \"classical_cv\",\n                \"icon\": \"far fa-tally\",\n                \"blockPriority\": 2,\n                \"opencv\": True,\n            },\n        }\n    )\n    image: Selector(kind=[IMAGE_KIND]) = Field(\n        title=\"Input Image\",\n        description=\"The input image for this step.\",\n        examples=[\"$inputs.image\", \"$steps.cropping.crops\"],\n        validation_alias=AliasChoices(\"image\", \"images\"),\n    )\n    target_color: Union[\n        Selector(kind=[STRING_KIND]),\n        Selector(kind=[RGB_COLOR_KIND]),\n        str,\n        Tuple[int, int, int],\n    ] = Field(\n        description=\"Target color to count in the image. Can be a hex string \"\n        \"(like '#431112') RGB string (like '(128, 32, 64)') or a RGB tuple \"\n        \"(like (18, 17, 67)).\",\n        examples=[\"#431112\", \"$inputs.target_color\", (18, 17, 67)],\n    )\n    tolerance: Union[Selector(kind=[INTEGER_KIND]), int] = Field(\n        default=10,\n        description=\"Tolerance for color matching.\",\n        examples=[10, \"$inputs.tolerance\"],\n    )\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(\n                name=\"matching_pixels_count\",\n                kind=[INTEGER_KIND],\n            ),\n        ]\n\n\nclass PixelationCountBlockV1(WorkflowBlock):\n\n    @classmethod\n    def get_manifest(cls) -> Type[ColorPixelCountManifest]:\n        return ColorPixelCountManifest\n\n    def run(\n        self,\n        image: WorkflowImageData,\n        target_color: Union[str, tuple],\n        tolerance: int,\n    ) -> BlockResult:\n        color_pixel_count = count_specific_color_pixels(\n            image.numpy_image, target_color, tolerance\n        )\n        return {\"matching_pixels_count\": color_pixel_count}\n\n\ndef count_specific_color_pixels(\n    image: np.ndarray,\n    target_color: Union[str, Tuple[int, int, int]],\n    tolerance: int,\n) -> int:\n    \"\"\"\n    Counts the number of pixels that match the target color within the given tolerance.\n\n    Args:\n        image: Input image.\n        target_color (Union[str, tuple]): Target color in hex format (e.g., '#431112') or BGR tuple (e.g., (18, 17, 67)).\n        tolerance (int, optional): Tolerance for color matching. Defaults to 10.\n\n    Returns:\n        int: Number of pixels that match the target color.\n    \"\"\"\n    target_color_bgr = convert_color_to_bgr_tuple(color=target_color)\n    lower_bound = np.array(\n        [\n            target_color_bgr[0] - tolerance,\n            target_color_bgr[1] - tolerance,\n            target_color_bgr[2] - tolerance,\n        ]\n    )\n    upper_bound = np.array(\n        [\n            target_color_bgr[0] + tolerance,\n            target_color_bgr[1] + tolerance,\n            target_color_bgr[2] + tolerance,\n        ]\n    )\n    mask = cv2.inRange(image, lower_bound, upper_bound)\n    return int(np.sum(mask > 0))\n\n\ndef convert_color_to_bgr_tuple(\n    color: Union[str, Tuple[int, int, int]],\n) -> Tuple[int, int, int]:\n    if isinstance(color, str):\n        return convert_string_color_to_bgr_tuple(color=color)\n    if isinstance(color, tuple) and len(color) == 3:\n        return color[::-1]\n    raise ValueError(f\"Invalid color format: {color}\")\n\n\ndef convert_string_color_to_bgr_tuple(color: str) -> Tuple[int, int, int]:\n    # Check if color is in hex format\n    if color.startswith(\"#\"):\n        try:\n            if len(color) == 7:\n                return (int(color[5:7], 16), int(color[3:5], 16), int(color[1:3], 16))\n            elif len(color) == 4:\n                return (\n                    int(color[3] * 2, 16),\n                    int(color[2] * 2, 16),\n                    int(color[1] * 2, 16),\n                )\n        except ValueError as e:\n            raise ValueError(f\"Invalid hex color format: {color}\") from e\n\n    # Check if color is in tuple format\n    elif color.startswith(\"(\") and color.endswith(\")\"):\n        try:\n            return tuple(map(int, color[1:-1].split(\",\")))[::-1]\n        except ValueError as e:\n            raise ValueError(f\"Invalid tuple color format: {color}\") from e\n\n    raise ValueError(f\"Invalid color format: {color}\")\n",
    "optimized_raw_markdown": "",
    "optimized_function_only": "def convert_string_color_to_bgr_tuple(color: str) -> Tuple[int, int, int]:\n    # Check if color is in hex format\n    if color.startswith(\"#\"):\n        try:\n            if len(color) == 7:\n                return (int(color[5:7], 16), int(color[3:5], 16), int(color[1:3], 16))\n            elif len(color) == 4:\n                return (\n                    int(color[3] * 2, 16),\n                    int(color[2] * 2, 16),\n                    int(color[1] * 2, 16),\n                )\n        except ValueError as e:\n            raise ValueError(f\"Invalid hex color format: {color}\") from e\n\n    # Check if color is in tuple format\n    elif color.startswith(\"(\") and color.endswith(\")\"):\n        try:\n            return tuple(map(int, color[1:-1].split(\",\")))[::-1]\n        except ValueError as e:\n            raise ValueError(f\"Invalid tuple color format: {color}\") from e\n\n    raise ValueError(f\"Invalid color format: {color}\")\n",
    "original_file_content": "from typing import List, Literal, Optional, Tuple, Type, Union\n\nimport cv2\nimport numpy as np\nfrom pydantic import AliasChoices, ConfigDict, Field\n\nfrom inference.core.workflows.execution_engine.entities.base import (\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    IMAGE_KIND,\n    INTEGER_KIND,\n    RGB_COLOR_KIND,\n    STRING_KIND,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nSHORT_DESCRIPTION: str = (\n    \"Count the number of pixels that match a specific color within a given tolerance.\"\n)\n\n\nclass ColorPixelCountManifest(WorkflowBlockManifest):\n    type: Literal[\"roboflow_core/pixel_color_count@v1\"]\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Pixel Color Count\",\n            \"version\": \"v1\",\n            \"short_description\": SHORT_DESCRIPTION,\n            \"long_description\": SHORT_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"classical_computer_vision\",\n            \"ui_manifest\": {\n                \"section\": \"classical_cv\",\n                \"icon\": \"far fa-tally\",\n                \"blockPriority\": 2,\n                \"opencv\": True,\n            },\n        }\n    )\n    image: Selector(kind=[IMAGE_KIND]) = Field(\n        title=\"Input Image\",\n        description=\"The input image for this step.\",\n        examples=[\"$inputs.image\", \"$steps.cropping.crops\"],\n        validation_alias=AliasChoices(\"image\", \"images\"),\n    )\n    target_color: Union[\n        Selector(kind=[STRING_KIND]),\n        Selector(kind=[RGB_COLOR_KIND]),\n        str,\n        Tuple[int, int, int],\n    ] = Field(\n        description=\"Target color to count in the image. Can be a hex string \"\n        \"(like '#431112') RGB string (like '(128, 32, 64)') or a RGB tuple \"\n        \"(like (18, 17, 67)).\",\n        examples=[\"#431112\", \"$inputs.target_color\", (18, 17, 67)],\n    )\n    tolerance: Union[Selector(kind=[INTEGER_KIND]), int] = Field(\n        default=10,\n        description=\"Tolerance for color matching.\",\n        examples=[10, \"$inputs.tolerance\"],\n    )\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(\n                name=\"matching_pixels_count\",\n                kind=[INTEGER_KIND],\n            ),\n        ]\n\n\nclass PixelationCountBlockV1(WorkflowBlock):\n\n    @classmethod\n    def get_manifest(cls) -> Type[ColorPixelCountManifest]:\n        return ColorPixelCountManifest\n\n    def run(\n        self,\n        image: WorkflowImageData,\n        target_color: Union[str, tuple],\n        tolerance: int,\n    ) -> BlockResult:\n        color_pixel_count = count_specific_color_pixels(\n            image.numpy_image, target_color, tolerance\n        )\n        return {\"matching_pixels_count\": color_pixel_count}\n\n\ndef count_specific_color_pixels(\n    image: np.ndarray,\n    target_color: Union[str, Tuple[int, int, int]],\n    tolerance: int,\n) -> int:\n    \"\"\"\n    Counts the number of pixels that match the target color within the given tolerance.\n\n    Args:\n        image: Input image.\n        target_color (Union[str, tuple]): Target color in hex format (e.g., '#431112') or BGR tuple (e.g., (18, 17, 67)).\n        tolerance (int, optional): Tolerance for color matching. Defaults to 10.\n\n    Returns:\n        int: Number of pixels that match the target color.\n    \"\"\"\n    target_color_bgr = convert_color_to_bgr_tuple(color=target_color)\n    lower_bound = np.array(\n        [\n            target_color_bgr[0] - tolerance,\n            target_color_bgr[1] - tolerance,\n            target_color_bgr[2] - tolerance,\n        ]\n    )\n    upper_bound = np.array(\n        [\n            target_color_bgr[0] + tolerance,\n            target_color_bgr[1] + tolerance,\n            target_color_bgr[2] + tolerance,\n        ]\n    )\n    mask = cv2.inRange(image, lower_bound, upper_bound)\n    return int(np.sum(mask > 0))\n\n\ndef convert_color_to_bgr_tuple(\n    color: Union[str, Tuple[int, int, int]],\n) -> Tuple[int, int, int]:\n    if isinstance(color, str):\n        return convert_string_color_to_bgr_tuple(color=color)\n    if isinstance(color, tuple) and len(color) == 3:\n        return color[::-1]\n    raise ValueError(f\"Invalid color format: {color}\")\n\n\ndef convert_string_color_to_bgr_tuple(color: str) -> Tuple[int, int, int]:\n    if color.startswith(\"#\") and len(color) == 7:\n        try:\n            return tuple(int(color[i : i + 2], 16) for i in (5, 3, 1))\n        except ValueError as e:\n            raise ValueError(f\"Invalid hex color format: {color}\") from e\n    if color.startswith(\"#\") and len(color) == 4:\n        try:\n            return tuple(int(color[i] + color[i], 16) for i in (3, 2, 1))\n        except ValueError as e:\n            raise ValueError(f\"Invalid hex color format: {color}\") from e\n    if color.startswith(\"(\") and color.endswith(\")\"):\n        try:\n            return tuple(map(int, color[1:-1].split(\",\")))[::-1]\n        except ValueError as e:\n            raise ValueError(f\"Invalid tuple color format: {color}\") from e\n    raise ValueError(f\"Invalid hex color format: {color}\")\n",
    "patch": "diff --git a/inference/core/workflows/core_steps/classical_cv/pixel_color_count/v1.py b/inference/core/workflows/core_steps/classical_cv/pixel_color_count/v1.py\nindex da5b436b6..ab923725c 100644\n--- a/inference/core/workflows/core_steps/classical_cv/pixel_color_count/v1.py\n+++ b/inference/core/workflows/core_steps/classical_cv/pixel_color_count/v1.py\n@@ -145,19 +145,25 @@ def convert_color_to_bgr_tuple(\n \n \n def convert_string_color_to_bgr_tuple(color: str) -> Tuple[int, int, int]:\n-    if color.startswith(\"#\") and len(color) == 7:\n+    # Check if color is in hex format\n+    if color.startswith(\"#\"):\n         try:\n-            return tuple(int(color[i : i + 2], 16) for i in (5, 3, 1))\n+            if len(color) == 7:\n+                return (int(color[5:7], 16), int(color[3:5], 16), int(color[1:3], 16))\n+            elif len(color) == 4:\n+                return (\n+                    int(color[3] * 2, 16),\n+                    int(color[2] * 2, 16),\n+                    int(color[1] * 2, 16),\n+                )\n         except ValueError as e:\n             raise ValueError(f\"Invalid hex color format: {color}\") from e\n-    if color.startswith(\"#\") and len(color) == 4:\n-        try:\n-            return tuple(int(color[i] + color[i], 16) for i in (3, 2, 1))\n-        except ValueError as e:\n-            raise ValueError(f\"Invalid hex color format: {color}\") from e\n-    if color.startswith(\"(\") and color.endswith(\")\"):\n+\n+    # Check if color is in tuple format\n+    elif color.startswith(\"(\") and color.endswith(\")\"):\n         try:\n             return tuple(map(int, color[1:-1].split(\",\")))[::-1]\n         except ValueError as e:\n             raise ValueError(f\"Invalid tuple color format: {color}\") from e\n-    raise ValueError(f\"Invalid hex color format: {color}\")\n+\n+    raise ValueError(f\"Invalid color format: {color}\")\n"
  },
  {
    "trace_id": "git_cf0f6d05af7f",
    "function_name": "count_specific_color_pixels",
    "file_path": "inference/core/workflows/core_steps/classical_cv/pixel_color_count/v1.py",
    "speedup_x": 0.6,
    "review_quality": null,
    "pre_optimization_commit": "f6289ddfeda5115df3edd38dec2ff6885098a6d8",
    "resolution_method": "git_parent",
    "source": "git",
    "original_function_code": "def count_specific_color_pixels(\n    image: np.ndarray,\n    target_color: Union[str, Tuple[int, int, int]],\n    tolerance: int,\n) -> int:\n    \"\"\"\n    Counts the number of pixels that match the target color within the given tolerance.\n\n    Args:\n        image: Input image.\n        target_color (Union[str, tuple]): Target color in hex format (e.g., '#431112') or BGR tuple (e.g., (18, 17, 67)).\n        tolerance (int, optional): Tolerance for color matching. Defaults to 10.\n\n    Returns:\n        int: Number of pixels that match the target color.\n    \"\"\"\n    target_color_bgr = convert_color_to_bgr_tuple(color=target_color)\n    lower_bound = np.array(\n        [\n            target_color_bgr[0] - tolerance,\n            target_color_bgr[1] - tolerance,\n            target_color_bgr[2] - tolerance,\n        ]\n    )\n    upper_bound = np.array(\n        [\n            target_color_bgr[0] + tolerance,\n            target_color_bgr[1] + tolerance,\n            target_color_bgr[2] + tolerance,\n        ]\n    )\n    mask = cv2.inRange(image, lower_bound, upper_bound)\n    return int(np.sum(mask > 0))\n",
    "optimized_function_code": "from typing import List, Literal, Optional, Tuple, Type, Union\n\nimport cv2\nimport numpy as np\nfrom pydantic import AliasChoices, ConfigDict, Field\n\nfrom inference.core.workflows.execution_engine.entities.base import (\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    IMAGE_KIND,\n    INTEGER_KIND,\n    RGB_COLOR_KIND,\n    STRING_KIND,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nSHORT_DESCRIPTION: str = (\n    \"Count the number of pixels that match a specific color within a given tolerance.\"\n)\n\n\nclass ColorPixelCountManifest(WorkflowBlockManifest):\n    type: Literal[\"roboflow_core/pixel_color_count@v1\"]\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Pixel Color Count\",\n            \"version\": \"v1\",\n            \"short_description\": SHORT_DESCRIPTION,\n            \"long_description\": SHORT_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"classical_computer_vision\",\n            \"ui_manifest\": {\n                \"section\": \"classical_cv\",\n                \"icon\": \"far fa-tally\",\n                \"blockPriority\": 2,\n                \"opencv\": True,\n            },\n        }\n    )\n    image: Selector(kind=[IMAGE_KIND]) = Field(\n        title=\"Input Image\",\n        description=\"The input image for this step.\",\n        examples=[\"$inputs.image\", \"$steps.cropping.crops\"],\n        validation_alias=AliasChoices(\"image\", \"images\"),\n    )\n    target_color: Union[\n        Selector(kind=[STRING_KIND]),\n        Selector(kind=[RGB_COLOR_KIND]),\n        str,\n        Tuple[int, int, int],\n    ] = Field(\n        description=\"Target color to count in the image. Can be a hex string \"\n        \"(like '#431112') RGB string (like '(128, 32, 64)') or a RGB tuple \"\n        \"(like (18, 17, 67)).\",\n        examples=[\"#431112\", \"$inputs.target_color\", (18, 17, 67)],\n    )\n    tolerance: Union[Selector(kind=[INTEGER_KIND]), int] = Field(\n        default=10,\n        description=\"Tolerance for color matching.\",\n        examples=[10, \"$inputs.tolerance\"],\n    )\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(\n                name=\"matching_pixels_count\",\n                kind=[INTEGER_KIND],\n            ),\n        ]\n\n\nclass PixelationCountBlockV1(WorkflowBlock):\n\n    @classmethod\n    def get_manifest(cls) -> Type[ColorPixelCountManifest]:\n        return ColorPixelCountManifest\n\n    def run(\n        self,\n        image: WorkflowImageData,\n        target_color: Union[str, tuple],\n        tolerance: int,\n    ) -> BlockResult:\n        color_pixel_count = count_specific_color_pixels(\n            image.numpy_image, target_color, tolerance\n        )\n        return {\"matching_pixels_count\": color_pixel_count}\n\n\ndef count_specific_color_pixels(\n    image: np.ndarray,\n    target_color: Union[str, Tuple[int, int, int]],\n    tolerance: int,\n) -> int:\n    \"\"\"\n    Counts the number of pixels that match the target color within the given tolerance.\n\n    Args:\n        image: Input image.\n        target_color (Union[str, tuple]): Target color in hex format (e.g., '#431112') or BGR tuple (e.g., (18, 17, 67)).\n        tolerance (int, optional): Tolerance for color matching. Defaults to 10.\n\n    Returns:\n        int: Number of pixels that match the target color.\n    \"\"\"\n    target_color_bgr = convert_color_to_bgr_tuple(color=target_color)\n    lower_bound = np.array(target_color_bgr) - tolerance\n    upper_bound = np.array(target_color_bgr) + tolerance\n\n    # Use vectorized comparison to directly create a mask and count non-zero elements\n    mask = cv2.inRange(image, lower_bound, upper_bound)\n\n    return int(cv2.countNonZero(mask))\n\n\ndef convert_color_to_bgr_tuple(\n    color: Union[str, Tuple[int, int, int]],\n) -> Tuple[int, int, int]:\n    if isinstance(color, str):\n        return convert_string_color_to_bgr_tuple(color=color)\n    if isinstance(color, tuple) and len(color) == 3:\n        return color[::-1]\n    raise ValueError(f\"Invalid color format: {color}\")\n\n\ndef convert_string_color_to_bgr_tuple(color: str) -> Tuple[int, int, int]:\n    if color.startswith(\"#\") and len(color) == 7:\n        try:\n            return tuple(int(color[i : i + 2], 16) for i in (5, 3, 1))\n        except ValueError as e:\n            raise ValueError(f\"Invalid hex color format: {color}\") from e\n    if color.startswith(\"#\") and len(color) == 4:\n        try:\n            return tuple(int(color[i] + color[i], 16) for i in (3, 2, 1))\n        except ValueError as e:\n            raise ValueError(f\"Invalid hex color format: {color}\") from e\n    if color.startswith(\"(\") and color.endswith(\")\"):\n        try:\n            return tuple(map(int, color[1:-1].split(\",\")))[::-1]\n        except ValueError as e:\n            raise ValueError(f\"Invalid tuple color format: {color}\") from e\n    raise ValueError(f\"Invalid hex color format: {color}\")\n",
    "optimized_raw_markdown": "",
    "optimized_function_only": "def count_specific_color_pixels(\n    image: np.ndarray,\n    target_color: Union[str, Tuple[int, int, int]],\n    tolerance: int,\n) -> int:\n    \"\"\"\n    Counts the number of pixels that match the target color within the given tolerance.\n\n    Args:\n        image: Input image.\n        target_color (Union[str, tuple]): Target color in hex format (e.g., '#431112') or BGR tuple (e.g., (18, 17, 67)).\n        tolerance (int, optional): Tolerance for color matching. Defaults to 10.\n\n    Returns:\n        int: Number of pixels that match the target color.\n    \"\"\"\n    target_color_bgr = convert_color_to_bgr_tuple(color=target_color)\n    lower_bound = np.array(target_color_bgr) - tolerance\n    upper_bound = np.array(target_color_bgr) + tolerance\n\n    # Use vectorized comparison to directly create a mask and count non-zero elements\n    mask = cv2.inRange(image, lower_bound, upper_bound)\n\n    return int(cv2.countNonZero(mask))\n",
    "original_file_content": "from typing import List, Literal, Optional, Tuple, Type, Union\n\nimport cv2\nimport numpy as np\nfrom pydantic import AliasChoices, ConfigDict, Field\n\nfrom inference.core.workflows.execution_engine.entities.base import (\n    OutputDefinition,\n    WorkflowImageData,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    IMAGE_KIND,\n    INTEGER_KIND,\n    RGB_COLOR_KIND,\n    STRING_KIND,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\nSHORT_DESCRIPTION: str = (\n    \"Count the number of pixels that match a specific color within a given tolerance.\"\n)\n\n\nclass ColorPixelCountManifest(WorkflowBlockManifest):\n    type: Literal[\"roboflow_core/pixel_color_count@v1\"]\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Pixel Color Count\",\n            \"version\": \"v1\",\n            \"short_description\": SHORT_DESCRIPTION,\n            \"long_description\": SHORT_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"classical_computer_vision\",\n            \"ui_manifest\": {\n                \"section\": \"classical_cv\",\n                \"icon\": \"far fa-tally\",\n                \"blockPriority\": 2,\n                \"opencv\": True,\n            },\n        }\n    )\n    image: Selector(kind=[IMAGE_KIND]) = Field(\n        title=\"Input Image\",\n        description=\"The input image for this step.\",\n        examples=[\"$inputs.image\", \"$steps.cropping.crops\"],\n        validation_alias=AliasChoices(\"image\", \"images\"),\n    )\n    target_color: Union[\n        Selector(kind=[STRING_KIND]),\n        Selector(kind=[RGB_COLOR_KIND]),\n        str,\n        Tuple[int, int, int],\n    ] = Field(\n        description=\"Target color to count in the image. Can be a hex string \"\n        \"(like '#431112') RGB string (like '(128, 32, 64)') or a RGB tuple \"\n        \"(like (18, 17, 67)).\",\n        examples=[\"#431112\", \"$inputs.target_color\", (18, 17, 67)],\n    )\n    tolerance: Union[Selector(kind=[INTEGER_KIND]), int] = Field(\n        default=10,\n        description=\"Tolerance for color matching.\",\n        examples=[10, \"$inputs.tolerance\"],\n    )\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(\n                name=\"matching_pixels_count\",\n                kind=[INTEGER_KIND],\n            ),\n        ]\n\n\nclass PixelationCountBlockV1(WorkflowBlock):\n\n    @classmethod\n    def get_manifest(cls) -> Type[ColorPixelCountManifest]:\n        return ColorPixelCountManifest\n\n    def run(\n        self,\n        image: WorkflowImageData,\n        target_color: Union[str, tuple],\n        tolerance: int,\n    ) -> BlockResult:\n        color_pixel_count = count_specific_color_pixels(\n            image.numpy_image, target_color, tolerance\n        )\n        return {\"matching_pixels_count\": color_pixel_count}\n\n\ndef count_specific_color_pixels(\n    image: np.ndarray,\n    target_color: Union[str, Tuple[int, int, int]],\n    tolerance: int,\n) -> int:\n    \"\"\"\n    Counts the number of pixels that match the target color within the given tolerance.\n\n    Args:\n        image: Input image.\n        target_color (Union[str, tuple]): Target color in hex format (e.g., '#431112') or BGR tuple (e.g., (18, 17, 67)).\n        tolerance (int, optional): Tolerance for color matching. Defaults to 10.\n\n    Returns:\n        int: Number of pixels that match the target color.\n    \"\"\"\n    target_color_bgr = convert_color_to_bgr_tuple(color=target_color)\n    lower_bound = np.array(\n        [\n            target_color_bgr[0] - tolerance,\n            target_color_bgr[1] - tolerance,\n            target_color_bgr[2] - tolerance,\n        ]\n    )\n    upper_bound = np.array(\n        [\n            target_color_bgr[0] + tolerance,\n            target_color_bgr[1] + tolerance,\n            target_color_bgr[2] + tolerance,\n        ]\n    )\n    mask = cv2.inRange(image, lower_bound, upper_bound)\n    return int(np.sum(mask > 0))\n\n\ndef convert_color_to_bgr_tuple(\n    color: Union[str, Tuple[int, int, int]],\n) -> Tuple[int, int, int]:\n    if isinstance(color, str):\n        return convert_string_color_to_bgr_tuple(color=color)\n    if isinstance(color, tuple) and len(color) == 3:\n        return color[::-1]\n    raise ValueError(f\"Invalid color format: {color}\")\n\n\ndef convert_string_color_to_bgr_tuple(color: str) -> Tuple[int, int, int]:\n    if color.startswith(\"#\") and len(color) == 7:\n        try:\n            return tuple(int(color[i : i + 2], 16) for i in (5, 3, 1))\n        except ValueError as e:\n            raise ValueError(f\"Invalid hex color format: {color}\") from e\n    if color.startswith(\"#\") and len(color) == 4:\n        try:\n            return tuple(int(color[i] + color[i], 16) for i in (3, 2, 1))\n        except ValueError as e:\n            raise ValueError(f\"Invalid hex color format: {color}\") from e\n    if color.startswith(\"(\") and color.endswith(\")\"):\n        try:\n            return tuple(map(int, color[1:-1].split(\",\")))[::-1]\n        except ValueError as e:\n            raise ValueError(f\"Invalid tuple color format: {color}\") from e\n    raise ValueError(f\"Invalid hex color format: {color}\")\n",
    "patch": "diff --git a/inference/core/workflows/core_steps/classical_cv/pixel_color_count/v1.py b/inference/core/workflows/core_steps/classical_cv/pixel_color_count/v1.py\nindex da5b436b6..bf8b5eebb 100644\n--- a/inference/core/workflows/core_steps/classical_cv/pixel_color_count/v1.py\n+++ b/inference/core/workflows/core_steps/classical_cv/pixel_color_count/v1.py\n@@ -116,22 +116,13 @@ def count_specific_color_pixels(\n         int: Number of pixels that match the target color.\n     \"\"\"\n     target_color_bgr = convert_color_to_bgr_tuple(color=target_color)\n-    lower_bound = np.array(\n-        [\n-            target_color_bgr[0] - tolerance,\n-            target_color_bgr[1] - tolerance,\n-            target_color_bgr[2] - tolerance,\n-        ]\n-    )\n-    upper_bound = np.array(\n-        [\n-            target_color_bgr[0] + tolerance,\n-            target_color_bgr[1] + tolerance,\n-            target_color_bgr[2] + tolerance,\n-        ]\n-    )\n+    lower_bound = np.array(target_color_bgr) - tolerance\n+    upper_bound = np.array(target_color_bgr) + tolerance\n+\n+    # Use vectorized comparison to directly create a mask and count non-zero elements\n     mask = cv2.inRange(image, lower_bound, upper_bound)\n-    return int(np.sum(mask > 0))\n+\n+    return int(cv2.countNonZero(mask))\n \n \n def convert_color_to_bgr_tuple(\n"
  },
  {
    "trace_id": "git_afcc3a60c882",
    "function_name": "select_top_confidence_detection",
    "file_path": "inference/core/workflows/core_steps/common/query_language/operations/detections/base.py",
    "speedup_x": 1.88,
    "review_quality": null,
    "pre_optimization_commit": "5b27747e3e1fb5596d09bc010d506a0ac7bbca7b",
    "resolution_method": "git_parent",
    "source": "git",
    "original_function_code": "def select_top_confidence_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return detections  # No need to deepcopy an empty detections object\n    max_index = np.argmax(detections.confidence)\n    return detections[max_index]\n",
    "optimized_function_code": "from copy import copy, deepcopy\nfrom typing import Any, Callable, Dict, List, Union\n\nimport numpy as np\nimport supervision as sv\nfrom supervision import Position\n\nfrom inference.core.workflows.core_steps.common.query_language.entities.enums import (\n    DetectionsProperty,\n    DetectionsSelectionMode,\n    DetectionsSortProperties,\n)\nfrom inference.core.workflows.core_steps.common.query_language.entities.operations import (\n    DEFAULT_OPERAND_NAME,\n)\nfrom inference.core.workflows.core_steps.common.query_language.errors import (\n    InvalidInputTypeError,\n    OperationError,\n    UndeclaredSymbolError,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.utils import (\n    safe_stringify,\n)\nfrom inference.core.workflows.core_steps.common.serializers import (\n    serialise_sv_detections,\n)\n\nPROPERTIES_EXTRACTORS = {\n    DetectionsProperty.CONFIDENCE: lambda detections: detections.confidence.tolist(),\n    DetectionsProperty.CLASS_NAME: lambda detections: detections.data.get(\n        \"class_name\", np.array([], dtype=str)\n    ).tolist(),\n    DetectionsProperty.X_MIN: lambda detections: detections.xyxy[:, 0].tolist(),\n    DetectionsProperty.Y_MIN: lambda detections: detections.xyxy[:, 1].tolist(),\n    DetectionsProperty.X_MAX: lambda detections: detections.xyxy[:, 2].tolist(),\n    DetectionsProperty.Y_MAX: lambda detections: detections.xyxy[:, 3].tolist(),\n    DetectionsProperty.CLASS_ID: lambda detections: detections.class_id.tolist(),\n    DetectionsProperty.SIZE: lambda detections: detections.box_area.tolist(),\n}\n\n\ndef extract_detections_property(\n    detections: Any,\n    property_name: DetectionsProperty,\n    execution_context: str,\n    **kwargs,\n) -> List[Any]:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing extract_detections_property(...) in context {execution_context}, \"\n            f\"expected sv.Detections object as value, got {value_as_str} of type {type(detections)}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n        )\n    return PROPERTIES_EXTRACTORS[property_name](detections)\n\n\ndef filter_detections(\n    detections: Any,\n    filtering_fun: Callable[[Dict[str, Any]], bool],\n    global_parameters: Dict[str, Any],\n) -> sv.Detections:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing filter_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(detections)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    local_parameters = copy(global_parameters)\n    result = []\n    for detection in detections:\n        local_parameters[DEFAULT_OPERAND_NAME] = detection\n        should_stay = filtering_fun(local_parameters)\n        result.append(should_stay)\n    return detections[result]\n\n\ndef offset_detections(\n    value: Any, offset_x: int, offset_y: int, **kwargs\n) -> sv.Detections:\n    if not isinstance(value, sv.Detections):\n        value_as_str = safe_stringify(value=value)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing offset_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(value)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    detections_copy = deepcopy(value)\n    detections_copy.xyxy += [-offset_x / 2, -offset_y / 2, offset_x / 2, offset_y / 2]\n    return detections_copy\n\n\ndef shift_detections(value: Any, shift_x: int, shift_y: int, **kwargs) -> sv.Detections:\n    if not isinstance(value, sv.Detections):\n        value_as_str = safe_stringify(value=value)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing shift_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(value)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    detections_copy = deepcopy(value)\n    detections_copy.xyxy += [shift_x, shift_y, shift_x, shift_y]\n    return detections_copy\n\n\ndef select_top_confidence_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    confidence = detections.confidence\n    max_value = confidence.max()\n    index = np.argwhere(confidence == max_value)[0].item()\n    return detections[index]\n\n\ndef select_leftmost_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return detections  # Directly return the original empty detections if empty\n\n    centers_x = detections.get_anchors_coordinates(anchor=Position.CENTER)[:, 0]\n    index = np.argmin(centers_x)\n    return detections[index]\n\n\ndef select_rightmost_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return detections\n\n    centers_x = detections.get_anchors_coordinates(anchor=Position.CENTER)[:, 0]\n    index = centers_x.argmax()\n    return detections[index]\n\n\ndef select_first_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    return detections[0]\n\n\ndef select_last_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    return detections[-1]\n\n\nDETECTIONS_SELECTORS = {\n    DetectionsSelectionMode.FIRST: select_first_detection,\n    DetectionsSelectionMode.LAST: select_last_detection,\n    DetectionsSelectionMode.LEFT_MOST: select_leftmost_detection,\n    DetectionsSelectionMode.RIGHT_MOST: select_rightmost_detection,\n    DetectionsSelectionMode.TOP_CONFIDENCE: select_top_confidence_detection,\n}\n\n\ndef select_detections(\n    value: Any, mode: DetectionsSelectionMode, **kwargs\n) -> sv.Detections:\n    if not isinstance(value, sv.Detections):\n        value_as_str = safe_stringify(value=value)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing select_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(value)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if mode not in DETECTIONS_SELECTORS:\n        InvalidInputTypeError(\n            public_message=f\"Executing select_detections(...), expected mode to be one of {DETECTIONS_SELECTORS.values()}, \"\n            f\"got {mode}.\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    return DETECTIONS_SELECTORS[mode](value)\n\n\ndef extract_x_coordinate_of_detections_center(detections: sv.Detections) -> np.ndarray:\n    return detections.xyxy[:, 0] + (detections.xyxy[:, 2] - detections.xyxy[:, 0]) / 2\n\n\ndef extract_y_coordinate_of_detections_center(detections: sv.Detections) -> np.ndarray:\n    return detections.xyxy[:, 1] + (detections.xyxy[:, 3] - detections.xyxy[:, 1]) / 2\n\n\nSORT_PROPERTIES_EXTRACT = {\n    DetectionsSortProperties.CONFIDENCE: lambda detections: detections.confidence,\n    DetectionsSortProperties.X_MIN: lambda detections: detections.xyxy[:, 0],\n    DetectionsSortProperties.X_MAX: lambda detections: detections.xyxy[:, 2],\n    DetectionsSortProperties.Y_MIN: lambda detections: detections.xyxy[:, 1],\n    DetectionsSortProperties.Y_MAX: lambda detections: detections.xyxy[:, 3],\n    DetectionsSortProperties.SIZE: lambda detections: detections.box_area,\n    DetectionsSortProperties.CENTER_X: extract_x_coordinate_of_detections_center,\n    DetectionsSortProperties.CENTER_Y: extract_y_coordinate_of_detections_center,\n}\n\n\ndef sort_detections(\n    value: Any, mode: DetectionsSortProperties, ascending: bool, **kwargs\n) -> sv.Detections:\n    if not isinstance(value, sv.Detections):\n        value_as_str = safe_stringify(value=value)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing sort_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(value)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if mode not in SORT_PROPERTIES_EXTRACT:\n        raise InvalidInputTypeError(\n            public_message=f\"Executing sort_detections(...), expected mode to be one of \"\n            f\"{SORT_PROPERTIES_EXTRACT.values()}, got {mode}.\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if len(value) == 0:\n        return value\n    extracted_property = SORT_PROPERTIES_EXTRACT[mode](value)\n    if extracted_property is None:\n        # property may not be set, as sv.Detections declares Optional[...]\n        return value\n    sorted_indices = np.argsort(extracted_property)\n    if not ascending:\n        sorted_indices = sorted_indices[::-1]\n    return value[sorted_indices]\n\n\ndef rename_detections(\n    detections: Any,\n    class_map: Union[Dict[str, str], str],\n    strict: Union[bool, str],\n    new_classes_id_offset: int,\n    global_parameters: Dict[str, Any],\n    **kwargs,\n) -> sv.Detections:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing rename_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(detections)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if isinstance(class_map, str):\n        if class_map not in global_parameters:\n            raise UndeclaredSymbolError(\n                public_message=f\"Attempted to retrieve variable `{class_map}` that was expected to hold \"\n                f\"class mapping of rename_detections(...), but that turned out not to be registered.\",\n                context=\"step_execution | roboflow_query_language_evaluation\",\n            )\n        class_map = global_parameters[class_map]\n    if not isinstance(class_map, dict):\n        value_as_str = safe_stringify(value=class_map)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing rename_detections(...), expected dictionary to be given as class map, \"\n            f\"got {value_as_str} of type {type(class_map)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if isinstance(strict, str):\n        if strict not in global_parameters:\n            raise UndeclaredSymbolError(\n                public_message=f\"Attempted to retrieve variable `{strict}` that was expected to hold \"\n                f\"parameter for `strict` flag of rename_detections(...), but that turned out not \"\n                f\"to be registered.\",\n                context=\"step_execution | roboflow_query_language_evaluation\",\n            )\n        strict = global_parameters[strict]\n    if not isinstance(strict, bool):\n        value_as_str = safe_stringify(value=strict)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing rename_detections(...), expected dictionary to be given as `strict` flag, \"\n            f\"got {value_as_str} of type {type(strict)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    detections_copy = deepcopy(detections)\n    original_class_names = detections_copy.data.get(\"class_name\", []).tolist()\n    original_class_ids = detections_copy.class_id.tolist()\n    new_class_names = []\n    new_class_ids = []\n    if strict:\n        _ensure_all_classes_covered_in_new_mapping(\n            original_class_names=original_class_names,\n            class_map=class_map,\n        )\n        new_class_mapping = {\n            class_name: class_id\n            for class_id, class_name in enumerate(sorted(set(class_map.values())))\n        }\n    else:\n        new_class_mapping = _build_non_strict_class_to_id_mapping(\n            original_class_names=original_class_names,\n            original_class_ids=original_class_ids,\n            class_map=class_map,\n            new_classes_id_offset=new_classes_id_offset,\n        )\n    for class_name in original_class_names:\n        new_class_name = class_map.get(class_name, class_name)\n        new_class_id = new_class_mapping[new_class_name]\n        new_class_names.append(new_class_name)\n        new_class_ids.append(new_class_id)\n    detections_copy.data[\"class_name\"] = np.array(new_class_names, dtype=object)\n    detections_copy.class_id = np.array(new_class_ids, dtype=int)\n    return detections_copy\n\n\ndef _ensure_all_classes_covered_in_new_mapping(\n    original_class_names: List[str],\n    class_map: Dict[str, str],\n) -> None:\n    for original_class in original_class_names:\n        if original_class not in class_map:\n            raise OperationError(\n                public_message=f\"Class '{original_class}' not found in class_map.\",\n                context=\"step_execution | roboflow_query_language_evaluation\",\n            )\n\n\ndef _build_non_strict_class_to_id_mapping(\n    original_class_names: List[str],\n    original_class_ids: List[int],\n    class_map: Dict[str, str],\n    new_classes_id_offset: int,\n) -> Dict[str, int]:\n    original_mapping = {\n        class_name: class_id\n        for class_name, class_id in zip(original_class_names, original_class_ids)\n    }\n    new_target_classes = {\n        new_class_name\n        for new_class_name in class_map.values()\n        if new_class_name not in original_mapping\n    }\n    new_class_id = new_classes_id_offset\n    for new_target_class in sorted(new_target_classes):\n        original_mapping[new_target_class] = new_class_id\n        new_class_id += 1\n    return original_mapping\n\n\ndef detections_to_dictionary(\n    detections: Any,\n    execution_context: str,\n    **kwargs,\n) -> dict:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing detections_to_dictionary(...) in context {execution_context}, \"\n            f\"expected sv.Detections object as value, got {value_as_str} of type {type(detections)}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n        )\n    try:\n        return serialise_sv_detections(detections=detections)\n    except Exception as error:\n        raise OperationError(\n            public_message=f\"While Using operation detections_to_dictionary(...) in context {execution_context} \"\n            f\"encountered error: {error}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n            inner_error=error,\n        )\n\n\ndef pick_detections_by_parent_class(\n    detections: Any,\n    parent_class: str,\n    execution_context: str,\n    **kwargs,\n) -> sv.Detections:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing pick_detections_by_parent_class(...) in context {execution_context}, \"\n            f\"expected sv.Detections object as value, got {value_as_str} of type {type(detections)}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n        )\n    try:\n        return _pick_detections_by_parent_class(\n            detections=detections, parent_class=parent_class\n        )\n    except Exception as error:\n        raise OperationError(\n            public_message=f\"While Using operation pick_detections_by_parent_class(...) in context {execution_context} \"\n            f\"encountered error: {error}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n            inner_error=error,\n        )\n\n\ndef _pick_detections_by_parent_class(\n    detections: sv.Detections,\n    parent_class: str,\n) -> sv.Detections:\n    class_names = detections.data.get(\"class_name\")\n    if class_names is None or len(class_names) == 0:\n        return sv.Detections.empty()\n    if not isinstance(class_names, np.ndarray):\n        class_names = np.array(class_names)\n    parent_mask = class_names == parent_class\n    parent_detections = detections[parent_mask]\n    if len(parent_detections) == 0:\n        return sv.Detections.empty()\n    dependent_detections = detections[~parent_mask]\n    dependent_detections_anchors = dependent_detections.get_anchors_coordinates(\n        anchor=Position.CENTER\n    )\n    dependent_detections_to_keep = set()\n    for detection_idx, anchor in enumerate(dependent_detections_anchors):\n        for parent_detection_box in parent_detections.xyxy:\n            if _is_point_within_box(point=anchor, box=parent_detection_box):\n                dependent_detections_to_keep.add(detection_idx)\n                continue\n    detections_to_keep_list = sorted(list(dependent_detections_to_keep))\n    filtered_dependent_detections = dependent_detections[detections_to_keep_list]\n    return sv.Detections.merge([parent_detections, filtered_dependent_detections])\n\n\ndef _is_point_within_box(point: np.ndarray, box: np.ndarray) -> bool:\n    px, py = point\n    x1, y1, x2, y2 = box\n    return x1 <= px <= x2 and y1 <= py <= y2\n",
    "optimized_raw_markdown": "",
    "optimized_function_only": "def select_top_confidence_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    confidence = detections.confidence\n    max_value = confidence.max()\n    index = np.argwhere(confidence == max_value)[0].item()\n    return detections[index]\n",
    "original_file_content": "from copy import copy, deepcopy\nfrom typing import Any, Callable, Dict, List, Union\n\nimport numpy as np\nimport supervision as sv\nfrom supervision import Position\n\nfrom inference.core.workflows.core_steps.common.query_language.entities.enums import (\n    DetectionsProperty,\n    DetectionsSelectionMode,\n    DetectionsSortProperties,\n)\nfrom inference.core.workflows.core_steps.common.query_language.entities.operations import (\n    DEFAULT_OPERAND_NAME,\n)\nfrom inference.core.workflows.core_steps.common.query_language.errors import (\n    InvalidInputTypeError,\n    OperationError,\n    UndeclaredSymbolError,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.utils import (\n    safe_stringify,\n)\nfrom inference.core.workflows.core_steps.common.serializers import (\n    serialise_sv_detections,\n)\n\nPROPERTIES_EXTRACTORS = {\n    DetectionsProperty.CONFIDENCE: lambda detections: detections.confidence.tolist(),\n    DetectionsProperty.CLASS_NAME: lambda detections: detections.data.get(\n        \"class_name\", np.array([], dtype=str)\n    ).tolist(),\n    DetectionsProperty.X_MIN: lambda detections: detections.xyxy[:, 0].tolist(),\n    DetectionsProperty.Y_MIN: lambda detections: detections.xyxy[:, 1].tolist(),\n    DetectionsProperty.X_MAX: lambda detections: detections.xyxy[:, 2].tolist(),\n    DetectionsProperty.Y_MAX: lambda detections: detections.xyxy[:, 3].tolist(),\n    DetectionsProperty.CLASS_ID: lambda detections: detections.class_id.tolist(),\n    DetectionsProperty.SIZE: lambda detections: detections.box_area.tolist(),\n}\n\n\ndef extract_detections_property(\n    detections: Any,\n    property_name: DetectionsProperty,\n    execution_context: str,\n    **kwargs,\n) -> List[Any]:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing extract_detections_property(...) in context {execution_context}, \"\n            f\"expected sv.Detections object as value, got {value_as_str} of type {type(detections)}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n        )\n    return PROPERTIES_EXTRACTORS[property_name](detections)\n\n\ndef filter_detections(\n    detections: Any,\n    filtering_fun: Callable[[Dict[str, Any]], bool],\n    global_parameters: Dict[str, Any],\n) -> sv.Detections:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing filter_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(detections)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    local_parameters = copy(global_parameters)\n    result = []\n    for detection in detections:\n        local_parameters[DEFAULT_OPERAND_NAME] = detection\n        should_stay = filtering_fun(local_parameters)\n        result.append(should_stay)\n    return detections[result]\n\n\ndef offset_detections(\n    value: Any, offset_x: int, offset_y: int, **kwargs\n) -> sv.Detections:\n    if not isinstance(value, sv.Detections):\n        value_as_str = safe_stringify(value=value)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing offset_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(value)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    detections_copy = deepcopy(value)\n    detections_copy.xyxy += [-offset_x / 2, -offset_y / 2, offset_x / 2, offset_y / 2]\n    return detections_copy\n\n\ndef shift_detections(value: Any, shift_x: int, shift_y: int, **kwargs) -> sv.Detections:\n    if not isinstance(value, sv.Detections):\n        value_as_str = safe_stringify(value=value)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing shift_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(value)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    detections_copy = deepcopy(value)\n    detections_copy.xyxy += [shift_x, shift_y, shift_x, shift_y]\n    return detections_copy\n\n\ndef select_top_confidence_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return detections  # No need to deepcopy an empty detections object\n    max_index = np.argmax(detections.confidence)\n    return detections[max_index]\n\n\ndef select_leftmost_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return detections  # Directly return the original empty detections if empty\n\n    centers_x = detections.get_anchors_coordinates(anchor=Position.CENTER)[:, 0]\n    index = np.argmin(centers_x)\n    return detections[index]\n\n\ndef select_rightmost_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return detections\n\n    centers_x = detections.get_anchors_coordinates(anchor=Position.CENTER)[:, 0]\n    index = centers_x.argmax()\n    return detections[index]\n\n\ndef select_first_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    return detections[0]\n\n\ndef select_last_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    return detections[-1]\n\n\nDETECTIONS_SELECTORS = {\n    DetectionsSelectionMode.FIRST: select_first_detection,\n    DetectionsSelectionMode.LAST: select_last_detection,\n    DetectionsSelectionMode.LEFT_MOST: select_leftmost_detection,\n    DetectionsSelectionMode.RIGHT_MOST: select_rightmost_detection,\n    DetectionsSelectionMode.TOP_CONFIDENCE: select_top_confidence_detection,\n}\n\n\ndef select_detections(\n    value: Any, mode: DetectionsSelectionMode, **kwargs\n) -> sv.Detections:\n    if not isinstance(value, sv.Detections):\n        value_as_str = safe_stringify(value=value)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing select_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(value)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if mode not in DETECTIONS_SELECTORS:\n        InvalidInputTypeError(\n            public_message=f\"Executing select_detections(...), expected mode to be one of {DETECTIONS_SELECTORS.values()}, \"\n            f\"got {mode}.\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    return DETECTIONS_SELECTORS[mode](value)\n\n\ndef extract_x_coordinate_of_detections_center(detections: sv.Detections) -> np.ndarray:\n    return detections.xyxy[:, 0] + (detections.xyxy[:, 2] - detections.xyxy[:, 0]) / 2\n\n\ndef extract_y_coordinate_of_detections_center(detections: sv.Detections) -> np.ndarray:\n    return detections.xyxy[:, 1] + (detections.xyxy[:, 3] - detections.xyxy[:, 1]) / 2\n\n\nSORT_PROPERTIES_EXTRACT = {\n    DetectionsSortProperties.CONFIDENCE: lambda detections: detections.confidence,\n    DetectionsSortProperties.X_MIN: lambda detections: detections.xyxy[:, 0],\n    DetectionsSortProperties.X_MAX: lambda detections: detections.xyxy[:, 2],\n    DetectionsSortProperties.Y_MIN: lambda detections: detections.xyxy[:, 1],\n    DetectionsSortProperties.Y_MAX: lambda detections: detections.xyxy[:, 3],\n    DetectionsSortProperties.SIZE: lambda detections: detections.box_area,\n    DetectionsSortProperties.CENTER_X: extract_x_coordinate_of_detections_center,\n    DetectionsSortProperties.CENTER_Y: extract_y_coordinate_of_detections_center,\n}\n\n\ndef sort_detections(\n    value: Any, mode: DetectionsSortProperties, ascending: bool, **kwargs\n) -> sv.Detections:\n    if not isinstance(value, sv.Detections):\n        value_as_str = safe_stringify(value=value)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing sort_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(value)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if mode not in SORT_PROPERTIES_EXTRACT:\n        raise InvalidInputTypeError(\n            public_message=f\"Executing sort_detections(...), expected mode to be one of \"\n            f\"{SORT_PROPERTIES_EXTRACT.values()}, got {mode}.\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if len(value) == 0:\n        return value\n    extracted_property = SORT_PROPERTIES_EXTRACT[mode](value)\n    if extracted_property is None:\n        # property may not be set, as sv.Detections declares Optional[...]\n        return value\n    sorted_indices = np.argsort(extracted_property)\n    if not ascending:\n        sorted_indices = sorted_indices[::-1]\n    return value[sorted_indices]\n\n\ndef rename_detections(\n    detections: Any,\n    class_map: Union[Dict[str, str], str],\n    strict: Union[bool, str],\n    new_classes_id_offset: int,\n    global_parameters: Dict[str, Any],\n    **kwargs,\n) -> sv.Detections:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing rename_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(detections)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if isinstance(class_map, str):\n        if class_map not in global_parameters:\n            raise UndeclaredSymbolError(\n                public_message=f\"Attempted to retrieve variable `{class_map}` that was expected to hold \"\n                f\"class mapping of rename_detections(...), but that turned out not to be registered.\",\n                context=\"step_execution | roboflow_query_language_evaluation\",\n            )\n        class_map = global_parameters[class_map]\n    if not isinstance(class_map, dict):\n        value_as_str = safe_stringify(value=class_map)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing rename_detections(...), expected dictionary to be given as class map, \"\n            f\"got {value_as_str} of type {type(class_map)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if isinstance(strict, str):\n        if strict not in global_parameters:\n            raise UndeclaredSymbolError(\n                public_message=f\"Attempted to retrieve variable `{strict}` that was expected to hold \"\n                f\"parameter for `strict` flag of rename_detections(...), but that turned out not \"\n                f\"to be registered.\",\n                context=\"step_execution | roboflow_query_language_evaluation\",\n            )\n        strict = global_parameters[strict]\n    if not isinstance(strict, bool):\n        value_as_str = safe_stringify(value=strict)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing rename_detections(...), expected dictionary to be given as `strict` flag, \"\n            f\"got {value_as_str} of type {type(strict)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    detections_copy = deepcopy(detections)\n    original_class_names = detections_copy.data.get(\"class_name\", []).tolist()\n    original_class_ids = detections_copy.class_id.tolist()\n    new_class_names = []\n    new_class_ids = []\n    if strict:\n        _ensure_all_classes_covered_in_new_mapping(\n            original_class_names=original_class_names,\n            class_map=class_map,\n        )\n        new_class_mapping = {\n            class_name: class_id\n            for class_id, class_name in enumerate(sorted(set(class_map.values())))\n        }\n    else:\n        new_class_mapping = _build_non_strict_class_to_id_mapping(\n            original_class_names=original_class_names,\n            original_class_ids=original_class_ids,\n            class_map=class_map,\n            new_classes_id_offset=new_classes_id_offset,\n        )\n    for class_name in original_class_names:\n        new_class_name = class_map.get(class_name, class_name)\n        new_class_id = new_class_mapping[new_class_name]\n        new_class_names.append(new_class_name)\n        new_class_ids.append(new_class_id)\n    detections_copy.data[\"class_name\"] = np.array(new_class_names, dtype=object)\n    detections_copy.class_id = np.array(new_class_ids, dtype=int)\n    return detections_copy\n\n\ndef _ensure_all_classes_covered_in_new_mapping(\n    original_class_names: List[str],\n    class_map: Dict[str, str],\n) -> None:\n    for original_class in original_class_names:\n        if original_class not in class_map:\n            raise OperationError(\n                public_message=f\"Class '{original_class}' not found in class_map.\",\n                context=\"step_execution | roboflow_query_language_evaluation\",\n            )\n\n\ndef _build_non_strict_class_to_id_mapping(\n    original_class_names: List[str],\n    original_class_ids: List[int],\n    class_map: Dict[str, str],\n    new_classes_id_offset: int,\n) -> Dict[str, int]:\n    original_mapping = {\n        class_name: class_id\n        for class_name, class_id in zip(original_class_names, original_class_ids)\n    }\n    new_target_classes = {\n        new_class_name\n        for new_class_name in class_map.values()\n        if new_class_name not in original_mapping\n    }\n    new_class_id = new_classes_id_offset\n    for new_target_class in sorted(new_target_classes):\n        original_mapping[new_target_class] = new_class_id\n        new_class_id += 1\n    return original_mapping\n\n\ndef detections_to_dictionary(\n    detections: Any,\n    execution_context: str,\n    **kwargs,\n) -> dict:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing detections_to_dictionary(...) in context {execution_context}, \"\n            f\"expected sv.Detections object as value, got {value_as_str} of type {type(detections)}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n        )\n    try:\n        return serialise_sv_detections(detections=detections)\n    except Exception as error:\n        raise OperationError(\n            public_message=f\"While Using operation detections_to_dictionary(...) in context {execution_context} \"\n            f\"encountered error: {error}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n            inner_error=error,\n        )\n\n\ndef pick_detections_by_parent_class(\n    detections: Any,\n    parent_class: str,\n    execution_context: str,\n    **kwargs,\n) -> sv.Detections:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing pick_detections_by_parent_class(...) in context {execution_context}, \"\n            f\"expected sv.Detections object as value, got {value_as_str} of type {type(detections)}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n        )\n    try:\n        return _pick_detections_by_parent_class(\n            detections=detections, parent_class=parent_class\n        )\n    except Exception as error:\n        raise OperationError(\n            public_message=f\"While Using operation pick_detections_by_parent_class(...) in context {execution_context} \"\n            f\"encountered error: {error}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n            inner_error=error,\n        )\n\n\ndef _pick_detections_by_parent_class(\n    detections: sv.Detections,\n    parent_class: str,\n) -> sv.Detections:\n    class_names = detections.data.get(\"class_name\")\n    if class_names is None or len(class_names) == 0:\n        return sv.Detections.empty()\n    if not isinstance(class_names, np.ndarray):\n        class_names = np.array(class_names)\n    parent_mask = class_names == parent_class\n    parent_detections = detections[parent_mask]\n    if len(parent_detections) == 0:\n        return sv.Detections.empty()\n    dependent_detections = detections[~parent_mask]\n    dependent_detections_anchors = dependent_detections.get_anchors_coordinates(\n        anchor=Position.CENTER\n    )\n    dependent_detections_to_keep = set()\n    for detection_idx, anchor in enumerate(dependent_detections_anchors):\n        for parent_detection_box in parent_detections.xyxy:\n            if _is_point_within_box(point=anchor, box=parent_detection_box):\n                dependent_detections_to_keep.add(detection_idx)\n                continue\n    detections_to_keep_list = sorted(list(dependent_detections_to_keep))\n    filtered_dependent_detections = dependent_detections[detections_to_keep_list]\n    return sv.Detections.merge([parent_detections, filtered_dependent_detections])\n\n\ndef _is_point_within_box(point: np.ndarray, box: np.ndarray) -> bool:\n    px, py = point\n    x1, y1, x2, y2 = box\n    return x1 <= px <= x2 and y1 <= py <= y2\n",
    "patch": "diff --git a/inference/core/workflows/core_steps/common/query_language/operations/detections/base.py b/inference/core/workflows/core_steps/common/query_language/operations/detections/base.py\nindex 0551a1b31..0db557e86 100644\n--- a/inference/core/workflows/core_steps/common/query_language/operations/detections/base.py\n+++ b/inference/core/workflows/core_steps/common/query_language/operations/detections/base.py\n@@ -106,9 +106,11 @@ def shift_detections(value: Any, shift_x: int, shift_y: int, **kwargs) -> sv.Det\n \n def select_top_confidence_detection(detections: sv.Detections) -> sv.Detections:\n     if len(detections) == 0:\n-        return detections  # No need to deepcopy an empty detections object\n-    max_index = np.argmax(detections.confidence)\n-    return detections[max_index]\n+        return deepcopy(detections)\n+    confidence = detections.confidence\n+    max_value = confidence.max()\n+    index = np.argwhere(confidence == max_value)[0].item()\n+    return detections[index]\n \n \n def select_leftmost_detection(detections: sv.Detections) -> sv.Detections:\n"
  },
  {
    "trace_id": "git_6a3889233146",
    "function_name": "get_average_bounding_box",
    "file_path": "inference/core/workflows/core_steps/fusion/detections_consensus/v1.py",
    "speedup_x": 1.66,
    "review_quality": null,
    "pre_optimization_commit": "f6289ddfeda5115df3edd38dec2ff6885098a6d8",
    "resolution_method": "git_parent",
    "source": "git",
    "original_function_code": "def get_average_bounding_box(detections: sv.Detections) -> Tuple[int, int, int, int]:\n    avg_xyxy: np.ndarray = sum(detections.xyxy) / len(detections)\n    return tuple(avg_xyxy.astype(float))\n",
    "optimized_function_code": "import math\nimport statistics\nfrom collections import Counter\nfrom enum import Enum\nfrom typing import Dict, Generator, List, Literal, Optional, Set, Tuple, Type, Union\nfrom uuid import uuid4\n\nimport numpy as np\nimport supervision as sv\nfrom pydantic import AliasChoices, ConfigDict, Field, PositiveInt\n\nfrom inference.core.workflows.execution_engine.constants import (\n    DETECTION_ID_KEY,\n    IMAGE_DIMENSIONS_KEY,\n    PARENT_COORDINATES_KEY,\n    PARENT_DIMENSIONS_KEY,\n    PARENT_ID_KEY,\n    PREDICTION_TYPE_KEY,\n    ROOT_PARENT_COORDINATES_KEY,\n    ROOT_PARENT_DIMENSIONS_KEY,\n    ROOT_PARENT_ID_KEY,\n    SCALING_RELATIVE_TO_PARENT_KEY,\n    SCALING_RELATIVE_TO_ROOT_PARENT_KEY,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    BOOLEAN_KIND,\n    DICTIONARY_KIND,\n    FLOAT_ZERO_TO_ONE_KIND,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    INTEGER_KIND,\n    KEYPOINT_DETECTION_PREDICTION_KIND,\n    LIST_OF_VALUES_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    FloatZeroToOne,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\n\nclass AggregationMode(Enum):\n    AVERAGE = \"average\"\n    MAX = \"max\"\n    MIN = \"min\"\n\n\nLONG_DESCRIPTION = \"\"\"\nCombine detections from multiple detection-based models based on a majority vote \nstrategy.\n\nThis block is useful if you have multiple specialized models that you want to consult \nto determine whether a certain object is present in an image.\n\nSee the table below to explore the values you can use to configure the consensus block.\n\"\"\"\n\nSHORT_DESCRIPTION = (\n    \"Combine predictions from multiple detections models to make a \"\n    \"decision about object presence.\"\n)\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Detections Consensus\",\n            \"version\": \"v1\",\n            \"short_description\": SHORT_DESCRIPTION,\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"fusion\",\n            \"ui_manifest\": {\n                \"section\": \"flow_control\",\n                \"icon\": \"fak fa-circles-overlap\",\n                \"blockPriority\": 4,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/detections_consensus@v1\", \"DetectionsConsensus\"]\n    predictions_batches: List[\n        Selector(\n            kind=[\n                OBJECT_DETECTION_PREDICTION_KIND,\n                INSTANCE_SEGMENTATION_PREDICTION_KIND,\n                KEYPOINT_DETECTION_PREDICTION_KIND,\n            ]\n        ),\n    ] = Field(\n        min_items=1,\n        description=\"Reference to detection-like model predictions made against single image to agree on model consensus\",\n        examples=[[\"$steps.a.predictions\", \"$steps.b.predictions\"]],\n        validation_alias=AliasChoices(\"predictions_batches\", \"predictions\"),\n    )\n    required_votes: Union[PositiveInt, Selector(kind=[INTEGER_KIND])] = Field(\n        description=\"Required number of votes for single detection from different models to accept detection as output detection\",\n        examples=[2, \"$inputs.required_votes\"],\n    )\n    class_aware: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=True,\n        description=\"Flag to decide if merging detections is class-aware or only bounding boxes aware\",\n        examples=[True, \"$inputs.class_aware\"],\n    )\n    iou_threshold: Union[FloatZeroToOne, Selector(kind=[FLOAT_ZERO_TO_ONE_KIND])] = (\n        Field(\n            default=0.3,\n            description=\"IoU threshold to consider detections from different models as matching (increasing votes for region)\",\n            examples=[0.3, \"$inputs.iou_threshold\"],\n        )\n    )\n    confidence: Union[FloatZeroToOne, Selector(kind=[FLOAT_ZERO_TO_ONE_KIND])] = Field(\n        default=0.0,\n        description=\"Confidence threshold for merged detections\",\n        examples=[0.1, \"$inputs.confidence\"],\n    )\n    classes_to_consider: Optional[\n        Union[List[str], Selector(kind=[LIST_OF_VALUES_KIND])]\n    ] = Field(\n        default=None,\n        description=\"Optional list of classes to consider in consensus procedure.\",\n        examples=[[\"a\", \"b\"], \"$inputs.classes_to_consider\"],\n    )\n    required_objects: Optional[\n        Union[\n            PositiveInt,\n            Dict[str, PositiveInt],\n            Selector(kind=[INTEGER_KIND, DICTIONARY_KIND]),\n        ]\n    ] = Field(\n        default=None,\n        description=\"If given, it holds the number of objects that must be present in merged results, to assume that object presence is reached. Can be selector to `InferenceParameter`, integer value or dictionary with mapping of class name into minimal number of merged detections of given class to assume consensus.\",\n        examples=[3, {\"a\": 7, \"b\": 2}, \"$inputs.required_objects\"],\n    )\n    presence_confidence_aggregation: AggregationMode = Field(\n        default=AggregationMode.MAX,\n        description=\"Mode dictating aggregation of confidence scores and classes both in case of object presence deduction procedure.\",\n        examples=[\"max\", \"min\"],\n    )\n    detections_merge_confidence_aggregation: AggregationMode = Field(\n        default=AggregationMode.AVERAGE,\n        description=\"Mode dictating aggregation of confidence scores and classes both in case of boxes consensus procedure. One of `average`, `max`, `min`. Default: `average`. While using for merging overlapping boxes, against classes - `average` equals to majority vote, `max` - for the class of detection with max confidence, `min` - for the class of detection with min confidence.\",\n        examples=[\"min\", \"max\"],\n    )\n    detections_merge_coordinates_aggregation: AggregationMode = Field(\n        default=AggregationMode.AVERAGE,\n        description=\"Mode dictating aggregation of bounding boxes. One of `average`, `max`, `min`. Default: `average`. `average` means taking mean from all boxes coordinates, `min` - taking smallest box, `max` - taking largest box.\",\n        examples=[\"min\", \"max\"],\n    )\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return [\"predictions_batches\"]\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(\n                name=\"predictions\",\n                kind=[OBJECT_DETECTION_PREDICTION_KIND],\n            ),\n            OutputDefinition(\n                name=\"object_present\", kind=[BOOLEAN_KIND, DICTIONARY_KIND]\n            ),\n            OutputDefinition(\n                name=\"presence_confidence\",\n                kind=[FLOAT_ZERO_TO_ONE_KIND, DICTIONARY_KIND],\n            ),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass DetectionsConsensusBlockV1(WorkflowBlock):\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        predictions_batches: List[Batch[sv.Detections]],\n        required_votes: int,\n        class_aware: bool,\n        iou_threshold: float,\n        confidence: float,\n        classes_to_consider: Optional[List[str]],\n        required_objects: Optional[Union[int, Dict[str, int]]],\n        presence_confidence_aggregation: AggregationMode,\n        detections_merge_confidence_aggregation: AggregationMode,\n        detections_merge_coordinates_aggregation: AggregationMode,\n    ) -> BlockResult:\n        if len(predictions_batches) < 1:\n            raise ValueError(\n                f\"Consensus step requires at least one source of predictions.\"\n            )\n        results = []\n        for detections_from_sources in zip(*predictions_batches):\n            (\n                parent_id,\n                object_present,\n                presence_confidence,\n                consensus_detections,\n            ) = agree_on_consensus_for_all_detections_sources(\n                detections_from_sources=list(detections_from_sources),\n                required_votes=required_votes,\n                class_aware=class_aware,\n                iou_threshold=iou_threshold,\n                confidence=confidence,\n                classes_to_consider=classes_to_consider,\n                required_objects=required_objects,\n                presence_confidence_aggregation=presence_confidence_aggregation,\n                detections_merge_confidence_aggregation=detections_merge_confidence_aggregation,\n                detections_merge_coordinates_aggregation=detections_merge_coordinates_aggregation,\n            )\n            results.append(\n                {\n                    \"predictions\": consensus_detections,\n                    \"object_present\": object_present,\n                    \"presence_confidence\": presence_confidence,\n                }\n            )\n        return results\n\n\ndef does_not_detect_objects_in_any_source(\n    detections_from_sources: List[sv.Detections],\n) -> bool:\n    return all(len(p) == 0 for p in detections_from_sources)\n\n\ndef get_parent_id_of_detections_from_sources(\n    detections_from_sources: List[sv.Detections],\n) -> str:\n    encountered_parent_ids = set(\n        np.concatenate(\n            [\n                detections[PARENT_ID_KEY]\n                for detections in detections_from_sources\n                if PARENT_ID_KEY in detections.data\n            ]\n        ).tolist()\n    )\n    if len(encountered_parent_ids) != 1:\n        raise ValueError(\n            \"Missmatch in predictions - while executing consensus step, \"\n            \"in equivalent batches, detections are assigned different parent \"\n            \"identifiers, whereas consensus can only be applied for predictions \"\n            \"made against the same input.\"\n        )\n    return next(iter(encountered_parent_ids))\n\n\ndef filter_predictions(\n    predictions: List[sv.Detections],\n    classes_to_consider: Optional[List[str]],\n) -> List[sv.Detections]:\n    if not classes_to_consider:\n        return predictions\n    return [\n        detections[np.isin(detections[\"class_name\"], classes_to_consider)]\n        for detections in predictions\n        if \"class_name\" in detections.data\n    ]\n\n\ndef get_detections_from_different_sources_with_max_overlap(\n    detection: sv.Detections,\n    source: int,\n    detections_from_sources: List[sv.Detections],\n    iou_threshold: float,\n    class_aware: bool,\n    detections_already_considered: Set[str],\n) -> Dict[int, Tuple[sv.Detections, float]]:\n    current_max_overlap = {}\n    for other_source, other_detection in enumerate_detections(\n        detections_from_sources=detections_from_sources,\n        excluded_source_id=source,\n    ):\n        if other_detection[DETECTION_ID_KEY][0] in detections_already_considered:\n            continue\n        if (\n            class_aware\n            and detection[\"class_name\"][0] != other_detection[\"class_name\"][0]\n        ):\n            continue\n        iou_value = calculate_iou(\n            detection_a=detection,\n            detection_b=other_detection,\n        )\n        if iou_value <= iou_threshold:\n            continue\n        if current_max_overlap.get(other_source) is None:\n            current_max_overlap[other_source] = (other_detection, iou_value)\n        if current_max_overlap[other_source][1] < iou_value:\n            current_max_overlap[other_source] = (other_detection, iou_value)\n    return current_max_overlap\n\n\ndef enumerate_detections(\n    detections_from_sources: List[sv.Detections],\n    excluded_source_id: Optional[int] = None,\n) -> Generator[Tuple[int, sv.Detections], None, None]:\n    for source_id, detections in enumerate(detections_from_sources):\n        if excluded_source_id == source_id:\n            continue\n        for i in range(len(detections)):\n            yield source_id, detections[i]\n\n\ndef calculate_iou(detection_a: sv.Detections, detection_b: sv.Detections) -> float:\n    iou = float(sv.box_iou_batch(detection_a.xyxy, detection_b.xyxy)[0][0])\n    if math.isnan(iou):\n        iou = 0\n    return iou\n\n\ndef agree_on_consensus_for_all_detections_sources(\n    detections_from_sources: List[sv.Detections],\n    required_votes: int,\n    class_aware: bool,\n    iou_threshold: float,\n    confidence: float,\n    classes_to_consider: Optional[List[str]],\n    required_objects: Optional[Union[int, Dict[str, int]]],\n    presence_confidence_aggregation: AggregationMode,\n    detections_merge_confidence_aggregation: AggregationMode,\n    detections_merge_coordinates_aggregation: AggregationMode,\n) -> Tuple[str, bool, Dict[str, float], sv.Detections]:\n    if does_not_detect_objects_in_any_source(\n        detections_from_sources=detections_from_sources\n    ):\n        return \"undefined\", False, {}, sv.Detections.empty()\n    parent_id = get_parent_id_of_detections_from_sources(\n        detections_from_sources=detections_from_sources,\n    )\n    detections_from_sources = filter_predictions(\n        predictions=detections_from_sources,\n        classes_to_consider=classes_to_consider,\n    )\n    detections_already_considered = set()\n    consensus_detections = []\n    for source_id, detection in enumerate_detections(\n        detections_from_sources=detections_from_sources\n    ):\n        (\n            consensus_detections_update,\n            detections_already_considered,\n        ) = get_consensus_for_single_detection(\n            detection=detection,\n            source_id=source_id,\n            detections_from_sources=detections_from_sources,\n            iou_threshold=iou_threshold,\n            class_aware=class_aware,\n            required_votes=required_votes,\n            confidence=confidence,\n            detections_merge_confidence_aggregation=detections_merge_confidence_aggregation,\n            detections_merge_coordinates_aggregation=detections_merge_coordinates_aggregation,\n            detections_already_considered=detections_already_considered,\n        )\n        consensus_detections += consensus_detections_update\n    consensus_detections = sv.Detections.merge(consensus_detections)\n    (\n        object_present,\n        presence_confidence,\n    ) = check_objects_presence_in_consensus_detections(\n        consensus_detections=consensus_detections,\n        aggregation_mode=presence_confidence_aggregation,\n        class_aware=class_aware,\n        required_objects=required_objects,\n    )\n    return (\n        parent_id,\n        object_present,\n        presence_confidence,\n        consensus_detections,\n    )\n\n\ndef get_consensus_for_single_detection(\n    detection: sv.Detections,\n    source_id: int,\n    detections_from_sources: List[sv.Detections],\n    iou_threshold: float,\n    class_aware: bool,\n    required_votes: int,\n    confidence: float,\n    detections_merge_confidence_aggregation: AggregationMode,\n    detections_merge_coordinates_aggregation: AggregationMode,\n    detections_already_considered: Set[str],\n) -> Tuple[List[sv.Detections], Set[str]]:\n    if detection and detection[\"detection_id\"][0] in detections_already_considered:\n        return [], detections_already_considered\n    consensus_detections = []\n    detections_with_max_overlap = (\n        get_detections_from_different_sources_with_max_overlap(\n            detection=detection,\n            source=source_id,\n            detections_from_sources=detections_from_sources,\n            iou_threshold=iou_threshold,\n            class_aware=class_aware,\n            detections_already_considered=detections_already_considered,\n        )\n    )\n\n    if len(detections_with_max_overlap) < (required_votes - 1):\n        # Returning empty sv.Detections\n        return consensus_detections, detections_already_considered\n    detections_to_merge = sv.Detections.merge(\n        [detection]\n        + [matched_value[0] for matched_value in detections_with_max_overlap.values()]\n    )\n    merged_detection = merge_detections(\n        detections=detections_to_merge,\n        confidence_aggregation_mode=detections_merge_confidence_aggregation,\n        boxes_aggregation_mode=detections_merge_coordinates_aggregation,\n    )\n    if merged_detection.confidence[0] < confidence:\n        # Returning empty sv.Detections\n        return consensus_detections, detections_already_considered\n    consensus_detections.append(merged_detection)\n    detections_already_considered.add(detection[DETECTION_ID_KEY][0])\n    for matched_value in detections_with_max_overlap.values():\n        detections_already_considered.add(matched_value[0][DETECTION_ID_KEY][0])\n    return consensus_detections, detections_already_considered\n\n\ndef check_objects_presence_in_consensus_detections(\n    consensus_detections: sv.Detections,\n    class_aware: bool,\n    aggregation_mode: AggregationMode,\n    required_objects: Optional[Union[int, Dict[str, int]]],\n) -> Tuple[bool, Dict[str, float]]:\n    if not consensus_detections:\n        return False, {}\n    if required_objects is None:\n        required_objects = 0\n    if isinstance(required_objects, dict) and not class_aware:\n        required_objects = sum(required_objects.values())\n    if (\n        isinstance(required_objects, int)\n        and len(consensus_detections) < required_objects\n    ):\n        return False, {}\n    if not class_aware:\n        aggregated_confidence = aggregate_field_values(\n            detections=consensus_detections,\n            field=\"confidence\",\n            aggregation_mode=aggregation_mode,\n        )\n        return True, {\"any_object\": aggregated_confidence}\n    class2detections = {}\n    for class_name in set(consensus_detections[\"class_name\"]):\n        class2detections[class_name] = consensus_detections[\n            consensus_detections[\"class_name\"] == class_name\n        ]\n    if isinstance(required_objects, dict):\n        for requested_class, required_objects_count in required_objects.items():\n            if (\n                requested_class not in class2detections\n                or len(class2detections[requested_class]) < required_objects_count\n            ):\n                return False, {}\n    class2confidence = {\n        class_name: aggregate_field_values(\n            detections=class_detections,\n            field=\"confidence\",\n            aggregation_mode=aggregation_mode,\n        )\n        for class_name, class_detections in class2detections.items()\n    }\n    return True, class2confidence\n\n\ndef merge_detections(\n    detections: sv.Detections,\n    confidence_aggregation_mode: AggregationMode,\n    boxes_aggregation_mode: AggregationMode,\n) -> sv.Detections:\n    class_name, class_id = AGGREGATION_MODE2CLASS_SELECTOR[confidence_aggregation_mode](\n        detections\n    )\n    x1, y1, x2, y2 = AGGREGATION_MODE2BOXES_AGGREGATOR[boxes_aggregation_mode](\n        detections\n    )\n    data = {\n        \"class_name\": np.array([class_name]),\n        PARENT_ID_KEY: np.array([detections[PARENT_ID_KEY][0]]),\n        DETECTION_ID_KEY: np.array([str(uuid4())]),\n        PREDICTION_TYPE_KEY: np.array([\"object-detection\"]),\n        PARENT_COORDINATES_KEY: np.array([detections[PARENT_COORDINATES_KEY][0]]),\n        PARENT_DIMENSIONS_KEY: np.array([detections[PARENT_DIMENSIONS_KEY][0]]),\n        ROOT_PARENT_ID_KEY: np.array([detections[ROOT_PARENT_ID_KEY][0]]),\n        ROOT_PARENT_COORDINATES_KEY: np.array(\n            [detections[ROOT_PARENT_COORDINATES_KEY][0]]\n        ),\n        ROOT_PARENT_DIMENSIONS_KEY: np.array(\n            [detections[ROOT_PARENT_DIMENSIONS_KEY][0]]\n        ),\n        IMAGE_DIMENSIONS_KEY: np.array([detections[IMAGE_DIMENSIONS_KEY][0]]),\n    }\n    if SCALING_RELATIVE_TO_PARENT_KEY in detections.data:\n        data[SCALING_RELATIVE_TO_PARENT_KEY] = np.array(\n            [detections[SCALING_RELATIVE_TO_PARENT_KEY][0]]\n        )\n    else:\n        data[SCALING_RELATIVE_TO_PARENT_KEY] = np.array([1.0])\n    if SCALING_RELATIVE_TO_ROOT_PARENT_KEY in detections.data:\n        data[SCALING_RELATIVE_TO_ROOT_PARENT_KEY] = np.array(\n            [detections[SCALING_RELATIVE_TO_ROOT_PARENT_KEY][0]]\n        )\n    else:\n        data[SCALING_RELATIVE_TO_ROOT_PARENT_KEY] = np.array([1.0])\n    return sv.Detections(\n        xyxy=np.array([[x1, y1, x2, y2]], dtype=np.float64),\n        class_id=np.array([class_id]),\n        confidence=np.array(\n            [\n                aggregate_field_values(\n                    detections=detections,\n                    field=\"confidence\",\n                    aggregation_mode=confidence_aggregation_mode,\n                )\n            ],\n            dtype=np.float64,\n        ),\n        data=data,\n    )\n\n\ndef get_majority_class(detections: sv.Detections) -> Tuple[str, int]:\n    class_counts = Counter(\n        [\n            (str(class_name), int(class_id))\n            for class_name, class_id in zip(\n                detections[\"class_name\"], detections.class_id\n            )\n        ]\n    )\n    return class_counts.most_common(1)[0][0]\n\n\ndef get_class_of_most_confident_detection(detections: sv.Detections) -> Tuple[str, int]:\n    confidences: List[float] = detections.confidence.astype(float).tolist()\n    max_confidence_index = confidences.index(max(confidences))\n    max_confidence_detection = detections[max_confidence_index]\n    return (\n        max_confidence_detection[\"class_name\"][0],\n        max_confidence_detection.class_id[0],\n    )\n\n\ndef get_class_of_least_confident_detection(\n    detections: sv.Detections,\n) -> Tuple[str, int]:\n    confidences: List[float] = detections.confidence.astype(float).tolist()\n    min_confidence_index = confidences.index(min(confidences))\n    min_confidence_detection = detections[min_confidence_index]\n    return (\n        min_confidence_detection[\"class_name\"][0],\n        min_confidence_detection.class_id[0],\n    )\n\n\nAGGREGATION_MODE2CLASS_SELECTOR = {\n    AggregationMode.MAX: get_class_of_most_confident_detection,\n    AggregationMode.MIN: get_class_of_least_confident_detection,\n    AggregationMode.AVERAGE: get_majority_class,\n}\n\n\ndef get_average_bounding_box(detections: sv.Detections) -> Tuple[int, int, int, int]:\n    if len(detections) == 0:\n        return (0.0, 0.0, 0.0, 0.0)\n\n    avg_xyxy = np.mean(detections.xyxy, axis=0)\n    return tuple(avg_xyxy)\n\n\ndef get_smallest_bounding_box(detections: sv.Detections) -> Tuple[int, int, int, int]:\n    areas: List[float] = detections.area.astype(float).tolist()\n    min_area = min(areas)\n    min_area_index = areas.index(min_area)\n    return tuple(detections[min_area_index].xyxy[0])\n\n\ndef get_largest_bounding_box(detections: sv.Detections) -> Tuple[int, int, int, int]:\n    areas: List[float] = detections.area.astype(float).tolist()\n    max_area = max(areas)\n    max_area_index = areas.index(max_area)\n    return tuple(detections[max_area_index].xyxy[0])\n\n\nAGGREGATION_MODE2BOXES_AGGREGATOR = {\n    AggregationMode.MAX: get_largest_bounding_box,\n    AggregationMode.MIN: get_smallest_bounding_box,\n    AggregationMode.AVERAGE: get_average_bounding_box,\n}\n\nAGGREGATION_MODE2FIELD_AGGREGATOR = {\n    AggregationMode.MAX: max,\n    AggregationMode.MIN: min,\n    AggregationMode.AVERAGE: statistics.mean,\n}\n\n\ndef aggregate_field_values(\n    detections: sv.Detections,\n    field: str,\n    aggregation_mode: AggregationMode = AggregationMode.AVERAGE,\n) -> float:\n    values = []\n    if hasattr(detections, field):\n        values = getattr(detections, field)\n        if isinstance(values, np.ndarray):\n            values = values.astype(float).tolist()\n    elif hasattr(detections, \"data\") and field in detections.data:\n        values = detections[field]\n        if isinstance(values, np.ndarray):\n            values = values.astype(float).tolist()\n    return AGGREGATION_MODE2FIELD_AGGREGATOR[aggregation_mode](values)\n",
    "optimized_raw_markdown": "",
    "optimized_function_only": "def get_average_bounding_box(detections: sv.Detections) -> Tuple[int, int, int, int]:\n    if len(detections) == 0:\n        return (0.0, 0.0, 0.0, 0.0)\n\n    avg_xyxy = np.mean(detections.xyxy, axis=0)\n    return tuple(avg_xyxy)\n",
    "original_file_content": "import math\nimport statistics\nfrom collections import Counter\nfrom enum import Enum\nfrom typing import Dict, Generator, List, Literal, Optional, Set, Tuple, Type, Union\nfrom uuid import uuid4\n\nimport numpy as np\nimport supervision as sv\nfrom pydantic import AliasChoices, ConfigDict, Field, PositiveInt\n\nfrom inference.core.workflows.execution_engine.constants import (\n    DETECTION_ID_KEY,\n    IMAGE_DIMENSIONS_KEY,\n    PARENT_COORDINATES_KEY,\n    PARENT_DIMENSIONS_KEY,\n    PARENT_ID_KEY,\n    PREDICTION_TYPE_KEY,\n    ROOT_PARENT_COORDINATES_KEY,\n    ROOT_PARENT_DIMENSIONS_KEY,\n    ROOT_PARENT_ID_KEY,\n    SCALING_RELATIVE_TO_PARENT_KEY,\n    SCALING_RELATIVE_TO_ROOT_PARENT_KEY,\n)\nfrom inference.core.workflows.execution_engine.entities.base import (\n    Batch,\n    OutputDefinition,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    BOOLEAN_KIND,\n    DICTIONARY_KIND,\n    FLOAT_ZERO_TO_ONE_KIND,\n    INSTANCE_SEGMENTATION_PREDICTION_KIND,\n    INTEGER_KIND,\n    KEYPOINT_DETECTION_PREDICTION_KIND,\n    LIST_OF_VALUES_KIND,\n    OBJECT_DETECTION_PREDICTION_KIND,\n    FloatZeroToOne,\n    Selector,\n)\nfrom inference.core.workflows.prototypes.block import (\n    BlockResult,\n    WorkflowBlock,\n    WorkflowBlockManifest,\n)\n\n\nclass AggregationMode(Enum):\n    AVERAGE = \"average\"\n    MAX = \"max\"\n    MIN = \"min\"\n\n\nLONG_DESCRIPTION = \"\"\"\nCombine detections from multiple detection-based models based on a majority vote \nstrategy.\n\nThis block is useful if you have multiple specialized models that you want to consult \nto determine whether a certain object is present in an image.\n\nSee the table below to explore the values you can use to configure the consensus block.\n\"\"\"\n\nSHORT_DESCRIPTION = (\n    \"Combine predictions from multiple detections models to make a \"\n    \"decision about object presence.\"\n)\n\n\nclass BlockManifest(WorkflowBlockManifest):\n    model_config = ConfigDict(\n        json_schema_extra={\n            \"name\": \"Detections Consensus\",\n            \"version\": \"v1\",\n            \"short_description\": SHORT_DESCRIPTION,\n            \"long_description\": LONG_DESCRIPTION,\n            \"license\": \"Apache-2.0\",\n            \"block_type\": \"fusion\",\n            \"ui_manifest\": {\n                \"section\": \"flow_control\",\n                \"icon\": \"fak fa-circles-overlap\",\n                \"blockPriority\": 4,\n            },\n        }\n    )\n    type: Literal[\"roboflow_core/detections_consensus@v1\", \"DetectionsConsensus\"]\n    predictions_batches: List[\n        Selector(\n            kind=[\n                OBJECT_DETECTION_PREDICTION_KIND,\n                INSTANCE_SEGMENTATION_PREDICTION_KIND,\n                KEYPOINT_DETECTION_PREDICTION_KIND,\n            ]\n        ),\n    ] = Field(\n        min_items=1,\n        description=\"Reference to detection-like model predictions made against single image to agree on model consensus\",\n        examples=[[\"$steps.a.predictions\", \"$steps.b.predictions\"]],\n        validation_alias=AliasChoices(\"predictions_batches\", \"predictions\"),\n    )\n    required_votes: Union[PositiveInt, Selector(kind=[INTEGER_KIND])] = Field(\n        description=\"Required number of votes for single detection from different models to accept detection as output detection\",\n        examples=[2, \"$inputs.required_votes\"],\n    )\n    class_aware: Union[bool, Selector(kind=[BOOLEAN_KIND])] = Field(\n        default=True,\n        description=\"Flag to decide if merging detections is class-aware or only bounding boxes aware\",\n        examples=[True, \"$inputs.class_aware\"],\n    )\n    iou_threshold: Union[FloatZeroToOne, Selector(kind=[FLOAT_ZERO_TO_ONE_KIND])] = (\n        Field(\n            default=0.3,\n            description=\"IoU threshold to consider detections from different models as matching (increasing votes for region)\",\n            examples=[0.3, \"$inputs.iou_threshold\"],\n        )\n    )\n    confidence: Union[FloatZeroToOne, Selector(kind=[FLOAT_ZERO_TO_ONE_KIND])] = Field(\n        default=0.0,\n        description=\"Confidence threshold for merged detections\",\n        examples=[0.1, \"$inputs.confidence\"],\n    )\n    classes_to_consider: Optional[\n        Union[List[str], Selector(kind=[LIST_OF_VALUES_KIND])]\n    ] = Field(\n        default=None,\n        description=\"Optional list of classes to consider in consensus procedure.\",\n        examples=[[\"a\", \"b\"], \"$inputs.classes_to_consider\"],\n    )\n    required_objects: Optional[\n        Union[\n            PositiveInt,\n            Dict[str, PositiveInt],\n            Selector(kind=[INTEGER_KIND, DICTIONARY_KIND]),\n        ]\n    ] = Field(\n        default=None,\n        description=\"If given, it holds the number of objects that must be present in merged results, to assume that object presence is reached. Can be selector to `InferenceParameter`, integer value or dictionary with mapping of class name into minimal number of merged detections of given class to assume consensus.\",\n        examples=[3, {\"a\": 7, \"b\": 2}, \"$inputs.required_objects\"],\n    )\n    presence_confidence_aggregation: AggregationMode = Field(\n        default=AggregationMode.MAX,\n        description=\"Mode dictating aggregation of confidence scores and classes both in case of object presence deduction procedure.\",\n        examples=[\"max\", \"min\"],\n    )\n    detections_merge_confidence_aggregation: AggregationMode = Field(\n        default=AggregationMode.AVERAGE,\n        description=\"Mode dictating aggregation of confidence scores and classes both in case of boxes consensus procedure. One of `average`, `max`, `min`. Default: `average`. While using for merging overlapping boxes, against classes - `average` equals to majority vote, `max` - for the class of detection with max confidence, `min` - for the class of detection with min confidence.\",\n        examples=[\"min\", \"max\"],\n    )\n    detections_merge_coordinates_aggregation: AggregationMode = Field(\n        default=AggregationMode.AVERAGE,\n        description=\"Mode dictating aggregation of bounding boxes. One of `average`, `max`, `min`. Default: `average`. `average` means taking mean from all boxes coordinates, `min` - taking smallest box, `max` - taking largest box.\",\n        examples=[\"min\", \"max\"],\n    )\n\n    @classmethod\n    def get_parameters_accepting_batches(cls) -> List[str]:\n        return [\"predictions_batches\"]\n\n    @classmethod\n    def describe_outputs(cls) -> List[OutputDefinition]:\n        return [\n            OutputDefinition(\n                name=\"predictions\",\n                kind=[OBJECT_DETECTION_PREDICTION_KIND],\n            ),\n            OutputDefinition(\n                name=\"object_present\", kind=[BOOLEAN_KIND, DICTIONARY_KIND]\n            ),\n            OutputDefinition(\n                name=\"presence_confidence\",\n                kind=[FLOAT_ZERO_TO_ONE_KIND, DICTIONARY_KIND],\n            ),\n        ]\n\n    @classmethod\n    def get_execution_engine_compatibility(cls) -> Optional[str]:\n        return \">=1.3.0,<2.0.0\"\n\n\nclass DetectionsConsensusBlockV1(WorkflowBlock):\n    @classmethod\n    def get_manifest(cls) -> Type[WorkflowBlockManifest]:\n        return BlockManifest\n\n    def run(\n        self,\n        predictions_batches: List[Batch[sv.Detections]],\n        required_votes: int,\n        class_aware: bool,\n        iou_threshold: float,\n        confidence: float,\n        classes_to_consider: Optional[List[str]],\n        required_objects: Optional[Union[int, Dict[str, int]]],\n        presence_confidence_aggregation: AggregationMode,\n        detections_merge_confidence_aggregation: AggregationMode,\n        detections_merge_coordinates_aggregation: AggregationMode,\n    ) -> BlockResult:\n        if len(predictions_batches) < 1:\n            raise ValueError(\n                f\"Consensus step requires at least one source of predictions.\"\n            )\n        results = []\n        for detections_from_sources in zip(*predictions_batches):\n            (\n                parent_id,\n                object_present,\n                presence_confidence,\n                consensus_detections,\n            ) = agree_on_consensus_for_all_detections_sources(\n                detections_from_sources=list(detections_from_sources),\n                required_votes=required_votes,\n                class_aware=class_aware,\n                iou_threshold=iou_threshold,\n                confidence=confidence,\n                classes_to_consider=classes_to_consider,\n                required_objects=required_objects,\n                presence_confidence_aggregation=presence_confidence_aggregation,\n                detections_merge_confidence_aggregation=detections_merge_confidence_aggregation,\n                detections_merge_coordinates_aggregation=detections_merge_coordinates_aggregation,\n            )\n            results.append(\n                {\n                    \"predictions\": consensus_detections,\n                    \"object_present\": object_present,\n                    \"presence_confidence\": presence_confidence,\n                }\n            )\n        return results\n\n\ndef does_not_detect_objects_in_any_source(\n    detections_from_sources: List[sv.Detections],\n) -> bool:\n    return all(len(p) == 0 for p in detections_from_sources)\n\n\ndef get_parent_id_of_detections_from_sources(\n    detections_from_sources: List[sv.Detections],\n) -> str:\n    encountered_parent_ids = set(\n        np.concatenate(\n            [\n                detections[PARENT_ID_KEY]\n                for detections in detections_from_sources\n                if PARENT_ID_KEY in detections.data\n            ]\n        ).tolist()\n    )\n    if len(encountered_parent_ids) != 1:\n        raise ValueError(\n            \"Missmatch in predictions - while executing consensus step, \"\n            \"in equivalent batches, detections are assigned different parent \"\n            \"identifiers, whereas consensus can only be applied for predictions \"\n            \"made against the same input.\"\n        )\n    return next(iter(encountered_parent_ids))\n\n\ndef filter_predictions(\n    predictions: List[sv.Detections],\n    classes_to_consider: Optional[List[str]],\n) -> List[sv.Detections]:\n    if not classes_to_consider:\n        return predictions\n    return [\n        detections[np.isin(detections[\"class_name\"], classes_to_consider)]\n        for detections in predictions\n        if \"class_name\" in detections.data\n    ]\n\n\ndef get_detections_from_different_sources_with_max_overlap(\n    detection: sv.Detections,\n    source: int,\n    detections_from_sources: List[sv.Detections],\n    iou_threshold: float,\n    class_aware: bool,\n    detections_already_considered: Set[str],\n) -> Dict[int, Tuple[sv.Detections, float]]:\n    current_max_overlap = {}\n    for other_source, other_detection in enumerate_detections(\n        detections_from_sources=detections_from_sources,\n        excluded_source_id=source,\n    ):\n        if other_detection[DETECTION_ID_KEY][0] in detections_already_considered:\n            continue\n        if (\n            class_aware\n            and detection[\"class_name\"][0] != other_detection[\"class_name\"][0]\n        ):\n            continue\n        iou_value = calculate_iou(\n            detection_a=detection,\n            detection_b=other_detection,\n        )\n        if iou_value <= iou_threshold:\n            continue\n        if current_max_overlap.get(other_source) is None:\n            current_max_overlap[other_source] = (other_detection, iou_value)\n        if current_max_overlap[other_source][1] < iou_value:\n            current_max_overlap[other_source] = (other_detection, iou_value)\n    return current_max_overlap\n\n\ndef enumerate_detections(\n    detections_from_sources: List[sv.Detections],\n    excluded_source_id: Optional[int] = None,\n) -> Generator[Tuple[int, sv.Detections], None, None]:\n    for source_id, detections in enumerate(detections_from_sources):\n        if excluded_source_id == source_id:\n            continue\n        for i in range(len(detections)):\n            yield source_id, detections[i]\n\n\ndef calculate_iou(detection_a: sv.Detections, detection_b: sv.Detections) -> float:\n    iou = float(sv.box_iou_batch(detection_a.xyxy, detection_b.xyxy)[0][0])\n    if math.isnan(iou):\n        iou = 0\n    return iou\n\n\ndef agree_on_consensus_for_all_detections_sources(\n    detections_from_sources: List[sv.Detections],\n    required_votes: int,\n    class_aware: bool,\n    iou_threshold: float,\n    confidence: float,\n    classes_to_consider: Optional[List[str]],\n    required_objects: Optional[Union[int, Dict[str, int]]],\n    presence_confidence_aggregation: AggregationMode,\n    detections_merge_confidence_aggregation: AggregationMode,\n    detections_merge_coordinates_aggregation: AggregationMode,\n) -> Tuple[str, bool, Dict[str, float], sv.Detections]:\n    if does_not_detect_objects_in_any_source(\n        detections_from_sources=detections_from_sources\n    ):\n        return \"undefined\", False, {}, sv.Detections.empty()\n    parent_id = get_parent_id_of_detections_from_sources(\n        detections_from_sources=detections_from_sources,\n    )\n    detections_from_sources = filter_predictions(\n        predictions=detections_from_sources,\n        classes_to_consider=classes_to_consider,\n    )\n    detections_already_considered = set()\n    consensus_detections = []\n    for source_id, detection in enumerate_detections(\n        detections_from_sources=detections_from_sources\n    ):\n        (\n            consensus_detections_update,\n            detections_already_considered,\n        ) = get_consensus_for_single_detection(\n            detection=detection,\n            source_id=source_id,\n            detections_from_sources=detections_from_sources,\n            iou_threshold=iou_threshold,\n            class_aware=class_aware,\n            required_votes=required_votes,\n            confidence=confidence,\n            detections_merge_confidence_aggregation=detections_merge_confidence_aggregation,\n            detections_merge_coordinates_aggregation=detections_merge_coordinates_aggregation,\n            detections_already_considered=detections_already_considered,\n        )\n        consensus_detections += consensus_detections_update\n    consensus_detections = sv.Detections.merge(consensus_detections)\n    (\n        object_present,\n        presence_confidence,\n    ) = check_objects_presence_in_consensus_detections(\n        consensus_detections=consensus_detections,\n        aggregation_mode=presence_confidence_aggregation,\n        class_aware=class_aware,\n        required_objects=required_objects,\n    )\n    return (\n        parent_id,\n        object_present,\n        presence_confidence,\n        consensus_detections,\n    )\n\n\ndef get_consensus_for_single_detection(\n    detection: sv.Detections,\n    source_id: int,\n    detections_from_sources: List[sv.Detections],\n    iou_threshold: float,\n    class_aware: bool,\n    required_votes: int,\n    confidence: float,\n    detections_merge_confidence_aggregation: AggregationMode,\n    detections_merge_coordinates_aggregation: AggregationMode,\n    detections_already_considered: Set[str],\n) -> Tuple[List[sv.Detections], Set[str]]:\n    if detection and detection[\"detection_id\"][0] in detections_already_considered:\n        return [], detections_already_considered\n    consensus_detections = []\n    detections_with_max_overlap = (\n        get_detections_from_different_sources_with_max_overlap(\n            detection=detection,\n            source=source_id,\n            detections_from_sources=detections_from_sources,\n            iou_threshold=iou_threshold,\n            class_aware=class_aware,\n            detections_already_considered=detections_already_considered,\n        )\n    )\n\n    if len(detections_with_max_overlap) < (required_votes - 1):\n        # Returning empty sv.Detections\n        return consensus_detections, detections_already_considered\n    detections_to_merge = sv.Detections.merge(\n        [detection]\n        + [matched_value[0] for matched_value in detections_with_max_overlap.values()]\n    )\n    merged_detection = merge_detections(\n        detections=detections_to_merge,\n        confidence_aggregation_mode=detections_merge_confidence_aggregation,\n        boxes_aggregation_mode=detections_merge_coordinates_aggregation,\n    )\n    if merged_detection.confidence[0] < confidence:\n        # Returning empty sv.Detections\n        return consensus_detections, detections_already_considered\n    consensus_detections.append(merged_detection)\n    detections_already_considered.add(detection[DETECTION_ID_KEY][0])\n    for matched_value in detections_with_max_overlap.values():\n        detections_already_considered.add(matched_value[0][DETECTION_ID_KEY][0])\n    return consensus_detections, detections_already_considered\n\n\ndef check_objects_presence_in_consensus_detections(\n    consensus_detections: sv.Detections,\n    class_aware: bool,\n    aggregation_mode: AggregationMode,\n    required_objects: Optional[Union[int, Dict[str, int]]],\n) -> Tuple[bool, Dict[str, float]]:\n    if not consensus_detections:\n        return False, {}\n    if required_objects is None:\n        required_objects = 0\n    if isinstance(required_objects, dict) and not class_aware:\n        required_objects = sum(required_objects.values())\n    if (\n        isinstance(required_objects, int)\n        and len(consensus_detections) < required_objects\n    ):\n        return False, {}\n    if not class_aware:\n        aggregated_confidence = aggregate_field_values(\n            detections=consensus_detections,\n            field=\"confidence\",\n            aggregation_mode=aggregation_mode,\n        )\n        return True, {\"any_object\": aggregated_confidence}\n    class2detections = {}\n    for class_name in set(consensus_detections[\"class_name\"]):\n        class2detections[class_name] = consensus_detections[\n            consensus_detections[\"class_name\"] == class_name\n        ]\n    if isinstance(required_objects, dict):\n        for requested_class, required_objects_count in required_objects.items():\n            if (\n                requested_class not in class2detections\n                or len(class2detections[requested_class]) < required_objects_count\n            ):\n                return False, {}\n    class2confidence = {\n        class_name: aggregate_field_values(\n            detections=class_detections,\n            field=\"confidence\",\n            aggregation_mode=aggregation_mode,\n        )\n        for class_name, class_detections in class2detections.items()\n    }\n    return True, class2confidence\n\n\ndef merge_detections(\n    detections: sv.Detections,\n    confidence_aggregation_mode: AggregationMode,\n    boxes_aggregation_mode: AggregationMode,\n) -> sv.Detections:\n    class_name, class_id = AGGREGATION_MODE2CLASS_SELECTOR[confidence_aggregation_mode](\n        detections\n    )\n    x1, y1, x2, y2 = AGGREGATION_MODE2BOXES_AGGREGATOR[boxes_aggregation_mode](\n        detections\n    )\n    data = {\n        \"class_name\": np.array([class_name]),\n        PARENT_ID_KEY: np.array([detections[PARENT_ID_KEY][0]]),\n        DETECTION_ID_KEY: np.array([str(uuid4())]),\n        PREDICTION_TYPE_KEY: np.array([\"object-detection\"]),\n        PARENT_COORDINATES_KEY: np.array([detections[PARENT_COORDINATES_KEY][0]]),\n        PARENT_DIMENSIONS_KEY: np.array([detections[PARENT_DIMENSIONS_KEY][0]]),\n        ROOT_PARENT_ID_KEY: np.array([detections[ROOT_PARENT_ID_KEY][0]]),\n        ROOT_PARENT_COORDINATES_KEY: np.array(\n            [detections[ROOT_PARENT_COORDINATES_KEY][0]]\n        ),\n        ROOT_PARENT_DIMENSIONS_KEY: np.array(\n            [detections[ROOT_PARENT_DIMENSIONS_KEY][0]]\n        ),\n        IMAGE_DIMENSIONS_KEY: np.array([detections[IMAGE_DIMENSIONS_KEY][0]]),\n    }\n    if SCALING_RELATIVE_TO_PARENT_KEY in detections.data:\n        data[SCALING_RELATIVE_TO_PARENT_KEY] = np.array(\n            [detections[SCALING_RELATIVE_TO_PARENT_KEY][0]]\n        )\n    else:\n        data[SCALING_RELATIVE_TO_PARENT_KEY] = np.array([1.0])\n    if SCALING_RELATIVE_TO_ROOT_PARENT_KEY in detections.data:\n        data[SCALING_RELATIVE_TO_ROOT_PARENT_KEY] = np.array(\n            [detections[SCALING_RELATIVE_TO_ROOT_PARENT_KEY][0]]\n        )\n    else:\n        data[SCALING_RELATIVE_TO_ROOT_PARENT_KEY] = np.array([1.0])\n    return sv.Detections(\n        xyxy=np.array([[x1, y1, x2, y2]], dtype=np.float64),\n        class_id=np.array([class_id]),\n        confidence=np.array(\n            [\n                aggregate_field_values(\n                    detections=detections,\n                    field=\"confidence\",\n                    aggregation_mode=confidence_aggregation_mode,\n                )\n            ],\n            dtype=np.float64,\n        ),\n        data=data,\n    )\n\n\ndef get_majority_class(detections: sv.Detections) -> Tuple[str, int]:\n    class_counts = Counter(\n        [\n            (str(class_name), int(class_id))\n            for class_name, class_id in zip(\n                detections[\"class_name\"], detections.class_id\n            )\n        ]\n    )\n    return class_counts.most_common(1)[0][0]\n\n\ndef get_class_of_most_confident_detection(detections: sv.Detections) -> Tuple[str, int]:\n    confidences: List[float] = detections.confidence.astype(float).tolist()\n    max_confidence_index = confidences.index(max(confidences))\n    max_confidence_detection = detections[max_confidence_index]\n    return (\n        max_confidence_detection[\"class_name\"][0],\n        max_confidence_detection.class_id[0],\n    )\n\n\ndef get_class_of_least_confident_detection(\n    detections: sv.Detections,\n) -> Tuple[str, int]:\n    confidences: List[float] = detections.confidence.astype(float).tolist()\n    min_confidence_index = confidences.index(min(confidences))\n    min_confidence_detection = detections[min_confidence_index]\n    return (\n        min_confidence_detection[\"class_name\"][0],\n        min_confidence_detection.class_id[0],\n    )\n\n\nAGGREGATION_MODE2CLASS_SELECTOR = {\n    AggregationMode.MAX: get_class_of_most_confident_detection,\n    AggregationMode.MIN: get_class_of_least_confident_detection,\n    AggregationMode.AVERAGE: get_majority_class,\n}\n\n\ndef get_average_bounding_box(detections: sv.Detections) -> Tuple[int, int, int, int]:\n    avg_xyxy: np.ndarray = sum(detections.xyxy) / len(detections)\n    return tuple(avg_xyxy.astype(float))\n\n\ndef get_smallest_bounding_box(detections: sv.Detections) -> Tuple[int, int, int, int]:\n    areas: List[float] = detections.area.astype(float).tolist()\n    min_area = min(areas)\n    min_area_index = areas.index(min_area)\n    return tuple(detections[min_area_index].xyxy[0])\n\n\ndef get_largest_bounding_box(detections: sv.Detections) -> Tuple[int, int, int, int]:\n    areas: List[float] = detections.area.astype(float).tolist()\n    max_area = max(areas)\n    max_area_index = areas.index(max_area)\n    return tuple(detections[max_area_index].xyxy[0])\n\n\nAGGREGATION_MODE2BOXES_AGGREGATOR = {\n    AggregationMode.MAX: get_largest_bounding_box,\n    AggregationMode.MIN: get_smallest_bounding_box,\n    AggregationMode.AVERAGE: get_average_bounding_box,\n}\n\nAGGREGATION_MODE2FIELD_AGGREGATOR = {\n    AggregationMode.MAX: max,\n    AggregationMode.MIN: min,\n    AggregationMode.AVERAGE: statistics.mean,\n}\n\n\ndef aggregate_field_values(\n    detections: sv.Detections,\n    field: str,\n    aggregation_mode: AggregationMode = AggregationMode.AVERAGE,\n) -> float:\n    values = []\n    if hasattr(detections, field):\n        values = getattr(detections, field)\n        if isinstance(values, np.ndarray):\n            values = values.astype(float).tolist()\n    elif hasattr(detections, \"data\") and field in detections.data:\n        values = detections[field]\n        if isinstance(values, np.ndarray):\n            values = values.astype(float).tolist()\n    return AGGREGATION_MODE2FIELD_AGGREGATOR[aggregation_mode](values)\n",
    "patch": "diff --git a/inference/core/workflows/core_steps/fusion/detections_consensus/v1.py b/inference/core/workflows/core_steps/fusion/detections_consensus/v1.py\nindex 1d2089aa1..9ef1ee8f4 100644\n--- a/inference/core/workflows/core_steps/fusion/detections_consensus/v1.py\n+++ b/inference/core/workflows/core_steps/fusion/detections_consensus/v1.py\n@@ -576,8 +576,11 @@ AGGREGATION_MODE2CLASS_SELECTOR = {\n \n \n def get_average_bounding_box(detections: sv.Detections) -> Tuple[int, int, int, int]:\n-    avg_xyxy: np.ndarray = sum(detections.xyxy) / len(detections)\n-    return tuple(avg_xyxy.astype(float))\n+    if len(detections) == 0:\n+        return (0.0, 0.0, 0.0, 0.0)\n+\n+    avg_xyxy = np.mean(detections.xyxy, axis=0)\n+    return tuple(avg_xyxy)\n \n \n def get_smallest_bounding_box(detections: sv.Detections) -> Tuple[int, int, int, int]:\n"
  },
  {
    "trace_id": "git_cab7bd9dfa29",
    "function_name": "collect_func_params",
    "file_path": "inference/usage_tracking/utils.py",
    "speedup_x": 3.92,
    "review_quality": null,
    "pre_optimization_commit": "326999fd4355e9ee816e8f257ca3312bd833e5f0",
    "resolution_method": "git_parent",
    "source": "git",
    "original_function_code": "def collect_func_params(\n    func: Callable[[Any], Any], args: Iterable[Any], kwargs: Dict[Any, Any]\n) -> Dict[str, Any]:\n    signature = inspect.signature(func)\n\n    params = {}\n    if args:\n        for param, arg_value in zip(signature.parameters.keys(), args):\n            params[param] = arg_value\n    if kwargs:\n        params = {**params, **kwargs}\n    defaults = set(signature.parameters.keys()).difference(set(params.keys()))\n    for default_arg in defaults:\n        params[default_arg] = signature.parameters[default_arg].default\n\n    signature_params = set(signature.parameters)\n    if set(params) != signature_params:\n        if \"kwargs\" in signature_params:\n            params[\"kwargs\"] = kwargs\n        if \"args\" in signature_params:\n            params[\"args\"] = args\n        if not set(params).issuperset(signature_params):\n            logger.error(\"Params mismatch for %s.%s\", func.__module__, func.__name__)\n\n    return params\n",
    "optimized_function_code": "import inspect\nfrom typing import Any, Callable, Dict, Iterable\n\nfrom inference.core.logger import logger\n\n\ndef collect_func_params(\n    func: Callable[[Any], Any], args: Iterable[Any], kwargs: Dict[Any, Any]\n) -> Dict[str, Any]:\n    signature = func.__code__.co_varnames\n    params = dict(zip(signature, args))\n\n    for param in signature[len(args) :]:\n        if param in kwargs:\n            params[param] = kwargs[param]\n\n    # Add missing parameters with default values\n    for i, param in enumerate(signature):\n        if param not in params:\n            try:\n                default_index = i - (func.__code__.co_argcount - len(func.__defaults__))\n                if default_index >= 0:\n                    params[param] = func.__defaults__[default_index]\n            except (AttributeError, TypeError):\n                # There is no default value for this parameter\n                continue\n\n    # Add *args and **kwargs if they exist in the function definition\n    if func.__code__.co_flags & 0x04:  # CO_VARARGS flag\n        params[\"args\"] = args[len(signature) :]\n    if func.__code__.co_flags & 0x08:  # CO_VARKEYWORDS flag\n        params[\"kwargs\"] = {k: v for k, v in kwargs.items() if k not in signature}\n\n    if not set(params).issuperset(signature):\n        logger.error(\"Params mismatch for %s.%s\", func.__module__, func.__name__)\n\n    return params\n",
    "optimized_raw_markdown": "",
    "optimized_function_only": "def collect_func_params(\n    func: Callable[[Any], Any], args: Iterable[Any], kwargs: Dict[Any, Any]\n) -> Dict[str, Any]:\n    signature = func.__code__.co_varnames\n    params = dict(zip(signature, args))\n\n    for param in signature[len(args) :]:\n        if param in kwargs:\n            params[param] = kwargs[param]\n\n    # Add missing parameters with default values\n    for i, param in enumerate(signature):\n        if param not in params:\n            try:\n                default_index = i - (func.__code__.co_argcount - len(func.__defaults__))\n                if default_index >= 0:\n                    params[param] = func.__defaults__[default_index]\n            except (AttributeError, TypeError):\n                # There is no default value for this parameter\n                continue\n\n    # Add *args and **kwargs if they exist in the function definition\n    if func.__code__.co_flags & 0x04:  # CO_VARARGS flag\n        params[\"args\"] = args[len(signature) :]\n    if func.__code__.co_flags & 0x08:  # CO_VARKEYWORDS flag\n        params[\"kwargs\"] = {k: v for k, v in kwargs.items() if k not in signature}\n\n    if not set(params).issuperset(signature):\n        logger.error(\"Params mismatch for %s.%s\", func.__module__, func.__name__)\n\n    return params\n",
    "original_file_content": "import inspect\nfrom typing import Any, Callable, Dict, Iterable\n\nfrom inference.core.logger import logger\n\n\ndef collect_func_params(\n    func: Callable[[Any], Any], args: Iterable[Any], kwargs: Dict[Any, Any]\n) -> Dict[str, Any]:\n    signature = inspect.signature(func)\n\n    params = {}\n    if args:\n        for param, arg_value in zip(signature.parameters.keys(), args):\n            params[param] = arg_value\n    if kwargs:\n        params = {**params, **kwargs}\n    defaults = set(signature.parameters.keys()).difference(set(params.keys()))\n    for default_arg in defaults:\n        params[default_arg] = signature.parameters[default_arg].default\n\n    signature_params = set(signature.parameters)\n    if set(params) != signature_params:\n        if \"kwargs\" in signature_params:\n            params[\"kwargs\"] = kwargs\n        if \"args\" in signature_params:\n            params[\"args\"] = args\n        if not set(params).issuperset(signature_params):\n            logger.error(\"Params mismatch for %s.%s\", func.__module__, func.__name__)\n\n    return params\n",
    "patch": "diff --git a/inference/usage_tracking/utils.py b/inference/usage_tracking/utils.py\nindex 41220e21a..58d97b360 100644\n--- a/inference/usage_tracking/utils.py\n+++ b/inference/usage_tracking/utils.py\n@@ -7,25 +7,31 @@ from inference.core.logger import logger\n def collect_func_params(\n     func: Callable[[Any], Any], args: Iterable[Any], kwargs: Dict[Any, Any]\n ) -> Dict[str, Any]:\n-    signature = inspect.signature(func)\n-\n-    params = {}\n-    if args:\n-        for param, arg_value in zip(signature.parameters.keys(), args):\n-            params[param] = arg_value\n-    if kwargs:\n-        params = {**params, **kwargs}\n-    defaults = set(signature.parameters.keys()).difference(set(params.keys()))\n-    for default_arg in defaults:\n-        params[default_arg] = signature.parameters[default_arg].default\n-\n-    signature_params = set(signature.parameters)\n-    if set(params) != signature_params:\n-        if \"kwargs\" in signature_params:\n-            params[\"kwargs\"] = kwargs\n-        if \"args\" in signature_params:\n-            params[\"args\"] = args\n-        if not set(params).issuperset(signature_params):\n-            logger.error(\"Params mismatch for %s.%s\", func.__module__, func.__name__)\n+    signature = func.__code__.co_varnames\n+    params = dict(zip(signature, args))\n+\n+    for param in signature[len(args) :]:\n+        if param in kwargs:\n+            params[param] = kwargs[param]\n+\n+    # Add missing parameters with default values\n+    for i, param in enumerate(signature):\n+        if param not in params:\n+            try:\n+                default_index = i - (func.__code__.co_argcount - len(func.__defaults__))\n+                if default_index >= 0:\n+                    params[param] = func.__defaults__[default_index]\n+            except (AttributeError, TypeError):\n+                # There is no default value for this parameter\n+                continue\n+\n+    # Add *args and **kwargs if they exist in the function definition\n+    if func.__code__.co_flags & 0x04:  # CO_VARARGS flag\n+        params[\"args\"] = args[len(signature) :]\n+    if func.__code__.co_flags & 0x08:  # CO_VARKEYWORDS flag\n+        params[\"kwargs\"] = {k: v for k, v in kwargs.items() if k not in signature}\n+\n+    if not set(params).issuperset(signature):\n+        logger.error(\"Params mismatch for %s.%s\", func.__module__, func.__name__)\n \n     return params\n"
  },
  {
    "trace_id": "git_6a764e92a196",
    "function_name": "Batch.broadcast",
    "file_path": "inference/core/workflows/execution_engine/entities/base.py",
    "speedup_x": 0.12,
    "review_quality": null,
    "pre_optimization_commit": "326999fd4355e9ee816e8f257ca3312bd833e5f0",
    "resolution_method": "git_parent",
    "source": "git",
    "original_function_code": "    def broadcast(self, n: int) -> \"Batch\":\n        if n <= 0:\n            raise ValueError(\n                f\"Broadcast to size {n} requested which is invalid operation.\"\n            )\n        if len(self._content) == n:\n            return self\n        if len(self._content) == 1:\n            return Batch(content=[self._content[0]] * n, indices=[self._indices[0]] * n)\n        raise ValueError(\n            f\"Could not broadcast batch of size {len(self._content)} to size {n}\"\n        )\n",
    "optimized_function_code": "import base64\nfrom copy import copy\nfrom dataclasses import dataclass, replace\nfrom datetime import datetime\nfrom enum import Enum\nfrom typing import (\n    Any,\n    Dict,\n    Generic,\n    Iterator,\n    List,\n    Optional,\n    Set,\n    Tuple,\n    TypeVar,\n    Union,\n)\n\nimport cv2\nimport numpy as np\nfrom pydantic import BaseModel, Field\nfrom typing_extensions import Annotated, Literal\n\nfrom inference.core.utils.image_utils import (\n    attempt_loading_image_from_string,\n    encode_image_to_jpeg_bytes,\n    load_image_from_url,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    IMAGE_KIND,\n    VIDEO_METADATA_KIND,\n    WILDCARD_KIND,\n    Kind,\n)\n\n\nclass OutputDefinition(BaseModel):\n    name: str\n    kind: List[Kind] = Field(default_factory=lambda: [WILDCARD_KIND])\n\n\nclass CoordinatesSystem(Enum):\n    OWN = \"own\"\n    PARENT = \"parent\"\n\n\nclass JsonField(BaseModel):\n    type: Literal[\"JsonField\"]\n    name: str\n    selector: str\n    coordinates_system: CoordinatesSystem = Field(default=CoordinatesSystem.PARENT)\n\n    def get_type(self) -> str:\n        return self.type\n\n\nclass WorkflowInput(BaseModel):\n    type: str\n    name: str\n    kind: List[Union[str, Kind]]\n    dimensionality: int\n\n    @classmethod\n    def is_batch_oriented(cls) -> bool:\n        return False\n\n\nclass WorkflowImage(WorkflowInput):\n    type: Literal[\"WorkflowImage\", \"InferenceImage\"]\n    name: str\n    kind: List[Union[str, Kind]] = Field(default=[IMAGE_KIND])\n    dimensionality: int = Field(default=1, ge=1, le=1)\n\n    @classmethod\n    def is_batch_oriented(cls) -> bool:\n        return True\n\n\nclass WorkflowVideoMetadata(WorkflowInput):\n    type: Literal[\"WorkflowVideoMetadata\"]\n    name: str\n    kind: List[Union[str, Kind]] = Field(default=[VIDEO_METADATA_KIND])\n    dimensionality: int = Field(default=1, ge=1, le=1)\n\n    @classmethod\n    def is_batch_oriented(cls) -> bool:\n        return True\n\n\nclass WorkflowBatchInput(WorkflowInput):\n    type: Literal[\"WorkflowBatchInput\"]\n    name: str\n    kind: List[Union[str, Kind]] = Field(default_factory=lambda: [WILDCARD_KIND])\n    dimensionality: int = Field(default=1)\n\n    @classmethod\n    def is_batch_oriented(cls) -> bool:\n        return True\n\n\nclass WorkflowParameter(WorkflowInput):\n    type: Literal[\"WorkflowParameter\", \"InferenceParameter\"]\n    name: str\n    kind: List[Union[str, Kind]] = Field(default_factory=lambda: [WILDCARD_KIND])\n    default_value: Optional[Union[float, int, str, bool, list, set]] = Field(\n        default=None\n    )\n    dimensionality: int = Field(default=0, ge=0, le=0)\n\n\nInputType = Annotated[\n    Union[WorkflowImage, WorkflowVideoMetadata, WorkflowParameter, WorkflowBatchInput],\n    Field(discriminator=\"type\"),\n]\n\nB = TypeVar(\"B\")\n\n\nclass Batch(Generic[B]):\n\n    @classmethod\n    def init(\n        cls,\n        content: List[B],\n        indices: List[Tuple[int, ...]],\n    ) -> \"Batch\":\n        if len(content) != len(indices):\n            raise ValueError(\n                \"Attempted to initialise Batch object providing batch indices of size differing \"\n                \"from size of the data.\"\n            )\n\n        return cls(content=content, indices=indices)\n\n    def __init__(\n        self,\n        content: List[B],\n        indices: Optional[List[Tuple[int, ...]]] = None,\n    ):\n        self._content = content\n        self._indices = indices\n\n    @property\n    def indices(self) -> List[Tuple[int, ...]]:\n        return copy(self._indices)\n\n    def __getitem__(\n        self,\n        index: int,\n    ) -> B:\n        return self._content[index]\n\n    def __len__(self):\n        return len(self._content)\n\n    def __iter__(self) -> Iterator[B]:\n        yield from self._content\n\n    def remove_by_indices(self, indices_to_remove: Set[tuple]) -> \"Batch\":\n        content, new_indices = [], []\n        for index, element in self.iter_with_indices():\n            if index in indices_to_remove:\n                continue\n            content.append(element)\n            new_indices.append(index)\n        return Batch(\n            content=content,\n            indices=new_indices,\n        )\n\n    def iter_with_indices(self) -> Iterator[Tuple[Tuple[int, ...], B]]:\n        for index, element in zip(self._indices, self._content):\n            yield index, element\n\n    def broadcast(self, n: int) -> \"Batch\":\n        if n <= 0:\n            raise ValueError(\n                f\"Broadcast to size {n} requested which is an invalid operation.\"\n            )\n\n        num_content = len(self._content)\n\n        if num_content == n:\n            return self\n\n        if num_content == 1:\n            return Batch(content=self._content * n, indices=self._indices * n)\n\n        raise ValueError(f\"Could not broadcast batch of size {num_content} to size {n}\")\n\n\nclass VideoMetadata(BaseModel):\n    video_identifier: str = Field(\n        description=\"Identifier string for video. To be treated as opaque.\"\n    )\n    frame_number: int\n    frame_timestamp: datetime = Field(\n        description=\"The timestamp of video frame. When processing video it is suggested that \"\n        \"blocks rely on `fps` and `frame_number`, as real-world time-elapse will not \"\n        \"match time-elapse in video file\",\n    )\n    fps: Optional[float] = Field(\n        description=\"Field represents FPS value (if possible to be retrieved)\",\n        default=None,\n    )\n    measured_fps: Optional[float] = Field(\n        description=\"Field represents measured FPS of live stream\",\n        default=None,\n    )\n    comes_from_video_file: Optional[bool] = Field(\n        description=\"Field is a flag telling if frame comes from video file or stream - \"\n        \"if not possible to be determined - pass None\",\n        default=None,\n    )\n\n\n@dataclass(frozen=True)\nclass OriginCoordinatesSystem:\n    left_top_x: int\n    left_top_y: int\n    origin_width: int\n    origin_height: int\n\n\n@dataclass(frozen=True)\nclass ImageParentMetadata:\n    parent_id: str\n    origin_coordinates: Optional[OriginCoordinatesSystem] = None\n\n\nclass WorkflowImageData:\n\n    def __init__(\n        self,\n        parent_metadata: ImageParentMetadata,\n        workflow_root_ancestor_metadata: Optional[ImageParentMetadata] = None,\n        image_reference: Optional[str] = None,\n        base64_image: Optional[str] = None,\n        numpy_image: Optional[np.ndarray] = None,\n        video_metadata: Optional[VideoMetadata] = None,\n    ):\n        if not base64_image and numpy_image is None and not image_reference:\n            raise ValueError(\"Could not initialise empty `WorkflowImageData`.\")\n        self._parent_metadata = parent_metadata\n        self._workflow_root_ancestor_metadata = (\n            workflow_root_ancestor_metadata\n            if workflow_root_ancestor_metadata\n            else self._parent_metadata\n        )\n        self._image_reference = image_reference\n        self._base64_image = base64_image\n        self._numpy_image = numpy_image\n        self._video_metadata = video_metadata\n\n    @classmethod\n    def copy_and_replace(\n        cls, origin_image_data: \"WorkflowImageData\", **kwargs\n    ) -> \"WorkflowImageData\":\n        \"\"\"\n        Creates new instance of `WorkflowImageData` with updated property.\n\n        Properties are passed by kwargs, supported properties are:\n        * parent_metadata\n        * workflow_root_ancestor_metadata\n        * image_reference\n        * base64_image\n        * numpy_image\n        * video_metadata\n\n        When more than one from [\"numpy_image\", \"base64_image\", \"image_reference\"] args are\n        given, they MUST be compliant.\n        \"\"\"\n        parent_metadata = origin_image_data._parent_metadata\n        workflow_root_ancestor_metadata = (\n            origin_image_data._workflow_root_ancestor_metadata\n        )\n        image_reference = origin_image_data._image_reference\n        base64_image = origin_image_data._base64_image\n        numpy_image = origin_image_data._numpy_image\n        video_metadata = origin_image_data._video_metadata\n        if any(k in kwargs for k in [\"numpy_image\", \"base64_image\", \"image_reference\"]):\n            numpy_image = kwargs.get(\"numpy_image\")\n            base64_image = kwargs.get(\"base64_image\")\n            image_reference = kwargs.get(\"image_reference\")\n        if \"parent_metadata\" in kwargs:\n            if workflow_root_ancestor_metadata is parent_metadata:\n                workflow_root_ancestor_metadata = kwargs[\"parent_metadata\"]\n            parent_metadata = kwargs[\"parent_metadata\"]\n        if \"workflow_root_ancestor_metadata\" in kwargs:\n            if parent_metadata is workflow_root_ancestor_metadata:\n                parent_metadata = kwargs[\"workflow_root_ancestor_metadata\"]\n            workflow_root_ancestor_metadata = kwargs[\"workflow_root_ancestor_metadata\"]\n        if \"video_metadata\" in kwargs:\n            video_metadata = kwargs[\"video_metadata\"]\n        return cls(\n            parent_metadata=parent_metadata,\n            workflow_root_ancestor_metadata=workflow_root_ancestor_metadata,\n            image_reference=image_reference,\n            base64_image=base64_image,\n            numpy_image=numpy_image,\n            video_metadata=video_metadata,\n        )\n\n    @classmethod\n    def create_crop(\n        cls,\n        origin_image_data: \"WorkflowImageData\",\n        crop_identifier: str,\n        cropped_image: np.ndarray,\n        offset_x: int,\n        offset_y: int,\n        preserve_video_metadata: bool = False,\n    ) -> \"WorkflowImageData\":\n        \"\"\"\n        Creates new instance of `WorkflowImageData` being a crop of original image,\n        making adjustment to all metadata.\n        \"\"\"\n        parent_metadata = ImageParentMetadata(\n            parent_id=crop_identifier,\n            origin_coordinates=OriginCoordinatesSystem(\n                left_top_x=offset_x,\n                left_top_y=offset_y,\n                origin_width=origin_image_data.numpy_image.shape[1],\n                origin_height=origin_image_data.numpy_image.shape[0],\n            ),\n        )\n        workflow_root_ancestor_coordinates = replace(\n            origin_image_data.workflow_root_ancestor_metadata.origin_coordinates,\n            left_top_x=origin_image_data.workflow_root_ancestor_metadata.origin_coordinates.left_top_x\n            + offset_x,\n            left_top_y=origin_image_data.workflow_root_ancestor_metadata.origin_coordinates.left_top_y\n            + offset_y,\n        )\n        workflow_root_ancestor_metadata = ImageParentMetadata(\n            parent_id=origin_image_data.workflow_root_ancestor_metadata.parent_id,\n            origin_coordinates=workflow_root_ancestor_coordinates,\n        )\n        video_metadata = None\n        if preserve_video_metadata and origin_image_data._video_metadata is not None:\n            video_metadata = copy(origin_image_data._video_metadata)\n            video_metadata.video_identifier = (\n                f\"{video_metadata.video_identifier} | crop: {crop_identifier}\"\n            )\n        return WorkflowImageData(\n            parent_metadata=parent_metadata,\n            workflow_root_ancestor_metadata=workflow_root_ancestor_metadata,\n            numpy_image=cropped_image,\n            video_metadata=video_metadata,\n        )\n\n    @property\n    def parent_metadata(self) -> ImageParentMetadata:\n        if self._parent_metadata.origin_coordinates is None:\n            numpy_image = self.numpy_image\n            origin_coordinates = OriginCoordinatesSystem(\n                left_top_y=0,\n                left_top_x=0,\n                origin_width=numpy_image.shape[1],\n                origin_height=numpy_image.shape[0],\n            )\n            self._parent_metadata = replace(\n                self._parent_metadata, origin_coordinates=origin_coordinates\n            )\n        return self._parent_metadata\n\n    @property\n    def workflow_root_ancestor_metadata(self) -> ImageParentMetadata:\n        if self._workflow_root_ancestor_metadata.origin_coordinates is None:\n            numpy_image = self.numpy_image\n            origin_coordinates = OriginCoordinatesSystem(\n                left_top_y=0,\n                left_top_x=0,\n                origin_width=numpy_image.shape[1],\n                origin_height=numpy_image.shape[0],\n            )\n            self._workflow_root_ancestor_metadata = replace(\n                self._workflow_root_ancestor_metadata,\n                origin_coordinates=origin_coordinates,\n            )\n        return self._workflow_root_ancestor_metadata\n\n    @property\n    def numpy_image(self) -> np.ndarray:\n        if self._numpy_image is not None:\n            return self._numpy_image\n        if self._base64_image:\n            self._numpy_image = attempt_loading_image_from_string(self._base64_image)[0]\n            return self._numpy_image\n        if self._image_reference.startswith(\n            \"http://\"\n        ) or self._image_reference.startswith(\"https://\"):\n            self._numpy_image = load_image_from_url(value=self._image_reference)\n        else:\n            self._numpy_image = cv2.imread(self._image_reference)\n        return self._numpy_image\n\n    @property\n    def base64_image(self) -> str:\n        if self._base64_image is not None:\n            return self._base64_image\n        numpy_image = self.numpy_image\n        self._base64_image = base64.b64encode(\n            encode_image_to_jpeg_bytes(numpy_image, jpeg_quality=95)\n        ).decode(\"ascii\")\n        return self._base64_image\n\n    @property\n    def video_metadata(self) -> VideoMetadata:\n        if self._video_metadata is not None:\n            return self._video_metadata\n        return VideoMetadata(\n            video_identifier=self.parent_metadata.parent_id,\n            frame_number=0,\n            frame_timestamp=datetime.now(),\n            fps=30,\n            comes_from_video_file=None,\n        )\n\n    def to_inference_format(self, numpy_preferred: bool = False) -> Dict[str, Any]:\n        if numpy_preferred:\n            return {\"type\": \"numpy_object\", \"value\": self.numpy_image}\n        if self._image_reference:\n            if self._image_reference.startswith(\n                \"http://\"\n            ) or self._image_reference.startswith(\"https://\"):\n                return {\"type\": \"url\", \"value\": self._image_reference}\n            return {\"type\": \"file\", \"value\": self._image_reference}\n        if self._base64_image:\n            return {\"type\": \"base64\", \"value\": self.base64_image}\n        return {\"type\": \"numpy_object\", \"value\": self.numpy_image}\n",
    "optimized_raw_markdown": "",
    "optimized_function_only": "    def broadcast(self, n: int) -> \"Batch\":\n        if n <= 0:\n            raise ValueError(\n                f\"Broadcast to size {n} requested which is an invalid operation.\"\n            )\n\n        num_content = len(self._content)\n\n        if num_content == n:\n            return self\n\n        if num_content == 1:\n            return Batch(content=self._content * n, indices=self._indices * n)\n\n        raise ValueError(f\"Could not broadcast batch of size {num_content} to size {n}\")\n",
    "original_file_content": "import base64\nfrom copy import copy\nfrom dataclasses import dataclass, replace\nfrom datetime import datetime\nfrom enum import Enum\nfrom typing import (\n    Any,\n    Dict,\n    Generic,\n    Iterator,\n    List,\n    Optional,\n    Set,\n    Tuple,\n    TypeVar,\n    Union,\n)\n\nimport cv2\nimport numpy as np\nfrom pydantic import BaseModel, Field\nfrom typing_extensions import Annotated, Literal\n\nfrom inference.core.utils.image_utils import (\n    attempt_loading_image_from_string,\n    encode_image_to_jpeg_bytes,\n    load_image_from_url,\n)\nfrom inference.core.workflows.execution_engine.entities.types import (\n    IMAGE_KIND,\n    VIDEO_METADATA_KIND,\n    WILDCARD_KIND,\n    Kind,\n)\n\n\nclass OutputDefinition(BaseModel):\n    name: str\n    kind: List[Kind] = Field(default_factory=lambda: [WILDCARD_KIND])\n\n\nclass CoordinatesSystem(Enum):\n    OWN = \"own\"\n    PARENT = \"parent\"\n\n\nclass JsonField(BaseModel):\n    type: Literal[\"JsonField\"]\n    name: str\n    selector: str\n    coordinates_system: CoordinatesSystem = Field(default=CoordinatesSystem.PARENT)\n\n    def get_type(self) -> str:\n        return self.type\n\n\nclass WorkflowInput(BaseModel):\n    type: str\n    name: str\n    kind: List[Union[str, Kind]]\n    dimensionality: int\n\n    @classmethod\n    def is_batch_oriented(cls) -> bool:\n        return False\n\n\nclass WorkflowImage(WorkflowInput):\n    type: Literal[\"WorkflowImage\", \"InferenceImage\"]\n    name: str\n    kind: List[Union[str, Kind]] = Field(default=[IMAGE_KIND])\n    dimensionality: int = Field(default=1, ge=1, le=1)\n\n    @classmethod\n    def is_batch_oriented(cls) -> bool:\n        return True\n\n\nclass WorkflowVideoMetadata(WorkflowInput):\n    type: Literal[\"WorkflowVideoMetadata\"]\n    name: str\n    kind: List[Union[str, Kind]] = Field(default=[VIDEO_METADATA_KIND])\n    dimensionality: int = Field(default=1, ge=1, le=1)\n\n    @classmethod\n    def is_batch_oriented(cls) -> bool:\n        return True\n\n\nclass WorkflowBatchInput(WorkflowInput):\n    type: Literal[\"WorkflowBatchInput\"]\n    name: str\n    kind: List[Union[str, Kind]] = Field(default_factory=lambda: [WILDCARD_KIND])\n    dimensionality: int = Field(default=1)\n\n    @classmethod\n    def is_batch_oriented(cls) -> bool:\n        return True\n\n\nclass WorkflowParameter(WorkflowInput):\n    type: Literal[\"WorkflowParameter\", \"InferenceParameter\"]\n    name: str\n    kind: List[Union[str, Kind]] = Field(default_factory=lambda: [WILDCARD_KIND])\n    default_value: Optional[Union[float, int, str, bool, list, set]] = Field(\n        default=None\n    )\n    dimensionality: int = Field(default=0, ge=0, le=0)\n\n\nInputType = Annotated[\n    Union[WorkflowImage, WorkflowVideoMetadata, WorkflowParameter, WorkflowBatchInput],\n    Field(discriminator=\"type\"),\n]\n\nB = TypeVar(\"B\")\n\n\nclass Batch(Generic[B]):\n\n    @classmethod\n    def init(\n        cls,\n        content: List[B],\n        indices: List[Tuple[int, ...]],\n    ) -> \"Batch\":\n        if len(content) != len(indices):\n            raise ValueError(\n                \"Attempted to initialise Batch object providing batch indices of size differing \"\n                \"from size of the data.\"\n            )\n\n        return cls(content=content, indices=indices)\n\n    def __init__(\n        self,\n        content: List[B],\n        indices: Optional[List[Tuple[int, ...]]],\n    ):\n        self._content = content\n        self._indices = indices\n\n    @property\n    def indices(self) -> List[Tuple[int, ...]]:\n        return copy(self._indices)\n\n    def __getitem__(\n        self,\n        index: int,\n    ) -> B:\n        return self._content[index]\n\n    def __len__(self):\n        return len(self._content)\n\n    def __iter__(self) -> Iterator[B]:\n        yield from self._content\n\n    def remove_by_indices(self, indices_to_remove: Set[tuple]) -> \"Batch\":\n        content, new_indices = [], []\n        for index, element in self.iter_with_indices():\n            if index in indices_to_remove:\n                continue\n            content.append(element)\n            new_indices.append(index)\n        return Batch(\n            content=content,\n            indices=new_indices,\n        )\n\n    def iter_with_indices(self) -> Iterator[Tuple[Tuple[int, ...], B]]:\n        for index, element in zip(self._indices, self._content):\n            yield index, element\n\n    def broadcast(self, n: int) -> \"Batch\":\n        if n <= 0:\n            raise ValueError(\n                f\"Broadcast to size {n} requested which is invalid operation.\"\n            )\n        if len(self._content) == n:\n            return self\n        if len(self._content) == 1:\n            return Batch(content=[self._content[0]] * n, indices=[self._indices[0]] * n)\n        raise ValueError(\n            f\"Could not broadcast batch of size {len(self._content)} to size {n}\"\n        )\n\n\nclass VideoMetadata(BaseModel):\n    video_identifier: str = Field(\n        description=\"Identifier string for video. To be treated as opaque.\"\n    )\n    frame_number: int\n    frame_timestamp: datetime = Field(\n        description=\"The timestamp of video frame. When processing video it is suggested that \"\n        \"blocks rely on `fps` and `frame_number`, as real-world time-elapse will not \"\n        \"match time-elapse in video file\",\n    )\n    fps: Optional[float] = Field(\n        description=\"Field represents FPS value (if possible to be retrieved)\",\n        default=None,\n    )\n    measured_fps: Optional[float] = Field(\n        description=\"Field represents measured FPS of live stream\",\n        default=None,\n    )\n    comes_from_video_file: Optional[bool] = Field(\n        description=\"Field is a flag telling if frame comes from video file or stream - \"\n        \"if not possible to be determined - pass None\",\n        default=None,\n    )\n\n\n@dataclass(frozen=True)\nclass OriginCoordinatesSystem:\n    left_top_x: int\n    left_top_y: int\n    origin_width: int\n    origin_height: int\n\n\n@dataclass(frozen=True)\nclass ImageParentMetadata:\n    parent_id: str\n    origin_coordinates: Optional[OriginCoordinatesSystem] = None\n\n\nclass WorkflowImageData:\n\n    def __init__(\n        self,\n        parent_metadata: ImageParentMetadata,\n        workflow_root_ancestor_metadata: Optional[ImageParentMetadata] = None,\n        image_reference: Optional[str] = None,\n        base64_image: Optional[str] = None,\n        numpy_image: Optional[np.ndarray] = None,\n        video_metadata: Optional[VideoMetadata] = None,\n    ):\n        if not base64_image and numpy_image is None and not image_reference:\n            raise ValueError(\"Could not initialise empty `WorkflowImageData`.\")\n        self._parent_metadata = parent_metadata\n        self._workflow_root_ancestor_metadata = (\n            workflow_root_ancestor_metadata\n            if workflow_root_ancestor_metadata\n            else self._parent_metadata\n        )\n        self._image_reference = image_reference\n        self._base64_image = base64_image\n        self._numpy_image = numpy_image\n        self._video_metadata = video_metadata\n\n    @classmethod\n    def copy_and_replace(\n        cls, origin_image_data: \"WorkflowImageData\", **kwargs\n    ) -> \"WorkflowImageData\":\n        \"\"\"\n        Creates new instance of `WorkflowImageData` with updated property.\n\n        Properties are passed by kwargs, supported properties are:\n        * parent_metadata\n        * workflow_root_ancestor_metadata\n        * image_reference\n        * base64_image\n        * numpy_image\n        * video_metadata\n\n        When more than one from [\"numpy_image\", \"base64_image\", \"image_reference\"] args are\n        given, they MUST be compliant.\n        \"\"\"\n        parent_metadata = origin_image_data._parent_metadata\n        workflow_root_ancestor_metadata = (\n            origin_image_data._workflow_root_ancestor_metadata\n        )\n        image_reference = origin_image_data._image_reference\n        base64_image = origin_image_data._base64_image\n        numpy_image = origin_image_data._numpy_image\n        video_metadata = origin_image_data._video_metadata\n        if any(k in kwargs for k in [\"numpy_image\", \"base64_image\", \"image_reference\"]):\n            numpy_image = kwargs.get(\"numpy_image\")\n            base64_image = kwargs.get(\"base64_image\")\n            image_reference = kwargs.get(\"image_reference\")\n        if \"parent_metadata\" in kwargs:\n            if workflow_root_ancestor_metadata is parent_metadata:\n                workflow_root_ancestor_metadata = kwargs[\"parent_metadata\"]\n            parent_metadata = kwargs[\"parent_metadata\"]\n        if \"workflow_root_ancestor_metadata\" in kwargs:\n            if parent_metadata is workflow_root_ancestor_metadata:\n                parent_metadata = kwargs[\"workflow_root_ancestor_metadata\"]\n            workflow_root_ancestor_metadata = kwargs[\"workflow_root_ancestor_metadata\"]\n        if \"video_metadata\" in kwargs:\n            video_metadata = kwargs[\"video_metadata\"]\n        return cls(\n            parent_metadata=parent_metadata,\n            workflow_root_ancestor_metadata=workflow_root_ancestor_metadata,\n            image_reference=image_reference,\n            base64_image=base64_image,\n            numpy_image=numpy_image,\n            video_metadata=video_metadata,\n        )\n\n    @classmethod\n    def create_crop(\n        cls,\n        origin_image_data: \"WorkflowImageData\",\n        crop_identifier: str,\n        cropped_image: np.ndarray,\n        offset_x: int,\n        offset_y: int,\n        preserve_video_metadata: bool = False,\n    ) -> \"WorkflowImageData\":\n        \"\"\"\n        Creates new instance of `WorkflowImageData` being a crop of original image,\n        making adjustment to all metadata.\n        \"\"\"\n        parent_metadata = ImageParentMetadata(\n            parent_id=crop_identifier,\n            origin_coordinates=OriginCoordinatesSystem(\n                left_top_x=offset_x,\n                left_top_y=offset_y,\n                origin_width=origin_image_data.numpy_image.shape[1],\n                origin_height=origin_image_data.numpy_image.shape[0],\n            ),\n        )\n        workflow_root_ancestor_coordinates = replace(\n            origin_image_data.workflow_root_ancestor_metadata.origin_coordinates,\n            left_top_x=origin_image_data.workflow_root_ancestor_metadata.origin_coordinates.left_top_x\n            + offset_x,\n            left_top_y=origin_image_data.workflow_root_ancestor_metadata.origin_coordinates.left_top_y\n            + offset_y,\n        )\n        workflow_root_ancestor_metadata = ImageParentMetadata(\n            parent_id=origin_image_data.workflow_root_ancestor_metadata.parent_id,\n            origin_coordinates=workflow_root_ancestor_coordinates,\n        )\n        video_metadata = None\n        if preserve_video_metadata and origin_image_data._video_metadata is not None:\n            video_metadata = copy(origin_image_data._video_metadata)\n            video_metadata.video_identifier = (\n                f\"{video_metadata.video_identifier} | crop: {crop_identifier}\"\n            )\n        return WorkflowImageData(\n            parent_metadata=parent_metadata,\n            workflow_root_ancestor_metadata=workflow_root_ancestor_metadata,\n            numpy_image=cropped_image,\n            video_metadata=video_metadata,\n        )\n\n    @property\n    def parent_metadata(self) -> ImageParentMetadata:\n        if self._parent_metadata.origin_coordinates is None:\n            numpy_image = self.numpy_image\n            origin_coordinates = OriginCoordinatesSystem(\n                left_top_y=0,\n                left_top_x=0,\n                origin_width=numpy_image.shape[1],\n                origin_height=numpy_image.shape[0],\n            )\n            self._parent_metadata = replace(\n                self._parent_metadata, origin_coordinates=origin_coordinates\n            )\n        return self._parent_metadata\n\n    @property\n    def workflow_root_ancestor_metadata(self) -> ImageParentMetadata:\n        if self._workflow_root_ancestor_metadata.origin_coordinates is None:\n            numpy_image = self.numpy_image\n            origin_coordinates = OriginCoordinatesSystem(\n                left_top_y=0,\n                left_top_x=0,\n                origin_width=numpy_image.shape[1],\n                origin_height=numpy_image.shape[0],\n            )\n            self._workflow_root_ancestor_metadata = replace(\n                self._workflow_root_ancestor_metadata,\n                origin_coordinates=origin_coordinates,\n            )\n        return self._workflow_root_ancestor_metadata\n\n    @property\n    def numpy_image(self) -> np.ndarray:\n        if self._numpy_image is not None:\n            return self._numpy_image\n        if self._base64_image:\n            self._numpy_image = attempt_loading_image_from_string(self._base64_image)[0]\n            return self._numpy_image\n        if self._image_reference.startswith(\n            \"http://\"\n        ) or self._image_reference.startswith(\"https://\"):\n            self._numpy_image = load_image_from_url(value=self._image_reference)\n        else:\n            self._numpy_image = cv2.imread(self._image_reference)\n        return self._numpy_image\n\n    @property\n    def base64_image(self) -> str:\n        if self._base64_image is not None:\n            return self._base64_image\n        numpy_image = self.numpy_image\n        self._base64_image = base64.b64encode(\n            encode_image_to_jpeg_bytes(numpy_image, jpeg_quality=95)\n        ).decode(\"ascii\")\n        return self._base64_image\n\n    @property\n    def video_metadata(self) -> VideoMetadata:\n        if self._video_metadata is not None:\n            return self._video_metadata\n        return VideoMetadata(\n            video_identifier=self.parent_metadata.parent_id,\n            frame_number=0,\n            frame_timestamp=datetime.now(),\n            fps=30,\n            comes_from_video_file=None,\n        )\n\n    def to_inference_format(self, numpy_preferred: bool = False) -> Dict[str, Any]:\n        if numpy_preferred:\n            return {\"type\": \"numpy_object\", \"value\": self.numpy_image}\n        if self._image_reference:\n            if self._image_reference.startswith(\n                \"http://\"\n            ) or self._image_reference.startswith(\"https://\"):\n                return {\"type\": \"url\", \"value\": self._image_reference}\n            return {\"type\": \"file\", \"value\": self._image_reference}\n        if self._base64_image:\n            return {\"type\": \"base64\", \"value\": self.base64_image}\n        return {\"type\": \"numpy_object\", \"value\": self.numpy_image}\n",
    "patch": "diff --git a/inference/core/workflows/execution_engine/entities/base.py b/inference/core/workflows/execution_engine/entities/base.py\nindex 97579f0fe..75ed51119 100644\n--- a/inference/core/workflows/execution_engine/entities/base.py\n+++ b/inference/core/workflows/execution_engine/entities/base.py\n@@ -135,7 +135,7 @@ class Batch(Generic[B]):\n     def __init__(\n         self,\n         content: List[B],\n-        indices: Optional[List[Tuple[int, ...]]],\n+        indices: Optional[List[Tuple[int, ...]]] = None,\n     ):\n         self._content = content\n         self._indices = indices\n@@ -175,15 +175,18 @@ class Batch(Generic[B]):\n     def broadcast(self, n: int) -> \"Batch\":\n         if n <= 0:\n             raise ValueError(\n-                f\"Broadcast to size {n} requested which is invalid operation.\"\n+                f\"Broadcast to size {n} requested which is an invalid operation.\"\n             )\n-        if len(self._content) == n:\n+\n+        num_content = len(self._content)\n+\n+        if num_content == n:\n             return self\n-        if len(self._content) == 1:\n-            return Batch(content=[self._content[0]] * n, indices=[self._indices[0]] * n)\n-        raise ValueError(\n-            f\"Could not broadcast batch of size {len(self._content)} to size {n}\"\n-        )\n+\n+        if num_content == 1:\n+            return Batch(content=self._content * n, indices=self._indices * n)\n+\n+        raise ValueError(f\"Could not broadcast batch of size {num_content} to size {n}\")\n \n \n class VideoMetadata(BaseModel):\n"
  },
  {
    "trace_id": "git_84788ea648a7",
    "function_name": "extract_x_coordinate_of_detections_center",
    "file_path": "inference/core/workflows/core_steps/common/query_language/operations/detections/base.py",
    "speedup_x": 0.35,
    "review_quality": null,
    "pre_optimization_commit": "326999fd4355e9ee816e8f257ca3312bd833e5f0",
    "resolution_method": "git_parent",
    "source": "git",
    "original_function_code": "def extract_x_coordinate_of_detections_center(detections: sv.Detections) -> np.ndarray:\n    return detections.xyxy[:, 0] + (detections.xyxy[:, 2] - detections.xyxy[:, 0]) / 2\n",
    "optimized_function_code": "from copy import copy, deepcopy\nfrom typing import Any, Callable, Dict, List, Union\n\nimport numpy as np\nimport supervision as sv\nfrom supervision import Position\n\nfrom inference.core.workflows.core_steps.common.query_language.entities.enums import (\n    DetectionsProperty,\n    DetectionsSelectionMode,\n    DetectionsSortProperties,\n)\nfrom inference.core.workflows.core_steps.common.query_language.entities.operations import (\n    DEFAULT_OPERAND_NAME,\n)\nfrom inference.core.workflows.core_steps.common.query_language.errors import (\n    InvalidInputTypeError,\n    OperationError,\n    UndeclaredSymbolError,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.utils import (\n    safe_stringify,\n)\nfrom inference.core.workflows.core_steps.common.serializers import (\n    serialise_sv_detections,\n)\n\nPROPERTIES_EXTRACTORS = {\n    DetectionsProperty.CONFIDENCE: lambda detections: detections.confidence.tolist(),\n    DetectionsProperty.CLASS_NAME: lambda detections: detections.data.get(\n        \"class_name\", np.array([], dtype=str)\n    ).tolist(),\n    DetectionsProperty.X_MIN: lambda detections: detections.xyxy[:, 0].tolist(),\n    DetectionsProperty.Y_MIN: lambda detections: detections.xyxy[:, 1].tolist(),\n    DetectionsProperty.X_MAX: lambda detections: detections.xyxy[:, 2].tolist(),\n    DetectionsProperty.Y_MAX: lambda detections: detections.xyxy[:, 3].tolist(),\n    DetectionsProperty.CLASS_ID: lambda detections: detections.class_id.tolist(),\n    DetectionsProperty.SIZE: lambda detections: detections.box_area.tolist(),\n}\n\n\ndef extract_detections_property(\n    detections: Any,\n    property_name: DetectionsProperty,\n    execution_context: str,\n    **kwargs,\n) -> List[Any]:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing extract_detections_property(...) in context {execution_context}, \"\n            f\"expected sv.Detections object as value, got {value_as_str} of type {type(detections)}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n        )\n    return PROPERTIES_EXTRACTORS[property_name](detections)\n\n\ndef filter_detections(\n    detections: Any,\n    filtering_fun: Callable[[Dict[str, Any]], bool],\n    global_parameters: Dict[str, Any],\n) -> sv.Detections:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing filter_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(detections)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    local_parameters = copy(global_parameters)\n    result = []\n    for detection in detections:\n        local_parameters[DEFAULT_OPERAND_NAME] = detection\n        should_stay = filtering_fun(local_parameters)\n        result.append(should_stay)\n    return detections[result]\n\n\ndef offset_detections(\n    value: Any, offset_x: int, offset_y: int, **kwargs\n) -> sv.Detections:\n    if not isinstance(value, sv.Detections):\n        value_as_str = safe_stringify(value=value)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing offset_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(value)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    detections_copy = deepcopy(value)\n    detections_copy.xyxy += [-offset_x / 2, -offset_y / 2, offset_x / 2, offset_y / 2]\n    return detections_copy\n\n\ndef shift_detections(value: Any, shift_x: int, shift_y: int, **kwargs) -> sv.Detections:\n    if not isinstance(value, sv.Detections):\n        value_as_str = safe_stringify(value=value)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing shift_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(value)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    detections_copy = deepcopy(value)\n    detections_copy.xyxy += [shift_x, shift_y, shift_x, shift_y]\n    return detections_copy\n\n\ndef select_top_confidence_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    confidence = detections.confidence\n    max_value = confidence.max()\n    index = np.argwhere(confidence == max_value)[0].item()\n    return detections[index]\n\n\ndef select_leftmost_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    centers_x = detections.get_anchors_coordinates(anchor=Position.CENTER)[:, 0]\n    min_value = centers_x.min()\n    index = np.argwhere(centers_x == min_value)[0].item()\n    return detections[index]\n\n\ndef select_rightmost_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    centers_x = detections.get_anchors_coordinates(anchor=Position.CENTER)[:, 0]\n    max_value = centers_x.max()\n    index = np.argwhere(centers_x == max_value)[-1].item()\n    return detections[index]\n\n\ndef select_first_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    return detections[0]\n\n\ndef select_last_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    return detections[-1]\n\n\nDETECTIONS_SELECTORS = {\n    DetectionsSelectionMode.FIRST: select_first_detection,\n    DetectionsSelectionMode.LAST: select_last_detection,\n    DetectionsSelectionMode.LEFT_MOST: select_leftmost_detection,\n    DetectionsSelectionMode.RIGHT_MOST: select_rightmost_detection,\n    DetectionsSelectionMode.TOP_CONFIDENCE: select_top_confidence_detection,\n}\n\n\ndef select_detections(\n    value: Any, mode: DetectionsSelectionMode, **kwargs\n) -> sv.Detections:\n    if not isinstance(value, sv.Detections):\n        value_as_str = safe_stringify(value=value)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing select_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(value)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if mode not in DETECTIONS_SELECTORS:\n        InvalidInputTypeError(\n            public_message=f\"Executing select_detections(...), expected mode to be one of {DETECTIONS_SELECTORS.values()}, \"\n            f\"got {mode}.\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    return DETECTIONS_SELECTORS[mode](value)\n\n\ndef extract_x_coordinate_of_detections_center(detections: sv.Detections) -> np.ndarray:\n    # Utilize efficient NumPy broadcasting to compute the center x-coordinate\n    return (detections.xyxy[:, 0] + detections.xyxy[:, 2]) * 0.5\n\n\ndef extract_y_coordinate_of_detections_center(detections: sv.Detections) -> np.ndarray:\n    return detections.xyxy[:, 1] + (detections.xyxy[:, 3] - detections.xyxy[:, 1]) / 2\n\n\nSORT_PROPERTIES_EXTRACT = {\n    DetectionsSortProperties.CONFIDENCE: lambda detections: detections.confidence,\n    DetectionsSortProperties.X_MIN: lambda detections: detections.xyxy[:, 0],\n    DetectionsSortProperties.X_MAX: lambda detections: detections.xyxy[:, 2],\n    DetectionsSortProperties.Y_MIN: lambda detections: detections.xyxy[:, 1],\n    DetectionsSortProperties.Y_MAX: lambda detections: detections.xyxy[:, 3],\n    DetectionsSortProperties.SIZE: lambda detections: detections.box_area,\n    DetectionsSortProperties.CENTER_X: extract_x_coordinate_of_detections_center,\n    DetectionsSortProperties.CENTER_Y: extract_y_coordinate_of_detections_center,\n}\n\n\ndef sort_detections(\n    value: Any, mode: DetectionsSortProperties, ascending: bool, **kwargs\n) -> sv.Detections:\n    if not isinstance(value, sv.Detections):\n        value_as_str = safe_stringify(value=value)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing sort_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(value)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if mode not in SORT_PROPERTIES_EXTRACT:\n        raise InvalidInputTypeError(\n            public_message=f\"Executing sort_detections(...), expected mode to be one of \"\n            f\"{SORT_PROPERTIES_EXTRACT.values()}, got {mode}.\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if len(value) == 0:\n        return value\n    extracted_property = SORT_PROPERTIES_EXTRACT[mode](value)\n    if extracted_property is None:\n        # property may not be set, as sv.Detections declares Optional[...]\n        return value\n    sorted_indices = np.argsort(extracted_property)\n    if not ascending:\n        sorted_indices = sorted_indices[::-1]\n    return value[sorted_indices]\n\n\ndef rename_detections(\n    detections: Any,\n    class_map: Union[Dict[str, str], str],\n    strict: Union[bool, str],\n    new_classes_id_offset: int,\n    global_parameters: Dict[str, Any],\n    **kwargs,\n) -> sv.Detections:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing rename_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(detections)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if isinstance(class_map, str):\n        if class_map not in global_parameters:\n            raise UndeclaredSymbolError(\n                public_message=f\"Attempted to retrieve variable `{class_map}` that was expected to hold \"\n                f\"class mapping of rename_detections(...), but that turned out not to be registered.\",\n                context=\"step_execution | roboflow_query_language_evaluation\",\n            )\n        class_map = global_parameters[class_map]\n    if not isinstance(class_map, dict):\n        value_as_str = safe_stringify(value=class_map)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing rename_detections(...), expected dictionary to be given as class map, \"\n            f\"got {value_as_str} of type {type(class_map)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if isinstance(strict, str):\n        if strict not in global_parameters:\n            raise UndeclaredSymbolError(\n                public_message=f\"Attempted to retrieve variable `{strict}` that was expected to hold \"\n                f\"parameter for `strict` flag of rename_detections(...), but that turned out not \"\n                f\"to be registered.\",\n                context=\"step_execution | roboflow_query_language_evaluation\",\n            )\n        strict = global_parameters[strict]\n    if not isinstance(strict, bool):\n        value_as_str = safe_stringify(value=strict)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing rename_detections(...), expected dictionary to be given as `strict` flag, \"\n            f\"got {value_as_str} of type {type(strict)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    detections_copy = deepcopy(detections)\n    original_class_names = detections_copy.data.get(\"class_name\", []).tolist()\n    original_class_ids = detections_copy.class_id.tolist()\n    new_class_names = []\n    new_class_ids = []\n    if strict:\n        _ensure_all_classes_covered_in_new_mapping(\n            original_class_names=original_class_names,\n            class_map=class_map,\n        )\n        new_class_mapping = {\n            class_name: class_id\n            for class_id, class_name in enumerate(sorted(set(class_map.values())))\n        }\n    else:\n        new_class_mapping = _build_non_strict_class_to_id_mapping(\n            original_class_names=original_class_names,\n            original_class_ids=original_class_ids,\n            class_map=class_map,\n            new_classes_id_offset=new_classes_id_offset,\n        )\n    for class_name in original_class_names:\n        new_class_name = class_map.get(class_name, class_name)\n        new_class_id = new_class_mapping[new_class_name]\n        new_class_names.append(new_class_name)\n        new_class_ids.append(new_class_id)\n    detections_copy.data[\"class_name\"] = np.array(new_class_names, dtype=object)\n    detections_copy.class_id = np.array(new_class_ids, dtype=int)\n    return detections_copy\n\n\ndef _ensure_all_classes_covered_in_new_mapping(\n    original_class_names: List[str],\n    class_map: Dict[str, str],\n) -> None:\n    for original_class in original_class_names:\n        if original_class not in class_map:\n            raise OperationError(\n                public_message=f\"Class '{original_class}' not found in class_map.\",\n                context=\"step_execution | roboflow_query_language_evaluation\",\n            )\n\n\ndef _build_non_strict_class_to_id_mapping(\n    original_class_names: List[str],\n    original_class_ids: List[int],\n    class_map: Dict[str, str],\n    new_classes_id_offset: int,\n) -> Dict[str, int]:\n    original_mapping = {\n        class_name: class_id\n        for class_name, class_id in zip(original_class_names, original_class_ids)\n    }\n    new_target_classes = {\n        new_class_name\n        for new_class_name in class_map.values()\n        if new_class_name not in original_mapping\n    }\n    new_class_id = new_classes_id_offset\n    for new_target_class in sorted(new_target_classes):\n        original_mapping[new_target_class] = new_class_id\n        new_class_id += 1\n    return original_mapping\n\n\ndef detections_to_dictionary(\n    detections: Any,\n    execution_context: str,\n    **kwargs,\n) -> dict:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing detections_to_dictionary(...) in context {execution_context}, \"\n            f\"expected sv.Detections object as value, got {value_as_str} of type {type(detections)}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n        )\n    try:\n        return serialise_sv_detections(detections=detections)\n    except Exception as error:\n        raise OperationError(\n            public_message=f\"While Using operation detections_to_dictionary(...) in context {execution_context} \"\n            f\"encountered error: {error}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n            inner_error=error,\n        )\n\n\ndef pick_detections_by_parent_class(\n    detections: Any,\n    parent_class: str,\n    execution_context: str,\n    **kwargs,\n) -> sv.Detections:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing pick_detections_by_parent_class(...) in context {execution_context}, \"\n            f\"expected sv.Detections object as value, got {value_as_str} of type {type(detections)}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n        )\n    try:\n        return _pick_detections_by_parent_class(\n            detections=detections, parent_class=parent_class\n        )\n    except Exception as error:\n        raise OperationError(\n            public_message=f\"While Using operation pick_detections_by_parent_class(...) in context {execution_context} \"\n            f\"encountered error: {error}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n            inner_error=error,\n        )\n\n\ndef _pick_detections_by_parent_class(\n    detections: sv.Detections,\n    parent_class: str,\n) -> sv.Detections:\n    class_names = detections.data.get(\"class_name\")\n    if class_names is None or len(class_names) == 0:\n        return sv.Detections.empty()\n    if not isinstance(class_names, np.ndarray):\n        class_names = np.array(class_names)\n    parent_mask = class_names == parent_class\n    parent_detections = detections[parent_mask]\n    if len(parent_detections) == 0:\n        return sv.Detections.empty()\n    dependent_detections = detections[~parent_mask]\n    dependent_detections_anchors = dependent_detections.get_anchors_coordinates(\n        anchor=Position.CENTER\n    )\n    dependent_detections_to_keep = set()\n    for detection_idx, anchor in enumerate(dependent_detections_anchors):\n        for parent_detection_box in parent_detections.xyxy:\n            if _is_point_within_box(point=anchor, box=parent_detection_box):\n                dependent_detections_to_keep.add(detection_idx)\n                continue\n    detections_to_keep_list = sorted(list(dependent_detections_to_keep))\n    filtered_dependent_detections = dependent_detections[detections_to_keep_list]\n    return sv.Detections.merge([parent_detections, filtered_dependent_detections])\n\n\ndef _is_point_within_box(point: np.ndarray, box: np.ndarray) -> bool:\n    px, py = point\n    x1, y1, x2, y2 = box\n    return x1 <= px <= x2 and y1 <= py <= y2\n",
    "optimized_raw_markdown": "",
    "optimized_function_only": "def extract_x_coordinate_of_detections_center(detections: sv.Detections) -> np.ndarray:\n    # Utilize efficient NumPy broadcasting to compute the center x-coordinate\n    return (detections.xyxy[:, 0] + detections.xyxy[:, 2]) * 0.5\n",
    "original_file_content": "from copy import copy, deepcopy\nfrom typing import Any, Callable, Dict, List, Union\n\nimport numpy as np\nimport supervision as sv\nfrom supervision import Position\n\nfrom inference.core.workflows.core_steps.common.query_language.entities.enums import (\n    DetectionsProperty,\n    DetectionsSelectionMode,\n    DetectionsSortProperties,\n)\nfrom inference.core.workflows.core_steps.common.query_language.entities.operations import (\n    DEFAULT_OPERAND_NAME,\n)\nfrom inference.core.workflows.core_steps.common.query_language.errors import (\n    InvalidInputTypeError,\n    OperationError,\n    UndeclaredSymbolError,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.utils import (\n    safe_stringify,\n)\nfrom inference.core.workflows.core_steps.common.serializers import (\n    serialise_sv_detections,\n)\n\nPROPERTIES_EXTRACTORS = {\n    DetectionsProperty.CONFIDENCE: lambda detections: detections.confidence.tolist(),\n    DetectionsProperty.CLASS_NAME: lambda detections: detections.data.get(\n        \"class_name\", np.array([], dtype=str)\n    ).tolist(),\n    DetectionsProperty.X_MIN: lambda detections: detections.xyxy[:, 0].tolist(),\n    DetectionsProperty.Y_MIN: lambda detections: detections.xyxy[:, 1].tolist(),\n    DetectionsProperty.X_MAX: lambda detections: detections.xyxy[:, 2].tolist(),\n    DetectionsProperty.Y_MAX: lambda detections: detections.xyxy[:, 3].tolist(),\n    DetectionsProperty.CLASS_ID: lambda detections: detections.class_id.tolist(),\n    DetectionsProperty.SIZE: lambda detections: detections.box_area.tolist(),\n}\n\n\ndef extract_detections_property(\n    detections: Any,\n    property_name: DetectionsProperty,\n    execution_context: str,\n    **kwargs,\n) -> List[Any]:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing extract_detections_property(...) in context {execution_context}, \"\n            f\"expected sv.Detections object as value, got {value_as_str} of type {type(detections)}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n        )\n    return PROPERTIES_EXTRACTORS[property_name](detections)\n\n\ndef filter_detections(\n    detections: Any,\n    filtering_fun: Callable[[Dict[str, Any]], bool],\n    global_parameters: Dict[str, Any],\n) -> sv.Detections:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing filter_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(detections)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    local_parameters = copy(global_parameters)\n    result = []\n    for detection in detections:\n        local_parameters[DEFAULT_OPERAND_NAME] = detection\n        should_stay = filtering_fun(local_parameters)\n        result.append(should_stay)\n    return detections[result]\n\n\ndef offset_detections(\n    value: Any, offset_x: int, offset_y: int, **kwargs\n) -> sv.Detections:\n    if not isinstance(value, sv.Detections):\n        value_as_str = safe_stringify(value=value)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing offset_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(value)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    detections_copy = deepcopy(value)\n    detections_copy.xyxy += [-offset_x / 2, -offset_y / 2, offset_x / 2, offset_y / 2]\n    return detections_copy\n\n\ndef shift_detections(value: Any, shift_x: int, shift_y: int, **kwargs) -> sv.Detections:\n    if not isinstance(value, sv.Detections):\n        value_as_str = safe_stringify(value=value)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing shift_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(value)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    detections_copy = deepcopy(value)\n    detections_copy.xyxy += [shift_x, shift_y, shift_x, shift_y]\n    return detections_copy\n\n\ndef select_top_confidence_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    confidence = detections.confidence\n    max_value = confidence.max()\n    index = np.argwhere(confidence == max_value)[0].item()\n    return detections[index]\n\n\ndef select_leftmost_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    centers_x = detections.get_anchors_coordinates(anchor=Position.CENTER)[:, 0]\n    min_value = centers_x.min()\n    index = np.argwhere(centers_x == min_value)[0].item()\n    return detections[index]\n\n\ndef select_rightmost_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    centers_x = detections.get_anchors_coordinates(anchor=Position.CENTER)[:, 0]\n    max_value = centers_x.max()\n    index = np.argwhere(centers_x == max_value)[-1].item()\n    return detections[index]\n\n\ndef select_first_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    return detections[0]\n\n\ndef select_last_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    return detections[-1]\n\n\nDETECTIONS_SELECTORS = {\n    DetectionsSelectionMode.FIRST: select_first_detection,\n    DetectionsSelectionMode.LAST: select_last_detection,\n    DetectionsSelectionMode.LEFT_MOST: select_leftmost_detection,\n    DetectionsSelectionMode.RIGHT_MOST: select_rightmost_detection,\n    DetectionsSelectionMode.TOP_CONFIDENCE: select_top_confidence_detection,\n}\n\n\ndef select_detections(\n    value: Any, mode: DetectionsSelectionMode, **kwargs\n) -> sv.Detections:\n    if not isinstance(value, sv.Detections):\n        value_as_str = safe_stringify(value=value)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing select_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(value)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if mode not in DETECTIONS_SELECTORS:\n        InvalidInputTypeError(\n            public_message=f\"Executing select_detections(...), expected mode to be one of {DETECTIONS_SELECTORS.values()}, \"\n            f\"got {mode}.\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    return DETECTIONS_SELECTORS[mode](value)\n\n\ndef extract_x_coordinate_of_detections_center(detections: sv.Detections) -> np.ndarray:\n    return detections.xyxy[:, 0] + (detections.xyxy[:, 2] - detections.xyxy[:, 0]) / 2\n\n\ndef extract_y_coordinate_of_detections_center(detections: sv.Detections) -> np.ndarray:\n    return detections.xyxy[:, 1] + (detections.xyxy[:, 3] - detections.xyxy[:, 1]) / 2\n\n\nSORT_PROPERTIES_EXTRACT = {\n    DetectionsSortProperties.CONFIDENCE: lambda detections: detections.confidence,\n    DetectionsSortProperties.X_MIN: lambda detections: detections.xyxy[:, 0],\n    DetectionsSortProperties.X_MAX: lambda detections: detections.xyxy[:, 2],\n    DetectionsSortProperties.Y_MIN: lambda detections: detections.xyxy[:, 1],\n    DetectionsSortProperties.Y_MAX: lambda detections: detections.xyxy[:, 3],\n    DetectionsSortProperties.SIZE: lambda detections: detections.box_area,\n    DetectionsSortProperties.CENTER_X: extract_x_coordinate_of_detections_center,\n    DetectionsSortProperties.CENTER_Y: extract_y_coordinate_of_detections_center,\n}\n\n\ndef sort_detections(\n    value: Any, mode: DetectionsSortProperties, ascending: bool, **kwargs\n) -> sv.Detections:\n    if not isinstance(value, sv.Detections):\n        value_as_str = safe_stringify(value=value)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing sort_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(value)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if mode not in SORT_PROPERTIES_EXTRACT:\n        raise InvalidInputTypeError(\n            public_message=f\"Executing sort_detections(...), expected mode to be one of \"\n            f\"{SORT_PROPERTIES_EXTRACT.values()}, got {mode}.\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if len(value) == 0:\n        return value\n    extracted_property = SORT_PROPERTIES_EXTRACT[mode](value)\n    if extracted_property is None:\n        # property may not be set, as sv.Detections declares Optional[...]\n        return value\n    sorted_indices = np.argsort(extracted_property)\n    if not ascending:\n        sorted_indices = sorted_indices[::-1]\n    return value[sorted_indices]\n\n\ndef rename_detections(\n    detections: Any,\n    class_map: Union[Dict[str, str], str],\n    strict: Union[bool, str],\n    new_classes_id_offset: int,\n    global_parameters: Dict[str, Any],\n    **kwargs,\n) -> sv.Detections:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing rename_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(detections)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if isinstance(class_map, str):\n        if class_map not in global_parameters:\n            raise UndeclaredSymbolError(\n                public_message=f\"Attempted to retrieve variable `{class_map}` that was expected to hold \"\n                f\"class mapping of rename_detections(...), but that turned out not to be registered.\",\n                context=\"step_execution | roboflow_query_language_evaluation\",\n            )\n        class_map = global_parameters[class_map]\n    if not isinstance(class_map, dict):\n        value_as_str = safe_stringify(value=class_map)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing rename_detections(...), expected dictionary to be given as class map, \"\n            f\"got {value_as_str} of type {type(class_map)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if isinstance(strict, str):\n        if strict not in global_parameters:\n            raise UndeclaredSymbolError(\n                public_message=f\"Attempted to retrieve variable `{strict}` that was expected to hold \"\n                f\"parameter for `strict` flag of rename_detections(...), but that turned out not \"\n                f\"to be registered.\",\n                context=\"step_execution | roboflow_query_language_evaluation\",\n            )\n        strict = global_parameters[strict]\n    if not isinstance(strict, bool):\n        value_as_str = safe_stringify(value=strict)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing rename_detections(...), expected dictionary to be given as `strict` flag, \"\n            f\"got {value_as_str} of type {type(strict)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    detections_copy = deepcopy(detections)\n    original_class_names = detections_copy.data.get(\"class_name\", []).tolist()\n    original_class_ids = detections_copy.class_id.tolist()\n    new_class_names = []\n    new_class_ids = []\n    if strict:\n        _ensure_all_classes_covered_in_new_mapping(\n            original_class_names=original_class_names,\n            class_map=class_map,\n        )\n        new_class_mapping = {\n            class_name: class_id\n            for class_id, class_name in enumerate(sorted(set(class_map.values())))\n        }\n    else:\n        new_class_mapping = _build_non_strict_class_to_id_mapping(\n            original_class_names=original_class_names,\n            original_class_ids=original_class_ids,\n            class_map=class_map,\n            new_classes_id_offset=new_classes_id_offset,\n        )\n    for class_name in original_class_names:\n        new_class_name = class_map.get(class_name, class_name)\n        new_class_id = new_class_mapping[new_class_name]\n        new_class_names.append(new_class_name)\n        new_class_ids.append(new_class_id)\n    detections_copy.data[\"class_name\"] = np.array(new_class_names, dtype=object)\n    detections_copy.class_id = np.array(new_class_ids, dtype=int)\n    return detections_copy\n\n\ndef _ensure_all_classes_covered_in_new_mapping(\n    original_class_names: List[str],\n    class_map: Dict[str, str],\n) -> None:\n    for original_class in original_class_names:\n        if original_class not in class_map:\n            raise OperationError(\n                public_message=f\"Class '{original_class}' not found in class_map.\",\n                context=\"step_execution | roboflow_query_language_evaluation\",\n            )\n\n\ndef _build_non_strict_class_to_id_mapping(\n    original_class_names: List[str],\n    original_class_ids: List[int],\n    class_map: Dict[str, str],\n    new_classes_id_offset: int,\n) -> Dict[str, int]:\n    original_mapping = {\n        class_name: class_id\n        for class_name, class_id in zip(original_class_names, original_class_ids)\n    }\n    new_target_classes = {\n        new_class_name\n        for new_class_name in class_map.values()\n        if new_class_name not in original_mapping\n    }\n    new_class_id = new_classes_id_offset\n    for new_target_class in sorted(new_target_classes):\n        original_mapping[new_target_class] = new_class_id\n        new_class_id += 1\n    return original_mapping\n\n\ndef detections_to_dictionary(\n    detections: Any,\n    execution_context: str,\n    **kwargs,\n) -> dict:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing detections_to_dictionary(...) in context {execution_context}, \"\n            f\"expected sv.Detections object as value, got {value_as_str} of type {type(detections)}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n        )\n    try:\n        return serialise_sv_detections(detections=detections)\n    except Exception as error:\n        raise OperationError(\n            public_message=f\"While Using operation detections_to_dictionary(...) in context {execution_context} \"\n            f\"encountered error: {error}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n            inner_error=error,\n        )\n\n\ndef pick_detections_by_parent_class(\n    detections: Any,\n    parent_class: str,\n    execution_context: str,\n    **kwargs,\n) -> sv.Detections:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing pick_detections_by_parent_class(...) in context {execution_context}, \"\n            f\"expected sv.Detections object as value, got {value_as_str} of type {type(detections)}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n        )\n    try:\n        return _pick_detections_by_parent_class(\n            detections=detections, parent_class=parent_class\n        )\n    except Exception as error:\n        raise OperationError(\n            public_message=f\"While Using operation pick_detections_by_parent_class(...) in context {execution_context} \"\n            f\"encountered error: {error}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n            inner_error=error,\n        )\n\n\ndef _pick_detections_by_parent_class(\n    detections: sv.Detections,\n    parent_class: str,\n) -> sv.Detections:\n    class_names = detections.data.get(\"class_name\")\n    if class_names is None or len(class_names) == 0:\n        return sv.Detections.empty()\n    if not isinstance(class_names, np.ndarray):\n        class_names = np.array(class_names)\n    parent_mask = class_names == parent_class\n    parent_detections = detections[parent_mask]\n    if len(parent_detections) == 0:\n        return sv.Detections.empty()\n    dependent_detections = detections[~parent_mask]\n    dependent_detections_anchors = dependent_detections.get_anchors_coordinates(\n        anchor=Position.CENTER\n    )\n    dependent_detections_to_keep = set()\n    for detection_idx, anchor in enumerate(dependent_detections_anchors):\n        for parent_detection_box in parent_detections.xyxy:\n            if _is_point_within_box(point=anchor, box=parent_detection_box):\n                dependent_detections_to_keep.add(detection_idx)\n                continue\n    detections_to_keep_list = sorted(list(dependent_detections_to_keep))\n    filtered_dependent_detections = dependent_detections[detections_to_keep_list]\n    return sv.Detections.merge([parent_detections, filtered_dependent_detections])\n\n\ndef _is_point_within_box(point: np.ndarray, box: np.ndarray) -> bool:\n    px, py = point\n    x1, y1, x2, y2 = box\n    return x1 <= px <= x2 and y1 <= py <= y2\n",
    "patch": "diff --git a/inference/core/workflows/core_steps/common/query_language/operations/detections/base.py b/inference/core/workflows/core_steps/common/query_language/operations/detections/base.py\nindex 04c6921f7..96e79364f 100644\n--- a/inference/core/workflows/core_steps/common/query_language/operations/detections/base.py\n+++ b/inference/core/workflows/core_steps/common/query_language/operations/detections/base.py\n@@ -172,7 +172,8 @@ def select_detections(\n \n \n def extract_x_coordinate_of_detections_center(detections: sv.Detections) -> np.ndarray:\n-    return detections.xyxy[:, 0] + (detections.xyxy[:, 2] - detections.xyxy[:, 0]) / 2\n+    # Utilize efficient NumPy broadcasting to compute the center x-coordinate\n+    return (detections.xyxy[:, 0] + detections.xyxy[:, 2]) * 0.5\n \n \n def extract_y_coordinate_of_detections_center(detections: sv.Detections) -> np.ndarray:\n"
  },
  {
    "trace_id": "git_6b58b72b86fd",
    "function_name": "select_rightmost_detection",
    "file_path": "inference/core/workflows/core_steps/common/query_language/operations/detections/base.py",
    "speedup_x": 0.7,
    "review_quality": null,
    "pre_optimization_commit": "326999fd4355e9ee816e8f257ca3312bd833e5f0",
    "resolution_method": "git_parent",
    "source": "git",
    "original_function_code": "def select_rightmost_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    centers_x = detections.get_anchors_coordinates(anchor=Position.CENTER)[:, 0]\n    max_value = centers_x.max()\n    index = np.argwhere(centers_x == max_value)[-1].item()\n    return detections[index]\n",
    "optimized_function_code": "from copy import copy, deepcopy\nfrom typing import Any, Callable, Dict, List, Union\n\nimport numpy as np\nimport supervision as sv\nfrom supervision import Position\n\nfrom inference.core.workflows.core_steps.common.query_language.entities.enums import (\n    DetectionsProperty,\n    DetectionsSelectionMode,\n    DetectionsSortProperties,\n)\nfrom inference.core.workflows.core_steps.common.query_language.entities.operations import (\n    DEFAULT_OPERAND_NAME,\n)\nfrom inference.core.workflows.core_steps.common.query_language.errors import (\n    InvalidInputTypeError,\n    OperationError,\n    UndeclaredSymbolError,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.utils import (\n    safe_stringify,\n)\nfrom inference.core.workflows.core_steps.common.serializers import (\n    serialise_sv_detections,\n)\n\nPROPERTIES_EXTRACTORS = {\n    DetectionsProperty.CONFIDENCE: lambda detections: detections.confidence.tolist(),\n    DetectionsProperty.CLASS_NAME: lambda detections: detections.data.get(\n        \"class_name\", np.array([], dtype=str)\n    ).tolist(),\n    DetectionsProperty.X_MIN: lambda detections: detections.xyxy[:, 0].tolist(),\n    DetectionsProperty.Y_MIN: lambda detections: detections.xyxy[:, 1].tolist(),\n    DetectionsProperty.X_MAX: lambda detections: detections.xyxy[:, 2].tolist(),\n    DetectionsProperty.Y_MAX: lambda detections: detections.xyxy[:, 3].tolist(),\n    DetectionsProperty.CLASS_ID: lambda detections: detections.class_id.tolist(),\n    DetectionsProperty.SIZE: lambda detections: detections.box_area.tolist(),\n}\n\n\ndef extract_detections_property(\n    detections: Any,\n    property_name: DetectionsProperty,\n    execution_context: str,\n    **kwargs,\n) -> List[Any]:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing extract_detections_property(...) in context {execution_context}, \"\n            f\"expected sv.Detections object as value, got {value_as_str} of type {type(detections)}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n        )\n    return PROPERTIES_EXTRACTORS[property_name](detections)\n\n\ndef filter_detections(\n    detections: Any,\n    filtering_fun: Callable[[Dict[str, Any]], bool],\n    global_parameters: Dict[str, Any],\n) -> sv.Detections:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing filter_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(detections)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    local_parameters = copy(global_parameters)\n    result = []\n    for detection in detections:\n        local_parameters[DEFAULT_OPERAND_NAME] = detection\n        should_stay = filtering_fun(local_parameters)\n        result.append(should_stay)\n    return detections[result]\n\n\ndef offset_detections(\n    value: Any, offset_x: int, offset_y: int, **kwargs\n) -> sv.Detections:\n    if not isinstance(value, sv.Detections):\n        value_as_str = safe_stringify(value=value)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing offset_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(value)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    detections_copy = deepcopy(value)\n    detections_copy.xyxy += [-offset_x / 2, -offset_y / 2, offset_x / 2, offset_y / 2]\n    return detections_copy\n\n\ndef shift_detections(value: Any, shift_x: int, shift_y: int, **kwargs) -> sv.Detections:\n    if not isinstance(value, sv.Detections):\n        value_as_str = safe_stringify(value=value)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing shift_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(value)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    detections_copy = deepcopy(value)\n    detections_copy.xyxy += [shift_x, shift_y, shift_x, shift_y]\n    return detections_copy\n\n\ndef select_top_confidence_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    confidence = detections.confidence\n    max_value = confidence.max()\n    index = np.argwhere(confidence == max_value)[0].item()\n    return detections[index]\n\n\ndef select_leftmost_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    centers_x = detections.get_anchors_coordinates(anchor=Position.CENTER)[:, 0]\n    min_value = centers_x.min()\n    index = np.argwhere(centers_x == min_value)[0].item()\n    return detections[index]\n\n\ndef select_rightmost_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return detections\n\n    centers_x = detections.get_anchors_coordinates(anchor=Position.CENTER)[:, 0]\n    index = centers_x.argmax()\n    return detections[index]\n\n\ndef select_first_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    return detections[0]\n\n\ndef select_last_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    return detections[-1]\n\n\nDETECTIONS_SELECTORS = {\n    DetectionsSelectionMode.FIRST: select_first_detection,\n    DetectionsSelectionMode.LAST: select_last_detection,\n    DetectionsSelectionMode.LEFT_MOST: select_leftmost_detection,\n    DetectionsSelectionMode.RIGHT_MOST: select_rightmost_detection,\n    DetectionsSelectionMode.TOP_CONFIDENCE: select_top_confidence_detection,\n}\n\n\ndef select_detections(\n    value: Any, mode: DetectionsSelectionMode, **kwargs\n) -> sv.Detections:\n    if not isinstance(value, sv.Detections):\n        value_as_str = safe_stringify(value=value)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing select_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(value)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if mode not in DETECTIONS_SELECTORS:\n        InvalidInputTypeError(\n            public_message=f\"Executing select_detections(...), expected mode to be one of {DETECTIONS_SELECTORS.values()}, \"\n            f\"got {mode}.\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    return DETECTIONS_SELECTORS[mode](value)\n\n\ndef extract_x_coordinate_of_detections_center(detections: sv.Detections) -> np.ndarray:\n    return detections.xyxy[:, 0] + (detections.xyxy[:, 2] - detections.xyxy[:, 0]) / 2\n\n\ndef extract_y_coordinate_of_detections_center(detections: sv.Detections) -> np.ndarray:\n    return detections.xyxy[:, 1] + (detections.xyxy[:, 3] - detections.xyxy[:, 1]) / 2\n\n\nSORT_PROPERTIES_EXTRACT = {\n    DetectionsSortProperties.CONFIDENCE: lambda detections: detections.confidence,\n    DetectionsSortProperties.X_MIN: lambda detections: detections.xyxy[:, 0],\n    DetectionsSortProperties.X_MAX: lambda detections: detections.xyxy[:, 2],\n    DetectionsSortProperties.Y_MIN: lambda detections: detections.xyxy[:, 1],\n    DetectionsSortProperties.Y_MAX: lambda detections: detections.xyxy[:, 3],\n    DetectionsSortProperties.SIZE: lambda detections: detections.box_area,\n    DetectionsSortProperties.CENTER_X: extract_x_coordinate_of_detections_center,\n    DetectionsSortProperties.CENTER_Y: extract_y_coordinate_of_detections_center,\n}\n\n\ndef sort_detections(\n    value: Any, mode: DetectionsSortProperties, ascending: bool, **kwargs\n) -> sv.Detections:\n    if not isinstance(value, sv.Detections):\n        value_as_str = safe_stringify(value=value)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing sort_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(value)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if mode not in SORT_PROPERTIES_EXTRACT:\n        raise InvalidInputTypeError(\n            public_message=f\"Executing sort_detections(...), expected mode to be one of \"\n            f\"{SORT_PROPERTIES_EXTRACT.values()}, got {mode}.\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if len(value) == 0:\n        return value\n    extracted_property = SORT_PROPERTIES_EXTRACT[mode](value)\n    if extracted_property is None:\n        # property may not be set, as sv.Detections declares Optional[...]\n        return value\n    sorted_indices = np.argsort(extracted_property)\n    if not ascending:\n        sorted_indices = sorted_indices[::-1]\n    return value[sorted_indices]\n\n\ndef rename_detections(\n    detections: Any,\n    class_map: Union[Dict[str, str], str],\n    strict: Union[bool, str],\n    new_classes_id_offset: int,\n    global_parameters: Dict[str, Any],\n    **kwargs,\n) -> sv.Detections:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing rename_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(detections)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if isinstance(class_map, str):\n        if class_map not in global_parameters:\n            raise UndeclaredSymbolError(\n                public_message=f\"Attempted to retrieve variable `{class_map}` that was expected to hold \"\n                f\"class mapping of rename_detections(...), but that turned out not to be registered.\",\n                context=\"step_execution | roboflow_query_language_evaluation\",\n            )\n        class_map = global_parameters[class_map]\n    if not isinstance(class_map, dict):\n        value_as_str = safe_stringify(value=class_map)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing rename_detections(...), expected dictionary to be given as class map, \"\n            f\"got {value_as_str} of type {type(class_map)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if isinstance(strict, str):\n        if strict not in global_parameters:\n            raise UndeclaredSymbolError(\n                public_message=f\"Attempted to retrieve variable `{strict}` that was expected to hold \"\n                f\"parameter for `strict` flag of rename_detections(...), but that turned out not \"\n                f\"to be registered.\",\n                context=\"step_execution | roboflow_query_language_evaluation\",\n            )\n        strict = global_parameters[strict]\n    if not isinstance(strict, bool):\n        value_as_str = safe_stringify(value=strict)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing rename_detections(...), expected dictionary to be given as `strict` flag, \"\n            f\"got {value_as_str} of type {type(strict)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    detections_copy = deepcopy(detections)\n    original_class_names = detections_copy.data.get(\"class_name\", []).tolist()\n    original_class_ids = detections_copy.class_id.tolist()\n    new_class_names = []\n    new_class_ids = []\n    if strict:\n        _ensure_all_classes_covered_in_new_mapping(\n            original_class_names=original_class_names,\n            class_map=class_map,\n        )\n        new_class_mapping = {\n            class_name: class_id\n            for class_id, class_name in enumerate(sorted(set(class_map.values())))\n        }\n    else:\n        new_class_mapping = _build_non_strict_class_to_id_mapping(\n            original_class_names=original_class_names,\n            original_class_ids=original_class_ids,\n            class_map=class_map,\n            new_classes_id_offset=new_classes_id_offset,\n        )\n    for class_name in original_class_names:\n        new_class_name = class_map.get(class_name, class_name)\n        new_class_id = new_class_mapping[new_class_name]\n        new_class_names.append(new_class_name)\n        new_class_ids.append(new_class_id)\n    detections_copy.data[\"class_name\"] = np.array(new_class_names, dtype=object)\n    detections_copy.class_id = np.array(new_class_ids, dtype=int)\n    return detections_copy\n\n\ndef _ensure_all_classes_covered_in_new_mapping(\n    original_class_names: List[str],\n    class_map: Dict[str, str],\n) -> None:\n    for original_class in original_class_names:\n        if original_class not in class_map:\n            raise OperationError(\n                public_message=f\"Class '{original_class}' not found in class_map.\",\n                context=\"step_execution | roboflow_query_language_evaluation\",\n            )\n\n\ndef _build_non_strict_class_to_id_mapping(\n    original_class_names: List[str],\n    original_class_ids: List[int],\n    class_map: Dict[str, str],\n    new_classes_id_offset: int,\n) -> Dict[str, int]:\n    original_mapping = {\n        class_name: class_id\n        for class_name, class_id in zip(original_class_names, original_class_ids)\n    }\n    new_target_classes = {\n        new_class_name\n        for new_class_name in class_map.values()\n        if new_class_name not in original_mapping\n    }\n    new_class_id = new_classes_id_offset\n    for new_target_class in sorted(new_target_classes):\n        original_mapping[new_target_class] = new_class_id\n        new_class_id += 1\n    return original_mapping\n\n\ndef detections_to_dictionary(\n    detections: Any,\n    execution_context: str,\n    **kwargs,\n) -> dict:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing detections_to_dictionary(...) in context {execution_context}, \"\n            f\"expected sv.Detections object as value, got {value_as_str} of type {type(detections)}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n        )\n    try:\n        return serialise_sv_detections(detections=detections)\n    except Exception as error:\n        raise OperationError(\n            public_message=f\"While Using operation detections_to_dictionary(...) in context {execution_context} \"\n            f\"encountered error: {error}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n            inner_error=error,\n        )\n\n\ndef pick_detections_by_parent_class(\n    detections: Any,\n    parent_class: str,\n    execution_context: str,\n    **kwargs,\n) -> sv.Detections:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing pick_detections_by_parent_class(...) in context {execution_context}, \"\n            f\"expected sv.Detections object as value, got {value_as_str} of type {type(detections)}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n        )\n    try:\n        return _pick_detections_by_parent_class(\n            detections=detections, parent_class=parent_class\n        )\n    except Exception as error:\n        raise OperationError(\n            public_message=f\"While Using operation pick_detections_by_parent_class(...) in context {execution_context} \"\n            f\"encountered error: {error}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n            inner_error=error,\n        )\n\n\ndef _pick_detections_by_parent_class(\n    detections: sv.Detections,\n    parent_class: str,\n) -> sv.Detections:\n    class_names = detections.data.get(\"class_name\")\n    if class_names is None or len(class_names) == 0:\n        return sv.Detections.empty()\n    if not isinstance(class_names, np.ndarray):\n        class_names = np.array(class_names)\n    parent_mask = class_names == parent_class\n    parent_detections = detections[parent_mask]\n    if len(parent_detections) == 0:\n        return sv.Detections.empty()\n    dependent_detections = detections[~parent_mask]\n    dependent_detections_anchors = dependent_detections.get_anchors_coordinates(\n        anchor=Position.CENTER\n    )\n    dependent_detections_to_keep = set()\n    for detection_idx, anchor in enumerate(dependent_detections_anchors):\n        for parent_detection_box in parent_detections.xyxy:\n            if _is_point_within_box(point=anchor, box=parent_detection_box):\n                dependent_detections_to_keep.add(detection_idx)\n                continue\n    detections_to_keep_list = sorted(list(dependent_detections_to_keep))\n    filtered_dependent_detections = dependent_detections[detections_to_keep_list]\n    return sv.Detections.merge([parent_detections, filtered_dependent_detections])\n\n\ndef _is_point_within_box(point: np.ndarray, box: np.ndarray) -> bool:\n    px, py = point\n    x1, y1, x2, y2 = box\n    return x1 <= px <= x2 and y1 <= py <= y2\n",
    "optimized_raw_markdown": "",
    "optimized_function_only": "def select_rightmost_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return detections\n\n    centers_x = detections.get_anchors_coordinates(anchor=Position.CENTER)[:, 0]\n    index = centers_x.argmax()\n    return detections[index]\n",
    "original_file_content": "from copy import copy, deepcopy\nfrom typing import Any, Callable, Dict, List, Union\n\nimport numpy as np\nimport supervision as sv\nfrom supervision import Position\n\nfrom inference.core.workflows.core_steps.common.query_language.entities.enums import (\n    DetectionsProperty,\n    DetectionsSelectionMode,\n    DetectionsSortProperties,\n)\nfrom inference.core.workflows.core_steps.common.query_language.entities.operations import (\n    DEFAULT_OPERAND_NAME,\n)\nfrom inference.core.workflows.core_steps.common.query_language.errors import (\n    InvalidInputTypeError,\n    OperationError,\n    UndeclaredSymbolError,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.utils import (\n    safe_stringify,\n)\nfrom inference.core.workflows.core_steps.common.serializers import (\n    serialise_sv_detections,\n)\n\nPROPERTIES_EXTRACTORS = {\n    DetectionsProperty.CONFIDENCE: lambda detections: detections.confidence.tolist(),\n    DetectionsProperty.CLASS_NAME: lambda detections: detections.data.get(\n        \"class_name\", np.array([], dtype=str)\n    ).tolist(),\n    DetectionsProperty.X_MIN: lambda detections: detections.xyxy[:, 0].tolist(),\n    DetectionsProperty.Y_MIN: lambda detections: detections.xyxy[:, 1].tolist(),\n    DetectionsProperty.X_MAX: lambda detections: detections.xyxy[:, 2].tolist(),\n    DetectionsProperty.Y_MAX: lambda detections: detections.xyxy[:, 3].tolist(),\n    DetectionsProperty.CLASS_ID: lambda detections: detections.class_id.tolist(),\n    DetectionsProperty.SIZE: lambda detections: detections.box_area.tolist(),\n}\n\n\ndef extract_detections_property(\n    detections: Any,\n    property_name: DetectionsProperty,\n    execution_context: str,\n    **kwargs,\n) -> List[Any]:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing extract_detections_property(...) in context {execution_context}, \"\n            f\"expected sv.Detections object as value, got {value_as_str} of type {type(detections)}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n        )\n    return PROPERTIES_EXTRACTORS[property_name](detections)\n\n\ndef filter_detections(\n    detections: Any,\n    filtering_fun: Callable[[Dict[str, Any]], bool],\n    global_parameters: Dict[str, Any],\n) -> sv.Detections:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing filter_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(detections)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    local_parameters = copy(global_parameters)\n    result = []\n    for detection in detections:\n        local_parameters[DEFAULT_OPERAND_NAME] = detection\n        should_stay = filtering_fun(local_parameters)\n        result.append(should_stay)\n    return detections[result]\n\n\ndef offset_detections(\n    value: Any, offset_x: int, offset_y: int, **kwargs\n) -> sv.Detections:\n    if not isinstance(value, sv.Detections):\n        value_as_str = safe_stringify(value=value)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing offset_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(value)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    detections_copy = deepcopy(value)\n    detections_copy.xyxy += [-offset_x / 2, -offset_y / 2, offset_x / 2, offset_y / 2]\n    return detections_copy\n\n\ndef shift_detections(value: Any, shift_x: int, shift_y: int, **kwargs) -> sv.Detections:\n    if not isinstance(value, sv.Detections):\n        value_as_str = safe_stringify(value=value)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing shift_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(value)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    detections_copy = deepcopy(value)\n    detections_copy.xyxy += [shift_x, shift_y, shift_x, shift_y]\n    return detections_copy\n\n\ndef select_top_confidence_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    confidence = detections.confidence\n    max_value = confidence.max()\n    index = np.argwhere(confidence == max_value)[0].item()\n    return detections[index]\n\n\ndef select_leftmost_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    centers_x = detections.get_anchors_coordinates(anchor=Position.CENTER)[:, 0]\n    min_value = centers_x.min()\n    index = np.argwhere(centers_x == min_value)[0].item()\n    return detections[index]\n\n\ndef select_rightmost_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    centers_x = detections.get_anchors_coordinates(anchor=Position.CENTER)[:, 0]\n    max_value = centers_x.max()\n    index = np.argwhere(centers_x == max_value)[-1].item()\n    return detections[index]\n\n\ndef select_first_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    return detections[0]\n\n\ndef select_last_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    return detections[-1]\n\n\nDETECTIONS_SELECTORS = {\n    DetectionsSelectionMode.FIRST: select_first_detection,\n    DetectionsSelectionMode.LAST: select_last_detection,\n    DetectionsSelectionMode.LEFT_MOST: select_leftmost_detection,\n    DetectionsSelectionMode.RIGHT_MOST: select_rightmost_detection,\n    DetectionsSelectionMode.TOP_CONFIDENCE: select_top_confidence_detection,\n}\n\n\ndef select_detections(\n    value: Any, mode: DetectionsSelectionMode, **kwargs\n) -> sv.Detections:\n    if not isinstance(value, sv.Detections):\n        value_as_str = safe_stringify(value=value)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing select_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(value)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if mode not in DETECTIONS_SELECTORS:\n        InvalidInputTypeError(\n            public_message=f\"Executing select_detections(...), expected mode to be one of {DETECTIONS_SELECTORS.values()}, \"\n            f\"got {mode}.\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    return DETECTIONS_SELECTORS[mode](value)\n\n\ndef extract_x_coordinate_of_detections_center(detections: sv.Detections) -> np.ndarray:\n    return detections.xyxy[:, 0] + (detections.xyxy[:, 2] - detections.xyxy[:, 0]) / 2\n\n\ndef extract_y_coordinate_of_detections_center(detections: sv.Detections) -> np.ndarray:\n    return detections.xyxy[:, 1] + (detections.xyxy[:, 3] - detections.xyxy[:, 1]) / 2\n\n\nSORT_PROPERTIES_EXTRACT = {\n    DetectionsSortProperties.CONFIDENCE: lambda detections: detections.confidence,\n    DetectionsSortProperties.X_MIN: lambda detections: detections.xyxy[:, 0],\n    DetectionsSortProperties.X_MAX: lambda detections: detections.xyxy[:, 2],\n    DetectionsSortProperties.Y_MIN: lambda detections: detections.xyxy[:, 1],\n    DetectionsSortProperties.Y_MAX: lambda detections: detections.xyxy[:, 3],\n    DetectionsSortProperties.SIZE: lambda detections: detections.box_area,\n    DetectionsSortProperties.CENTER_X: extract_x_coordinate_of_detections_center,\n    DetectionsSortProperties.CENTER_Y: extract_y_coordinate_of_detections_center,\n}\n\n\ndef sort_detections(\n    value: Any, mode: DetectionsSortProperties, ascending: bool, **kwargs\n) -> sv.Detections:\n    if not isinstance(value, sv.Detections):\n        value_as_str = safe_stringify(value=value)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing sort_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(value)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if mode not in SORT_PROPERTIES_EXTRACT:\n        raise InvalidInputTypeError(\n            public_message=f\"Executing sort_detections(...), expected mode to be one of \"\n            f\"{SORT_PROPERTIES_EXTRACT.values()}, got {mode}.\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if len(value) == 0:\n        return value\n    extracted_property = SORT_PROPERTIES_EXTRACT[mode](value)\n    if extracted_property is None:\n        # property may not be set, as sv.Detections declares Optional[...]\n        return value\n    sorted_indices = np.argsort(extracted_property)\n    if not ascending:\n        sorted_indices = sorted_indices[::-1]\n    return value[sorted_indices]\n\n\ndef rename_detections(\n    detections: Any,\n    class_map: Union[Dict[str, str], str],\n    strict: Union[bool, str],\n    new_classes_id_offset: int,\n    global_parameters: Dict[str, Any],\n    **kwargs,\n) -> sv.Detections:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing rename_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(detections)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if isinstance(class_map, str):\n        if class_map not in global_parameters:\n            raise UndeclaredSymbolError(\n                public_message=f\"Attempted to retrieve variable `{class_map}` that was expected to hold \"\n                f\"class mapping of rename_detections(...), but that turned out not to be registered.\",\n                context=\"step_execution | roboflow_query_language_evaluation\",\n            )\n        class_map = global_parameters[class_map]\n    if not isinstance(class_map, dict):\n        value_as_str = safe_stringify(value=class_map)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing rename_detections(...), expected dictionary to be given as class map, \"\n            f\"got {value_as_str} of type {type(class_map)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if isinstance(strict, str):\n        if strict not in global_parameters:\n            raise UndeclaredSymbolError(\n                public_message=f\"Attempted to retrieve variable `{strict}` that was expected to hold \"\n                f\"parameter for `strict` flag of rename_detections(...), but that turned out not \"\n                f\"to be registered.\",\n                context=\"step_execution | roboflow_query_language_evaluation\",\n            )\n        strict = global_parameters[strict]\n    if not isinstance(strict, bool):\n        value_as_str = safe_stringify(value=strict)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing rename_detections(...), expected dictionary to be given as `strict` flag, \"\n            f\"got {value_as_str} of type {type(strict)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    detections_copy = deepcopy(detections)\n    original_class_names = detections_copy.data.get(\"class_name\", []).tolist()\n    original_class_ids = detections_copy.class_id.tolist()\n    new_class_names = []\n    new_class_ids = []\n    if strict:\n        _ensure_all_classes_covered_in_new_mapping(\n            original_class_names=original_class_names,\n            class_map=class_map,\n        )\n        new_class_mapping = {\n            class_name: class_id\n            for class_id, class_name in enumerate(sorted(set(class_map.values())))\n        }\n    else:\n        new_class_mapping = _build_non_strict_class_to_id_mapping(\n            original_class_names=original_class_names,\n            original_class_ids=original_class_ids,\n            class_map=class_map,\n            new_classes_id_offset=new_classes_id_offset,\n        )\n    for class_name in original_class_names:\n        new_class_name = class_map.get(class_name, class_name)\n        new_class_id = new_class_mapping[new_class_name]\n        new_class_names.append(new_class_name)\n        new_class_ids.append(new_class_id)\n    detections_copy.data[\"class_name\"] = np.array(new_class_names, dtype=object)\n    detections_copy.class_id = np.array(new_class_ids, dtype=int)\n    return detections_copy\n\n\ndef _ensure_all_classes_covered_in_new_mapping(\n    original_class_names: List[str],\n    class_map: Dict[str, str],\n) -> None:\n    for original_class in original_class_names:\n        if original_class not in class_map:\n            raise OperationError(\n                public_message=f\"Class '{original_class}' not found in class_map.\",\n                context=\"step_execution | roboflow_query_language_evaluation\",\n            )\n\n\ndef _build_non_strict_class_to_id_mapping(\n    original_class_names: List[str],\n    original_class_ids: List[int],\n    class_map: Dict[str, str],\n    new_classes_id_offset: int,\n) -> Dict[str, int]:\n    original_mapping = {\n        class_name: class_id\n        for class_name, class_id in zip(original_class_names, original_class_ids)\n    }\n    new_target_classes = {\n        new_class_name\n        for new_class_name in class_map.values()\n        if new_class_name not in original_mapping\n    }\n    new_class_id = new_classes_id_offset\n    for new_target_class in sorted(new_target_classes):\n        original_mapping[new_target_class] = new_class_id\n        new_class_id += 1\n    return original_mapping\n\n\ndef detections_to_dictionary(\n    detections: Any,\n    execution_context: str,\n    **kwargs,\n) -> dict:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing detections_to_dictionary(...) in context {execution_context}, \"\n            f\"expected sv.Detections object as value, got {value_as_str} of type {type(detections)}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n        )\n    try:\n        return serialise_sv_detections(detections=detections)\n    except Exception as error:\n        raise OperationError(\n            public_message=f\"While Using operation detections_to_dictionary(...) in context {execution_context} \"\n            f\"encountered error: {error}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n            inner_error=error,\n        )\n\n\ndef pick_detections_by_parent_class(\n    detections: Any,\n    parent_class: str,\n    execution_context: str,\n    **kwargs,\n) -> sv.Detections:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing pick_detections_by_parent_class(...) in context {execution_context}, \"\n            f\"expected sv.Detections object as value, got {value_as_str} of type {type(detections)}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n        )\n    try:\n        return _pick_detections_by_parent_class(\n            detections=detections, parent_class=parent_class\n        )\n    except Exception as error:\n        raise OperationError(\n            public_message=f\"While Using operation pick_detections_by_parent_class(...) in context {execution_context} \"\n            f\"encountered error: {error}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n            inner_error=error,\n        )\n\n\ndef _pick_detections_by_parent_class(\n    detections: sv.Detections,\n    parent_class: str,\n) -> sv.Detections:\n    class_names = detections.data.get(\"class_name\")\n    if class_names is None or len(class_names) == 0:\n        return sv.Detections.empty()\n    if not isinstance(class_names, np.ndarray):\n        class_names = np.array(class_names)\n    parent_mask = class_names == parent_class\n    parent_detections = detections[parent_mask]\n    if len(parent_detections) == 0:\n        return sv.Detections.empty()\n    dependent_detections = detections[~parent_mask]\n    dependent_detections_anchors = dependent_detections.get_anchors_coordinates(\n        anchor=Position.CENTER\n    )\n    dependent_detections_to_keep = set()\n    for detection_idx, anchor in enumerate(dependent_detections_anchors):\n        for parent_detection_box in parent_detections.xyxy:\n            if _is_point_within_box(point=anchor, box=parent_detection_box):\n                dependent_detections_to_keep.add(detection_idx)\n                continue\n    detections_to_keep_list = sorted(list(dependent_detections_to_keep))\n    filtered_dependent_detections = dependent_detections[detections_to_keep_list]\n    return sv.Detections.merge([parent_detections, filtered_dependent_detections])\n\n\ndef _is_point_within_box(point: np.ndarray, box: np.ndarray) -> bool:\n    px, py = point\n    x1, y1, x2, y2 = box\n    return x1 <= px <= x2 and y1 <= py <= y2\n",
    "patch": "diff --git a/inference/core/workflows/core_steps/common/query_language/operations/detections/base.py b/inference/core/workflows/core_steps/common/query_language/operations/detections/base.py\nindex 04c6921f7..df1eaf746 100644\n--- a/inference/core/workflows/core_steps/common/query_language/operations/detections/base.py\n+++ b/inference/core/workflows/core_steps/common/query_language/operations/detections/base.py\n@@ -124,10 +124,10 @@ def select_leftmost_detection(detections: sv.Detections) -> sv.Detections:\n \n def select_rightmost_detection(detections: sv.Detections) -> sv.Detections:\n     if len(detections) == 0:\n-        return deepcopy(detections)\n+        return detections\n+\n     centers_x = detections.get_anchors_coordinates(anchor=Position.CENTER)[:, 0]\n-    max_value = centers_x.max()\n-    index = np.argwhere(centers_x == max_value)[-1].item()\n+    index = centers_x.argmax()\n     return detections[index]\n \n \n"
  },
  {
    "trace_id": "git_0da1c62df7b5",
    "function_name": "select_leftmost_detection",
    "file_path": "inference/core/workflows/core_steps/common/query_language/operations/detections/base.py",
    "speedup_x": 1.53,
    "review_quality": null,
    "pre_optimization_commit": "326999fd4355e9ee816e8f257ca3312bd833e5f0",
    "resolution_method": "git_parent",
    "source": "git",
    "original_function_code": "def select_leftmost_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    centers_x = detections.get_anchors_coordinates(anchor=Position.CENTER)[:, 0]\n    min_value = centers_x.min()\n    index = np.argwhere(centers_x == min_value)[0].item()\n    return detections[index]\n",
    "optimized_function_code": "from copy import copy, deepcopy\nfrom typing import Any, Callable, Dict, List, Union\n\nimport numpy as np\nimport supervision as sv\nfrom supervision import Position\n\nfrom inference.core.workflows.core_steps.common.query_language.entities.enums import (\n    DetectionsProperty,\n    DetectionsSelectionMode,\n    DetectionsSortProperties,\n)\nfrom inference.core.workflows.core_steps.common.query_language.entities.operations import (\n    DEFAULT_OPERAND_NAME,\n)\nfrom inference.core.workflows.core_steps.common.query_language.errors import (\n    InvalidInputTypeError,\n    OperationError,\n    UndeclaredSymbolError,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.utils import (\n    safe_stringify,\n)\nfrom inference.core.workflows.core_steps.common.serializers import (\n    serialise_sv_detections,\n)\n\nPROPERTIES_EXTRACTORS = {\n    DetectionsProperty.CONFIDENCE: lambda detections: detections.confidence.tolist(),\n    DetectionsProperty.CLASS_NAME: lambda detections: detections.data.get(\n        \"class_name\", np.array([], dtype=str)\n    ).tolist(),\n    DetectionsProperty.X_MIN: lambda detections: detections.xyxy[:, 0].tolist(),\n    DetectionsProperty.Y_MIN: lambda detections: detections.xyxy[:, 1].tolist(),\n    DetectionsProperty.X_MAX: lambda detections: detections.xyxy[:, 2].tolist(),\n    DetectionsProperty.Y_MAX: lambda detections: detections.xyxy[:, 3].tolist(),\n    DetectionsProperty.CLASS_ID: lambda detections: detections.class_id.tolist(),\n    DetectionsProperty.SIZE: lambda detections: detections.box_area.tolist(),\n}\n\n\ndef extract_detections_property(\n    detections: Any,\n    property_name: DetectionsProperty,\n    execution_context: str,\n    **kwargs,\n) -> List[Any]:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing extract_detections_property(...) in context {execution_context}, \"\n            f\"expected sv.Detections object as value, got {value_as_str} of type {type(detections)}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n        )\n    return PROPERTIES_EXTRACTORS[property_name](detections)\n\n\ndef filter_detections(\n    detections: Any,\n    filtering_fun: Callable[[Dict[str, Any]], bool],\n    global_parameters: Dict[str, Any],\n) -> sv.Detections:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing filter_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(detections)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    local_parameters = copy(global_parameters)\n    result = []\n    for detection in detections:\n        local_parameters[DEFAULT_OPERAND_NAME] = detection\n        should_stay = filtering_fun(local_parameters)\n        result.append(should_stay)\n    return detections[result]\n\n\ndef offset_detections(\n    value: Any, offset_x: int, offset_y: int, **kwargs\n) -> sv.Detections:\n    if not isinstance(value, sv.Detections):\n        value_as_str = safe_stringify(value=value)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing offset_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(value)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    detections_copy = deepcopy(value)\n    detections_copy.xyxy += [-offset_x / 2, -offset_y / 2, offset_x / 2, offset_y / 2]\n    return detections_copy\n\n\ndef shift_detections(value: Any, shift_x: int, shift_y: int, **kwargs) -> sv.Detections:\n    if not isinstance(value, sv.Detections):\n        value_as_str = safe_stringify(value=value)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing shift_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(value)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    detections_copy = deepcopy(value)\n    detections_copy.xyxy += [shift_x, shift_y, shift_x, shift_y]\n    return detections_copy\n\n\ndef select_top_confidence_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    confidence = detections.confidence\n    max_value = confidence.max()\n    index = np.argwhere(confidence == max_value)[0].item()\n    return detections[index]\n\n\ndef select_leftmost_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return detections  # Directly return the original empty detections if empty\n\n    centers_x = detections.get_anchors_coordinates(anchor=Position.CENTER)[:, 0]\n    index = np.argmin(\n        centers_x\n    )  # Using np.argmin directly to find the index of the minimum value\n    return detections[\n        index\n    ].copy()  # Use copy instead of deepcopy for better performance\n\n\ndef select_rightmost_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    centers_x = detections.get_anchors_coordinates(anchor=Position.CENTER)[:, 0]\n    max_value = centers_x.max()\n    index = np.argwhere(centers_x == max_value)[-1].item()\n    return detections[index]\n\n\ndef select_first_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    return detections[0]\n\n\ndef select_last_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    return detections[-1]\n\n\nDETECTIONS_SELECTORS = {\n    DetectionsSelectionMode.FIRST: select_first_detection,\n    DetectionsSelectionMode.LAST: select_last_detection,\n    DetectionsSelectionMode.LEFT_MOST: select_leftmost_detection,\n    DetectionsSelectionMode.RIGHT_MOST: select_rightmost_detection,\n    DetectionsSelectionMode.TOP_CONFIDENCE: select_top_confidence_detection,\n}\n\n\ndef select_detections(\n    value: Any, mode: DetectionsSelectionMode, **kwargs\n) -> sv.Detections:\n    if not isinstance(value, sv.Detections):\n        value_as_str = safe_stringify(value=value)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing select_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(value)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if mode not in DETECTIONS_SELECTORS:\n        InvalidInputTypeError(\n            public_message=f\"Executing select_detections(...), expected mode to be one of {DETECTIONS_SELECTORS.values()}, \"\n            f\"got {mode}.\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    return DETECTIONS_SELECTORS[mode](value)\n\n\ndef extract_x_coordinate_of_detections_center(detections: sv.Detections) -> np.ndarray:\n    return detections.xyxy[:, 0] + (detections.xyxy[:, 2] - detections.xyxy[:, 0]) / 2\n\n\ndef extract_y_coordinate_of_detections_center(detections: sv.Detections) -> np.ndarray:\n    return detections.xyxy[:, 1] + (detections.xyxy[:, 3] - detections.xyxy[:, 1]) / 2\n\n\nSORT_PROPERTIES_EXTRACT = {\n    DetectionsSortProperties.CONFIDENCE: lambda detections: detections.confidence,\n    DetectionsSortProperties.X_MIN: lambda detections: detections.xyxy[:, 0],\n    DetectionsSortProperties.X_MAX: lambda detections: detections.xyxy[:, 2],\n    DetectionsSortProperties.Y_MIN: lambda detections: detections.xyxy[:, 1],\n    DetectionsSortProperties.Y_MAX: lambda detections: detections.xyxy[:, 3],\n    DetectionsSortProperties.SIZE: lambda detections: detections.box_area,\n    DetectionsSortProperties.CENTER_X: extract_x_coordinate_of_detections_center,\n    DetectionsSortProperties.CENTER_Y: extract_y_coordinate_of_detections_center,\n}\n\n\ndef sort_detections(\n    value: Any, mode: DetectionsSortProperties, ascending: bool, **kwargs\n) -> sv.Detections:\n    if not isinstance(value, sv.Detections):\n        value_as_str = safe_stringify(value=value)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing sort_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(value)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if mode not in SORT_PROPERTIES_EXTRACT:\n        raise InvalidInputTypeError(\n            public_message=f\"Executing sort_detections(...), expected mode to be one of \"\n            f\"{SORT_PROPERTIES_EXTRACT.values()}, got {mode}.\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if len(value) == 0:\n        return value\n    extracted_property = SORT_PROPERTIES_EXTRACT[mode](value)\n    if extracted_property is None:\n        # property may not be set, as sv.Detections declares Optional[...]\n        return value\n    sorted_indices = np.argsort(extracted_property)\n    if not ascending:\n        sorted_indices = sorted_indices[::-1]\n    return value[sorted_indices]\n\n\ndef rename_detections(\n    detections: Any,\n    class_map: Union[Dict[str, str], str],\n    strict: Union[bool, str],\n    new_classes_id_offset: int,\n    global_parameters: Dict[str, Any],\n    **kwargs,\n) -> sv.Detections:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing rename_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(detections)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if isinstance(class_map, str):\n        if class_map not in global_parameters:\n            raise UndeclaredSymbolError(\n                public_message=f\"Attempted to retrieve variable `{class_map}` that was expected to hold \"\n                f\"class mapping of rename_detections(...), but that turned out not to be registered.\",\n                context=\"step_execution | roboflow_query_language_evaluation\",\n            )\n        class_map = global_parameters[class_map]\n    if not isinstance(class_map, dict):\n        value_as_str = safe_stringify(value=class_map)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing rename_detections(...), expected dictionary to be given as class map, \"\n            f\"got {value_as_str} of type {type(class_map)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if isinstance(strict, str):\n        if strict not in global_parameters:\n            raise UndeclaredSymbolError(\n                public_message=f\"Attempted to retrieve variable `{strict}` that was expected to hold \"\n                f\"parameter for `strict` flag of rename_detections(...), but that turned out not \"\n                f\"to be registered.\",\n                context=\"step_execution | roboflow_query_language_evaluation\",\n            )\n        strict = global_parameters[strict]\n    if not isinstance(strict, bool):\n        value_as_str = safe_stringify(value=strict)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing rename_detections(...), expected dictionary to be given as `strict` flag, \"\n            f\"got {value_as_str} of type {type(strict)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    detections_copy = deepcopy(detections)\n    original_class_names = detections_copy.data.get(\"class_name\", []).tolist()\n    original_class_ids = detections_copy.class_id.tolist()\n    new_class_names = []\n    new_class_ids = []\n    if strict:\n        _ensure_all_classes_covered_in_new_mapping(\n            original_class_names=original_class_names,\n            class_map=class_map,\n        )\n        new_class_mapping = {\n            class_name: class_id\n            for class_id, class_name in enumerate(sorted(set(class_map.values())))\n        }\n    else:\n        new_class_mapping = _build_non_strict_class_to_id_mapping(\n            original_class_names=original_class_names,\n            original_class_ids=original_class_ids,\n            class_map=class_map,\n            new_classes_id_offset=new_classes_id_offset,\n        )\n    for class_name in original_class_names:\n        new_class_name = class_map.get(class_name, class_name)\n        new_class_id = new_class_mapping[new_class_name]\n        new_class_names.append(new_class_name)\n        new_class_ids.append(new_class_id)\n    detections_copy.data[\"class_name\"] = np.array(new_class_names, dtype=object)\n    detections_copy.class_id = np.array(new_class_ids, dtype=int)\n    return detections_copy\n\n\ndef _ensure_all_classes_covered_in_new_mapping(\n    original_class_names: List[str],\n    class_map: Dict[str, str],\n) -> None:\n    for original_class in original_class_names:\n        if original_class not in class_map:\n            raise OperationError(\n                public_message=f\"Class '{original_class}' not found in class_map.\",\n                context=\"step_execution | roboflow_query_language_evaluation\",\n            )\n\n\ndef _build_non_strict_class_to_id_mapping(\n    original_class_names: List[str],\n    original_class_ids: List[int],\n    class_map: Dict[str, str],\n    new_classes_id_offset: int,\n) -> Dict[str, int]:\n    original_mapping = {\n        class_name: class_id\n        for class_name, class_id in zip(original_class_names, original_class_ids)\n    }\n    new_target_classes = {\n        new_class_name\n        for new_class_name in class_map.values()\n        if new_class_name not in original_mapping\n    }\n    new_class_id = new_classes_id_offset\n    for new_target_class in sorted(new_target_classes):\n        original_mapping[new_target_class] = new_class_id\n        new_class_id += 1\n    return original_mapping\n\n\ndef detections_to_dictionary(\n    detections: Any,\n    execution_context: str,\n    **kwargs,\n) -> dict:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing detections_to_dictionary(...) in context {execution_context}, \"\n            f\"expected sv.Detections object as value, got {value_as_str} of type {type(detections)}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n        )\n    try:\n        return serialise_sv_detections(detections=detections)\n    except Exception as error:\n        raise OperationError(\n            public_message=f\"While Using operation detections_to_dictionary(...) in context {execution_context} \"\n            f\"encountered error: {error}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n            inner_error=error,\n        )\n\n\ndef pick_detections_by_parent_class(\n    detections: Any,\n    parent_class: str,\n    execution_context: str,\n    **kwargs,\n) -> sv.Detections:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing pick_detections_by_parent_class(...) in context {execution_context}, \"\n            f\"expected sv.Detections object as value, got {value_as_str} of type {type(detections)}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n        )\n    try:\n        return _pick_detections_by_parent_class(\n            detections=detections, parent_class=parent_class\n        )\n    except Exception as error:\n        raise OperationError(\n            public_message=f\"While Using operation pick_detections_by_parent_class(...) in context {execution_context} \"\n            f\"encountered error: {error}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n            inner_error=error,\n        )\n\n\ndef _pick_detections_by_parent_class(\n    detections: sv.Detections,\n    parent_class: str,\n) -> sv.Detections:\n    class_names = detections.data.get(\"class_name\")\n    if class_names is None or len(class_names) == 0:\n        return sv.Detections.empty()\n    if not isinstance(class_names, np.ndarray):\n        class_names = np.array(class_names)\n    parent_mask = class_names == parent_class\n    parent_detections = detections[parent_mask]\n    if len(parent_detections) == 0:\n        return sv.Detections.empty()\n    dependent_detections = detections[~parent_mask]\n    dependent_detections_anchors = dependent_detections.get_anchors_coordinates(\n        anchor=Position.CENTER\n    )\n    dependent_detections_to_keep = set()\n    for detection_idx, anchor in enumerate(dependent_detections_anchors):\n        for parent_detection_box in parent_detections.xyxy:\n            if _is_point_within_box(point=anchor, box=parent_detection_box):\n                dependent_detections_to_keep.add(detection_idx)\n                continue\n    detections_to_keep_list = sorted(list(dependent_detections_to_keep))\n    filtered_dependent_detections = dependent_detections[detections_to_keep_list]\n    return sv.Detections.merge([parent_detections, filtered_dependent_detections])\n\n\ndef _is_point_within_box(point: np.ndarray, box: np.ndarray) -> bool:\n    px, py = point\n    x1, y1, x2, y2 = box\n    return x1 <= px <= x2 and y1 <= py <= y2\n",
    "optimized_raw_markdown": "",
    "optimized_function_only": "def select_leftmost_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return detections  # Directly return the original empty detections if empty\n\n    centers_x = detections.get_anchors_coordinates(anchor=Position.CENTER)[:, 0]\n    index = np.argmin(\n        centers_x\n    )  # Using np.argmin directly to find the index of the minimum value\n    return detections[\n        index\n    ].copy()  # Use copy instead of deepcopy for better performance\n",
    "original_file_content": "from copy import copy, deepcopy\nfrom typing import Any, Callable, Dict, List, Union\n\nimport numpy as np\nimport supervision as sv\nfrom supervision import Position\n\nfrom inference.core.workflows.core_steps.common.query_language.entities.enums import (\n    DetectionsProperty,\n    DetectionsSelectionMode,\n    DetectionsSortProperties,\n)\nfrom inference.core.workflows.core_steps.common.query_language.entities.operations import (\n    DEFAULT_OPERAND_NAME,\n)\nfrom inference.core.workflows.core_steps.common.query_language.errors import (\n    InvalidInputTypeError,\n    OperationError,\n    UndeclaredSymbolError,\n)\nfrom inference.core.workflows.core_steps.common.query_language.operations.utils import (\n    safe_stringify,\n)\nfrom inference.core.workflows.core_steps.common.serializers import (\n    serialise_sv_detections,\n)\n\nPROPERTIES_EXTRACTORS = {\n    DetectionsProperty.CONFIDENCE: lambda detections: detections.confidence.tolist(),\n    DetectionsProperty.CLASS_NAME: lambda detections: detections.data.get(\n        \"class_name\", np.array([], dtype=str)\n    ).tolist(),\n    DetectionsProperty.X_MIN: lambda detections: detections.xyxy[:, 0].tolist(),\n    DetectionsProperty.Y_MIN: lambda detections: detections.xyxy[:, 1].tolist(),\n    DetectionsProperty.X_MAX: lambda detections: detections.xyxy[:, 2].tolist(),\n    DetectionsProperty.Y_MAX: lambda detections: detections.xyxy[:, 3].tolist(),\n    DetectionsProperty.CLASS_ID: lambda detections: detections.class_id.tolist(),\n    DetectionsProperty.SIZE: lambda detections: detections.box_area.tolist(),\n}\n\n\ndef extract_detections_property(\n    detections: Any,\n    property_name: DetectionsProperty,\n    execution_context: str,\n    **kwargs,\n) -> List[Any]:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing extract_detections_property(...) in context {execution_context}, \"\n            f\"expected sv.Detections object as value, got {value_as_str} of type {type(detections)}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n        )\n    return PROPERTIES_EXTRACTORS[property_name](detections)\n\n\ndef filter_detections(\n    detections: Any,\n    filtering_fun: Callable[[Dict[str, Any]], bool],\n    global_parameters: Dict[str, Any],\n) -> sv.Detections:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing filter_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(detections)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    local_parameters = copy(global_parameters)\n    result = []\n    for detection in detections:\n        local_parameters[DEFAULT_OPERAND_NAME] = detection\n        should_stay = filtering_fun(local_parameters)\n        result.append(should_stay)\n    return detections[result]\n\n\ndef offset_detections(\n    value: Any, offset_x: int, offset_y: int, **kwargs\n) -> sv.Detections:\n    if not isinstance(value, sv.Detections):\n        value_as_str = safe_stringify(value=value)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing offset_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(value)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    detections_copy = deepcopy(value)\n    detections_copy.xyxy += [-offset_x / 2, -offset_y / 2, offset_x / 2, offset_y / 2]\n    return detections_copy\n\n\ndef shift_detections(value: Any, shift_x: int, shift_y: int, **kwargs) -> sv.Detections:\n    if not isinstance(value, sv.Detections):\n        value_as_str = safe_stringify(value=value)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing shift_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(value)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    detections_copy = deepcopy(value)\n    detections_copy.xyxy += [shift_x, shift_y, shift_x, shift_y]\n    return detections_copy\n\n\ndef select_top_confidence_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    confidence = detections.confidence\n    max_value = confidence.max()\n    index = np.argwhere(confidence == max_value)[0].item()\n    return detections[index]\n\n\ndef select_leftmost_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    centers_x = detections.get_anchors_coordinates(anchor=Position.CENTER)[:, 0]\n    min_value = centers_x.min()\n    index = np.argwhere(centers_x == min_value)[0].item()\n    return detections[index]\n\n\ndef select_rightmost_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    centers_x = detections.get_anchors_coordinates(anchor=Position.CENTER)[:, 0]\n    max_value = centers_x.max()\n    index = np.argwhere(centers_x == max_value)[-1].item()\n    return detections[index]\n\n\ndef select_first_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    return detections[0]\n\n\ndef select_last_detection(detections: sv.Detections) -> sv.Detections:\n    if len(detections) == 0:\n        return deepcopy(detections)\n    return detections[-1]\n\n\nDETECTIONS_SELECTORS = {\n    DetectionsSelectionMode.FIRST: select_first_detection,\n    DetectionsSelectionMode.LAST: select_last_detection,\n    DetectionsSelectionMode.LEFT_MOST: select_leftmost_detection,\n    DetectionsSelectionMode.RIGHT_MOST: select_rightmost_detection,\n    DetectionsSelectionMode.TOP_CONFIDENCE: select_top_confidence_detection,\n}\n\n\ndef select_detections(\n    value: Any, mode: DetectionsSelectionMode, **kwargs\n) -> sv.Detections:\n    if not isinstance(value, sv.Detections):\n        value_as_str = safe_stringify(value=value)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing select_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(value)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if mode not in DETECTIONS_SELECTORS:\n        InvalidInputTypeError(\n            public_message=f\"Executing select_detections(...), expected mode to be one of {DETECTIONS_SELECTORS.values()}, \"\n            f\"got {mode}.\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    return DETECTIONS_SELECTORS[mode](value)\n\n\ndef extract_x_coordinate_of_detections_center(detections: sv.Detections) -> np.ndarray:\n    return detections.xyxy[:, 0] + (detections.xyxy[:, 2] - detections.xyxy[:, 0]) / 2\n\n\ndef extract_y_coordinate_of_detections_center(detections: sv.Detections) -> np.ndarray:\n    return detections.xyxy[:, 1] + (detections.xyxy[:, 3] - detections.xyxy[:, 1]) / 2\n\n\nSORT_PROPERTIES_EXTRACT = {\n    DetectionsSortProperties.CONFIDENCE: lambda detections: detections.confidence,\n    DetectionsSortProperties.X_MIN: lambda detections: detections.xyxy[:, 0],\n    DetectionsSortProperties.X_MAX: lambda detections: detections.xyxy[:, 2],\n    DetectionsSortProperties.Y_MIN: lambda detections: detections.xyxy[:, 1],\n    DetectionsSortProperties.Y_MAX: lambda detections: detections.xyxy[:, 3],\n    DetectionsSortProperties.SIZE: lambda detections: detections.box_area,\n    DetectionsSortProperties.CENTER_X: extract_x_coordinate_of_detections_center,\n    DetectionsSortProperties.CENTER_Y: extract_y_coordinate_of_detections_center,\n}\n\n\ndef sort_detections(\n    value: Any, mode: DetectionsSortProperties, ascending: bool, **kwargs\n) -> sv.Detections:\n    if not isinstance(value, sv.Detections):\n        value_as_str = safe_stringify(value=value)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing sort_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(value)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if mode not in SORT_PROPERTIES_EXTRACT:\n        raise InvalidInputTypeError(\n            public_message=f\"Executing sort_detections(...), expected mode to be one of \"\n            f\"{SORT_PROPERTIES_EXTRACT.values()}, got {mode}.\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if len(value) == 0:\n        return value\n    extracted_property = SORT_PROPERTIES_EXTRACT[mode](value)\n    if extracted_property is None:\n        # property may not be set, as sv.Detections declares Optional[...]\n        return value\n    sorted_indices = np.argsort(extracted_property)\n    if not ascending:\n        sorted_indices = sorted_indices[::-1]\n    return value[sorted_indices]\n\n\ndef rename_detections(\n    detections: Any,\n    class_map: Union[Dict[str, str], str],\n    strict: Union[bool, str],\n    new_classes_id_offset: int,\n    global_parameters: Dict[str, Any],\n    **kwargs,\n) -> sv.Detections:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing rename_detections(...), expected sv.Detections object as value, \"\n            f\"got {value_as_str} of type {type(detections)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if isinstance(class_map, str):\n        if class_map not in global_parameters:\n            raise UndeclaredSymbolError(\n                public_message=f\"Attempted to retrieve variable `{class_map}` that was expected to hold \"\n                f\"class mapping of rename_detections(...), but that turned out not to be registered.\",\n                context=\"step_execution | roboflow_query_language_evaluation\",\n            )\n        class_map = global_parameters[class_map]\n    if not isinstance(class_map, dict):\n        value_as_str = safe_stringify(value=class_map)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing rename_detections(...), expected dictionary to be given as class map, \"\n            f\"got {value_as_str} of type {type(class_map)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    if isinstance(strict, str):\n        if strict not in global_parameters:\n            raise UndeclaredSymbolError(\n                public_message=f\"Attempted to retrieve variable `{strict}` that was expected to hold \"\n                f\"parameter for `strict` flag of rename_detections(...), but that turned out not \"\n                f\"to be registered.\",\n                context=\"step_execution | roboflow_query_language_evaluation\",\n            )\n        strict = global_parameters[strict]\n    if not isinstance(strict, bool):\n        value_as_str = safe_stringify(value=strict)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing rename_detections(...), expected dictionary to be given as `strict` flag, \"\n            f\"got {value_as_str} of type {type(strict)}\",\n            context=\"step_execution | roboflow_query_language_evaluation\",\n        )\n    detections_copy = deepcopy(detections)\n    original_class_names = detections_copy.data.get(\"class_name\", []).tolist()\n    original_class_ids = detections_copy.class_id.tolist()\n    new_class_names = []\n    new_class_ids = []\n    if strict:\n        _ensure_all_classes_covered_in_new_mapping(\n            original_class_names=original_class_names,\n            class_map=class_map,\n        )\n        new_class_mapping = {\n            class_name: class_id\n            for class_id, class_name in enumerate(sorted(set(class_map.values())))\n        }\n    else:\n        new_class_mapping = _build_non_strict_class_to_id_mapping(\n            original_class_names=original_class_names,\n            original_class_ids=original_class_ids,\n            class_map=class_map,\n            new_classes_id_offset=new_classes_id_offset,\n        )\n    for class_name in original_class_names:\n        new_class_name = class_map.get(class_name, class_name)\n        new_class_id = new_class_mapping[new_class_name]\n        new_class_names.append(new_class_name)\n        new_class_ids.append(new_class_id)\n    detections_copy.data[\"class_name\"] = np.array(new_class_names, dtype=object)\n    detections_copy.class_id = np.array(new_class_ids, dtype=int)\n    return detections_copy\n\n\ndef _ensure_all_classes_covered_in_new_mapping(\n    original_class_names: List[str],\n    class_map: Dict[str, str],\n) -> None:\n    for original_class in original_class_names:\n        if original_class not in class_map:\n            raise OperationError(\n                public_message=f\"Class '{original_class}' not found in class_map.\",\n                context=\"step_execution | roboflow_query_language_evaluation\",\n            )\n\n\ndef _build_non_strict_class_to_id_mapping(\n    original_class_names: List[str],\n    original_class_ids: List[int],\n    class_map: Dict[str, str],\n    new_classes_id_offset: int,\n) -> Dict[str, int]:\n    original_mapping = {\n        class_name: class_id\n        for class_name, class_id in zip(original_class_names, original_class_ids)\n    }\n    new_target_classes = {\n        new_class_name\n        for new_class_name in class_map.values()\n        if new_class_name not in original_mapping\n    }\n    new_class_id = new_classes_id_offset\n    for new_target_class in sorted(new_target_classes):\n        original_mapping[new_target_class] = new_class_id\n        new_class_id += 1\n    return original_mapping\n\n\ndef detections_to_dictionary(\n    detections: Any,\n    execution_context: str,\n    **kwargs,\n) -> dict:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing detections_to_dictionary(...) in context {execution_context}, \"\n            f\"expected sv.Detections object as value, got {value_as_str} of type {type(detections)}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n        )\n    try:\n        return serialise_sv_detections(detections=detections)\n    except Exception as error:\n        raise OperationError(\n            public_message=f\"While Using operation detections_to_dictionary(...) in context {execution_context} \"\n            f\"encountered error: {error}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n            inner_error=error,\n        )\n\n\ndef pick_detections_by_parent_class(\n    detections: Any,\n    parent_class: str,\n    execution_context: str,\n    **kwargs,\n) -> sv.Detections:\n    if not isinstance(detections, sv.Detections):\n        value_as_str = safe_stringify(value=detections)\n        raise InvalidInputTypeError(\n            public_message=f\"Executing pick_detections_by_parent_class(...) in context {execution_context}, \"\n            f\"expected sv.Detections object as value, got {value_as_str} of type {type(detections)}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n        )\n    try:\n        return _pick_detections_by_parent_class(\n            detections=detections, parent_class=parent_class\n        )\n    except Exception as error:\n        raise OperationError(\n            public_message=f\"While Using operation pick_detections_by_parent_class(...) in context {execution_context} \"\n            f\"encountered error: {error}\",\n            context=f\"step_execution | roboflow_query_language_evaluation | {execution_context}\",\n            inner_error=error,\n        )\n\n\ndef _pick_detections_by_parent_class(\n    detections: sv.Detections,\n    parent_class: str,\n) -> sv.Detections:\n    class_names = detections.data.get(\"class_name\")\n    if class_names is None or len(class_names) == 0:\n        return sv.Detections.empty()\n    if not isinstance(class_names, np.ndarray):\n        class_names = np.array(class_names)\n    parent_mask = class_names == parent_class\n    parent_detections = detections[parent_mask]\n    if len(parent_detections) == 0:\n        return sv.Detections.empty()\n    dependent_detections = detections[~parent_mask]\n    dependent_detections_anchors = dependent_detections.get_anchors_coordinates(\n        anchor=Position.CENTER\n    )\n    dependent_detections_to_keep = set()\n    for detection_idx, anchor in enumerate(dependent_detections_anchors):\n        for parent_detection_box in parent_detections.xyxy:\n            if _is_point_within_box(point=anchor, box=parent_detection_box):\n                dependent_detections_to_keep.add(detection_idx)\n                continue\n    detections_to_keep_list = sorted(list(dependent_detections_to_keep))\n    filtered_dependent_detections = dependent_detections[detections_to_keep_list]\n    return sv.Detections.merge([parent_detections, filtered_dependent_detections])\n\n\ndef _is_point_within_box(point: np.ndarray, box: np.ndarray) -> bool:\n    px, py = point\n    x1, y1, x2, y2 = box\n    return x1 <= px <= x2 and y1 <= py <= y2\n",
    "patch": "diff --git a/inference/core/workflows/core_steps/common/query_language/operations/detections/base.py b/inference/core/workflows/core_steps/common/query_language/operations/detections/base.py\nindex 04c6921f7..0cb5497c5 100644\n--- a/inference/core/workflows/core_steps/common/query_language/operations/detections/base.py\n+++ b/inference/core/workflows/core_steps/common/query_language/operations/detections/base.py\n@@ -115,11 +115,15 @@ def select_top_confidence_detection(detections: sv.Detections) -> sv.Detections:\n \n def select_leftmost_detection(detections: sv.Detections) -> sv.Detections:\n     if len(detections) == 0:\n-        return deepcopy(detections)\n+        return detections  # Directly return the original empty detections if empty\n+\n     centers_x = detections.get_anchors_coordinates(anchor=Position.CENTER)[:, 0]\n-    min_value = centers_x.min()\n-    index = np.argwhere(centers_x == min_value)[0].item()\n-    return detections[index]\n+    index = np.argmin(\n+        centers_x\n+    )  # Using np.argmin directly to find the index of the minimum value\n+    return detections[\n+        index\n+    ].copy()  # Use copy instead of deepcopy for better performance\n \n \n def select_rightmost_detection(detections: sv.Detections) -> sv.Detections:\n"
  }
]