zenml-nightly 0.70.0.dev20241122__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 (103) 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/constants.py +1 -0
  20. zenml/enums.py +1 -0
  21. zenml/image_builders/local_image_builder.py +13 -3
  22. zenml/integrations/__init__.py +1 -0
  23. zenml/integrations/aws/orchestrators/sagemaker_orchestrator.py +14 -6
  24. zenml/integrations/constants.py +1 -0
  25. zenml/integrations/feast/__init__.py +1 -1
  26. zenml/integrations/feast/feature_stores/feast_feature_store.py +13 -9
  27. zenml/integrations/kubernetes/orchestrators/kube_utils.py +54 -9
  28. zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator.py +65 -3
  29. zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator_entrypoint.py +14 -2
  30. zenml/integrations/kubernetes/orchestrators/manifest_utils.py +6 -5
  31. zenml/integrations/kubernetes/service_connectors/kubernetes_service_connector.py +2 -1
  32. zenml/integrations/kubernetes/step_operators/kubernetes_step_operator.py +3 -1
  33. zenml/integrations/modal/__init__.py +46 -0
  34. zenml/integrations/modal/flavors/__init__.py +26 -0
  35. zenml/integrations/modal/flavors/modal_step_operator_flavor.py +125 -0
  36. zenml/integrations/modal/step_operators/__init__.py +22 -0
  37. zenml/integrations/modal/step_operators/modal_step_operator.py +242 -0
  38. zenml/io/filesystem.py +2 -2
  39. zenml/io/local_filesystem.py +3 -3
  40. zenml/materializers/built_in_materializer.py +18 -1
  41. zenml/materializers/structured_string_materializer.py +8 -3
  42. zenml/model/model.py +11 -85
  43. zenml/model/utils.py +18 -16
  44. zenml/models/__init__.py +12 -1
  45. zenml/models/v2/core/artifact_version.py +6 -3
  46. zenml/models/v2/core/component.py +0 -22
  47. zenml/models/v2/core/model_version.py +6 -3
  48. zenml/models/v2/core/pipeline_run.py +19 -3
  49. zenml/models/v2/core/run_metadata.py +30 -9
  50. zenml/models/v2/core/service_connector.py +4 -0
  51. zenml/models/v2/core/step_run.py +6 -4
  52. zenml/models/v2/misc/run_metadata.py +38 -0
  53. zenml/models/v2/misc/server_models.py +23 -0
  54. zenml/orchestrators/input_utils.py +19 -6
  55. zenml/orchestrators/publish_utils.py +12 -5
  56. zenml/orchestrators/step_launcher.py +7 -3
  57. zenml/orchestrators/step_run_utils.py +26 -9
  58. zenml/orchestrators/step_runner.py +40 -3
  59. zenml/orchestrators/utils.py +24 -23
  60. zenml/pipelines/pipeline_decorator.py +4 -0
  61. zenml/pipelines/pipeline_definition.py +26 -8
  62. zenml/pipelines/run_utils.py +9 -5
  63. zenml/steps/base_step.py +11 -1
  64. zenml/steps/entrypoint_function_utils.py +7 -3
  65. zenml/steps/step_decorator.py +4 -0
  66. zenml/steps/utils.py +23 -7
  67. zenml/types.py +4 -0
  68. zenml/utils/metadata_utils.py +186 -153
  69. zenml/utils/string_utils.py +41 -16
  70. zenml/utils/visualization_utils.py +4 -1
  71. zenml/zen_server/cloud_utils.py +3 -1
  72. zenml/zen_server/deploy/helm/templates/_environment.tpl +117 -0
  73. zenml/zen_server/deploy/helm/templates/server-db-job.yaml +3 -14
  74. zenml/zen_server/deploy/helm/templates/server-deployment.yaml +16 -4
  75. zenml/zen_server/deploy/helm/templates/server-secret.yaml +2 -17
  76. zenml/zen_server/rbac/endpoint_utils.py +6 -4
  77. zenml/zen_server/rbac/models.py +3 -2
  78. zenml/zen_server/rbac/utils.py +4 -7
  79. zenml/zen_server/routers/server_endpoints.py +47 -0
  80. zenml/zen_server/routers/users_endpoints.py +35 -37
  81. zenml/zen_server/routers/workspaces_endpoints.py +44 -55
  82. zenml/zen_server/template_execution/utils.py +1 -0
  83. zenml/zen_server/zen_server_api.py +45 -6
  84. zenml/zen_stores/migrations/utils.py +40 -24
  85. zenml/zen_stores/migrations/versions/b73bc71f1106_remove_component_spec_path.py +36 -0
  86. zenml/zen_stores/migrations/versions/cc269488e5a9_separate_run_metadata.py +135 -0
  87. zenml/zen_stores/migrations/versions/ec6307720f92_simplify_model_version_links.py +7 -6
  88. zenml/zen_stores/rest_zen_store.py +38 -1
  89. zenml/zen_stores/schemas/__init__.py +5 -1
  90. zenml/zen_stores/schemas/artifact_schemas.py +12 -11
  91. zenml/zen_stores/schemas/component_schemas.py +0 -3
  92. zenml/zen_stores/schemas/model_schemas.py +13 -11
  93. zenml/zen_stores/schemas/pipeline_run_schemas.py +44 -16
  94. zenml/zen_stores/schemas/run_metadata_schemas.py +66 -31
  95. zenml/zen_stores/schemas/step_run_schemas.py +32 -12
  96. zenml/zen_stores/schemas/utils.py +47 -3
  97. zenml/zen_stores/sql_zen_store.py +130 -34
  98. {zenml_nightly-0.70.0.dev20241122.dist-info → zenml_nightly-0.70.0.dev20241201.dist-info}/METADATA +1 -1
  99. {zenml_nightly-0.70.0.dev20241122.dist-info → zenml_nightly-0.70.0.dev20241201.dist-info}/RECORD +102 -95
  100. zenml/utils/cloud_utils.py +0 -40
  101. {zenml_nightly-0.70.0.dev20241122.dist-info → zenml_nightly-0.70.0.dev20241201.dist-info}/LICENSE +0 -0
  102. {zenml_nightly-0.70.0.dev20241122.dist-info → zenml_nightly-0.70.0.dev20241201.dist-info}/WHEEL +0 -0
  103. {zenml_nightly-0.70.0.dev20241122.dist-info → zenml_nightly-0.70.0.dev20241201.dist-info}/entry_points.txt +0 -0
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
@@ -328,7 +328,11 @@ from zenml.models.v2.misc.service_connector_type import (
328
328
  ServiceConnectorTypedResourcesModel,
329
329
  ResourceTypeModel,
330
330
  )
331
- from zenml.models.v2.misc.server_models import ServerDatabaseType, ServerModel
331
+ from zenml.models.v2.misc.server_models import (
332
+ ServerDatabaseType,
333
+ ServerLoadInfo,
334
+ ServerModel,
335
+ )
332
336
  from zenml.models.v2.core.trigger import (
333
337
  TriggerRequest,
334
338
  TriggerFilter,
@@ -368,6 +372,10 @@ from zenml.models.v2.misc.auth_models import (
368
372
  OAuthRedirectResponse,
369
373
  OAuthTokenResponse,
370
374
  )
375
+ from zenml.models.v2.misc.run_metadata import (
376
+ RunMetadataEntry,
377
+ RunMetadataResource,
378
+ )
371
379
  from zenml.models.v2.misc.server_models import (
372
380
  ServerModel,
373
381
  ServerDatabaseType,
@@ -731,6 +739,7 @@ __all__ = [
731
739
  "ExternalUserModel",
732
740
  "BuildItem",
733
741
  "LoadedVisualization",
742
+ "ServerLoadInfo",
734
743
  "ServerModel",
735
744
  "ServerDatabaseType",
736
745
  "ServerDeploymentType",
@@ -747,4 +756,6 @@ __all__ = [
747
756
  "ServiceConnectorInfo",
748
757
  "ServiceConnectorResourcesInfo",
749
758
  "ResourcesInfo",
759
+ "RunMetadataEntry",
760
+ "RunMetadataResource",
750
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,
@@ -237,6 +237,10 @@ class PipelineRunResponseMetadata(WorkspaceScopedResponseMetadata):
237
237
  default=False,
238
238
  description="Whether a template can be created from this run.",
239
239
  )
240
+ step_substitutions: Dict[str, Dict[str, str]] = Field(
241
+ title="Substitutions used in the step runs of this pipeline run.",
242
+ default_factory=dict,
243
+ )
240
244
 
241
245
 
242
246
  class PipelineRunResponseResources(WorkspaceScopedResponseResources):
@@ -546,6 +550,15 @@ class PipelineRunResponse(
546
550
  """
547
551
  return self.get_metadata().is_templatable
548
552
 
553
+ @property
554
+ def step_substitutions(self) -> Dict[str, Dict[str, str]]:
555
+ """The `step_substitutions` property.
556
+
557
+ Returns:
558
+ the value of the property.
559
+ """
560
+ return self.get_metadata().step_substitutions
561
+
549
562
  @property
550
563
  def model_version(self) -> Optional[ModelVersionResponse]:
551
564
  """The `model_version` property.
@@ -722,6 +735,7 @@ class PipelineRunFilter(WorkspaceScopedTaggableFilter):
722
735
  PipelineDeploymentSchema,
723
736
  PipelineRunSchema,
724
737
  PipelineSchema,
738
+ RunMetadataResourceSchema,
725
739
  RunMetadataSchema,
726
740
  ScheduleSchema,
727
741
  StackComponentSchema,
@@ -897,10 +911,12 @@ class PipelineRunFilter(WorkspaceScopedTaggableFilter):
897
911
 
898
912
  for key, value in self.run_metadata.items():
899
913
  additional_filter = and_(
900
- RunMetadataSchema.resource_id == PipelineRunSchema.id,
901
- RunMetadataSchema.resource_type
914
+ RunMetadataResourceSchema.resource_id
915
+ == PipelineRunSchema.id,
916
+ RunMetadataResourceSchema.resource_type
902
917
  == MetadataResourceTypes.PIPELINE_RUN,
903
- RunMetadataSchema.key == key,
918
+ RunMetadataResourceSchema.run_metadata_id
919
+ == RunMetadataSchema.id,
904
920
  self.generate_custom_query_conditions_for_column(
905
921
  value=value,
906
922
  table=RunMetadataSchema,
@@ -13,16 +13,16 @@
13
13
  # permissions and limitations under the License.
14
14
  """Models representing run metadata."""
15
15
 
16
- from typing import Dict, Optional
16
+ from typing import Dict, List, Optional
17
17
  from uuid import UUID
18
18
 
19
- from pydantic import Field
19
+ from pydantic import Field, model_validator
20
20
 
21
- from zenml.enums import MetadataResourceTypes
22
21
  from zenml.metadata.metadata_types import MetadataType, MetadataTypeEnum
23
22
  from zenml.models.v2.base.scoped import (
24
23
  WorkspaceScopedRequest,
25
24
  )
25
+ from zenml.models.v2.misc.run_metadata import RunMetadataResource
26
26
 
27
27
  # ------------------ Request Model ------------------
28
28
 
@@ -30,14 +30,12 @@ from zenml.models.v2.base.scoped import (
30
30
  class RunMetadataRequest(WorkspaceScopedRequest):
31
31
  """Request model for run metadata."""
32
32
 
33
- resource_id: UUID = Field(
34
- title="The ID of the resource that this metadata belongs to.",
35
- )
36
- resource_type: MetadataResourceTypes = Field(
37
- title="The type of the resource that this metadata belongs to.",
33
+ resources: List[RunMetadataResource] = Field(
34
+ title="The list of resources that this metadata belongs to."
38
35
  )
39
36
  stack_component_id: Optional[UUID] = Field(
40
- title="The ID of the stack component that this metadata belongs to."
37
+ title="The ID of the stack component that this metadata belongs to.",
38
+ default=None,
41
39
  )
42
40
  values: Dict[str, "MetadataType"] = Field(
43
41
  title="The metadata to be created.",
@@ -45,3 +43,26 @@ class RunMetadataRequest(WorkspaceScopedRequest):
45
43
  types: Dict[str, "MetadataTypeEnum"] = Field(
46
44
  title="The types of the metadata to be created.",
47
45
  )
46
+ publisher_step_id: Optional[UUID] = Field(
47
+ title="The ID of the step execution that published this metadata.",
48
+ default=None,
49
+ )
50
+
51
+ @model_validator(mode="after")
52
+ def validate_values_keys(self) -> "RunMetadataRequest":
53
+ """Validates if the keys in the metadata are properly defined.
54
+
55
+ Returns:
56
+ self
57
+
58
+ Raises:
59
+ ValueError: if one of the key in the metadata contains `:`
60
+ """
61
+ invalid_keys = [key for key in self.values.keys() if ":" in key]
62
+ if invalid_keys:
63
+ raise ValueError(
64
+ "You can not use colons (`:`) in the key names when you "
65
+ "are creating metadata for your ZenML objects. Please change "
66
+ f"the following keys: {invalid_keys}"
67
+ )
68
+ return self
@@ -488,6 +488,10 @@ class ServiceConnectorResponse(
488
488
  ):
489
489
  """Response model for service connectors."""
490
490
 
491
+ # Disable the warning for updating responses, because we update the
492
+ # service connector type in place
493
+ _warn_on_response_updates: bool = False
494
+
491
495
  name: str = Field(
492
496
  title="The service connector name.",
493
497
  max_length=STR_FIELD_MAX_LENGTH,
@@ -142,7 +142,7 @@ class StepRunRequest(WorkspaceScopedRequest):
142
142
  class StepRunUpdate(BaseModel):
143
143
  """Update model for step runs."""
144
144
 
145
- outputs: Dict[str, UUID] = Field(
145
+ outputs: Dict[str, List[UUID]] = Field(
146
146
  title="The IDs of the output artifact versions of the step run.",
147
147
  default={},
148
148
  )
@@ -594,6 +594,7 @@ class StepRunFilter(WorkspaceScopedFilter):
594
594
  from zenml.zen_stores.schemas import (
595
595
  ModelSchema,
596
596
  ModelVersionSchema,
597
+ RunMetadataResourceSchema,
597
598
  RunMetadataSchema,
598
599
  StepRunSchema,
599
600
  )
@@ -612,10 +613,11 @@ class StepRunFilter(WorkspaceScopedFilter):
612
613
 
613
614
  for key, value in self.run_metadata.items():
614
615
  additional_filter = and_(
615
- RunMetadataSchema.resource_id == StepRunSchema.id,
616
- RunMetadataSchema.resource_type
616
+ RunMetadataResourceSchema.resource_id == StepRunSchema.id,
617
+ RunMetadataResourceSchema.resource_type
617
618
  == MetadataResourceTypes.STEP_RUN,
618
- RunMetadataSchema.key == key,
619
+ RunMetadataResourceSchema.run_metadata_id
620
+ == RunMetadataSchema.id,
619
621
  self.generate_custom_query_conditions_for_column(
620
622
  value=value,
621
623
  table=RunMetadataSchema,
@@ -0,0 +1,38 @@
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
+ """Utility classes for modeling run metadata."""
15
+
16
+ from datetime import datetime
17
+ from uuid import UUID
18
+
19
+ from pydantic import BaseModel, Field
20
+
21
+ from zenml.enums import MetadataResourceTypes
22
+ from zenml.metadata.metadata_types import MetadataType
23
+
24
+
25
+ class RunMetadataResource(BaseModel):
26
+ """Utility class to help identify resources to tag metadata to."""
27
+
28
+ id: UUID = Field(title="The ID of the resource.")
29
+ type: MetadataResourceTypes = Field(title="The type of the resource.")
30
+
31
+
32
+ class RunMetadataEntry(BaseModel):
33
+ """Utility class to sort/list run metadata entries."""
34
+
35
+ value: MetadataType = Field(title="The value for the run metadata entry")
36
+ created: datetime = Field(
37
+ title="The timestamp when this resource was created."
38
+ )
@@ -118,3 +118,26 @@ class ServerModel(BaseModel):
118
118
  # Local ZenML servers are identifiable by the fact that their
119
119
  # server ID is the same as the local client (user) ID.
120
120
  return self.id == GlobalConfiguration().user_id
121
+
122
+
123
+ class ServerLoadInfo(BaseModel):
124
+ """Domain model for ZenML server load information."""
125
+
126
+ threads: int = Field(
127
+ title="Number of threads that the server is currently using."
128
+ )
129
+
130
+ db_connections_total: int = Field(
131
+ title="Total number of database connections (active and idle) that the "
132
+ "server currently has established."
133
+ )
134
+
135
+ db_connections_active: int = Field(
136
+ title="Number of database connections that the server is currently "
137
+ "actively using to make queries or transactions."
138
+ )
139
+
140
+ db_connections_overflow: int = Field(
141
+ title="Number of overflow database connections that the server is "
142
+ "currently actively using to make queries or transactions."
143
+ )
@@ -20,7 +20,7 @@ from zenml.client import Client
20
20
  from zenml.config.step_configurations import Step
21
21
  from zenml.enums import ArtifactSaveType, StepRunInputArtifactType
22
22
  from zenml.exceptions import InputResolutionError
23
- from zenml.utils import pagination_utils
23
+ from zenml.utils import pagination_utils, string_utils
24
24
 
25
25
  if TYPE_CHECKING:
26
26
  from zenml.models import PipelineRunResponse
@@ -53,7 +53,8 @@ def resolve_step_inputs(
53
53
  current_run_steps = {
54
54
  run_step.name: run_step
55
55
  for run_step in pagination_utils.depaginate(
56
- Client().list_run_steps, pipeline_run_id=pipeline_run.id
56
+ Client().list_run_steps,
57
+ pipeline_run_id=pipeline_run.id,
57
58
  )
58
59
  }
59
60
 
@@ -66,11 +67,23 @@ def resolve_step_inputs(
66
67
  f"No step `{input_.step_name}` found in current run."
67
68
  )
68
69
 
70
+ # Try to get the substitutions from the pipeline run first, as we
71
+ # already have a hydrated version of that. In the unlikely case
72
+ # that the pipeline run is outdated, we fetch it from the step
73
+ # run instead which will costs us one hydration call.
74
+ substitutions = (
75
+ pipeline_run.step_substitutions.get(step_run.name)
76
+ or step_run.config.substitutions
77
+ )
78
+ output_name = string_utils.format_name_template(
79
+ input_.output_name, substitutions=substitutions
80
+ )
81
+
69
82
  try:
70
- outputs = step_run.outputs[input_.output_name]
83
+ outputs = step_run.outputs[output_name]
71
84
  except KeyError:
72
85
  raise InputResolutionError(
73
- f"No step output `{input_.output_name}` found for step "
86
+ f"No step output `{output_name}` found for step "
74
87
  f"`{input_.step_name}`."
75
88
  )
76
89
 
@@ -83,12 +96,12 @@ def resolve_step_inputs(
83
96
  # This should never happen, there can only be a single regular step
84
97
  # output for a name
85
98
  raise InputResolutionError(
86
- f"Too many step outputs for output `{input_.output_name}` of "
99
+ f"Too many step outputs for output `{output_name}` of "
87
100
  f"step `{input_.step_name}`."
88
101
  )
89
102
  elif len(step_outputs) == 0:
90
103
  raise InputResolutionError(
91
- f"No step output `{input_.output_name}` found for step "
104
+ f"No step output `{output_name}` found for step "
92
105
  f"`{input_.step_name}`."
93
106
  )
94
107
 
@@ -21,6 +21,7 @@ from zenml.enums import ExecutionStatus, MetadataResourceTypes
21
21
  from zenml.models import (
22
22
  PipelineRunResponse,
23
23
  PipelineRunUpdate,
24
+ RunMetadataResource,
24
25
  StepRunResponse,
25
26
  StepRunUpdate,
26
27
  )
@@ -32,7 +33,7 @@ if TYPE_CHECKING:
32
33
 
33
34
 
34
35
  def publish_successful_step_run(
35
- step_run_id: "UUID", output_artifact_ids: Dict[str, "UUID"]
36
+ step_run_id: "UUID", output_artifact_ids: Dict[str, List["UUID"]]
36
37
  ) -> "StepRunResponse":
37
38
  """Publishes a successful step run.
38
39
 
@@ -129,8 +130,11 @@ def publish_pipeline_run_metadata(
129
130
  for stack_component_id, metadata in pipeline_run_metadata.items():
130
131
  client.create_run_metadata(
131
132
  metadata=metadata,
132
- resource_id=pipeline_run_id,
133
- resource_type=MetadataResourceTypes.PIPELINE_RUN,
133
+ resources=[
134
+ RunMetadataResource(
135
+ id=pipeline_run_id, type=MetadataResourceTypes.PIPELINE_RUN
136
+ )
137
+ ],
134
138
  stack_component_id=stack_component_id,
135
139
  )
136
140
 
@@ -150,7 +154,10 @@ def publish_step_run_metadata(
150
154
  for stack_component_id, metadata in step_run_metadata.items():
151
155
  client.create_run_metadata(
152
156
  metadata=metadata,
153
- resource_id=step_run_id,
154
- resource_type=MetadataResourceTypes.STEP_RUN,
157
+ resources=[
158
+ RunMetadataResource(
159
+ id=step_run_id, type=MetadataResourceTypes.STEP_RUN
160
+ )
161
+ ],
155
162
  stack_component_id=stack_component_id,
156
163
  )
@@ -309,8 +309,12 @@ class StepLauncher:
309
309
  The created or existing pipeline run,
310
310
  and a boolean indicating whether the run was created or reused.
311
311
  """
312
- run_name = orchestrator_utils.get_run_name(
313
- run_name_template=self._deployment.run_name_template
312
+ start_time = datetime.utcnow()
313
+ run_name = string_utils.format_name_template(
314
+ name_template=self._deployment.run_name_template,
315
+ substitutions=self._deployment.pipeline_configuration._get_full_substitutions(
316
+ start_time
317
+ ),
314
318
  )
315
319
 
316
320
  logger.debug("Creating pipeline run %s", run_name)
@@ -329,7 +333,7 @@ class StepLauncher:
329
333
  ),
330
334
  status=ExecutionStatus.RUNNING,
331
335
  orchestrator_environment=get_run_environment_dict(),
332
- start_time=datetime.utcnow(),
336
+ start_time=start_time,
333
337
  tags=self._deployment.pipeline_configuration.tags,
334
338
  )
335
339
  return client.zen_store.get_or_create_run(pipeline_run)
@@ -309,6 +309,9 @@ def create_cached_step_runs(
309
309
  for invocation_id in cache_candidates:
310
310
  visited_invocations.add(invocation_id)
311
311
 
312
+ # Make sure the request factory has the most up to date pipeline
313
+ # run to avoid hydration calls
314
+ request_factory.pipeline_run = pipeline_run
312
315
  try:
313
316
  step_run_request = request_factory.create_request(
314
317
  invocation_id
@@ -354,13 +357,16 @@ def create_cached_step_runs(
354
357
 
355
358
 
356
359
  def get_or_create_model_version_for_pipeline_run(
357
- model: "Model", pipeline_run: PipelineRunResponse
360
+ model: "Model",
361
+ pipeline_run: PipelineRunResponse,
362
+ substitutions: Dict[str, str],
358
363
  ) -> Tuple[ModelVersionResponse, bool]:
359
364
  """Get or create a model version as part of a pipeline run.
360
365
 
361
366
  Args:
362
367
  model: The model to get or create.
363
368
  pipeline_run: The pipeline run for which the model should be created.
369
+ substitutions: Substitutions to apply to the model version name.
364
370
 
365
371
  Returns:
366
372
  The model version and a boolean indicating whether it was newly created
@@ -374,12 +380,14 @@ def get_or_create_model_version_for_pipeline_run(
374
380
  return model._get_model_version(), False
375
381
  elif model.version:
376
382
  if isinstance(model.version, str):
377
- start_time = pipeline_run.start_time or datetime.utcnow()
378
383
  model.version = string_utils.format_name_template(
379
384
  model.version,
380
- date=start_time.strftime("%Y_%m_%d"),
381
- time=start_time.strftime("%H_%M_%S_%f"),
385
+ substitutions=substitutions,
382
386
  )
387
+ model.name = string_utils.format_name_template(
388
+ model.name,
389
+ substitutions=substitutions,
390
+ )
383
391
 
384
392
  return (
385
393
  model._get_or_create_model_version(),
@@ -460,7 +468,9 @@ def prepare_pipeline_run_model_version(
460
468
  model_version = pipeline_run.model_version
461
469
  elif config_model := pipeline_run.config.model:
462
470
  model_version, _ = get_or_create_model_version_for_pipeline_run(
463
- model=config_model, pipeline_run=pipeline_run
471
+ model=config_model,
472
+ pipeline_run=pipeline_run,
473
+ substitutions=pipeline_run.config.substitutions,
464
474
  )
465
475
  pipeline_run = Client().zen_store.update_run(
466
476
  run_id=pipeline_run.id,
@@ -492,7 +502,9 @@ def prepare_step_run_model_version(
492
502
  model_version = step_run.model_version
493
503
  elif config_model := step_run.config.model:
494
504
  model_version, created = get_or_create_model_version_for_pipeline_run(
495
- model=config_model, pipeline_run=pipeline_run
505
+ model=config_model,
506
+ pipeline_run=pipeline_run,
507
+ substitutions=step_run.config.substitutions,
496
508
  )
497
509
  step_run = Client().zen_store.update_run_step(
498
510
  step_run_id=step_run.id,
@@ -518,10 +530,15 @@ def log_model_version_dashboard_url(
518
530
  Args:
519
531
  model_version: The model version for which to log the dashboard URL.
520
532
  """
521
- from zenml.utils.cloud_utils import try_get_model_version_url
533
+ from zenml.utils.dashboard_utils import get_model_version_url
522
534
 
523
- if model_version_url_logs := try_get_model_version_url(model_version):
524
- logger.info(model_version_url_logs)
535
+ if model_version_url := get_model_version_url(model_version.id):
536
+ logger.info(
537
+ "Dashboard URL for Model Version `%s (%s)`:\n%s",
538
+ model_version.model.name,
539
+ model_version.name,
540
+ model_version_url,
541
+ )
525
542
  else:
526
543
  logger.info(
527
544
  "Models can be viewed in the dashboard using ZenML Pro. Sign up "