zenml-nightly 0.70.0.dev20241125__py3-none-any.whl → 0.70.0.dev20241201__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. zenml/VERSION +1 -1
  2. zenml/artifact_stores/base_artifact_store.py +2 -2
  3. zenml/artifacts/artifact_config.py +7 -1
  4. zenml/artifacts/utils.py +56 -31
  5. zenml/cli/__init__.py +18 -0
  6. zenml/cli/base.py +4 -4
  7. zenml/cli/login.py +26 -0
  8. zenml/cli/pipeline.py +80 -0
  9. zenml/cli/server.py +1 -1
  10. zenml/cli/service_connectors.py +3 -3
  11. zenml/cli/stack.py +0 -3
  12. zenml/cli/stack_components.py +0 -1
  13. zenml/cli/utils.py +0 -5
  14. zenml/client.py +8 -18
  15. zenml/config/compiler.py +12 -3
  16. zenml/config/pipeline_configurations.py +20 -0
  17. zenml/config/pipeline_run_configuration.py +1 -0
  18. zenml/config/step_configurations.py +21 -0
  19. zenml/enums.py +1 -0
  20. zenml/image_builders/local_image_builder.py +13 -3
  21. zenml/integrations/__init__.py +1 -0
  22. zenml/integrations/aws/orchestrators/sagemaker_orchestrator.py +14 -6
  23. zenml/integrations/constants.py +1 -0
  24. zenml/integrations/feast/__init__.py +1 -1
  25. zenml/integrations/feast/feature_stores/feast_feature_store.py +13 -9
  26. zenml/integrations/kubernetes/orchestrators/kube_utils.py +46 -2
  27. zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator.py +13 -2
  28. zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator_entrypoint.py +3 -1
  29. zenml/integrations/kubernetes/orchestrators/manifest_utils.py +3 -2
  30. zenml/integrations/kubernetes/step_operators/kubernetes_step_operator.py +3 -1
  31. zenml/integrations/modal/__init__.py +46 -0
  32. zenml/integrations/modal/flavors/__init__.py +26 -0
  33. zenml/integrations/modal/flavors/modal_step_operator_flavor.py +125 -0
  34. zenml/integrations/modal/step_operators/__init__.py +22 -0
  35. zenml/integrations/modal/step_operators/modal_step_operator.py +242 -0
  36. zenml/io/filesystem.py +2 -2
  37. zenml/io/local_filesystem.py +3 -3
  38. zenml/materializers/built_in_materializer.py +18 -1
  39. zenml/materializers/structured_string_materializer.py +8 -3
  40. zenml/model/model.py +11 -85
  41. zenml/model/utils.py +18 -16
  42. zenml/models/__init__.py +6 -0
  43. zenml/models/v2/core/artifact_version.py +6 -3
  44. zenml/models/v2/core/component.py +0 -22
  45. zenml/models/v2/core/model_version.py +6 -3
  46. zenml/models/v2/core/pipeline_run.py +19 -3
  47. zenml/models/v2/core/run_metadata.py +30 -9
  48. zenml/models/v2/core/step_run.py +6 -4
  49. zenml/models/v2/misc/run_metadata.py +38 -0
  50. zenml/orchestrators/input_utils.py +19 -6
  51. zenml/orchestrators/publish_utils.py +12 -5
  52. zenml/orchestrators/step_launcher.py +7 -3
  53. zenml/orchestrators/step_run_utils.py +26 -9
  54. zenml/orchestrators/step_runner.py +40 -3
  55. zenml/orchestrators/utils.py +24 -23
  56. zenml/pipelines/pipeline_decorator.py +4 -0
  57. zenml/pipelines/pipeline_definition.py +26 -8
  58. zenml/pipelines/run_utils.py +9 -5
  59. zenml/steps/base_step.py +11 -1
  60. zenml/steps/entrypoint_function_utils.py +7 -3
  61. zenml/steps/step_decorator.py +4 -0
  62. zenml/steps/utils.py +23 -7
  63. zenml/types.py +4 -0
  64. zenml/utils/metadata_utils.py +186 -153
  65. zenml/utils/string_utils.py +41 -16
  66. zenml/utils/visualization_utils.py +4 -1
  67. zenml/zen_server/cloud_utils.py +3 -1
  68. zenml/zen_server/rbac/endpoint_utils.py +6 -4
  69. zenml/zen_server/rbac/models.py +3 -2
  70. zenml/zen_server/rbac/utils.py +4 -7
  71. zenml/zen_server/routers/users_endpoints.py +35 -37
  72. zenml/zen_server/routers/workspaces_endpoints.py +44 -55
  73. zenml/zen_server/template_execution/utils.py +1 -0
  74. zenml/zen_stores/migrations/versions/b73bc71f1106_remove_component_spec_path.py +36 -0
  75. zenml/zen_stores/migrations/versions/cc269488e5a9_separate_run_metadata.py +135 -0
  76. zenml/zen_stores/migrations/versions/ec6307720f92_simplify_model_version_links.py +7 -6
  77. zenml/zen_stores/schemas/__init__.py +5 -1
  78. zenml/zen_stores/schemas/artifact_schemas.py +12 -11
  79. zenml/zen_stores/schemas/component_schemas.py +0 -3
  80. zenml/zen_stores/schemas/model_schemas.py +13 -11
  81. zenml/zen_stores/schemas/pipeline_run_schemas.py +44 -16
  82. zenml/zen_stores/schemas/run_metadata_schemas.py +66 -31
  83. zenml/zen_stores/schemas/step_run_schemas.py +32 -12
  84. zenml/zen_stores/schemas/utils.py +47 -3
  85. zenml/zen_stores/sql_zen_store.py +130 -34
  86. {zenml_nightly-0.70.0.dev20241125.dist-info → zenml_nightly-0.70.0.dev20241201.dist-info}/METADATA +1 -1
  87. {zenml_nightly-0.70.0.dev20241125.dist-info → zenml_nightly-0.70.0.dev20241201.dist-info}/RECORD +90 -83
  88. zenml/utils/cloud_utils.py +0 -40
  89. {zenml_nightly-0.70.0.dev20241125.dist-info → zenml_nightly-0.70.0.dev20241201.dist-info}/LICENSE +0 -0
  90. {zenml_nightly-0.70.0.dev20241125.dist-info → zenml_nightly-0.70.0.dev20241201.dist-info}/WHEEL +0 -0
  91. {zenml_nightly-0.70.0.dev20241125.dist-info → zenml_nightly-0.70.0.dev20241201.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,242 @@
1
+ # Copyright (c) ZenML GmbH 2024. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at:
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12
+ # or implied. See the License for the specific language governing
13
+ # permissions and limitations under the License.
14
+ """Modal step operator implementation."""
15
+
16
+ import asyncio
17
+ from typing import TYPE_CHECKING, Dict, List, Optional, Tuple, Type, cast
18
+
19
+ import modal
20
+ from modal_proto import api_pb2
21
+
22
+ from zenml.client import Client
23
+ from zenml.config.build_configuration import BuildConfiguration
24
+ from zenml.config.resource_settings import ByteUnit, ResourceSettings
25
+ from zenml.enums import StackComponentType
26
+ from zenml.integrations.modal.flavors import (
27
+ ModalStepOperatorConfig,
28
+ ModalStepOperatorSettings,
29
+ )
30
+ from zenml.logger import get_logger
31
+ from zenml.stack import Stack, StackValidator
32
+ from zenml.step_operators import BaseStepOperator
33
+
34
+ if TYPE_CHECKING:
35
+ from zenml.config.base_settings import BaseSettings
36
+ from zenml.config.step_run_info import StepRunInfo
37
+ from zenml.models import PipelineDeploymentBase
38
+
39
+ logger = get_logger(__name__)
40
+
41
+ MODAL_STEP_OPERATOR_DOCKER_IMAGE_KEY = "modal_step_operator"
42
+
43
+
44
+ def get_gpu_values(
45
+ settings: ModalStepOperatorSettings, resource_settings: ResourceSettings
46
+ ) -> Optional[str]:
47
+ """Get the GPU values for the Modal step operator.
48
+
49
+ Args:
50
+ settings: The Modal step operator settings.
51
+ resource_settings: The resource settings.
52
+
53
+ Returns:
54
+ The GPU string if a count is specified, otherwise the GPU type.
55
+ """
56
+ if not settings.gpu:
57
+ return None
58
+ gpu_count = resource_settings.gpu_count
59
+ return f"{settings.gpu}:{gpu_count}" if gpu_count else settings.gpu
60
+
61
+
62
+ class ModalStepOperator(BaseStepOperator):
63
+ """Step operator to run a step on Modal.
64
+
65
+ This class defines code that can set up a Modal environment and run
66
+ functions in it.
67
+ """
68
+
69
+ @property
70
+ def config(self) -> ModalStepOperatorConfig:
71
+ """Get the Modal step operator configuration.
72
+
73
+ Returns:
74
+ The Modal step operator configuration.
75
+ """
76
+ return cast(ModalStepOperatorConfig, self._config)
77
+
78
+ @property
79
+ def settings_class(self) -> Optional[Type["BaseSettings"]]:
80
+ """Get the settings class for the Modal step operator.
81
+
82
+ Returns:
83
+ The Modal step operator settings class.
84
+ """
85
+ return ModalStepOperatorSettings
86
+
87
+ @property
88
+ def validator(self) -> Optional[StackValidator]:
89
+ """Get the stack validator for the Modal step operator.
90
+
91
+ Returns:
92
+ The stack validator.
93
+ """
94
+
95
+ def _validate_remote_components(stack: "Stack") -> Tuple[bool, str]:
96
+ if stack.artifact_store.config.is_local:
97
+ return False, (
98
+ "The Modal step operator runs code remotely and "
99
+ "needs to write files into the artifact store, but the "
100
+ f"artifact store `{stack.artifact_store.name}` of the "
101
+ "active stack is local. Please ensure that your stack "
102
+ "contains a remote artifact store when using the Modal "
103
+ "step operator."
104
+ )
105
+
106
+ container_registry = stack.container_registry
107
+ assert container_registry is not None
108
+
109
+ if container_registry.config.is_local:
110
+ return False, (
111
+ "The Modal step operator runs code remotely and "
112
+ "needs to push/pull Docker images, but the "
113
+ f"container registry `{container_registry.name}` of the "
114
+ "active stack is local. Please ensure that your stack "
115
+ "contains a remote container registry when using the "
116
+ "Modal step operator."
117
+ )
118
+
119
+ return True, ""
120
+
121
+ return StackValidator(
122
+ required_components={
123
+ StackComponentType.CONTAINER_REGISTRY,
124
+ StackComponentType.IMAGE_BUILDER,
125
+ },
126
+ custom_validation_function=_validate_remote_components,
127
+ )
128
+
129
+ def get_docker_builds(
130
+ self, deployment: "PipelineDeploymentBase"
131
+ ) -> List["BuildConfiguration"]:
132
+ """Get the Docker build configurations for the Modal step operator.
133
+
134
+ Args:
135
+ deployment: The pipeline deployment.
136
+
137
+ Returns:
138
+ A list of Docker build configurations.
139
+ """
140
+ builds = []
141
+ for step_name, step in deployment.step_configurations.items():
142
+ if step.config.step_operator == self.name:
143
+ build = BuildConfiguration(
144
+ key=MODAL_STEP_OPERATOR_DOCKER_IMAGE_KEY,
145
+ settings=step.config.docker_settings,
146
+ step_name=step_name,
147
+ )
148
+ builds.append(build)
149
+
150
+ return builds
151
+
152
+ def launch(
153
+ self,
154
+ info: "StepRunInfo",
155
+ entrypoint_command: List[str],
156
+ environment: Dict[str, str],
157
+ ) -> None:
158
+ """Launch a step run on Modal.
159
+
160
+ Args:
161
+ info: The step run information.
162
+ entrypoint_command: The entrypoint command for the step.
163
+ environment: The environment variables for the step.
164
+
165
+ Raises:
166
+ RuntimeError: If no Docker credentials are found for the container registry.
167
+ ValueError: If no container registry is found in the stack.
168
+ """
169
+ settings = cast(ModalStepOperatorSettings, self.get_settings(info))
170
+ image_name = info.get_image(key=MODAL_STEP_OPERATOR_DOCKER_IMAGE_KEY)
171
+ zc = Client()
172
+ stack = zc.active_stack
173
+
174
+ if not stack.container_registry:
175
+ raise ValueError(
176
+ "No Container registry found in the stack. "
177
+ "Please add a container registry and ensure "
178
+ "it is correctly configured."
179
+ )
180
+
181
+ if docker_creds := stack.container_registry.credentials:
182
+ docker_username, docker_password = docker_creds
183
+ else:
184
+ raise RuntimeError(
185
+ "No Docker credentials found for the container registry."
186
+ )
187
+
188
+ my_secret = modal.secret._Secret.from_dict(
189
+ {
190
+ "REGISTRY_USERNAME": docker_username,
191
+ "REGISTRY_PASSWORD": docker_password,
192
+ }
193
+ )
194
+
195
+ spec = modal.image.DockerfileSpec(
196
+ commands=[f"FROM {image_name}"], context_files={}
197
+ )
198
+
199
+ zenml_image = modal.Image._from_args(
200
+ dockerfile_function=lambda *_, **__: spec,
201
+ force_build=False,
202
+ image_registry_config=modal.image._ImageRegistryConfig(
203
+ api_pb2.REGISTRY_AUTH_TYPE_STATIC_CREDS, my_secret
204
+ ),
205
+ ).env(environment)
206
+
207
+ resource_settings = info.config.resource_settings
208
+ gpu_values = get_gpu_values(settings, resource_settings)
209
+
210
+ app = modal.App(
211
+ f"zenml-{info.run_name}-{info.step_run_id}-{info.pipeline_step_name}"
212
+ )
213
+
214
+ async def run_sandbox() -> asyncio.Future[None]:
215
+ loop = asyncio.get_event_loop()
216
+ future = loop.create_future()
217
+ with modal.enable_output():
218
+ async with app.run():
219
+ memory_mb = resource_settings.get_memory(ByteUnit.MB)
220
+ memory_int = (
221
+ int(memory_mb) if memory_mb is not None else None
222
+ )
223
+ sb = await modal.Sandbox.create.aio(
224
+ "bash",
225
+ "-c",
226
+ " ".join(entrypoint_command),
227
+ image=zenml_image,
228
+ gpu=gpu_values,
229
+ cpu=resource_settings.cpu_count,
230
+ memory=memory_int,
231
+ cloud=settings.cloud,
232
+ region=settings.region,
233
+ app=app,
234
+ timeout=86400, # 24h, the max Modal allows
235
+ )
236
+
237
+ await sb.wait.aio()
238
+
239
+ future.set_result(None)
240
+ return future
241
+
242
+ asyncio.run(run_sandbox())
zenml/io/filesystem.py CHANGED
@@ -54,11 +54,11 @@ class BaseFilesystem(ABC):
54
54
 
55
55
  @staticmethod
56
56
  @abstractmethod
57
- def open(name: PathType, mode: str = "r") -> Any:
57
+ def open(path: PathType, mode: str = "r") -> Any:
58
58
  """Opens a file.
59
59
 
60
60
  Args:
61
- name: The path to the file.
61
+ path: The path to the file.
62
62
  mode: The mode to open the file in.
63
63
 
64
64
  Returns:
@@ -55,18 +55,18 @@ class LocalFilesystem(BaseFilesystem):
55
55
  SUPPORTED_SCHEMES: ClassVar[Set[str]] = {""}
56
56
 
57
57
  @staticmethod
58
- def open(name: PathType, mode: str = "r") -> Any:
58
+ def open(path: PathType, mode: str = "r") -> Any:
59
59
  """Open a file at the given path.
60
60
 
61
61
  Args:
62
- name: The path to the file.
62
+ path: The path to the file.
63
63
  mode: The mode to open the file.
64
64
 
65
65
  Returns:
66
66
  Any: The file object.
67
67
  """
68
68
  encoding = "utf-8" if "b" not in mode else None
69
- return open(name, mode=mode, encoding=encoding)
69
+ return open(path, mode=mode, encoding=encoding)
70
70
 
71
71
  @staticmethod
72
72
  def copyfile(
@@ -28,7 +28,7 @@ from typing import (
28
28
  )
29
29
 
30
30
  from zenml.artifact_stores.base_artifact_store import BaseArtifactStore
31
- from zenml.enums import ArtifactType
31
+ from zenml.enums import ArtifactType, VisualizationType
32
32
  from zenml.logger import get_logger
33
33
  from zenml.materializers.base_materializer import BaseMaterializer
34
34
  from zenml.materializers.materializer_registry import materializer_registry
@@ -415,6 +415,23 @@ class BuiltInContainerMaterializer(BaseMaterializer):
415
415
  self.artifact_store.rmtree(entry["path"])
416
416
  raise e
417
417
 
418
+ # save dict type objects to JSON file with JSON visualization type
419
+ def save_visualizations(self, data: Any) -> Dict[str, "VisualizationType"]:
420
+ """Save visualizations for the given data.
421
+
422
+ Args:
423
+ data: The data to save visualizations for.
424
+
425
+ Returns:
426
+ A dictionary of visualization URIs and their types.
427
+ """
428
+ # dict/list type objects are always saved as JSON files
429
+ # doesn't work for non-serializable types as they
430
+ # are saved as list of lists in different files
431
+ if _is_serializable(data):
432
+ return {self.data_path: VisualizationType.JSON}
433
+ return {}
434
+
418
435
  def extract_metadata(self, data: Any) -> Dict[str, "MetadataType"]:
419
436
  """Extract metadata from the given built-in container object.
420
437
 
@@ -19,22 +19,23 @@ from typing import Dict, Type, Union
19
19
  from zenml.enums import ArtifactType, VisualizationType
20
20
  from zenml.logger import get_logger
21
21
  from zenml.materializers.base_materializer import BaseMaterializer
22
- from zenml.types import CSVString, HTMLString, MarkdownString
22
+ from zenml.types import CSVString, HTMLString, JSONString, MarkdownString
23
23
 
24
24
  logger = get_logger(__name__)
25
25
 
26
26
 
27
- STRUCTURED_STRINGS = Union[CSVString, HTMLString, MarkdownString]
27
+ STRUCTURED_STRINGS = Union[CSVString, HTMLString, MarkdownString, JSONString]
28
28
 
29
29
  HTML_FILENAME = "output.html"
30
30
  MARKDOWN_FILENAME = "output.md"
31
31
  CSV_FILENAME = "output.csv"
32
+ JSON_FILENAME = "output.json"
32
33
 
33
34
 
34
35
  class StructuredStringMaterializer(BaseMaterializer):
35
36
  """Materializer for HTML or Markdown strings."""
36
37
 
37
- ASSOCIATED_TYPES = (CSVString, HTMLString, MarkdownString)
38
+ ASSOCIATED_TYPES = (CSVString, HTMLString, MarkdownString, JSONString)
38
39
  ASSOCIATED_ARTIFACT_TYPE = ArtifactType.DATA_ANALYSIS
39
40
 
40
41
  def load(self, data_type: Type[STRUCTURED_STRINGS]) -> STRUCTURED_STRINGS:
@@ -94,6 +95,8 @@ class StructuredStringMaterializer(BaseMaterializer):
94
95
  filename = HTML_FILENAME
95
96
  elif issubclass(data_type, MarkdownString):
96
97
  filename = MARKDOWN_FILENAME
98
+ elif issubclass(data_type, JSONString):
99
+ filename = JSON_FILENAME
97
100
  else:
98
101
  raise ValueError(
99
102
  f"Data type {data_type} is not supported by this materializer."
@@ -120,6 +123,8 @@ class StructuredStringMaterializer(BaseMaterializer):
120
123
  return VisualizationType.HTML
121
124
  elif issubclass(data_type, MarkdownString):
122
125
  return VisualizationType.MARKDOWN
126
+ elif issubclass(data_type, JSONString):
127
+ return VisualizationType.JSON
123
128
  else:
124
129
  raise ValueError(
125
130
  f"Data type {data_type} is not supported by this materializer."
zenml/model/model.py CHANGED
@@ -13,14 +13,12 @@
13
13
  # permissions and limitations under the License.
14
14
  """Model user facing interface to pass into pipeline or step."""
15
15
 
16
- import datetime
17
16
  from typing import (
18
17
  TYPE_CHECKING,
19
18
  Any,
20
19
  Dict,
21
20
  List,
22
21
  Optional,
23
- Tuple,
24
22
  Union,
25
23
  )
26
24
  from uuid import UUID
@@ -41,7 +39,6 @@ if TYPE_CHECKING:
41
39
  ModelResponse,
42
40
  ModelVersionResponse,
43
41
  PipelineRunResponse,
44
- StepRunResponse,
45
42
  )
46
43
 
47
44
  logger = get_logger(__name__)
@@ -60,7 +57,9 @@ class Model(BaseModel):
60
57
  ethics: The ethical implications of the model.
61
58
  tags: Tags associated with the model.
62
59
  version: The version name, version number or stage is optional and points model context
63
- to a specific version/stage. If skipped new version will be created.
60
+ to a specific version/stage. If skipped new version will be created. `version`
61
+ also supports placeholders: standard `{date}` and `{time}` and any custom placeholders
62
+ that are passed as substitutions in the pipeline or step decorators.
64
63
  save_models_to_registry: Whether to save all ModelArtifacts to Model Registry,
65
64
  if available in active stack.
66
65
  """
@@ -337,12 +336,16 @@ class Model(BaseModel):
337
336
  metadata: The metadata to log.
338
337
  """
339
338
  from zenml.client import Client
339
+ from zenml.models import RunMetadataResource
340
340
 
341
341
  response = self._get_or_create_model_version()
342
342
  Client().create_run_metadata(
343
343
  metadata=metadata,
344
- resource_id=response.id,
345
- resource_type=MetadataResourceTypes.MODEL_VERSION,
344
+ resources=[
345
+ RunMetadataResource(
346
+ id=response.id, type=MetadataResourceTypes.MODEL_VERSION
347
+ )
348
+ ],
346
349
  )
347
350
 
348
351
  @property
@@ -537,6 +540,8 @@ class Model(BaseModel):
537
540
  from zenml.models import ModelRequest
538
541
 
539
542
  zenml_client = Client()
543
+ # backup logic, if the Model class is used directly from the code
544
+ self.name = format_name_template(self.name)
540
545
  if self.model_version_id:
541
546
  mv = zenml_client.get_model_version(
542
547
  model_version_name_or_number_or_id=self.model_version_id,
@@ -743,85 +748,6 @@ class Model(BaseModel):
743
748
  )
744
749
  )
745
750
 
746
- def _prepare_model_version_before_step_launch(
747
- self,
748
- pipeline_run: "PipelineRunResponse",
749
- step_run: Optional["StepRunResponse"],
750
- return_logs: bool,
751
- ) -> Tuple[str, "PipelineRunResponse", Optional["StepRunResponse"]]:
752
- """Prepares model version inside pipeline run.
753
-
754
- Args:
755
- pipeline_run: pipeline run
756
- step_run: step run (passed only if model version is defined in a step explicitly)
757
- return_logs: whether to return logs or not
758
-
759
- Returns:
760
- Logs related to the Dashboard URL to show later.
761
- """
762
- from zenml.client import Client
763
- from zenml.models import PipelineRunUpdate, StepRunUpdate
764
-
765
- logs = ""
766
-
767
- # copy Model instance to prevent corrupting configs of the
768
- # subsequent runs, if they share the same config object
769
- self_copy = self.model_copy()
770
-
771
- # in case request is within the step and no self-configuration is provided
772
- # try reuse what's in the pipeline run first
773
- if step_run is None and pipeline_run.model_version is not None:
774
- self_copy.version = pipeline_run.model_version.name
775
- self_copy.model_version_id = pipeline_run.model_version.id
776
- # otherwise try to fill the templated name, if needed
777
- elif isinstance(self_copy.version, str):
778
- if pipeline_run.start_time:
779
- start_time = pipeline_run.start_time
780
- else:
781
- start_time = datetime.datetime.now(datetime.timezone.utc)
782
- self_copy.version = format_name_template(
783
- self_copy.version,
784
- date=start_time.strftime("%Y_%m_%d"),
785
- time=start_time.strftime("%H_%M_%S_%f"),
786
- )
787
-
788
- # if exact model not yet defined - try to get/create and update it
789
- # back to the run accordingly
790
- if self_copy.model_version_id is None:
791
- model_version_response = self_copy._get_or_create_model_version()
792
-
793
- client = Client()
794
- # update the configured model version id in runs accordingly
795
- if step_run:
796
- step_run = client.zen_store.update_run_step(
797
- step_run_id=step_run.id,
798
- step_run_update=StepRunUpdate(
799
- model_version_id=model_version_response.id
800
- ),
801
- )
802
- else:
803
- pipeline_run = client.zen_store.update_run(
804
- run_id=pipeline_run.id,
805
- run_update=PipelineRunUpdate(
806
- model_version_id=model_version_response.id
807
- ),
808
- )
809
-
810
- if return_logs:
811
- from zenml.utils.cloud_utils import try_get_model_version_url
812
-
813
- if logs_to_show := try_get_model_version_url(
814
- model_version_response
815
- ):
816
- logs = logs_to_show
817
- else:
818
- logs = (
819
- "Models can be viewed in the dashboard using ZenML Pro. Sign up "
820
- "for a free trial at https://www.zenml.io/pro/"
821
- )
822
- self.model_version_id = self_copy.model_version_id
823
- return logs, pipeline_run, step_run
824
-
825
751
  @property
826
752
  def _lazy_version(self) -> Optional[str]:
827
753
  """Get version name for lazy loader.
zenml/model/utils.py CHANGED
@@ -52,29 +52,31 @@ def log_model_metadata(
52
52
  `model` in decorator.
53
53
 
54
54
  Raises:
55
- ValueError: If no model name/version is provided and the function is not
56
- called inside a step with configured `model` in decorator.
55
+ ValueError: If the function is not called with proper input.
57
56
  """
58
57
  logger.warning(
59
58
  "The `log_model_metadata` function is deprecated and will soon be "
60
59
  "removed. Please use `log_metadata` instead."
61
60
  )
62
61
 
63
- if model_name and model_version:
64
- from zenml import Model
62
+ from zenml import log_metadata
65
63
 
66
- mv = Model(name=model_name, version=model_version)
64
+ if model_name and model_version:
65
+ log_metadata(
66
+ metadata=metadata,
67
+ model_version=model_version,
68
+ model_name=model_name,
69
+ )
70
+ elif model_name is None and model_version is None:
71
+ log_metadata(
72
+ metadata=metadata,
73
+ infer_model=True,
74
+ )
67
75
  else:
68
- try:
69
- step_context = get_step_context()
70
- except RuntimeError:
71
- raise ValueError(
72
- "Model name and version must be provided unless the function is "
73
- "called inside a step with configured `model` in decorator."
74
- )
75
- mv = step_context.model
76
-
77
- mv.log_metadata(metadata)
76
+ raise ValueError(
77
+ "You can call `log_model_metadata` by either providing both "
78
+ "`model_name` and `model_version` or keeping both of them None."
79
+ )
78
80
 
79
81
 
80
82
  def link_artifact_version_to_model_version(
@@ -107,7 +109,7 @@ def link_artifact_to_model(
107
109
  model: The model to link to.
108
110
 
109
111
  Raises:
110
- RuntimeError: If called outside of a step.
112
+ RuntimeError: If called outside a step.
111
113
  """
112
114
  if not model:
113
115
  is_issue = False
zenml/models/__init__.py CHANGED
@@ -372,6 +372,10 @@ from zenml.models.v2.misc.auth_models import (
372
372
  OAuthRedirectResponse,
373
373
  OAuthTokenResponse,
374
374
  )
375
+ from zenml.models.v2.misc.run_metadata import (
376
+ RunMetadataEntry,
377
+ RunMetadataResource,
378
+ )
375
379
  from zenml.models.v2.misc.server_models import (
376
380
  ServerModel,
377
381
  ServerDatabaseType,
@@ -752,4 +756,6 @@ __all__ = [
752
756
  "ServiceConnectorInfo",
753
757
  "ServiceConnectorResourcesInfo",
754
758
  "ResourcesInfo",
759
+ "RunMetadataEntry",
760
+ "RunMetadataResource",
755
761
  ]
@@ -576,6 +576,7 @@ class ArtifactVersionFilter(WorkspaceScopedTaggableFilter):
576
576
  ModelVersionArtifactSchema,
577
577
  ModelVersionSchema,
578
578
  PipelineRunSchema,
579
+ RunMetadataResourceSchema,
579
580
  RunMetadataSchema,
580
581
  StepRunInputArtifactSchema,
581
582
  StepRunOutputArtifactSchema,
@@ -679,10 +680,12 @@ class ArtifactVersionFilter(WorkspaceScopedTaggableFilter):
679
680
 
680
681
  for key, value in self.run_metadata.items():
681
682
  additional_filter = and_(
682
- RunMetadataSchema.resource_id == ArtifactVersionSchema.id,
683
- RunMetadataSchema.resource_type
683
+ RunMetadataResourceSchema.resource_id
684
+ == ArtifactVersionSchema.id,
685
+ RunMetadataResourceSchema.resource_type
684
686
  == MetadataResourceTypes.ARTIFACT_VERSION,
685
- RunMetadataSchema.key == key,
687
+ RunMetadataResourceSchema.run_metadata_id
688
+ == RunMetadataSchema.id,
686
689
  self.generate_custom_query_conditions_for_column(
687
690
  value=value,
688
691
  table=RunMetadataSchema,
@@ -81,11 +81,6 @@ class ComponentBase(BaseModel):
81
81
  title="The stack component labels.",
82
82
  )
83
83
 
84
- component_spec_path: Optional[str] = Field(
85
- default=None,
86
- title="The path to the component spec used for mlstacks deployments.",
87
- )
88
-
89
84
 
90
85
  # ------------------ Request Model ------------------
91
86
 
@@ -155,10 +150,6 @@ class ComponentUpdate(BaseUpdate):
155
150
  title="The stack component labels.",
156
151
  default=None,
157
152
  )
158
- component_spec_path: Optional[str] = Field(
159
- title="The path to the component spec used for mlstacks deployments.",
160
- default=None,
161
- )
162
153
  connector: Optional[UUID] = Field(
163
154
  title="The service connector linked to this stack component.",
164
155
  default=None,
@@ -201,10 +192,6 @@ class ComponentResponseMetadata(WorkspaceScopedResponseMetadata):
201
192
  default=None,
202
193
  title="The stack component labels.",
203
194
  )
204
- component_spec_path: Optional[str] = Field(
205
- default=None,
206
- title="The path to the component spec used for mlstacks deployments.",
207
- )
208
195
  connector_resource_id: Optional[str] = Field(
209
196
  default=None,
210
197
  description="The ID of a specific resource instance to "
@@ -325,15 +312,6 @@ class ComponentResponse(
325
312
  """
326
313
  return self.get_metadata().labels
327
314
 
328
- @property
329
- def component_spec_path(self) -> Optional[str]:
330
- """The `component_spec_path` property.
331
-
332
- Returns:
333
- the value of the property.
334
- """
335
- return self.get_metadata().component_spec_path
336
-
337
315
  @property
338
316
  def connector_resource_id(self) -> Optional[str]:
339
317
  """The `connector_resource_id` property.
@@ -652,6 +652,7 @@ class ModelVersionFilter(WorkspaceScopedTaggableFilter):
652
652
 
653
653
  from zenml.zen_stores.schemas import (
654
654
  ModelVersionSchema,
655
+ RunMetadataResourceSchema,
655
656
  RunMetadataSchema,
656
657
  UserSchema,
657
658
  )
@@ -672,10 +673,12 @@ class ModelVersionFilter(WorkspaceScopedTaggableFilter):
672
673
 
673
674
  for key, value in self.run_metadata.items():
674
675
  additional_filter = and_(
675
- RunMetadataSchema.resource_id == ModelVersionSchema.id,
676
- RunMetadataSchema.resource_type
676
+ RunMetadataResourceSchema.resource_id
677
+ == ModelVersionSchema.id,
678
+ RunMetadataResourceSchema.resource_type
677
679
  == MetadataResourceTypes.MODEL_VERSION,
678
- RunMetadataSchema.key == key,
680
+ RunMetadataResourceSchema.run_metadata_id
681
+ == RunMetadataSchema.id,
679
682
  self.generate_custom_query_conditions_for_column(
680
683
  value=value,
681
684
  table=RunMetadataSchema,