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

Create tags table #2036

Merged
merged 37 commits into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
c9729d9
working option 2
avishniakov Nov 9, 2023
caecabc
working option 2
avishniakov Nov 9, 2023
27624c6
working option 2
avishniakov Nov 9, 2023
15df83c
fix mysql
avishniakov Nov 9, 2023
a813455
Merge branch 'develop' into feature/OSS-2610-create-tags-table
avishniakov Nov 9, 2023
331e1a1
fix bug + add tests
avishniakov Nov 9, 2023
7ab1a22
rename
avishniakov Nov 9, 2023
200776e
Merge branch 'develop' into feature/OSS-2610-create-tags-table
avishniakov Nov 10, 2023
a265b64
add alembic branches output on divergence
avishniakov Nov 10, 2023
4ff8b26
add client functions
avishniakov Nov 10, 2023
4438a5f
strenums for types/colors
avishniakov Nov 10, 2023
9f7daf6
add tags cli
avishniakov Nov 10, 2023
e9b539a
add tags cli
avishniakov Nov 10, 2023
da14b2b
try bypass alembic branching
avishniakov Nov 10, 2023
fb26bd4
remove tag<>resource endpoints
avishniakov Nov 10, 2023
df82b6e
rely on sql for tag links
avishniakov Nov 10, 2023
1dd232b
Merge branch 'develop' into feature/OSS-2610-create-tags-table
avishniakov Nov 10, 2023
17bced5
fix migration bug with uuids
avishniakov Nov 10, 2023
3bb6f82
remove `tagged`
avishniakov Nov 10, 2023
a8f508e
calm down branching check on zenml import
avishniakov Nov 10, 2023
3206946
update signature in tests
avishniakov Nov 10, 2023
994b59a
Merge branch 'develop' into feature/OSS-2610-create-tags-table
avishniakov Nov 10, 2023
ee57e87
update signature in tests
avishniakov Nov 10, 2023
7033f23
Merge branch 'develop' into feature/OSS-2610-create-tags-table
avishniakov Nov 10, 2023
4b51589
resolve branching
avishniakov Nov 10, 2023
81a0390
Auto-update of E2E template
actions-user Nov 10, 2023
de13f1e
move tagging code to sql store
avishniakov Nov 13, 2023
4adcd0b
resolve branching
avishniakov Nov 13, 2023
dce6439
Merge branch 'develop' into feature/OSS-2610-create-tags-table
avishniakov Nov 13, 2023
3f79f50
resolve alembic
avishniakov Nov 13, 2023
08649c8
stabilize test case
avishniakov Nov 13, 2023
005adcb
better cleanups in tests
avishniakov Nov 13, 2023
d6e76aa
workaround fix for quickstart
avishniakov Nov 13, 2023
5324f2b
revert hard cleanup
avishniakov Nov 13, 2023
1355e7c
explicit asserts in cli
avishniakov Nov 13, 2023
f388ae0
revert workaround fix for quickstart
avishniakov Nov 13, 2023
ed33c9f
Temporarily fix quickstart until the certificate is renewed
stefannica Nov 13, 2023
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 src/zenml/cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1488,3 +1488,4 @@ def my_pipeline(...):
from zenml.cli.stack_recipes import * # noqa
from zenml.cli.user_management import * # noqa
from zenml.cli.workspace import * # noqa
from zenml.cli.tag import * # noqa
32 changes: 18 additions & 14 deletions src/zenml/cli/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from zenml.cli.cli import TagGroup, cli
from zenml.client import Client
from zenml.enums import CliCategories, ModelStages
from zenml.exceptions import EntityExistsError
from zenml.logger import get_logger
from zenml.models.model_models import (
ModelFilterModel,
Expand Down Expand Up @@ -164,21 +165,24 @@ def register_model(
limitations: The know limitations of the model.
tag: Tags associated with the model.
"""
model = Client().create_model(
ModelRequestModel(
name=name,
license=license,
description=description,
audience=audience,
use_cases=use_cases,
trade_offs=tradeoffs,
ethics=ethical,
limitations=limitations,
tags=tag,
user=Client().active_user.id,
workspace=Client().active_workspace.id,
try:
model = Client().create_model(
ModelRequestModel(
name=name,
license=license,
description=description,
audience=audience,
use_cases=use_cases,
trade_offs=tradeoffs,
ethics=ethical,
limitations=limitations,
tags=tag,
user=Client().active_user.id,
workspace=Client().active_workspace.id,
)
)
)
except (EntityExistsError, ValueError) as e:
cli_utils.error(str(e))

cli_utils.print_pydantic_models(
[model],
Expand Down
183 changes: 183 additions & 0 deletions src/zenml/cli/tag.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
# Copyright (c) ZenML GmbH 2023. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
# or implied. See the License for the specific language governing
# permissions and limitations under the License.
"""CLI functionality to interact with tags."""
# from functools import partial
from typing import Any, Optional, Union
from uuid import UUID

import click

# from uuid import UUID
# import click
from zenml.cli import utils as cli_utils
from zenml.cli.cli import TagGroup, cli
from zenml.client import Client
from zenml.enums import CliCategories, ColorVariants
from zenml.exceptions import EntityExistsError
from zenml.logger import get_logger
from zenml.models.tag_models import (
TagFilterModel,
TagRequestModel,
TagUpdateModel,
)
from zenml.utils.dict_utils import remove_none_values

logger = get_logger(__name__)


@cli.group(cls=TagGroup, tag=CliCategories.MANAGEMENT_TOOLS)
def tag() -> None:
"""Interact with tags."""


@cli_utils.list_options(TagFilterModel)
@tag.command("list", help="List tags with filter.")
def list_tags(**kwargs: Any) -> None:
"""List tags with filter.

Args:
**kwargs: Keyword arguments to filter models.
"""
tags = Client().list_tags(TagFilterModel(**kwargs))

if not tags:
cli_utils.declare("No tags found.")
return

cli_utils.print_pydantic_models(
tags,
exclude_columns=["created"],
)


@tag.command("register", help="Register a new tag.")
@click.option(
"--name",
"-n",
help="The name of the tag.",
type=str,
required=True,
)
@click.option(
"--color",
"-c",
help="The color variant for UI.",
type=click.Choice(choices=ColorVariants.values()),
required=False,
)
def register_tag(name: str, color: Optional[ColorVariants]) -> None:
"""Register a new model in the Model Control Plane.

Args:
name: The name of the tag.
color: The color variant for UI.
"""
request_dict = remove_none_values(dict(name=name, color=color))
try:
tag = Client().create_tag(TagRequestModel(**request_dict))
except (EntityExistsError, ValueError) as e:
cli_utils.error(str(e))

cli_utils.print_pydantic_models(
[tag],
exclude_columns=["created"],
)


@tag.command("update", help="Update an existing tag.")
@click.argument("tag_name_or_id")
@click.option(
"--name",
"-n",
help="The name of the tag.",
type=str,
required=False,
)
@click.option(
"--color",
"-c",
help="The color variant for UI.",
type=click.Choice(choices=ColorVariants.values()),
required=False,
)
def update_tag(
tag_name_or_id: Union[str, UUID], name: Optional[str], color: Optional[str]
) -> None:
"""Register a new model in the Model Control Plane.

Args:
tag_name_or_id: The name or ID of the tag.
name: The name of the tag.
color: The color variant for UI.
"""
update_dict = remove_none_values(dict(name=name, color=color))
if not update_dict:
cli_utils.declare("You need to specify --name or --color for update.")
return

tag = Client().update_tag(
tag_name_or_id=tag_name_or_id,
tag_update_model=TagUpdateModel(**update_dict),
)

cli_utils.print_pydantic_models(
[tag],
exclude_columns=["created"],
)


@tag.command("delete", help="Delete an existing tag.")
@click.argument("tag_name_or_id")
@click.option(
"--yes",
"-y",
is_flag=True,
help="Don't ask for confirmation.",
)
def delete_tag(
tag_name_or_id: Union[str, UUID],
yes: bool = False,
) -> None:
"""Delete an existing tag.

Args:
tag_name_or_id: The ID or name of the tag to delete.
yes: If set, don't ask for confirmation.
"""
try:
tagged_count = Client().get_tag(tag_name_or_id).tagged_count
except (KeyError, ValueError) as e:
cli_utils.error(str(e))

if not yes or tagged_count > 0:
confirmation = cli_utils.confirmation(
f"Are you sure you want to delete tag '{tag_name_or_id}'?"
+ (
""
if tagged_count == 0
else f"\n{tagged_count} objects are tagged with it."
)
)
if not confirmation:
cli_utils.declare("Tag deletion canceled.")
return

try:
Client().delete_tag(
tag_name_or_id=tag_name_or_id,
)
except (KeyError, ValueError) as e:
cli_utils.error(str(e))
else:
cli_utils.declare(f"Tag '{tag_name_or_id}' deleted.")
76 changes: 76 additions & 0 deletions src/zenml/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,12 @@
ScheduleFilterModel,
ScheduleResponseModel,
)
from zenml.models.tag_models import (
TagFilterModel,
TagRequestModel,
TagResponseModel,
TagUpdateModel,
)
from zenml.utils import io_utils, source_utils
from zenml.utils.filesync_model import FileSyncModel
from zenml.utils.pagination_utils import depaginate
Expand Down Expand Up @@ -5475,3 +5481,73 @@ def _get_entity_by_prefix(
f"Please provide more characters to uniquely identify "
f"only one of the {entity_label}s."
)

#############################################
# Tags
#
# Note: tag<>resource are not exposed and
# can be accessed via relevant resources
#############################################

def create_tag(self, tag: TagRequestModel) -> TagResponseModel:
"""Creates a new tag.

Args:
tag: the Tag to be created.

Returns:
The newly created tag.
"""
return self.zen_store.create_tag(tag=tag)

def delete_tag(self, tag_name_or_id: Union[str, UUID]) -> None:
"""Deletes a tag.

Args:
tag_name_or_id: name or id of the tag to be deleted.
"""
self.zen_store.delete_tag(tag_name_or_id=tag_name_or_id)

def update_tag(
self,
tag_name_or_id: Union[str, UUID],
tag_update_model: TagUpdateModel,
) -> TagResponseModel:
"""Updates an existing tag.

Args:
tag_name_or_id: name or UUID of the tag to be updated.
tag_update_model: the tag to be updated.

Returns:
The updated tag.
"""
return self.zen_store.update_tag(
tag_name_or_id=tag_name_or_id, tag_update_model=tag_update_model
)

def get_tag(self, tag_name_or_id: Union[str, UUID]) -> TagResponseModel:
"""Get an existing tag.

Args:
tag_name_or_id: name or id of the model to be retrieved.

Returns:
The tag of interest.
"""
return self.zen_store.get_tag(tag_name_or_id=tag_name_or_id)

def list_tags(
self,
tag_filter_model: TagFilterModel,
) -> Page[TagResponseModel]:
"""Get tags by filter.

Args:
tag_filter_model: All filter parameters including pagination
params.

Returns:
A page of all tags.
"""
return self.zen_store.list_tags(tag_filter_model=tag_filter_model)
1 change: 0 additions & 1 deletion src/zenml/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,6 @@ def handle_int_env_var(var: str, default: int = 0) -> int:
DEVICE_VERIFY = "/verify"
API_TOKEN = "/api_token"
TAGS = "/tags"
TAG_RESOURCES = "/tag_resources"

# model metadata yaml file name
MODEL_METADATA_YAML_FILE_NAME = "model_metadata.yaml"
Expand Down
28 changes: 14 additions & 14 deletions src/zenml/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,23 +293,23 @@ class ModelStages(StrEnum):
ARCHIVED = "archived"


class ColorVariants(Enum):
class ColorVariants(StrEnum):
"""All possible color variants for frontend."""

GREY = 1
PURPLE = 2
RED = 3
GREEN = 4
YELLOW = 5
ORANGE = 6
LIME = 7
TEAL = 8
TURQUOISE = 9
MAGENTA = 10
BLUE = 11
GREY = "grey"
PURPLE = "purple"
RED = "red"
GREEN = "green"
YELLOW = "yellow"
ORANGE = "orange"
LIME = "lime"
TEAL = "teal"
TURQUOISE = "turquoise"
MAGENTA = "magenta"
BLUE = "blue"


class TaggableResourceTypes(Enum):
class TaggableResourceTypes(StrEnum):
"""All possible resource types for tagging."""

MODEL = 1
MODEL = "model"
9 changes: 1 addition & 8 deletions src/zenml/model/model_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
from pydantic import BaseModel, root_validator

from zenml.constants import RUNNING_MODEL_VERSION
from zenml.enums import ExecutionStatus, ModelStages, TaggableResourceTypes
from zenml.enums import ExecutionStatus, ModelStages
from zenml.exceptions import EntityExistsError
from zenml.logger import get_logger

Expand Down Expand Up @@ -177,7 +177,6 @@ def get_or_create_model(self) -> "ModelResponseModel":
"""
from zenml.client import Client
from zenml.models.model_models import ModelRequestModel
from zenml.utils.tag_utils import create_links

zenml_client = Client()
try:
Expand All @@ -199,12 +198,6 @@ def get_or_create_model(self) -> "ModelResponseModel":
model_request = ModelRequestModel.parse_obj(model_request)
try:
model = zenml_client.create_model(model=model_request)
if model_request.tags:
create_links(
model_request.tags,
model.id,
TaggableResourceTypes.MODEL,
)
logger.info(f"New model `{self.name}` was created implicitly.")
except EntityExistsError:
# this is backup logic, if model was created somehow in between get and create calls
Expand Down
Loading
Loading