diff --git a/development/docs/build_block_docs.py b/development/docs/build_block_docs.py index db6930dd2..84a507868 100644 --- a/development/docs/build_block_docs.py +++ b/development/docs/build_block_docs.py @@ -133,6 +133,9 @@ {details} """ +INLINE_UQL_PARAMETER_PATTERN = re.compile(r"({{\s*\$parameters\.(\w+)\s*}})") + + def main() -> None: os.makedirs(BLOCK_DOCUMENTATION_DIRECTORY, exist_ok=True) @@ -251,7 +254,7 @@ def main() -> None: ], block_type2manifest_type_identifier=block_type2manifest_type_identifier, ), - example="\n\t".join(json.dumps(example_definition, indent=4).split("\n")), + example=_dump_step_example_definition(example_definition=example_definition), ) versions_content.append(version_content) all_versions_compact = "\n\n".join(versions_content) @@ -279,6 +282,16 @@ def main() -> None: ) +def _dump_step_example_definition(example_definition: dict) -> str: + definition_stringified = "\n\t".join(json.dumps(example_definition, indent=4).split("\n")) + return INLINE_UQL_PARAMETER_PATTERN.sub(_escape_uql_brackets, definition_stringified) + + +def _escape_uql_brackets(match: re.Match) -> str: + content = match.group(0) + return "{{ '{{' }}" + content[2:-2] + "{{ '}}' }}" + + def get_auto_generation_markers( documentation_lines: List[str], token: str, diff --git a/development/docs/workflows_gallery_builder.py b/development/docs/workflows_gallery_builder.py index ae4830d16..1cf1b891b 100644 --- a/development/docs/workflows_gallery_builder.py +++ b/development/docs/workflows_gallery_builder.py @@ -16,8 +16,7 @@ API_KEY_PATTERN = re.compile(r"api_key=(.[^&]*)") KEY_VALUE_GROUP = 1 MIN_KEY_LENGTH_TO_REVEAL_PREFIX = 8 - - +INLINE_UQL_PARAMETER_PATTERN = re.compile(r"({{\s*\$parameters\.(\w+)\s*}})") INTEGRATION_TESTS_DIRECTORY = os.path.abspath(os.path.join( os.path.dirname(__file__), "..", @@ -120,14 +119,25 @@ def generate_gallery_entry_docs(entry: WorkflowGalleryEntry) -> str: workflow_name_in_app=entry.workflow_name_in_app, workflow_definition=entry.workflow_definition, ) + workflow_definition = _dump_workflow_definition(workflow_definition=entry.workflow_definition) return GALLERY_ENTRY_TEMPLATE.format( title=entry.use_case_title, description=entry.use_case_description, preview_iframe=preview_iframe, - workflow_definition="\n\t".join(json.dumps(entry.workflow_definition, indent=4).split("\n")), + workflow_definition=workflow_definition, ) +def _dump_workflow_definition(workflow_definition: dict) -> str: + definition_stringified = "\n\t".join(json.dumps(workflow_definition, indent=4).split("\n")) + return INLINE_UQL_PARAMETER_PATTERN.sub(_escape_uql_brackets, definition_stringified) + + +def _escape_uql_brackets(match: re.Match) -> str: + content = match.group(0) + return "{{ '{{' }}" + content[2:-2] + "{{ '}}' }}" + + def generate_preview_iframe(workflow_name_in_app: str, workflow_definition: dict) -> str: api_key = os.environ["WORKFLOWS_GALLERY_API_KEY"] workspace_name = retrieve_workspace_name_from_api(api_key=api_key) diff --git a/docs/workflows/kinds.md b/docs/workflows/kinds.md index a8cba0fc9..664937430 100644 --- a/docs/workflows/kinds.md +++ b/docs/workflows/kinds.md @@ -68,39 +68,39 @@ providing compile-time verification of Workflows definitions. ## Kinds declared in Roboflow plugins -* [`float_zero_to_one`](/workflows/kinds/float_zero_to_one): `float` value in range `[0.0, 1.0]` -* [`image_keypoints`](/workflows/kinds/image_keypoints): Image keypoints detected by classical Computer Vision method * [`float`](/workflows/kinds/float): Float value -* [`image_metadata`](/workflows/kinds/image_metadata): Dictionary with image metadata required by supervision -* [`object_detection_prediction`](/workflows/kinds/object_detection_prediction): Prediction with detected bounding boxes in form of sv.Detections(...) object -* [`integer`](/workflows/kinds/integer): Integer value -* [`bytes`](/workflows/kinds/bytes): This kind represent bytes -* [`roboflow_model_id`](/workflows/kinds/roboflow_model_id): Roboflow model id -* [`boolean`](/workflows/kinds/boolean): Boolean flag -* [`list_of_values`](/workflows/kinds/list_of_values): List of values of any type -* [`instance_segmentation_prediction`](/workflows/kinds/instance_segmentation_prediction): Prediction with detected bounding boxes and segmentation masks in form of sv.Detections(...) object -* [`video_metadata`](/workflows/kinds/video_metadata): Video image metadata -* [`secret`](/workflows/kinds/secret): Secret value -* [`classification_prediction`](/workflows/kinds/classification_prediction): Predictions from classifier -* [`string`](/workflows/kinds/string): String value * [`bar_code_detection`](/workflows/kinds/bar_code_detection): Prediction with barcode detection -* [`point`](/workflows/kinds/point): Single point in 2D -* [`parent_id`](/workflows/kinds/parent_id): Identifier of parent for step output -* [`zone`](/workflows/kinds/zone): Definition of polygon zone +* [`secret`](/workflows/kinds/secret): Secret value * [`keypoint_detection_prediction`](/workflows/kinds/keypoint_detection_prediction): Prediction with detected bounding boxes and detected keypoints in form of sv.Detections(...) object -* [`serialised_payloads`](/workflows/kinds/serialised_payloads): Serialised element that is usually accepted by sink -* [`roboflow_api_key`](/workflows/kinds/roboflow_api_key): Roboflow API key +* [`list_of_values`](/workflows/kinds/list_of_values): List of values of any type +* [`roboflow_model_id`](/workflows/kinds/roboflow_model_id): Roboflow model id +* [`prediction_type`](/workflows/kinds/prediction_type): String value with type of prediction * [`rgb_color`](/workflows/kinds/rgb_color): RGB color -* [`image`](/workflows/kinds/image): Image in workflows -* [`contours`](/workflows/kinds/contours): List of numpy arrays where each array represents contour points +* [`roboflow_api_key`](/workflows/kinds/roboflow_api_key): Roboflow API key +* [`instance_segmentation_prediction`](/workflows/kinds/instance_segmentation_prediction): Prediction with detected bounding boxes and segmentation masks in form of sv.Detections(...) object * [`roboflow_project`](/workflows/kinds/roboflow_project): Roboflow project name +* [`contours`](/workflows/kinds/contours): List of numpy arrays where each array represents contour points +* [`serialised_payloads`](/workflows/kinds/serialised_payloads): Serialised element that is usually accepted by sink * [`language_model_output`](/workflows/kinds/language_model_output): LLM / VLM output -* [`numpy_array`](/workflows/kinds/numpy_array): Numpy array -* [`inference_id`](/workflows/kinds/inference_id): Inference identifier -* [`dictionary`](/workflows/kinds/dictionary): Dictionary +* [`string`](/workflows/kinds/string): String value +* [`zone`](/workflows/kinds/zone): Definition of polygon zone +* [`top_class`](/workflows/kinds/top_class): String value representing top class predicted by classification model +* [`image_metadata`](/workflows/kinds/image_metadata): Dictionary with image metadata required by supervision +* [`video_metadata`](/workflows/kinds/video_metadata): Video image metadata +* [`object_detection_prediction`](/workflows/kinds/object_detection_prediction): Prediction with detected bounding boxes in form of sv.Detections(...) object +* [`integer`](/workflows/kinds/integer): Integer value +* [`classification_prediction`](/workflows/kinds/classification_prediction): Predictions from classifier +* [`image`](/workflows/kinds/image): Image in workflows +* [`point`](/workflows/kinds/point): Single point in 2D * [`detection`](/workflows/kinds/detection): Single element of detections-based prediction (like `object_detection_prediction`) +* [`bytes`](/workflows/kinds/bytes): This kind represent bytes +* [`boolean`](/workflows/kinds/boolean): Boolean flag * [`*`](/workflows/kinds/*): Equivalent of any element -* [`top_class`](/workflows/kinds/top_class): String value representing top class predicted by classification model +* [`float_zero_to_one`](/workflows/kinds/float_zero_to_one): `float` value in range `[0.0, 1.0]` +* [`inference_id`](/workflows/kinds/inference_id): Inference identifier +* [`dictionary`](/workflows/kinds/dictionary): Dictionary +* [`numpy_array`](/workflows/kinds/numpy_array): Numpy array * [`qr_code_detection`](/workflows/kinds/qr_code_detection): Prediction with QR code detection -* [`prediction_type`](/workflows/kinds/prediction_type): String value with type of prediction +* [`parent_id`](/workflows/kinds/parent_id): Identifier of parent for step output +* [`image_keypoints`](/workflows/kinds/image_keypoints): Image keypoints detected by classical Computer Vision method diff --git a/inference/core/workflows/core_steps/sinks/email_notification/v1.py b/inference/core/workflows/core_steps/sinks/email_notification/v1.py index e6a2651ca..a85aaba6f 100644 --- a/inference/core/workflows/core_steps/sinks/email_notification/v1.py +++ b/inference/core/workflows/core_steps/sinks/email_notification/v1.py @@ -60,7 +60,7 @@ message using dynamic parameters: ``` -message = "This is example notification. Predicted classes: \{\{ $parameters.predicted_classes \}\}" +message = "This is example notification. Predicted classes: {{ '{{' }} $parameters.predicted_classes {{ '}}' }}" ``` Message parameters are delivered by Workflows Execution Engine by setting proper data selectors in @@ -181,7 +181,7 @@ class BlockManifest(WorkflowBlockManifest): message: str = Field( description="Content of the message to be send", examples=[ - "During last 5 minutes detected \{\{ $parameters.num_instances \}\} instances" + "During last 5 minutes detected {{ $parameters.num_instances }} instances" ], ) sender_email: Union[str, Selector(kind=[STRING_KIND])] = Field( diff --git a/inference/core/workflows/core_steps/sinks/slack/notification/v1.py b/inference/core/workflows/core_steps/sinks/slack/notification/v1.py index 7438c9a91..cc8af72b0 100644 --- a/inference/core/workflows/core_steps/sinks/slack/notification/v1.py +++ b/inference/core/workflows/core_steps/sinks/slack/notification/v1.py @@ -87,7 +87,7 @@ class BlockManifest(WorkflowBlockManifest): message: str = Field( description="Content of the message to be send", examples=[ - "During last 5 minutes detected \{\{ $parameters.num_instances \}\} instances" + "During last 5 minutes detected {{ $parameters.num_instances }} instances" ], ) channel: Union[str, Selector(kind=[STRING_KIND])] = Field( diff --git a/inference/core/workflows/core_steps/sinks/twilio/sms/v1.py b/inference/core/workflows/core_steps/sinks/twilio/sms/v1.py index eda984ef6..5127089bb 100644 --- a/inference/core/workflows/core_steps/sinks/twilio/sms/v1.py +++ b/inference/core/workflows/core_steps/sinks/twilio/sms/v1.py @@ -94,7 +94,7 @@ class BlockManifest(WorkflowBlockManifest): message: str = Field( description="Content of the message to be send", examples=[ - "During last 5 minutes detected \{\{ $parameters.num_instances \}\} instances" + "During last 5 minutes detected {{ $parameters.num_instances }} instances" ], ) sender_number: Union[str, Selector(kind=[STRING_KIND])] = Field(