Skip to content

Commit

Permalink
Label studio settings and optional port (zenml-io#2628)
Browse files Browse the repository at this point in the history
* Added label studio setting

* Update

* Api key attribute

* Added zenml-io#2626

* Docs change

* Update src/zenml/integrations/label_studio/annotators/label_studio_annotator.py

* mypy fix #1

* mypy fix #2

* mypy fix #3

---------

Co-authored-by: Alex Strick van Linschoten <[email protected]>
Co-authored-by: Alex Strick van Linschoten <[email protected]>
  • Loading branch information
3 people committed Apr 30, 2024
1 parent 8e25fec commit cb07d3a
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,6 @@ The Label Studio integration currently is built to support workflows using the f
AWS S3, GCP/GCS, and Azure Blob Storage. Purely local stacks will currently _not_ work if you want to do add the
annotation stack component as part of your stack.

{% hint style="info" %}
COMING SOON: The Label Studio Integration supports the use of annotations in an ML workflow, but we do not currently
handle the universal conversion between data formats as part of the training workflow. Our initial use case was built to
support image classification and object detection, but we will add helper steps and functions for other use cases in due
course. We will update the docs when we enable this functionality.
{% endhint %}

### How to deploy it?

The Label Studio Annotator flavor is provided by the Label Studio ZenML integration, you need to install it, to be able
Expand All @@ -50,11 +43,6 @@ issue or [message us on Slack](https://zenml.io/slack-invite) if you need more h
definitive fix.
{% endhint %}

The following instructions below offer a general guide to the parts that need attention when deploying/using the Label
Studio stack component and integration.
The [`label_studio_annotation` example](https://github.com/zenml-io/zenml/tree/develop/examples/label\_studio\_annotation)
offers a detailed guide for each cloud provider on how to set it up.

Before registering a `label_studio` flavor stack component as part of your stack, you'll need to have registered a cloud
artifact store. (See the docs on how to register and set
up[ a cloud artifact store](/docs/book/stacks-and-components/component-guide/artifact-stores/artifact-stores.md).)
Expand Down Expand Up @@ -84,13 +72,13 @@ At this point you should register the API key under a custom secret name, making
with whatever you choose:

```shell
zenml secret create <LABEL_STUDIO_SECRET_NAME> --api_key="<your_label_studio_api_key>"
zenml secret create label_studio_secrets --api_key="<your_label_studio_api_key>"
```

Then register your annotator with ZenML:

```shell
zenml annotator register label_studio --flavor label_studio --authentication_secret="<LABEL_STUDIO_SECRET_NAME>"
zenml annotator register label_studio --flavor label_studio --api_key={{label_studio_secrets.api_key}}

# for deployed instances of Label Studio, you can also pass in the URL as follows, for example:
# zenml annotator register label_studio --flavor label_studio --authentication_secret="<LABEL_STUDIO_SECRET_NAME>" --instance_url="<your_label_studio_url>" --port=80
Expand Down Expand Up @@ -124,7 +112,7 @@ ZenML supports access to your data and annotations via the `zenml annotator ...`
You can access information about the datasets you're using with the `zenml annotator dataset list`. To work on
annotation for a particular dataset, you can run `zenml annotator dataset annotate <dataset_name>`.

[Our full continuous annotation/training example](https://github.com/zenml-io/zenml/tree/develop/examples/label\_studio\_annotation)
[Our computer vision end to end example](https://github.com/zenml-io/zenml-projects/tree/main/cv-webinar/end-to-end-computer-vision)
is the best place to see how all the pieces of making this integration work fit together. What follows is an overview of
some key components to the Label Studio integration and how it can be used.

Expand Down Expand Up @@ -167,10 +155,9 @@ Studio integration quickly. These include:
Label Studio requires the use of what it calls 'label config' when you are creating/registering your dataset. These are
strings containing HTML-like syntax that allow you to define a custom interface for your annotation. ZenML provides
three helper functions that will construct these label config strings in the case of object detection, image
classification, and OCR. See the `integrations.label_studio.label_config_generators` module for those three functions.

A concrete example of using the Label Studio annotator can be
found [here](https://github.com/zenml-io/zenml/tree/develop/examples/label\_studio\_annotation).
classification, and OCR. See the
[`integrations.label_studio.label_config_generators`](https://github.com/zenml-io/zenml/blob/main/src/zenml/integrations/label_studio/label_config_generators/label_config_generators.py)
module for those three functions.

<!-- For scarf -->
<figure><img alt="ZenML Scarf" referrerpolicy="no-referrer-when-downgrade" src="https://static.scarf.sh/a.png?x-pxid=f0b4f458-0a54-4fcd-aa95-d5ee424815bc" /></figure>
5 changes: 3 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ ipinfo = { version = ">=4.4.3", optional = true }

# Optional dependencies for project templates
copier = { version = ">=8.1.0", optional = true }
pyyaml-include = {version = "<2.0", optional = true}
pyyaml-include = { version = "<2.0", optional = true }
jinja2-time = { version = "^0.2.0", optional = true }

# Optional terraform dependency for stack recipes and ZenServer deployments
Expand Down Expand Up @@ -458,6 +458,7 @@ module = [
"mlstacks.*",
"matplotlib.*",
"IPython.*",
"huggingface_hub.*"
"huggingface_hub.*",
"label_studio_sdk.*"
]
ignore_missing_imports = true
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,17 @@
import os
import webbrowser
from pathlib import Path
from typing import Any, Dict, List, Optional, Tuple, cast
from typing import Any, Dict, List, Optional, Tuple, Type, cast

from label_studio_sdk import Client, Project # type: ignore[import-not-found]
from label_studio_sdk import Client, Project

from zenml import get_step_context
from zenml.annotators.base_annotator import BaseAnnotator
from zenml.artifact_stores.base_artifact_store import BaseArtifactStore
from zenml.config.global_config import GlobalConfiguration
from zenml.integrations.label_studio.flavors import (
LabelStudioAnnotatorSettings,
)
from zenml.integrations.label_studio.flavors.label_studio_annotator_flavor import (
LabelStudioAnnotatorConfig,
)
Expand All @@ -49,13 +53,26 @@ def config(self) -> LabelStudioAnnotatorConfig:
"""
return cast(LabelStudioAnnotatorConfig, self._config)

@property
def settings_class(self) -> Type[LabelStudioAnnotatorSettings]:
"""Settings class for the Label Studio annotator.
Returns:
The settings class.
"""
return LabelStudioAnnotatorSettings

def get_url(self) -> str:
"""Gets the top-level URL of the annotation interface.
Returns:
The URL of the annotation interface.
"""
return f"{self.config.instance_url}:{self.config.port}"
return (
f"{self.config.instance_url}:{self.config.port}"
if self.config.port
else self.config.instance_url
)

def get_url_for_dataset(self, dataset_name: str) -> str:
"""Gets the URL of the annotation interface for the given dataset.
Expand Down Expand Up @@ -151,12 +168,23 @@ def _get_client(self) -> Client:
Raises:
ValueError: when unable to access the Label Studio API key.
"""
secret = self.get_authentication_secret()
if not secret:
raise ValueError(
"Unable to access predefined secret to access Label Studio API key."
try:
settings = cast(
LabelStudioAnnotatorSettings,
self.get_settings(get_step_context().step_run),
)
api_key = secret.secret_values.get("api_key")
if settings.api_key is None:
raise RuntimeError
else:
api_key = settings.api_key
except RuntimeError:
# Try to get from secret
secret = self.get_authentication_secret()
if not secret:
raise ValueError(
"Unable to access predefined secret to access Label Studio API key."
)
api_key = secret.secret_values.get("api_key", "")
if not api_key:
raise ValueError(
"Unable to access Label Studio API key from secret."
Expand Down
2 changes: 2 additions & 0 deletions src/zenml/integrations/label_studio/flavors/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@
from zenml.integrations.label_studio.flavors.label_studio_annotator_flavor import (
LabelStudioAnnotatorConfig,
LabelStudioAnnotatorFlavor,
LabelStudioAnnotatorSettings,
)

__all__ = [
"LabelStudioAnnotatorFlavor",
"LabelStudioAnnotatorConfig",
"LabelStudioAnnotatorSettings"
]
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@
BaseAnnotatorConfig,
BaseAnnotatorFlavor,
)
from zenml.config.base_settings import BaseSettings
from zenml.integrations.label_studio import LABEL_STUDIO_ANNOTATOR_FLAVOR
from zenml.stack.authentication_mixin import AuthenticationConfigMixin
from zenml.utils.secret_utils import SecretField

if TYPE_CHECKING:
from zenml.integrations.label_studio.annotators import LabelStudioAnnotator
Expand All @@ -30,18 +32,31 @@
DEFAULT_LOCAL_LABEL_STUDIO_PORT = 8093


class LabelStudioAnnotatorConfig(
BaseAnnotatorConfig, AuthenticationConfigMixin
):
"""Config for the Label Studio annotator.
class LabelStudioAnnotatorSettings(BaseSettings):
"""Label studio annotator settings.
Attributes:
instance_url: URL of the Label Studio instance.
port: The port to use for the annotation interface.
api_key: The api_key for label studio.
"""

instance_url: str = DEFAULT_LOCAL_INSTANCE_URL
port: int = DEFAULT_LOCAL_LABEL_STUDIO_PORT
port: Optional[int] = DEFAULT_LOCAL_LABEL_STUDIO_PORT
api_key: Optional[str] = SecretField()


class LabelStudioAnnotatorConfig( # type: ignore[misc] # https://github.com/pydantic/pydantic/issues/4173
BaseAnnotatorConfig,
LabelStudioAnnotatorSettings,
AuthenticationConfigMixin,
):
"""Config for the Label Studio annotator.
This class combines settings and authentication configurations for
Label Studio into a single, usable configuration object without adding
additional functionality.
"""


class LabelStudioAnnotatorFlavor(BaseAnnotatorFlavor):
Expand Down

0 comments on commit cb07d3a

Please sign in to comment.