Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Slack and Twilio notifiers #845

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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
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
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
IMAGE_KIND,
IMAGE_METADATA_KIND,
PARENT_ID_KIND,
SECRET_KIND,
STRING_KIND,
WILDCARD_KIND,
ImageInputField,
Expand Down Expand Up @@ -112,11 +113,13 @@ class BlockManifest(WorkflowBlockManifest):
}
],
)
remote_api_key: Union[Selector(kind=[STRING_KIND]), Optional[str]] = Field(
default=None,
description="Holds API key required to call LMM model - in current state of development, we require OpenAI key when `lmm_type=gpt_4v` and do not require additional API key for CogVLM calls.",
examples=["xxx-xxx", "$inputs.api_key"],
private=True,
remote_api_key: Union[Selector(kind=[STRING_KIND, SECRET_KIND]), Optional[str]] = (
Field(
default=None,
description="Holds API key required to call LMM model - in current state of development, we require OpenAI key when `lmm_type=gpt_4v` and do not require additional API key for CogVLM calls.",
examples=["xxx-xxx", "$inputs.api_key"],
private=True,
)
)
json_output: Optional[Dict[str, str]] = Field(
default=None,
Expand Down Expand Up @@ -155,7 +158,7 @@ def get_actual_outputs(self) -> 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 LMMBlockV1(WorkflowBlock):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
LIST_OF_VALUES_KIND,
PARENT_ID_KIND,
PREDICTION_TYPE_KIND,
SECRET_KIND,
STRING_KIND,
TOP_CLASS_KIND,
ImageInputField,
Expand Down Expand Up @@ -86,11 +87,13 @@ class BlockManifest(WorkflowBlockManifest):
}
],
)
remote_api_key: Union[Selector(kind=[STRING_KIND]), Optional[str]] = Field(
default=None,
description="Holds API key required to call LMM model - in current state of development, we require OpenAI key when `lmm_type=gpt_4v` and do not require additional API key for CogVLM calls.",
examples=["xxx-xxx", "$inputs.api_key"],
private=True,
remote_api_key: Union[Selector(kind=[STRING_KIND, SECRET_KIND]), Optional[str]] = (
Field(
default=None,
description="Holds API key required to call LMM model - in current state of development, we require OpenAI key when `lmm_type=gpt_4v` and do not require additional API key for CogVLM calls.",
examples=["xxx-xxx", "$inputs.api_key"],
private=True,
)
)

@classmethod
Expand All @@ -110,7 +113,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 LMMForClassificationBlockV1(WorkflowBlock):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
IMAGE_KIND,
IMAGE_METADATA_KIND,
PARENT_ID_KIND,
SECRET_KIND,
STRING_KIND,
WILDCARD_KIND,
ImageInputField,
Expand Down Expand Up @@ -75,10 +76,12 @@ class BlockManifest(WorkflowBlockManifest):
description="Text prompt to the OpenAI model",
examples=["my prompt", "$inputs.prompt"],
)
openai_api_key: Union[Selector(kind=[STRING_KIND]), Optional[str]] = Field(
description="Your OpenAI API key",
examples=["xxx-xxx", "$inputs.openai_api_key"],
private=True,
openai_api_key: Union[Selector(kind=[STRING_KIND, SECRET_KIND]), Optional[str]] = (
Field(
description="Your OpenAI API key",
examples=["xxx-xxx", "$inputs.openai_api_key"],
private=True,
)
)
openai_model: Union[
Selector(kind=[STRING_KIND]), Literal["gpt-4o", "gpt-4o-mini"]
Expand Down Expand Up @@ -139,7 +142,7 @@ def get_actual_outputs(self) -> 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 OpenAIBlockV1(WorkflowBlock):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
IMAGE_KIND,
LANGUAGE_MODEL_OUTPUT_KIND,
LIST_OF_VALUES_KIND,
SECRET_KIND,
STRING_KIND,
ImageInputField,
Selector,
Expand Down Expand Up @@ -147,7 +148,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 OpenAI API key",
examples=["xxx-xxx", "$inputs.openai_api_key"],
private=True,
Expand Down Expand Up @@ -218,7 +219,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 OpenAIBlockV2(WorkflowBlock):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from inference.core.workflows.execution_engine.entities.types import (
IMAGE_KIND,
INSTANCE_SEGMENTATION_PREDICTION_KIND,
SECRET_KIND,
STRING_KIND,
Selector,
)
Expand Down Expand Up @@ -89,7 +90,7 @@ class BlockManifest(WorkflowBlockManifest):
description="Negative prompt to inpainting model (what you do not wish to see)",
examples=["my prompt", "$inputs.prompt"],
)
api_key: Union[Selector(kind=[STRING_KIND]), str] = Field(
api_key: Union[Selector(kind=[STRING_KIND, SECRET_KIND]), str] = Field(
description="Your Stability AI API key",
examples=["xxx-xxx", "$inputs.stability_ai_api_key"],
private=True,
Expand All @@ -103,7 +104,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 StabilityAIInpaintingBlockV1(WorkflowBlock):
Expand Down
Empty file.
Loading