Skip to content

Commit

Permalink
Merge pull request #845 from roboflow/feature/adding_notifiers_blocks
Browse files Browse the repository at this point in the history
Add Slack and Twilio notifiers
  • Loading branch information
PawelPeczek-Roboflow authored Nov 29, 2024
2 parents 0bc541c + fd89d25 commit 48a8c05
Show file tree
Hide file tree
Showing 52 changed files with 3,838 additions and 188 deletions.
1 change: 1 addition & 0 deletions docker/dockerfiles/Dockerfile.onnx.lambda
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ ENV ALLOW_CUSTOM_PYTHON_EXECUTION_IN_WORKFLOWS=False
ENV CORE_MODEL_TROCR_ENABLED=false
ENV USE_FILE_CACHE_FOR_WORKFLOWS_DEFINITIONS=False
ENV ALLOW_WORKFLOW_BLOCKS_ACCESSING_LOCAL_STORAGE=False
ENV ALLOW_WORKFLOW_BLOCKS_ACCESSING_ENVIRONMENTAL_VARIABLES=False

WORKDIR ${LAMBDA_TASK_ROOT}
RUN rm -rf /build
Expand Down
1 change: 1 addition & 0 deletions docker/dockerfiles/Dockerfile.onnx.lambda.slim
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ ENV CORE_MODEL_TROCR_ENABLED=false
ENV ENABLE_WORKFLOWS_PROFILING=True
ENV USE_FILE_CACHE_FOR_WORKFLOWS_DEFINITIONS=False
ENV ALLOW_WORKFLOW_BLOCKS_ACCESSING_LOCAL_STORAGE=False
ENV ALLOW_WORKFLOW_BLOCKS_ACCESSING_ENVIRONMENTAL_VARIABLES=False

WORKDIR ${LAMBDA_TASK_ROOT}

Expand Down
4 changes: 4 additions & 0 deletions docs/workflows/blocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ hide:
<p class="card block-card" data-url="qr_code_detection" data-name="QR Code Detection" data-desc="Detect and read QR codes in an image." data-labels="MODEL, APACHE-2.0" data-author="dummy"></p>
<p class="card block-card" data-url="single_label_classification_model" data-name="Single-Label Classification Model" data-desc="Apply a single tag to an image." data-labels="MODEL, APACHE-2.0" data-author="dummy"></p>
<p class="card block-card" data-url="roboflow_custom_metadata" data-name="Roboflow Custom Metadata" data-desc="Add custom metadata to Roboflow Model Monitoring dashboard" data-labels="SINK, APACHE-2.0" data-author="dummy"></p>
<p class="card block-card" data-url="model_monitoring_inference_aggregator" data-name="Model Monitoring Inference Aggregator" data-desc="Periodically report an aggregated sample of inference results to Roboflow Model Monitoring" data-labels="SINK, APACHE-2.0" data-author="dummy"></p>
<p class="card block-card" data-url="instance_segmentation_model" data-name="Instance Segmentation Model" data-desc="Predict the shape, size, and location of objects." data-labels="MODEL, APACHE-2.0" data-author="dummy"></p>
<p class="card block-card" data-url="keypoint_detection_model" data-name="Keypoint Detection Model" data-desc="Predict skeletons on objects." data-labels="MODEL, APACHE-2.0" data-author="dummy"></p>
<p class="card block-card" data-url="multi_label_classification_model" data-name="Multi-Label Classification Model" data-desc="Apply multiple tags to an image." data-labels="MODEL, APACHE-2.0" data-author="dummy"></p>
Expand All @@ -104,6 +105,9 @@ hide:
<p class="card block-card" data-url="trace_visualization" data-name="Trace Visualization" data-desc="Draws traces based on detections tracking results." data-labels="VISUALIZATION, APACHE-2.0" data-author="dummy"></p>
<p class="card block-card" data-url="reference_path_visualization" data-name="Reference Path Visualization" data-desc="Draws a reference path in the image" data-labels="VISUALIZATION, APACHE-2.0" data-author="dummy"></p>
<p class="card block-card" data-url="webhook_sink" data-name="Webhook Sink" data-desc="Sends the request to remote API with results of Workflow results" data-labels="SINK, APACHE-2.0" data-author="dummy"></p>
<p class="card block-card" data-url="environment_secrets_store" data-name="Environment Secrets Store" data-desc="Fetches secrets from environmental variables" data-labels="SECRETS_PROVIDER, APACHE-2.0" data-author="dummy"></p>
<p class="card block-card" data-url="slack_notification" data-name="Slack Notification" data-desc="Send notification via Slack" data-labels="SINK, APACHE-2.0" data-author="dummy"></p>
<p class="card block-card" data-url="twilio_sms_notification" data-name="Twilio SMS Notification" data-desc="Send notification via Twilio SMS service" data-labels="SINK, APACHE-2.0" data-author="dummy"></p>
<!--- AUTOGENERATED_BLOCKS_LIST -->
</div>
</div>
Expand Down
17 changes: 17 additions & 0 deletions docs/workflows/execution_engine_changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -301,3 +301,20 @@ subsets of steps**, enabling building such tools as debuggers.
feel free to alter the serialization methods for *kinds*, simply registering
the function in your plugin and loading it to the Execution Engine - the
serializer/deserializer defined as the last one will be in use.


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

* Added new kind - [`secret`](/workflows/kinds/secret/) to represent credentials. **No action needed** for existing
blocks, yet it is expected that over time blocks developers should use this kind, whenever block is to accept secret
value as parameter.

* Fixed issue with results serialization introduced in `v1.3.0` - by mistake, Execution Engine was not serializing
non-batch oriented outputs.

* Fixed Execution Engine bug with preparing inputs for steps. For non-SIMD steps before, while collecting inputs
in runtime, `WorkflowBlockManifest.accepts_empty_input()` method result was being ignored - causing the bug when
one non-SIMD step was feeding empty values to downstream blocks. Additionally, in the light of changes made in `v1.3.0`,
thanks to which non-SIMD blocks can easily feed inputs for downstream SIMD steps - it is needed to check if
upstream non-SIMD block yielded non-empty results (as SIMD block may not accept empty results). This check was added.
**No action needed** for existing blocks, but this fix may fix previously broken Workflows.
4 changes: 3 additions & 1 deletion docs/workflows/gallery_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ Browse through the various categories to find inspiration and ideas for building
<li><a href="/workflows/gallery/workflows_enhanced_by_roboflow_platform">Workflows enhanced by Roboflow Platform</a></li>
<li><a href="/workflows/gallery/basic_workflows">Basic Workflows</a></li>
<li><a href="/workflows/gallery/workflows_with_classical_computer_vision_methods">Workflows with classical Computer Vision methods</a></li>
<li><a href="/workflows/gallery/workflows_with_visualization_blocks">Workflows with visualization blocks</a></li>
<li><a href="/workflows/gallery/workflows_with_visual_language_models">Workflows with Visual Language Models</a></li>
<li><a href="/workflows/gallery/data_analytics_in_workflows">Data analytics in Workflows</a></li>
<li><a href="/workflows/gallery/workflows_with_dynamic_python_blocks">Workflows with dynamic Python Blocks</a></li>
<li><a href="/workflows/gallery/workflows_for_ocr">Workflows for OCR</a></li>
<li><a href="/workflows/gallery/workflows_with_data_transformations">Workflows with data transformations</a></li>
<li><a href="/workflows/gallery/workflows_with_flow_control">Workflows with flow control</a></li>
<li><a href="/workflows/gallery/workflows_with_business_logic">Workflows with business logic</a></li>
<li><a href="/workflows/gallery/advanced_inference_techniques">Advanced inference techniques</a></li>
<li><a href="/workflows/gallery/workflows_with_foundation_models">Workflows with foundation models</a></li>
<li><a href="/workflows/gallery/workflows_with_visualization_blocks">Workflows with visualization blocks</a></li>
<li><a href="/workflows/gallery/integration_with_external_apps">Integration with external apps</a></li>
</ul>
53 changes: 27 additions & 26 deletions docs/workflows/kinds.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,38 +68,39 @@ providing compile-time verification of Workflows definitions.

## Kinds declared in Roboflow plugins
<!--- AUTOGENERATED_KINDS_LIST -->
* [`object_detection_prediction`](/workflows/kinds/object_detection_prediction): Prediction with detected bounding boxes in form of sv.Detections(...) object
* [`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
* [`prediction_type`](/workflows/kinds/prediction_type): String value with type of prediction
* [`*`](/workflows/kinds/*): Equivalent of any element
* [`dictionary`](/workflows/kinds/dictionary): Dictionary
* [`roboflow_api_key`](/workflows/kinds/roboflow_api_key): Roboflow API key
* [`classification_prediction`](/workflows/kinds/classification_prediction): Predictions from classifier
* [`video_metadata`](/workflows/kinds/video_metadata): Video image metadata
* [`detection`](/workflows/kinds/detection): Single element of detections-based prediction (like `object_detection_prediction`)
* [`boolean`](/workflows/kinds/boolean): Boolean flag
* [`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
* [`qr_code_detection`](/workflows/kinds/qr_code_detection): Prediction with QR code detection
* [`contours`](/workflows/kinds/contours): List of numpy arrays where each array represents contour points
* [`language_model_output`](/workflows/kinds/language_model_output): LLM / VLM output
* [`inference_id`](/workflows/kinds/inference_id): Inference identifier
* [`serialised_payloads`](/workflows/kinds/serialised_payloads): Serialised element that is usually accepted by sink
* [`string`](/workflows/kinds/string): String value
* [`float_zero_to_one`](/workflows/kinds/float_zero_to_one): `float` value in range `[0.0, 1.0]`
* [`rgb_color`](/workflows/kinds/rgb_color): RGB color
* [`image`](/workflows/kinds/image): Image in workflows
* [`roboflow_project`](/workflows/kinds/roboflow_project): Roboflow project name
* [`top_class`](/workflows/kinds/top_class): String value representing top class predicted by classification model
* [`image_keypoints`](/workflows/kinds/image_keypoints): Image keypoints detected by classical Computer Vision method
* [`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
* [`keypoint_detection_prediction`](/workflows/kinds/keypoint_detection_prediction): Prediction with detected bounding boxes and detected keypoints in form of sv.Detections(...) object
* [`numpy_array`](/workflows/kinds/numpy_array): Numpy array
* [`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
* [`roboflow_model_id`](/workflows/kinds/roboflow_model_id): Roboflow model id
* [`integer`](/workflows/kinds/integer): Integer value
* [`parent_id`](/workflows/kinds/parent_id): Identifier of parent for step output
* [`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
* [`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
* [`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_project`](/workflows/kinds/roboflow_project): Roboflow project name
* [`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
* [`detection`](/workflows/kinds/detection): Single element of detections-based prediction (like `object_detection_prediction`)
* [`*`](/workflows/kinds/*): Equivalent of any element
* [`top_class`](/workflows/kinds/top_class): String value representing top class predicted by classification model
* [`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
<!--- AUTOGENERATED_KINDS_LIST -->
2 changes: 1 addition & 1 deletion inference/core/entities/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
ModelID = Field(example="raccoon-detector-1", description="A unique model identifier")
ModelType = Field(
default=None,
example="object-detection",
examples=["object-detection"],
description="The type of the model, usually referring to what task the model performs",
)
ApiKey = Field(
Expand Down
3 changes: 3 additions & 0 deletions inference/core/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,9 @@
ALLOW_WORKFLOW_BLOCKS_ACCESSING_LOCAL_STORAGE = str2bool(
os.getenv("ALLOW_WORKFLOW_BLOCKS_ACCESSING_LOCAL_STORAGE", "True")
)
ALLOW_WORKFLOW_BLOCKS_ACCESSING_ENVIRONMENTAL_VARIABLES = str2bool(
os.getenv("ALLOW_WORKFLOW_BLOCKS_ACCESSING_ENVIRONMENTAL_VARIABLES", "True")
)
WORKFLOW_BLOCKS_WRITE_DIRECTORY = os.getenv("WORKFLOW_BLOCKS_WRITE_DIRECTORY")

DEDICATED_DEPLOYMENT_ID = os.getenv("DEDICATED_DEPLOYMENT_ID")
Expand Down
2 changes: 1 addition & 1 deletion inference/core/version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "0.28.2"
__version__ = "0.29.0"


if __name__ == "__main__":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ class ImagePreprocessingManifest(WorkflowBlockManifest):
description="Positive value to rotate clockwise, negative value to rotate counterclockwise",
default=90,
examples=[90, "$inputs.rotation_degrees"],
gte=-360,
ge=-360,
le=360,
json_schema_extra={
"relevant_for": {
Expand Down
11 changes: 11 additions & 0 deletions inference/core/workflows/core_steps/common/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
WorkflowImageData,
)

MIN_SECRET_LENGTH_TO_REVEAL_PREFIX = 8


def serialise_sv_detections(detections: sv.Detections) -> dict:
serialized_detections = []
Expand Down Expand Up @@ -180,3 +182,12 @@ def serialize_dict(elements: Dict[str, Any]) -> Dict[str, Any]:
value = serialize_wildcard_kind(value=value)
serialized_result[key] = value
return serialized_result


def serialize_secret(secret: str) -> str:
if len(secret) < MIN_SECRET_LENGTH_TO_REVEAL_PREFIX:
return "*" * MIN_SECRET_LENGTH_TO_REVEAL_PREFIX
prefix = secret[:2]
infix = "*" * MIN_SECRET_LENGTH_TO_REVEAL_PREFIX
suffix = secret[-2:]
return f"{prefix}{infix}{suffix}"
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@
* adjust `cooldown_seconds` to specify what is the number of seconds that must be awaited before next time
when `step_2` is fired
!!! warning "Cooldown limitations"
Current implementation of cooldown is limited to video processing - using this block in context of a
Workflow that is run behind HTTP service (Roboflow Hosted API, Dedicated Deployment or self-hosted
`inference` server) will have no effect for processing HTTP requests.
"""


Expand Down
17 changes: 17 additions & 0 deletions inference/core/workflows/core_steps/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
from inference.core.workflows.core_steps.common.serializers import (
serialise_image,
serialise_sv_detections,
serialize_secret,
serialize_video_metadata_kind,
serialize_wildcard_kind,
)
Expand Down Expand Up @@ -217,6 +218,9 @@
from inference.core.workflows.core_steps.models.third_party.qr_code_detection.v1 import (
QRCodeDetectorBlockV1,
)
from inference.core.workflows.core_steps.secrets_providers.environment_secrets_store.v1 import (
EnvironmentSecretsStoreBlockV1,
)
from inference.core.workflows.core_steps.sinks.email_notification.v1 import (
EmailNotificationBlockV1,
)
Expand All @@ -233,6 +237,12 @@
from inference.core.workflows.core_steps.sinks.roboflow.model_monitoring_inference_aggregator.v1 import (
ModelMonitoringInferenceAggregatorBlockV1,
)
from inference.core.workflows.core_steps.sinks.slack.notification.v1 import (
SlackNotificationBlockV1,
)
from inference.core.workflows.core_steps.sinks.twilio.sms.v1 import (
TwilioSMSNotificationBlockV1,
)
from inference.core.workflows.core_steps.sinks.webhook.v1 import WebhookSinkBlockV1
from inference.core.workflows.core_steps.transformations.absolute_static_crop.v1 import (
AbsoluteStaticCropBlockV1,
Expand Down Expand Up @@ -379,6 +389,7 @@
ROBOFLOW_API_KEY_KIND,
ROBOFLOW_MODEL_ID_KIND,
ROBOFLOW_PROJECT_KIND,
SECRET_KIND,
SERIALISED_PAYLOADS_KIND,
STRING_KIND,
TOP_CLASS_KIND,
Expand All @@ -397,6 +408,7 @@
"thread_pool_executor": None,
"allow_access_to_file_system": ALLOW_WORKFLOW_BLOCKS_ACCESSING_LOCAL_STORAGE,
"allowed_write_directory": WORKFLOW_BLOCKS_WRITE_DIRECTORY,
"allow_access_to_environmental_variables": ALLOW_WORKFLOW_BLOCKS_ACCESSING_LOCAL_STORAGE,
}

KINDS_SERIALIZERS = {
Expand All @@ -407,6 +419,7 @@
KEYPOINT_DETECTION_PREDICTION_KIND.name: serialise_sv_detections,
QR_CODE_DETECTION_KIND.name: serialise_sv_detections,
BAR_CODE_DETECTION_KIND.name: serialise_sv_detections,
SECRET_KIND.name: serialize_secret,
WILDCARD_KIND.name: serialize_wildcard_kind,
}
KINDS_DESERIALIZERS = {
Expand Down Expand Up @@ -552,6 +565,9 @@ def load_blocks() -> List[Type[WorkflowBlock]]:
RoboflowObjectDetectionModelBlockV2,
VLMAsClassifierBlockV2,
VLMAsDetectorBlockV2,
EnvironmentSecretsStoreBlockV1,
SlackNotificationBlockV1,
TwilioSMSNotificationBlockV1,
]


Expand Down Expand Up @@ -591,4 +607,5 @@ def load_kinds() -> List[Kind]:
IMAGE_METADATA_KIND,
BYTES_KIND,
INFERENCE_ID_KIND,
SECRET_KIND,
]
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
INTEGER_KIND,
LANGUAGE_MODEL_OUTPUT_KIND,
LIST_OF_VALUES_KIND,
SECRET_KIND,
STRING_KIND,
ImageInputField,
Selector,
Expand Down Expand Up @@ -149,7 +150,7 @@ class BlockManifest(WorkflowBlockManifest):
},
},
)
api_key: Union[Selector(kind=[STRING_KIND]), str] = Field(
api_key: Union[Selector(kind=[STRING_KIND, SECRET_KIND]), str] = Field(
description="Your Antropic API key",
examples=["xxx-xxx", "$inputs.antropics_api_key"],
private=True,
Expand Down Expand Up @@ -220,7 +221,7 @@ def describe_outputs(cls) -> List[OutputDefinition]:

@classmethod
def get_execution_engine_compatibility(cls) -> Optional[str]:
return ">=1.3.0,<2.0.0"
return ">=1.4.0,<2.0.0"


class AntropicClaudeBlockV1(WorkflowBlock):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
IMAGE_KIND,
LANGUAGE_MODEL_OUTPUT_KIND,
LIST_OF_VALUES_KIND,
SECRET_KIND,
STRING_KIND,
ImageInputField,
Selector,
Expand Down Expand Up @@ -158,7 +159,7 @@ class BlockManifest(WorkflowBlockManifest):
},
},
)
api_key: Union[Selector(kind=[STRING_KIND]), str] = Field(
api_key: Union[Selector(kind=[STRING_KIND, SECRET_KIND]), str] = Field(
description="Your Google AI API key",
examples=["xxx-xxx", "$inputs.google_api_key"],
private=True,
Expand Down Expand Up @@ -223,7 +224,7 @@ def describe_outputs(cls) -> List[OutputDefinition]:

@classmethod
def get_execution_engine_compatibility(cls) -> Optional[str]:
return ">=1.3.0,<2.0.0"
return ">=1.4.0,<2.0.0"


class GoogleGeminiBlockV1(WorkflowBlock):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from inference.core.workflows.execution_engine.entities.types import (
IMAGE_KIND,
OBJECT_DETECTION_PREDICTION_KIND,
SECRET_KIND,
STRING_KIND,
Selector,
)
Expand Down Expand Up @@ -79,7 +80,7 @@ class BlockManifest(WorkflowBlockManifest):
},
},
)
api_key: Union[Selector(kind=[STRING_KIND]), str] = Field(
api_key: Union[Selector(kind=[STRING_KIND, SECRET_KIND]), str] = Field(
description="Your Google Vision API key",
examples=["xxx-xxx", "$inputs.google_api_key"],
private=True,
Expand All @@ -97,7 +98,7 @@ def describe_outputs(cls) -> List[OutputDefinition]:

@classmethod
def get_execution_engine_compatibility(cls) -> Optional[str]:
return ">=1.3.0,<2.0.0"
return ">=1.4.0,<2.0.0"


class GoogleVisionOCRBlockV1(WorkflowBlock):
Expand Down
Loading

0 comments on commit 48a8c05

Please sign in to comment.