zenml-nightly 0.72.0.dev20250121__py3-none-any.whl → 0.73.0.dev20250124__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 (167) hide show
  1. zenml/VERSION +1 -1
  2. zenml/cli/login.py +2 -0
  3. zenml/cli/server.py +1 -0
  4. zenml/cli/service_connectors.py +8 -4
  5. zenml/cli/stack.py +2 -2
  6. zenml/config/pipeline_configurations.py +2 -2
  7. zenml/config/server_config.py +20 -0
  8. zenml/enums.py +1 -0
  9. zenml/event_hub/base_event_hub.py +2 -2
  10. zenml/integrations/airflow/orchestrators/airflow_orchestrator.py +4 -2
  11. zenml/integrations/aws/__init__.py +2 -1
  12. zenml/integrations/aws/flavors/sagemaker_orchestrator_flavor.py +15 -0
  13. zenml/integrations/aws/orchestrators/sagemaker_orchestrator.py +308 -70
  14. zenml/integrations/gcp/__init__.py +3 -0
  15. zenml/integrations/gcp/experiment_trackers/__init__.py +18 -0
  16. zenml/integrations/gcp/experiment_trackers/vertex_experiment_tracker.py +214 -0
  17. zenml/integrations/gcp/flavors/__init__.py +6 -0
  18. zenml/integrations/gcp/flavors/vertex_experiment_tracker_flavor.py +199 -0
  19. zenml/integrations/huggingface/__init__.py +1 -6
  20. zenml/integrations/kubernetes/orchestrators/kube_utils.py +2 -2
  21. zenml/integrations/mlflow/experiment_trackers/mlflow_experiment_tracker.py +0 -1
  22. zenml/integrations/whylogs/data_validators/whylogs_data_validator.py +3 -1
  23. zenml/models/v2/core/api_key.py +2 -2
  24. zenml/models/v2/core/schedule.py +16 -1
  25. zenml/orchestrators/publish_utils.py +4 -4
  26. zenml/orchestrators/step_launcher.py +3 -3
  27. zenml/orchestrators/step_run_utils.py +2 -2
  28. zenml/pipelines/run_utils.py +2 -2
  29. zenml/service_connectors/service_connector.py +2 -2
  30. zenml/stack/stack.py +3 -3
  31. zenml/stack/stack_component.py +10 -2
  32. zenml/stack_deployments/stack_deployment.py +5 -0
  33. zenml/utils/git_utils.py +1 -1
  34. zenml/utils/string_utils.py +2 -2
  35. zenml/zen_server/auth.py +13 -6
  36. zenml/zen_server/dashboard/assets/{404-Dfq64Boz.js → 404-c8OuXDAT.js} +1 -1
  37. zenml/zen_server/dashboard/assets/{@reactflow-BUNIMFeC.js → @reactflow-6JPoencd.js} +1 -1
  38. zenml/zen_server/dashboard/assets/{AlertDialogDropdownItem-B73Vs10T.js → AlertDialogDropdownItem-8yPFDxEI.js} +1 -1
  39. zenml/zen_server/dashboard/assets/{CodeSnippet-DIJRT2NT.js → CodeSnippet-Qh1ae_DJ.js} +1 -1
  40. zenml/zen_server/dashboard/assets/{CollapsibleCard-BzUHGZOU.js → CollapsibleCard-TiI4lId1.js} +1 -1
  41. zenml/zen_server/dashboard/assets/{Commands-BEGyld4c.js → Commands-BcR2Arie.js} +1 -1
  42. zenml/zen_server/dashboard/assets/{ComponentBadge-xyKiek1s.js → ComponentBadge-BqQNUZgb.js} +1 -1
  43. zenml/zen_server/dashboard/assets/{CopyButton-DhW-mapu.js → CopyButton-DCiXO3JC.js} +1 -1
  44. zenml/zen_server/dashboard/assets/{CsvVizualization-D8oazBiE.js → CsvVizualization-O9cVIaL8.js} +1 -1
  45. zenml/zen_server/dashboard/assets/{DeleteAlertDialog-WkSIIgfy.js → DeleteAlertDialog-DrPjHtXX.js} +1 -1
  46. zenml/zen_server/dashboard/assets/{DialogItem-Bgroeg29.js → DialogItem-BYG7d_M2.js} +1 -1
  47. zenml/zen_server/dashboard/assets/{Error-CY5tlu17.js → Error-C1zbWr19.js} +1 -1
  48. zenml/zen_server/dashboard/assets/{ExecutionStatus-G8mjIaeA.js → ExecutionStatus-Ct9srgHC.js} +1 -1
  49. zenml/zen_server/dashboard/assets/{Helpbox-Bb1ed--O.js → Helpbox-Bm_1Zx9f.js} +1 -1
  50. zenml/zen_server/dashboard/assets/{Infobox-Da6-76M2.js → Infobox-OQdkCLSP.js} +1 -1
  51. zenml/zen_server/dashboard/assets/{InlineAvatar-DqnZaBNq.js → InlineAvatar-CQNjKoEQ.js} +1 -1
  52. zenml/zen_server/dashboard/assets/{NestedCollapsible-aK5ojKoF.js → NestedCollapsible-DDgd2SGb.js} +1 -1
  53. zenml/zen_server/dashboard/assets/Partials-MD3e95Dk.js +1 -0
  54. zenml/zen_server/dashboard/assets/{ProBadge-B4tRUYve.js → ProBadge-D784iVNC.js} +1 -1
  55. zenml/zen_server/dashboard/assets/{ProCta-CZuP29Qz.js → ProCta-W2PEvNow.js} +1 -1
  56. zenml/zen_server/dashboard/assets/{ProviderIcon-Bd7GUQ1_.js → ProviderIcon-DfDUOeAy.js} +1 -1
  57. zenml/zen_server/dashboard/assets/{ProviderRadio-mstdqzsS.js → ProviderRadio-B81Elxrc.js} +1 -1
  58. zenml/zen_server/dashboard/assets/{RunSelector-CsruSB4i.js → RunSelector-DOXgdry5.js} +1 -1
  59. zenml/zen_server/dashboard/assets/{RunsBody-DxxtWVYz.js → RunsBody-Bnx2fxub.js} +1 -1
  60. zenml/zen_server/dashboard/assets/SearchField-Yjv-KRW4.js +1 -0
  61. zenml/zen_server/dashboard/assets/{SecretTooltip-CLzJIYW_.js → SecretTooltip-EKpMlG2f.js} +1 -1
  62. zenml/zen_server/dashboard/assets/{SetPassword-Yn50ooBC.js → SetPassword-CDLy57PZ.js} +1 -1
  63. zenml/zen_server/dashboard/assets/StackList-DKQaLDo4.js +1 -0
  64. zenml/zen_server/dashboard/assets/{Tabs-CNv-eTYM.js → Tabs-B5E-o_h6.js} +1 -1
  65. zenml/zen_server/dashboard/assets/{Tick-jEIevzVf.js → Tick-DSYBiuXU.js} +1 -1
  66. zenml/zen_server/dashboard/assets/{UpdatePasswordSchemas-C16GW-kX.js → UpdatePasswordSchemas-HBNOeyoP.js} +1 -1
  67. zenml/zen_server/dashboard/assets/{UsageReason-Bf2tzhv1.js → UsageReason-DXtPS5nE.js} +1 -1
  68. zenml/zen_server/dashboard/assets/{WizardFooter-D6i-AP1K.js → WizardFooter-_1VSMZ_c.js} +1 -1
  69. zenml/zen_server/dashboard/assets/{all-pipeline-runs-query-DUti43aF.js → all-pipeline-runs-query-D0qDLdKB.js} +1 -1
  70. zenml/zen_server/dashboard/assets/{create-stack-Ch2WPs9U.js → create-stack-7JzgAYAm.js} +1 -1
  71. zenml/zen_server/dashboard/assets/{delete-run-Byf9hTjA.js → delete-run-CUdtYFLl.js} +1 -1
  72. zenml/zen_server/dashboard/assets/{form-schemas-BZqKBPBF.js → form-schemas-B6PCV3Y4.js} +1 -1
  73. zenml/zen_server/dashboard/assets/index-B6U0OkEN.css +1 -0
  74. zenml/zen_server/dashboard/assets/{index-CyBKZcpO.js → index-CJ5IfeAl.js} +1 -1
  75. zenml/zen_server/dashboard/assets/{index-CtdYkjUi.js → index-Ceyzb1yI.js} +1 -1
  76. zenml/zen_server/dashboard/assets/{index-CE0aQlv8.js → index-CxO6541P.js} +3 -3
  77. zenml/zen_server/dashboard/assets/{index-v6gQjDEo.js → index-D4yoZ_gH.js} +1 -1
  78. zenml/zen_server/dashboard/assets/{login-mutation-DNDVp_2H.js → login-mutation-BaeJ7MAg.js} +1 -1
  79. zenml/zen_server/dashboard/assets/{not-found-Bmup4ctE.js → not-found-MGptrNBk.js} +1 -1
  80. zenml/zen_server/dashboard/assets/{page-DGlm1RVc.js → page-Aeu3v0MQ.js} +1 -1
  81. zenml/zen_server/dashboard/assets/{page-CltCNL0T.js → page-BCgEdmhP.js} +1 -1
  82. zenml/zen_server/dashboard/assets/{page-Hn8q9iJZ.js → page-BKwwfTNy.js} +1 -1
  83. zenml/zen_server/dashboard/assets/{page-BNxYrN0q.js → page-BUjw8Tp1.js} +1 -1
  84. zenml/zen_server/dashboard/assets/{page-BYJfqgLN.js → page-BXgXP-Qj.js} +1 -1
  85. zenml/zen_server/dashboard/assets/{page-DN4BVIOL.js → page-BXrtxEbw.js} +1 -1
  86. zenml/zen_server/dashboard/assets/{page-CHRn1fQm.js → page-BaUDR9Ri.js} +1 -1
  87. zenml/zen_server/dashboard/assets/{page-DlIi5ThM.js → page-BbljjC-k.js} +1 -1
  88. zenml/zen_server/dashboard/assets/{page-BrmJp1Wt.js → page-BhOXn-s9.js} +1 -1
  89. zenml/zen_server/dashboard/assets/{page-Cc8ZEuj4.js → page-C37IDa-Q.js} +1 -1
  90. zenml/zen_server/dashboard/assets/{page-Dif8CWyZ.js → page-C4JpDeUM.js} +1 -1
  91. zenml/zen_server/dashboard/assets/{page-BC27C_OI.js → page-CB2_GdBA.js} +1 -1
  92. zenml/zen_server/dashboard/assets/{page-B5Sr8pib.js → page-CBiT2Ox9.js} +1 -1
  93. zenml/zen_server/dashboard/assets/{page-IhckKFnD.js → page-CXPc-HN1.js} +1 -1
  94. zenml/zen_server/dashboard/assets/{page-Dth9X1Ih.js → page-CbwI6emp.js} +1 -1
  95. zenml/zen_server/dashboard/assets/{page-DweqqCkF.js → page-CeNL9JWi.js} +1 -1
  96. zenml/zen_server/dashboard/assets/{page-LyZ_l8vR.js → page-CkPwPmLZ.js} +1 -1
  97. zenml/zen_server/dashboard/assets/{page-C70wZtV2.js → page-CmJU3Gqo.js} +1 -1
  98. zenml/zen_server/dashboard/assets/{page-D9Oh05fl.js → page-CoFVtzhG.js} +1 -1
  99. zenml/zen_server/dashboard/assets/{page-PamGpk0j.js → page-D-KPzeQb.js} +1 -1
  100. zenml/zen_server/dashboard/assets/{page-DoW7YxTu.js → page-DKQ3wZgr.js} +1 -1
  101. zenml/zen_server/dashboard/assets/page-DWWhxCoF.js +1 -0
  102. zenml/zen_server/dashboard/assets/{page-CmlYj7Nl.js → page-DbW8MfQ4.js} +1 -1
  103. zenml/zen_server/dashboard/assets/{page-CWr96ZKN.js → page-Dv5lN2w7.js} +1 -1
  104. zenml/zen_server/dashboard/assets/{page-ANYGfEUL.js → page-Dvbq1BoF.js} +1 -1
  105. zenml/zen_server/dashboard/assets/{page-D6Ev5P8V.js → page-DyAuja95.js} +1 -1
  106. zenml/zen_server/dashboard/assets/{page-DyOJ_pq3.js → page-DzrdL2v1.js} +1 -1
  107. zenml/zen_server/dashboard/assets/{page-CXAbSyp9.js → page-I2B4Ocv8.js} +1 -1
  108. zenml/zen_server/dashboard/assets/page-OdjGauvw.js +2 -0
  109. zenml/zen_server/dashboard/assets/{page-CaeI9ptC.js → page-Ox-eC1ik.js} +1 -1
  110. zenml/zen_server/dashboard/assets/{page-B_0XkV48.js → page-khp8QJ6b.js} +1 -1
  111. zenml/zen_server/dashboard/assets/{page--XLMzHrn.js → page-yNh6PQKt.js} +1 -1
  112. zenml/zen_server/dashboard/assets/{persist-vP0-Xl4f.js → persist-DBTFy--v.js} +1 -1
  113. zenml/zen_server/dashboard/assets/{persist-DeXRG61d.js → persist-K7AY0ju4.js} +1 -1
  114. zenml/zen_server/dashboard/assets/{service-DH_oUqQj.js → service-BvOYLH5b.js} +1 -1
  115. zenml/zen_server/dashboard/assets/{sharedSchema-Bw1_Wa7l.js → sharedSchema-xJDsJNgJ.js} +1 -1
  116. zenml/zen_server/dashboard/assets/{stack-detail-query-B_0R_fd6.js → stack-detail-query-DMJoxwgv.js} +1 -1
  117. zenml/zen_server/dashboard/assets/{update-server-settings-mutation-D9qYhfaN.js → update-server-settings-mutation-ATZDNNZk.js} +1 -1
  118. zenml/zen_server/dashboard/assets/{url-Dh93fvh0.js → url-BWJXzuI4.js} +1 -1
  119. zenml/zen_server/dashboard/index.html +4 -4
  120. zenml/zen_server/deploy/helm/Chart.yaml +1 -1
  121. zenml/zen_server/deploy/helm/README.md +2 -2
  122. zenml/zen_server/deploy/helm/templates/server-db-job.yaml +5 -3
  123. zenml/zen_server/deploy/helm/values.yaml +4 -0
  124. zenml/zen_server/routers/devices_endpoints.py +4 -2
  125. zenml/zen_server/routers/workspaces_endpoints.py +2 -0
  126. zenml/zen_stores/migrations/versions/0.73.0_release.py +23 -0
  127. zenml/zen_stores/migrations/versions/25155145c545_separate_actions_and_triggers.py +2 -2
  128. zenml/zen_stores/migrations/versions/46506f72f0ed_add_server_settings.py +2 -2
  129. zenml/zen_stores/migrations/versions/5994f9ad0489_introduce_role_permissions.py +6 -6
  130. zenml/zen_stores/migrations/versions/7500f434b71c_remove_shared_columns.py +2 -2
  131. zenml/zen_stores/migrations/versions/a91762e6be36_artifact_version_table.py +3 -3
  132. zenml/zen_stores/schemas/action_schemas.py +2 -2
  133. zenml/zen_stores/schemas/api_key_schemas.py +4 -4
  134. zenml/zen_stores/schemas/artifact_schemas.py +3 -3
  135. zenml/zen_stores/schemas/base_schemas.py +7 -3
  136. zenml/zen_stores/schemas/code_repository_schemas.py +2 -2
  137. zenml/zen_stores/schemas/component_schemas.py +2 -2
  138. zenml/zen_stores/schemas/device_schemas.py +4 -4
  139. zenml/zen_stores/schemas/event_source_schemas.py +2 -2
  140. zenml/zen_stores/schemas/flavor_schemas.py +2 -2
  141. zenml/zen_stores/schemas/model_schemas.py +3 -3
  142. zenml/zen_stores/schemas/pipeline_run_schemas.py +10 -3
  143. zenml/zen_stores/schemas/pipeline_schemas.py +2 -2
  144. zenml/zen_stores/schemas/run_template_schemas.py +2 -2
  145. zenml/zen_stores/schemas/schedule_schema.py +19 -4
  146. zenml/zen_stores/schemas/secret_schemas.py +2 -2
  147. zenml/zen_stores/schemas/server_settings_schemas.py +9 -5
  148. zenml/zen_stores/schemas/service_connector_schemas.py +2 -2
  149. zenml/zen_stores/schemas/service_schemas.py +2 -2
  150. zenml/zen_stores/schemas/stack_schemas.py +2 -2
  151. zenml/zen_stores/schemas/step_run_schemas.py +2 -2
  152. zenml/zen_stores/schemas/tag_schemas.py +2 -2
  153. zenml/zen_stores/schemas/trigger_schemas.py +2 -2
  154. zenml/zen_stores/schemas/user_schemas.py +3 -3
  155. zenml/zen_stores/schemas/workspace_schemas.py +2 -2
  156. zenml/zen_stores/sql_zen_store.py +10 -1
  157. {zenml_nightly-0.72.0.dev20250121.dist-info → zenml_nightly-0.73.0.dev20250124.dist-info}/METADATA +3 -3
  158. {zenml_nightly-0.72.0.dev20250121.dist-info → zenml_nightly-0.73.0.dev20250124.dist-info}/RECORD +161 -157
  159. zenml/zen_server/dashboard/assets/Partials-CqZp5NMX.js +0 -1
  160. zenml/zen_server/dashboard/assets/SearchField-D6tPxyqw.js +0 -1
  161. zenml/zen_server/dashboard/assets/StackList-U537qoYd.js +0 -1
  162. zenml/zen_server/dashboard/assets/index-DXvT1_Um.css +0 -1
  163. zenml/zen_server/dashboard/assets/page-C2nU3Gxn.js +0 -1
  164. zenml/zen_server/dashboard/assets/page-PxOWfKgF.js +0 -2
  165. {zenml_nightly-0.72.0.dev20250121.dist-info → zenml_nightly-0.73.0.dev20250124.dist-info}/LICENSE +0 -0
  166. {zenml_nightly-0.72.0.dev20250121.dist-info → zenml_nightly-0.73.0.dev20250124.dist-info}/WHEEL +0 -0
  167. {zenml_nightly-0.72.0.dev20250121.dist-info → zenml_nightly-0.73.0.dev20250124.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,214 @@
1
+ # Copyright (c) ZenML GmbH 2022. 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
+ """Implementation of the VertexAI experiment tracker for ZenML."""
15
+
16
+ import re
17
+ from typing import TYPE_CHECKING, Dict, Optional, Type, cast
18
+
19
+ from google.api_core import exceptions
20
+ from google.cloud import aiplatform
21
+ from google.cloud.aiplatform.compat.types import execution
22
+
23
+ from zenml.constants import METADATA_EXPERIMENT_TRACKER_URL
24
+ from zenml.experiment_trackers.base_experiment_tracker import (
25
+ BaseExperimentTracker,
26
+ )
27
+ from zenml.integrations.gcp.flavors.vertex_experiment_tracker_flavor import (
28
+ VertexExperimentTrackerConfig,
29
+ VertexExperimentTrackerSettings,
30
+ )
31
+ from zenml.integrations.gcp.google_credentials_mixin import (
32
+ GoogleCredentialsMixin,
33
+ )
34
+ from zenml.logger import get_logger
35
+ from zenml.metadata.metadata_types import Uri
36
+
37
+ if TYPE_CHECKING:
38
+ from zenml.config.step_run_info import StepRunInfo
39
+ from zenml.metadata.metadata_types import MetadataType
40
+
41
+ logger = get_logger(__name__)
42
+
43
+
44
+ class VertexExperimentTracker(BaseExperimentTracker, GoogleCredentialsMixin):
45
+ """Track experiments using VertexAI."""
46
+
47
+ @property
48
+ def config(self) -> VertexExperimentTrackerConfig:
49
+ """Returns the `VertexExperimentTrackerConfig` config.
50
+
51
+ Returns:
52
+ The configuration.
53
+ """
54
+ return cast(VertexExperimentTrackerConfig, self._config)
55
+
56
+ @property
57
+ def settings_class(self) -> Type[VertexExperimentTrackerSettings]:
58
+ """Returns the `BaseSettings` settings class.
59
+
60
+ Returns:
61
+ The settings class.
62
+ """
63
+ return VertexExperimentTrackerSettings
64
+
65
+ def prepare_step_run(self, info: "StepRunInfo") -> None:
66
+ """Configures a VertexAI run.
67
+
68
+ Args:
69
+ info: Info about the step that will be executed.
70
+ """
71
+ self._initialize_vertex(info=info)
72
+ self.experiment_name = self._get_experiment_name(info=info)
73
+ self.run_name = self._get_run_name(info=info)
74
+
75
+ def get_step_run_metadata(
76
+ self, info: "StepRunInfo"
77
+ ) -> Dict[str, "MetadataType"]:
78
+ """Get component- and step-specific metadata after a step ran.
79
+
80
+ Args:
81
+ info: Info about the step that was executed.
82
+
83
+ Returns:
84
+ A dictionary of metadata.
85
+ """
86
+ experiment_name = self._get_experiment_name(info=info)
87
+ run_name = self._get_run_name(info=info)
88
+ tensorboard_resource_name = self._get_tensorboard_resource_name(
89
+ experiment=experiment_name
90
+ )
91
+ dashboard_url = self._get_dashboard_url(experiment=experiment_name)
92
+ return {
93
+ METADATA_EXPERIMENT_TRACKER_URL: Uri(dashboard_url),
94
+ "tensorboard_resource_name": tensorboard_resource_name or "",
95
+ "vertex_run_name": run_name,
96
+ }
97
+
98
+ def _format_name(self, name: str) -> str:
99
+ return re.sub(r"[^a-z0-9-]", "-", name.strip().lower())[:128].rstrip(
100
+ "-"
101
+ )
102
+
103
+ def _get_experiment_name(self, info: "StepRunInfo") -> str:
104
+ """Gets the experiment name.
105
+
106
+ Args:
107
+ info: Info about the step.
108
+
109
+ Returns:
110
+ The experiment name.
111
+ """
112
+ settings = cast(
113
+ VertexExperimentTrackerSettings, self.get_settings(info)
114
+ )
115
+ name = settings.experiment or info.pipeline.name
116
+ return self._format_name(name)
117
+
118
+ def _get_run_name(self, info: "StepRunInfo") -> str:
119
+ """Gets the run name.
120
+
121
+ Args:
122
+ info: Info about the step that will be executed.
123
+
124
+ Returns:
125
+ The run name.
126
+ """
127
+ return self._format_name(info.run_name)
128
+
129
+ def _get_dashboard_url(self, experiment: str) -> str:
130
+ """Gets the run URL.
131
+
132
+ Args:
133
+ experiment: The name of the experiment.
134
+
135
+ Returns:
136
+ The run URL.
137
+ """
138
+ resource = aiplatform.Experiment(experiment_name=experiment)
139
+ return cast(str, resource.dashboard_url)
140
+
141
+ def _get_tensorboard_resource_name(self, experiment: str) -> Optional[str]:
142
+ resource = aiplatform.Experiment(
143
+ experiment_name=experiment
144
+ ).get_backing_tensorboard_resource()
145
+ resource_name = (
146
+ str(resource.resource_name) if resource is not None else None
147
+ )
148
+ return resource_name
149
+
150
+ def _initialize_vertex(self, info: "StepRunInfo") -> None:
151
+ """Initializes a VertexAI run.
152
+
153
+ Args:
154
+ info: Info about the step that will be executed.
155
+ """
156
+ settings = cast(
157
+ VertexExperimentTrackerSettings, self.get_settings(info)
158
+ )
159
+ experiment = self._get_experiment_name(info=info)
160
+ run_name = self._get_run_name(info=info)
161
+ credentials, project = self._get_authentication()
162
+ logger.info(
163
+ f"Initializing VertexAI with experiment name {experiment} "
164
+ f"and run name {run_name}."
165
+ )
166
+
167
+ aiplatform.init(
168
+ project=project,
169
+ location=self.config.location,
170
+ experiment=experiment,
171
+ experiment_tensorboard=settings.experiment_tensorboard,
172
+ staging_bucket=self.config.staging_bucket,
173
+ credentials=credentials,
174
+ encryption_spec_key_name=self.config.encryption_spec_key_name,
175
+ network=self.config.network,
176
+ api_endpoint=self.config.api_endpoint,
177
+ api_key=self.config.api_key,
178
+ api_transport=self.config.api_transport,
179
+ request_metadata=self.config.request_metadata,
180
+ )
181
+
182
+ try:
183
+ aiplatform.start_run(
184
+ run=run_name,
185
+ tensorboard=settings.experiment_tensorboard,
186
+ resume=True,
187
+ )
188
+ except exceptions.NotFound:
189
+ aiplatform.start_run(
190
+ run=run_name,
191
+ tensorboard=settings.experiment_tensorboard,
192
+ resume=False,
193
+ )
194
+
195
+ logger.info(
196
+ f"VertexAI experiment dashboard: {self._get_dashboard_url(experiment=experiment)}"
197
+ )
198
+ logger.info(
199
+ f"Tensorboard resource name: {self._get_tensorboard_resource_name(experiment=experiment)}"
200
+ )
201
+
202
+ def cleanup_step_run(self, info: "StepRunInfo", step_failed: bool) -> None:
203
+ """Stops the VertexAI run.
204
+
205
+ Args:
206
+ info: Info about the step that was executed.
207
+ step_failed: Whether the step failed or not.
208
+ """
209
+ state = (
210
+ execution.Execution.State.FAILED
211
+ if step_failed
212
+ else execution.Execution.State.COMPLETE
213
+ )
214
+ aiplatform.end_run(state=state)
@@ -21,6 +21,10 @@ from zenml.integrations.gcp.flavors.gcp_image_builder_flavor import (
21
21
  GCPImageBuilderConfig,
22
22
  GCPImageBuilderFlavor,
23
23
  )
24
+ from zenml.integrations.gcp.flavors.vertex_experiment_tracker_flavor import (
25
+ VertexExperimentTrackerConfig,
26
+ VertexExperimentTrackerFlavor,
27
+ )
24
28
  from zenml.integrations.gcp.flavors.vertex_orchestrator_flavor import (
25
29
  VertexOrchestratorConfig,
26
30
  VertexOrchestratorFlavor,
@@ -35,6 +39,8 @@ __all__ = [
35
39
  "GCPArtifactStoreConfig",
36
40
  "GCPImageBuilderFlavor",
37
41
  "GCPImageBuilderConfig",
42
+ "VertexExperimentTrackerFlavor",
43
+ "VertexExperimentTrackerConfig",
38
44
  "VertexOrchestratorFlavor",
39
45
  "VertexOrchestratorConfig",
40
46
  "VertexStepOperatorFlavor",
@@ -0,0 +1,199 @@
1
+ # Copyright (c) ZenML GmbH 2022. 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
+ """Vertex experiment tracker flavor."""
15
+
16
+ import re
17
+ from typing import TYPE_CHECKING, Any, Dict, Optional, Type, Union
18
+
19
+ from pydantic import field_validator
20
+
21
+ from zenml.config.base_settings import BaseSettings
22
+ from zenml.experiment_trackers.base_experiment_tracker import (
23
+ BaseExperimentTrackerConfig,
24
+ BaseExperimentTrackerFlavor,
25
+ )
26
+ from zenml.integrations.gcp import (
27
+ GCP_RESOURCE_TYPE,
28
+ GCP_VERTEX_EXPERIMENT_TRACKER_FLAVOR,
29
+ )
30
+ from zenml.integrations.gcp.google_credentials_mixin import (
31
+ GoogleCredentialsConfigMixin,
32
+ )
33
+ from zenml.models import ServiceConnectorRequirements
34
+ from zenml.utils.secret_utils import SecretField
35
+
36
+ if TYPE_CHECKING:
37
+ from zenml.integrations.gcp.experiment_trackers import (
38
+ VertexExperimentTracker,
39
+ )
40
+
41
+
42
+ class VertexExperimentTrackerSettings(BaseSettings):
43
+ """Settings for the VertexAI experiment tracker.
44
+
45
+ Attributes:
46
+ experiment: The VertexAI experiment name.
47
+ experiment_tensorboard: The VertexAI experiment tensorboard.
48
+ """
49
+
50
+ experiment: Optional[str] = None
51
+ experiment_tensorboard: Optional[Union[str, bool]] = None
52
+
53
+ @field_validator("experiment", mode="before")
54
+ def _validate_experiment(cls, value: str) -> str:
55
+ """Validates the experiment name matches the the allowed format.
56
+
57
+ Args:
58
+ value: The experiment.
59
+
60
+ Raises:
61
+ ValueError: If the experiment name does not match the expected
62
+ format.
63
+
64
+ Returns:
65
+ The experiment.
66
+ """
67
+ if value and not re.match(r"^[a-z0-9][a-z0-9-]{0,127}$", value):
68
+ raise ValueError(
69
+ "Experiment name must match regex [a-z0-9][a-z0-9-]{0,127}"
70
+ )
71
+ return value
72
+
73
+
74
+ class VertexExperimentTrackerConfig(
75
+ BaseExperimentTrackerConfig,
76
+ GoogleCredentialsConfigMixin,
77
+ VertexExperimentTrackerSettings,
78
+ ):
79
+ """Config for the VertexAI experiment tracker.
80
+
81
+ Attributes:
82
+ location: Optional. The default location to use when making API calls. If not
83
+ set defaults to us-central1.
84
+ staging_bucket: Optional. The default staging bucket to use to stage artifacts
85
+ when making API calls. In the form gs://...
86
+ network:
87
+ Optional. The full name of the Compute Engine network to which jobs
88
+ and resources should be peered. E.g. "projects/12345/global/networks/myVPC".
89
+ Private services access must already be configured for the network.
90
+ If specified, all eligible jobs and resources created will be peered
91
+ with this VPC.
92
+ encryption_spec_key_name:
93
+ Optional. The Cloud KMS resource identifier of the customer
94
+ managed encryption key used to protect a resource. Has the
95
+ form:
96
+ ``projects/my-project/locations/my-region/keyRings/my-kr/cryptoKeys/my-key``.
97
+ The key needs to be in the same region as where the compute
98
+ resource is created.
99
+ api_endpoint (str):
100
+ Optional. The desired API endpoint,
101
+ e.g., us-central1-aiplatform.googleapis.com
102
+ api_key (str):
103
+ Optional. The API key to use for service calls.
104
+ NOTE: Not all services support API keys.
105
+ api_transport (str):
106
+ Optional. The transport method which is either 'grpc' or 'rest'.
107
+ NOTE: "rest" transport functionality is currently in a
108
+ beta state (preview).
109
+ request_metadata:
110
+ Optional. Additional gRPC metadata to send with every client request.
111
+ """
112
+
113
+ location: Optional[str] = None
114
+ staging_bucket: Optional[str] = None
115
+ network: Optional[str] = None
116
+ encryption_spec_key_name: Optional[str] = SecretField(default=None)
117
+ api_endpoint: Optional[str] = SecretField(default=None)
118
+ api_key: Optional[str] = SecretField(default=None)
119
+ api_transport: Optional[str] = None
120
+ request_metadata: Optional[Dict[str, Any]] = None
121
+
122
+
123
+ class VertexExperimentTrackerFlavor(BaseExperimentTrackerFlavor):
124
+ """Flavor for the VertexAI experiment tracker."""
125
+
126
+ @property
127
+ def name(self) -> str:
128
+ """Name of the flavor.
129
+
130
+ Returns:
131
+ The name of the flavor.
132
+ """
133
+ return GCP_VERTEX_EXPERIMENT_TRACKER_FLAVOR
134
+
135
+ @property
136
+ def docs_url(self) -> Optional[str]:
137
+ """A URL to point at docs explaining this flavor.
138
+
139
+ Returns:
140
+ A flavor docs url.
141
+ """
142
+ return self.generate_default_docs_url()
143
+
144
+ @property
145
+ def sdk_docs_url(self) -> Optional[str]:
146
+ """A URL to point at SDK docs explaining this flavor.
147
+
148
+ Returns:
149
+ A flavor SDK docs url.
150
+ """
151
+ return self.generate_default_sdk_docs_url()
152
+
153
+ @property
154
+ def logo_url(self) -> str:
155
+ """A URL to represent the flavor in the dashboard.
156
+
157
+ Returns:
158
+ The flavor logo.
159
+ """
160
+ return "https://public-flavor-logos.s3.eu-central-1.amazonaws.com/experiment_tracker/vertexai.png"
161
+
162
+ @property
163
+ def config_class(self) -> Type[VertexExperimentTrackerConfig]:
164
+ """Returns `VertexExperimentTrackerConfig` config class.
165
+
166
+ Returns:
167
+ The config class.
168
+ """
169
+ return VertexExperimentTrackerConfig
170
+
171
+ @property
172
+ def implementation_class(self) -> Type["VertexExperimentTracker"]:
173
+ """Implementation class for this flavor.
174
+
175
+ Returns:
176
+ The implementation class.
177
+ """
178
+ from zenml.integrations.gcp.experiment_trackers import (
179
+ VertexExperimentTracker,
180
+ )
181
+
182
+ return VertexExperimentTracker
183
+
184
+ @property
185
+ def service_connector_requirements(
186
+ self,
187
+ ) -> Optional[ServiceConnectorRequirements]:
188
+ """Service connector resource requirements for service connectors.
189
+
190
+ Specifies resource requirements that are used to filter the available
191
+ service connector types that are compatible with this flavor.
192
+
193
+ Returns:
194
+ Requirements for compatible service connectors, if a service
195
+ connector is required for this flavor.
196
+ """
197
+ return ServiceConnectorRequirements(
198
+ resource_type=GCP_RESOURCE_TYPE,
199
+ )
@@ -47,16 +47,11 @@ class HuggingfaceIntegration(Integration):
47
47
  A list of requirements.
48
48
  """
49
49
  requirements = [
50
- "datasets",
50
+ "datasets>=2.16.0",
51
51
  "huggingface_hub>0.19.0",
52
52
  "accelerate",
53
53
  "bitsandbytes>=0.41.3",
54
54
  "peft",
55
- # temporary fix for CI issue similar to:
56
- # - https://github.com/huggingface/datasets/issues/6737
57
- # - https://github.com/huggingface/datasets/issues/6697
58
- # TODO try relaxing it back going forward
59
- "fsspec<=2023.12.0",
60
55
  "transformers",
61
56
  ]
62
57
 
@@ -248,7 +248,7 @@ def wait_pod(
248
248
  Returns:
249
249
  The pod object which meets the exit condition.
250
250
  """
251
- start_time = datetime.datetime.utcnow()
251
+ start_time = datetime.datetime.now(datetime.timezone.utc)
252
252
 
253
253
  # Link to exponential back-off algorithm used here:
254
254
  # https://cloud.google.com/storage/docs/exponential-backoff
@@ -288,7 +288,7 @@ def wait_pod(
288
288
  return resp
289
289
 
290
290
  # Check if wait timed out.
291
- elapse_time = datetime.datetime.utcnow() - start_time
291
+ elapse_time = datetime.datetime.now(datetime.timezone.utc) - start_time
292
292
  if elapse_time.seconds >= timeout_sec and timeout_sec != 0:
293
293
  raise RuntimeError(
294
294
  f"Waiting for pod `{namespace}:{pod_name}` timed out after "
@@ -236,7 +236,6 @@ class MLFlowExperimentTracker(BaseExperimentTracker):
236
236
  """Disables MLflow autologging for all supported frameworks."""
237
237
  frameworks = [
238
238
  "tensorflow",
239
- "gluon",
240
239
  "xgboost",
241
240
  "lightgbm",
242
241
  "statsmodels",
@@ -97,7 +97,9 @@ class WhylogsDataValidator(BaseDataValidator, AuthenticationMixin):
97
97
  """
98
98
  results = why.log(pandas=dataset)
99
99
  profile = results.profile()
100
- dataset_timestamp = dataset_timestamp or datetime.datetime.utcnow()
100
+ dataset_timestamp = dataset_timestamp or datetime.datetime.now(
101
+ datetime.timezone.utc
102
+ )
101
103
  profile.set_dataset_timestamp(dataset_timestamp=dataset_timestamp)
102
104
  return profile.view()
103
105
 
@@ -13,7 +13,7 @@
13
13
  # permissions and limitations under the License.
14
14
  """Models representing API keys."""
15
15
 
16
- from datetime import datetime, timedelta
16
+ from datetime import datetime, timedelta, timezone
17
17
  from typing import TYPE_CHECKING, ClassVar, List, Optional, Type, Union
18
18
  from uuid import UUID
19
19
 
@@ -319,7 +319,7 @@ class APIKeyInternalResponse(APIKeyResponse):
319
319
  and self.retain_period_minutes > 0
320
320
  ):
321
321
  # check if the previous key is still valid
322
- if datetime.utcnow() - self.last_rotated < timedelta(
322
+ if datetime.now(timezone.utc) - self.last_rotated < timedelta(
323
323
  minutes=self.retain_period_minutes
324
324
  ):
325
325
  key_hash = self.previous_key
@@ -14,13 +14,14 @@
14
14
  """Models representing schedules."""
15
15
 
16
16
  import datetime
17
- from typing import Optional, Union
17
+ from typing import Dict, Optional, Union
18
18
  from uuid import UUID
19
19
 
20
20
  from pydantic import Field, model_validator
21
21
 
22
22
  from zenml.constants import STR_FIELD_MAX_LENGTH
23
23
  from zenml.logger import get_logger
24
+ from zenml.metadata.metadata_types import MetadataType
24
25
  from zenml.models.v2.base.base import BaseUpdate
25
26
  from zenml.models.v2.base.scoped import (
26
27
  WorkspaceScopedFilter,
@@ -136,6 +137,11 @@ class ScheduleResponseMetadata(WorkspaceScopedResponseMetadata):
136
137
  orchestrator_id: Optional[UUID]
137
138
  pipeline_id: Optional[UUID]
138
139
 
140
+ run_metadata: Dict[str, MetadataType] = Field(
141
+ title="Metadata associated with this schedule.",
142
+ default={},
143
+ )
144
+
139
145
 
140
146
  class ScheduleResponseResources(WorkspaceScopedResponseResources):
141
147
  """Class for all resource models associated with the schedule entity."""
@@ -272,6 +278,15 @@ class ScheduleResponse(
272
278
  """
273
279
  return self.get_metadata().pipeline_id
274
280
 
281
+ @property
282
+ def run_metadata(self) -> Dict[str, MetadataType]:
283
+ """The `run_metadata` property.
284
+
285
+ Returns:
286
+ the value of the property.
287
+ """
288
+ return self.get_metadata().run_metadata
289
+
275
290
 
276
291
  # ------------------ Filter Model ------------------
277
292
 
@@ -13,7 +13,7 @@
13
13
  # permissions and limitations under the License.
14
14
  """Utilities to publish pipeline and step runs."""
15
15
 
16
- from datetime import datetime
16
+ from datetime import datetime, timezone
17
17
  from typing import TYPE_CHECKING, Dict, List
18
18
 
19
19
  from zenml.client import Client
@@ -48,7 +48,7 @@ def publish_successful_step_run(
48
48
  step_run_id=step_run_id,
49
49
  step_run_update=StepRunUpdate(
50
50
  status=ExecutionStatus.COMPLETED,
51
- end_time=datetime.utcnow(),
51
+ end_time=datetime.now(timezone.utc),
52
52
  outputs=output_artifact_ids,
53
53
  ),
54
54
  )
@@ -67,7 +67,7 @@ def publish_failed_step_run(step_run_id: "UUID") -> "StepRunResponse":
67
67
  step_run_id=step_run_id,
68
68
  step_run_update=StepRunUpdate(
69
69
  status=ExecutionStatus.FAILED,
70
- end_time=datetime.utcnow(),
70
+ end_time=datetime.now(timezone.utc),
71
71
  ),
72
72
  )
73
73
 
@@ -87,7 +87,7 @@ def publish_failed_pipeline_run(
87
87
  run_id=pipeline_run_id,
88
88
  run_update=PipelineRunUpdate(
89
89
  status=ExecutionStatus.FAILED,
90
- end_time=datetime.utcnow(),
90
+ end_time=datetime.now(timezone.utc),
91
91
  ),
92
92
  )
93
93
 
@@ -16,7 +16,7 @@
16
16
  import os
17
17
  import time
18
18
  from contextlib import nullcontext
19
- from datetime import datetime
19
+ from datetime import datetime, timezone
20
20
  from functools import partial
21
21
  from typing import TYPE_CHECKING, Any, Callable, Dict, Tuple
22
22
 
@@ -201,7 +201,7 @@ class StepLauncher:
201
201
  f"Failed preparing step `{self._step_name}`."
202
202
  )
203
203
  step_run_request.status = ExecutionStatus.FAILED
204
- step_run_request.end_time = datetime.utcnow()
204
+ step_run_request.end_time = datetime.now(timezone.utc)
205
205
  raise
206
206
  finally:
207
207
  step_run = Client().zen_store.create_run_step(
@@ -305,7 +305,7 @@ class StepLauncher:
305
305
  The created or existing pipeline run,
306
306
  and a boolean indicating whether the run was created or reused.
307
307
  """
308
- start_time = datetime.utcnow()
308
+ start_time = datetime.now(timezone.utc)
309
309
  run_name = string_utils.format_name_template(
310
310
  name_template=self._deployment.run_name_template,
311
311
  substitutions=self._deployment.pipeline_configuration._get_full_substitutions(
@@ -13,7 +13,7 @@
13
13
  # permissions and limitations under the License.
14
14
  """Utilities for creating step runs."""
15
15
 
16
- from datetime import datetime
16
+ from datetime import datetime, timezone
17
17
  from typing import Dict, List, Optional, Set, Tuple
18
18
 
19
19
  from zenml.client import Client
@@ -75,7 +75,7 @@ class StepRunRequestFactory:
75
75
  pipeline_run_id=self.pipeline_run.id,
76
76
  deployment=self.deployment.id,
77
77
  status=ExecutionStatus.RUNNING,
78
- start_time=datetime.utcnow(),
78
+ start_time=datetime.now(timezone.utc),
79
79
  user=Client().active_user.id,
80
80
  workspace=Client().active_workspace.id,
81
81
  )
@@ -1,7 +1,7 @@
1
1
  """Utility functions for running pipelines."""
2
2
 
3
3
  import time
4
- from datetime import datetime
4
+ from datetime import datetime, timezone
5
5
  from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Union
6
6
  from uuid import UUID
7
7
 
@@ -65,7 +65,7 @@ def create_placeholder_run(
65
65
 
66
66
  if deployment.schedule:
67
67
  return None
68
- start_time = datetime.utcnow()
68
+ start_time = datetime.now(timezone.utc)
69
69
  run_request = PipelineRunRequest(
70
70
  name=string_utils.format_name_template(
71
71
  name_template=deployment.run_name_template,
@@ -799,8 +799,8 @@ class ServiceConnector(BaseModel, metaclass=ServiceConnectorMeta):
799
799
  name=name,
800
800
  body=ServiceConnectorResponseBody(
801
801
  user=user,
802
- created=datetime.utcnow(),
803
- updated=datetime.utcnow(),
802
+ created=datetime.now(timezone.utc),
803
+ updated=datetime.now(timezone.utc),
804
804
  description=description,
805
805
  connector_type=self.get_type(),
806
806
  auth_method=self.auth_method,
zenml/stack/stack.py CHANGED
@@ -16,7 +16,7 @@
16
16
  import itertools
17
17
  import json
18
18
  import os
19
- from datetime import datetime
19
+ from datetime import datetime, timezone
20
20
  from typing import (
21
21
  TYPE_CHECKING,
22
22
  AbstractSet,
@@ -751,8 +751,8 @@ class Stack:
751
751
  config=LocalImageBuilderConfig(),
752
752
  user=Client().active_user.id,
753
753
  workspace=Client().active_workspace.id,
754
- created=datetime.utcnow(),
755
- updated=datetime.utcnow(),
754
+ created=datetime.now(timezone.utc),
755
+ updated=datetime.now(timezone.utc),
756
756
  )
757
757
 
758
758
  self._image_builder = image_builder