zenml-nightly 0.81.0.dev20250428__py3-none-any.whl → 0.81.0.dev20250430__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.
- zenml/VERSION +1 -1
- zenml/cli/model.py +2 -7
- zenml/client.py +17 -2
- zenml/config/build_configuration.py +4 -0
- zenml/config/docker_settings.py +1 -1
- zenml/config/resource_settings.py +1 -1
- zenml/config/strict_base_model.py +1 -1
- zenml/entrypoints/base_entrypoint_configuration.py +1 -1
- zenml/environment.py +37 -34
- zenml/exceptions.py +0 -78
- zenml/integrations/aws/__init__.py +1 -1
- zenml/integrations/evidently/__init__.py +1 -0
- zenml/integrations/evidently/metrics.py +1 -1
- zenml/integrations/evidently/tests.py +1 -1
- zenml/integrations/gcp/flavors/vertex_orchestrator_flavor.py +6 -0
- zenml/integrations/gcp/orchestrators/vertex_orchestrator.py +49 -28
- zenml/integrations/kubeflow/orchestrators/kubeflow_orchestrator.py +7 -29
- zenml/integrations/kubernetes/flavors/kubernetes_orchestrator_flavor.py +6 -0
- zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator.py +12 -5
- zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator_entrypoint.py +31 -18
- zenml/integrations/kubernetes/orchestrators/manifest_utils.py +21 -0
- zenml/integrations/kubernetes/pod_settings.py +6 -1
- zenml/integrations/numpy/__init__.py +4 -1
- zenml/integrations/numpy/materializers/numpy_materializer.py +75 -6
- zenml/integrations/pandas/materializers/pandas_materializer.py +118 -22
- zenml/integrations/tekton/orchestrators/tekton_orchestrator.py +8 -28
- zenml/models/v2/core/model_version.py +28 -33
- zenml/models/v2/core/pipeline_deployment.py +4 -4
- zenml/models/v2/core/pipeline_run.py +5 -12
- zenml/models/v2/core/user.py +1 -1
- zenml/orchestrators/dag_runner.py +50 -14
- zenml/secret/base_secret.py +1 -1
- zenml/stack/stack_component.py +1 -1
- zenml/stack/utils.py +1 -1
- zenml/utils/code_utils.py +1 -1
- zenml/zen_server/dashboard/assets/{404-o3nB5iwI.js → 404-D4aYbspS.js} +1 -1
- zenml/zen_server/dashboard/assets/{@react-router-BGgzhn5D.js → @react-router-CNP6g_RL.js} +1 -1
- zenml/zen_server/dashboard/assets/{AlertDialogDropdownItem-C_qWs-4u.js → AlertDialogDropdownItem-CRZjthRL.js} +1 -1
- zenml/zen_server/dashboard/assets/{CodeSnippet-nRnOvbOJ.js → CodeSnippet-Di-loaZu.js} +1 -1
- zenml/zen_server/dashboard/assets/CollapsibleCard-Dr5zb5T5.js +1 -0
- zenml/zen_server/dashboard/assets/{Commands-BwBzFj-5.js → Commands-CD9Y7FOE.js} +1 -1
- zenml/zen_server/dashboard/assets/{ComponentBadge-CMx2DbsV.js → ComponentBadge-BgGnzcLu.js} +1 -1
- zenml/zen_server/dashboard/assets/{ComponentIcon-CSxdApv8.js → ComponentIcon-B_7Y_oV-.js} +1 -1
- zenml/zen_server/dashboard/assets/{CsvVizualization-lxB2iyEh.js → CsvVizualization-CDrjL6bW.js} +1 -1
- zenml/zen_server/dashboard/assets/{DeleteAlertDialog-Bp0o-UXZ.js → DeleteAlertDialog-9RTDnEx3.js} +1 -1
- zenml/zen_server/dashboard/assets/DialogItem-0fWTH7ki.js +1 -0
- zenml/zen_server/dashboard/assets/{Error-DRhVeVHQ.js → Error-vBjUYjb-.js} +1 -1
- zenml/zen_server/dashboard/assets/{ExecutionStatus-HnZXi9bW.js → ExecutionStatus-B-ysY113.js} +1 -1
- zenml/zen_server/dashboard/assets/{Helpbox-Dsr3ZYcL.js → Helpbox-Dt3q7NGd.js} +1 -1
- zenml/zen_server/dashboard/assets/{Infobox-C4Op55B8.js → Infobox-Bai0JtFs.js} +1 -1
- zenml/zen_server/dashboard/assets/{InlineAvatar-CrAwe7Pl.js → InlineAvatar-Cpj0lVRQ.js} +1 -1
- zenml/zen_server/dashboard/assets/NestedCollapsible-DbhKdWx-.js +1 -0
- zenml/zen_server/dashboard/assets/{Partials-DjTM0Oe-.js → Partials-BNBtCjuT.js} +1 -1
- zenml/zen_server/dashboard/assets/ProBadge-3vtouJQf.js +1 -0
- zenml/zen_server/dashboard/assets/{ProCta-BYSSivgY.js → ProCta-BoTLdAdV.js} +1 -1
- zenml/zen_server/dashboard/assets/{ProviderIcon-B8W7AGNk.js → ProviderIcon-kkODO9tx.js} +1 -1
- zenml/zen_server/dashboard/assets/{ProviderRadio-BWFJPEY2.js → ProviderRadio-26EB5tY-.js} +1 -1
- zenml/zen_server/dashboard/assets/RunSelector-j0C_TPVp.js +1 -0
- zenml/zen_server/dashboard/assets/RunsBody-DexNouV4.js +1 -0
- zenml/zen_server/dashboard/assets/SearchField-DMCywawn.js +1 -0
- zenml/zen_server/dashboard/assets/{SecretTooltip-CCn9HfEh.js → SecretTooltip-LLGP7AIC.js} +1 -1
- zenml/zen_server/dashboard/assets/{SetPassword-BDFVwnNB.js → SetPassword-CBHW-Su8.js} +1 -1
- zenml/zen_server/dashboard/assets/StackList-S-9I1R4n.js +1 -0
- zenml/zen_server/dashboard/assets/Tabs-C2ufJX4t.js +1 -0
- zenml/zen_server/dashboard/assets/Tick-ay3Bgtro.js +1 -0
- zenml/zen_server/dashboard/assets/{UpdatePasswordSchemas-3gg2tC-H.js → UpdatePasswordSchemas-p3RX0P-Q.js} +1 -1
- zenml/zen_server/dashboard/assets/{UsageReason-DOMAzO02.js → UsageReason-C8sD2bOU.js} +1 -1
- zenml/zen_server/dashboard/assets/{Wizard-BSH_lIfi.js → Wizard-DIllc07n.js} +1 -1
- zenml/zen_server/dashboard/assets/{WizardFooter-CnM-50jL.js → WizardFooter-dNDpuero.js} +1 -1
- zenml/zen_server/dashboard/assets/{all-pipeline-runs-query-D9XfZpmV.js → all-pipeline-runs-query-BUT1PiTp.js} +1 -1
- zenml/zen_server/dashboard/assets/{configuration-form-Ci_QlfZC.js → configuration-form-DBZSb0FV.js} +1 -1
- zenml/zen_server/dashboard/assets/{create-stack-CoQ5SEJL.js → create-stack-BXLyjE58.js} +1 -1
- zenml/zen_server/dashboard/assets/{delete-run-B5xUZwdP.js → delete-run-DzcYxUnd.js} +1 -1
- zenml/zen_server/dashboard/assets/dots-horizontal-BGRJCPCs.js +1 -0
- zenml/zen_server/dashboard/assets/{flavor-select-DOLAl-S4.js → flavor-select-BTEwByv6.js} +1 -1
- zenml/zen_server/dashboard/assets/{form-schemas-BaEJ1z87.js → form-schemas-BJN_25Ua.js} +1 -1
- zenml/zen_server/dashboard/assets/{index-e8udi7QT.js → index-8uhUi12k.js} +1 -1
- zenml/zen_server/dashboard/assets/{index-hsSXyS3H.js → index-BygJE88j.js} +8 -8
- zenml/zen_server/dashboard/assets/{index-ojAuWXMf.js → index-D9-ukAem.js} +1 -1
- zenml/zen_server/dashboard/assets/index-DmTFrHJm.css +1 -0
- zenml/zen_server/dashboard/assets/{index-BoWZ9rXk.js → index-wYtmKLnQ.js} +1 -1
- zenml/zen_server/dashboard/assets/{login-mutation-CwraNa5G.js → login-mutation-DywLqguW.js} +1 -1
- zenml/zen_server/dashboard/assets/{not-found-BuK1QrF2.js → not-found-BOoklIG4.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-0AIX3VK8.js → page--hSXKqyG.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-CIDo1Ajk.js → page-2BsNK_sZ.js} +1 -1
- zenml/zen_server/dashboard/assets/page-4nVakAEl.js +1 -0
- zenml/zen_server/dashboard/assets/{page-CjRoKEQs.js → page-8AzB83Py.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-BQVPbNps.js → page-B0r9dBEU.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-hVng6ANV.js → page-B1Uq1S1Q.js} +1 -1
- zenml/zen_server/dashboard/assets/page-B3DscprQ.js +1 -0
- zenml/zen_server/dashboard/assets/{page-KRP_w5zH.js → page-B7Aj2XbV.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-CZgeF_wQ.js → page-BE8jdyaM.js} +1 -1
- zenml/zen_server/dashboard/assets/page-BIYqUwTI.js +1 -0
- zenml/zen_server/dashboard/assets/page-BTzhAVEn.js +1 -0
- zenml/zen_server/dashboard/assets/{page-_Zt6UwiG.js → page-ByXQN8A-.js} +1 -1
- zenml/zen_server/dashboard/assets/page-CI4a9CXs.js +1 -0
- zenml/zen_server/dashboard/assets/page-CPLlVRXx.js +6 -0
- zenml/zen_server/dashboard/assets/page-CSQOpvvK.js +3 -0
- zenml/zen_server/dashboard/assets/{page-DwIlrsF0.js → page-Ccnk_5ji.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-C-6XUKSp.js → page-Ci_n_x3a.js} +1 -1
- zenml/zen_server/dashboard/assets/page-D-ry_oLs.js +1 -0
- zenml/zen_server/dashboard/assets/{page-DbEn9V9E.js → page-D2TtSfnb.js} +1 -1
- zenml/zen_server/dashboard/assets/page-DHnkTzqs.js +1 -0
- zenml/zen_server/dashboard/assets/{page-B5clbTo4.js → page-DP2Ed-2m.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-C30HZCTR.js → page-D_5R6E7b.js} +1 -1
- zenml/zen_server/dashboard/assets/page-DfTsntQI.js +1 -0
- zenml/zen_server/dashboard/assets/page-DkY7AIhj.js +1 -0
- zenml/zen_server/dashboard/assets/page-DmteSSj6.js +1 -0
- zenml/zen_server/dashboard/assets/page-Dt3wHeWX.js +1 -0
- zenml/zen_server/dashboard/assets/page-EXvws1ss.js +1 -0
- zenml/zen_server/dashboard/assets/{page-Czj8fu8q.js → page-K9yjbnd4.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-DHDeVaMO.js → page-RV8wpZ_4.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-DLVtrRa5.js → page-bUVHi7DE.js} +1 -1
- zenml/zen_server/dashboard/assets/page-cOEvFs_l.js +1 -0
- zenml/zen_server/dashboard/assets/page-kzSGEVUs.js +1 -0
- zenml/zen_server/dashboard/assets/{page-C7buw8xJ.js → page-uDGvpa5g.js} +2 -2
- zenml/zen_server/dashboard/assets/{page-BbygQpf-.js → page-uN0n_DE2.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-CgJcperk.js → page-xa1EAPcI.js} +1 -1
- zenml/zen_server/dashboard/assets/{persist-xOAq24Bm.js → persist-CEeDYHW5.js} +1 -1
- zenml/zen_server/dashboard/assets/{persist-DLvsEXh0.js → persist-SSTTV5q0.js} +1 -1
- zenml/zen_server/dashboard/assets/{service-MHyqhRgp.js → service-BRoAA1Kq.js} +1 -1
- zenml/zen_server/dashboard/assets/sharedSchema-BACERDat.js +14 -0
- zenml/zen_server/dashboard/assets/{stack-detail-query-C1GoxBeK.js → stack-detail-query-ihiJr6nq.js} +1 -1
- zenml/zen_server/dashboard/assets/{update-server-settings-mutation-DduehrZn.js → update-server-settings-mutation-CK6COmw9.js} +1 -1
- zenml/zen_server/dashboard/index.html +4 -4
- zenml/zen_server/deploy/daemon/daemon_zen_server.py +1 -1
- zenml/zen_server/deploy/docker/docker_zen_server.py +1 -1
- zenml/zen_server/exceptions.py +0 -2
- zenml/zen_server/routers/model_versions_endpoints.py +10 -19
- zenml/zen_server/routers/runs_endpoints.py +7 -1
- zenml/zen_stores/schemas/pipeline_deployment_schemas.py +20 -3
- zenml/zen_stores/schemas/pipeline_run_schemas.py +21 -1
- zenml/zen_stores/secrets_stores/hashicorp_secrets_store.py +1 -1
- zenml/zen_stores/secrets_stores/sql_secrets_store.py +1 -1
- zenml/zen_stores/sql_zen_store.py +10 -34
- {zenml_nightly-0.81.0.dev20250428.dist-info → zenml_nightly-0.81.0.dev20250430.dist-info}/METADATA +2 -2
- {zenml_nightly-0.81.0.dev20250428.dist-info → zenml_nightly-0.81.0.dev20250430.dist-info}/RECORD +140 -139
- zenml/zen_server/dashboard/assets/CollapsibleCard-9sSz7n1R.js +0 -1
- zenml/zen_server/dashboard/assets/DialogItem-DHw2ihTx.js +0 -1
- zenml/zen_server/dashboard/assets/NestedCollapsible-Ce1bmT8N.js +0 -1
- zenml/zen_server/dashboard/assets/ProBadge-CDEqgzh8.js +0 -1
- zenml/zen_server/dashboard/assets/RunSelector-DoL_gMHJ.js +0 -1
- zenml/zen_server/dashboard/assets/RunsBody-B6mBjv-_.js +0 -1
- zenml/zen_server/dashboard/assets/SearchField-DHl5flXv.js +0 -1
- zenml/zen_server/dashboard/assets/StackList-dhdUtky3.js +0 -1
- zenml/zen_server/dashboard/assets/Tabs-BuZG8ft1.js +0 -1
- zenml/zen_server/dashboard/assets/Tick-C4gtED35.js +0 -1
- zenml/zen_server/dashboard/assets/index-6mLFgFwe.css +0 -1
- zenml/zen_server/dashboard/assets/page-3lW9eIer.js +0 -1
- zenml/zen_server/dashboard/assets/page-9PzQok8O.js +0 -1
- zenml/zen_server/dashboard/assets/page-BEibNYiA.js +0 -6
- zenml/zen_server/dashboard/assets/page-BOE2XBFy.js +0 -1
- zenml/zen_server/dashboard/assets/page-Bki79xdd.js +0 -1
- zenml/zen_server/dashboard/assets/page-BnKwJnOb.js +0 -1
- zenml/zen_server/dashboard/assets/page-CBGeo-7W.js +0 -2
- zenml/zen_server/dashboard/assets/page-Co-FJ5ds.js +0 -1
- zenml/zen_server/dashboard/assets/page-Cu8vuohQ.js +0 -1
- zenml/zen_server/dashboard/assets/page-D0QcEBi1.js +0 -1
- zenml/zen_server/dashboard/assets/page-DKY_U5Sz.js +0 -1
- zenml/zen_server/dashboard/assets/page-DQHU5o_C.js +0 -1
- zenml/zen_server/dashboard/assets/page-DpY1koQY.js +0 -1
- zenml/zen_server/dashboard/assets/page-DrS4WOup.js +0 -1
- zenml/zen_server/dashboard/assets/page-HIAPXq4w.js +0 -1
- zenml/zen_server/dashboard/assets/page-Jw2QAdxa.js +0 -1
- zenml/zen_server/dashboard/assets/sharedSchema-CQA5lnlU.js +0 -14
- {zenml_nightly-0.81.0.dev20250428.dist-info → zenml_nightly-0.81.0.dev20250430.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.81.0.dev20250428.dist-info → zenml_nightly-0.81.0.dev20250430.dist-info}/WHEEL +0 -0
- {zenml_nightly-0.81.0.dev20250428.dist-info → zenml_nightly-0.81.0.dev20250430.dist-info}/entry_points.txt +0 -0
zenml/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.81.0.
|
1
|
+
0.81.0.dev20250430
|
zenml/cli/model.py
CHANGED
@@ -398,18 +398,13 @@ def version() -> None:
|
|
398
398
|
|
399
399
|
@cli_utils.list_options(ModelVersionFilter)
|
400
400
|
@version.command("list", help="List model versions with filter.")
|
401
|
-
|
402
|
-
def list_model_versions(model_name_or_id: str, **kwargs: Any) -> None:
|
401
|
+
def list_model_versions(**kwargs: Any) -> None:
|
403
402
|
"""List model versions with filter in the Model Control Plane.
|
404
403
|
|
405
404
|
Args:
|
406
|
-
model_name_or_id: The name or ID of the parent model.
|
407
405
|
**kwargs: Keyword arguments to filter models.
|
408
406
|
"""
|
409
|
-
model_versions = Client().list_model_versions(
|
410
|
-
model_name_or_id=model_name_or_id,
|
411
|
-
**kwargs,
|
412
|
-
)
|
407
|
+
model_versions = Client().list_model_versions(**kwargs)
|
413
408
|
|
414
409
|
if not model_versions:
|
415
410
|
cli_utils.declare("No model versions found.")
|
zenml/client.py
CHANGED
@@ -6504,7 +6504,8 @@ class Client(metaclass=ClientMetaClass):
|
|
6504
6504
|
|
6505
6505
|
def list_model_versions(
|
6506
6506
|
self,
|
6507
|
-
|
6507
|
+
model: Optional[Union[str, UUID]] = None,
|
6508
|
+
model_name_or_id: Optional[Union[str, UUID]] = None,
|
6508
6509
|
sort_by: str = "number",
|
6509
6510
|
page: int = PAGINATION_STARTING_PAGE,
|
6510
6511
|
size: int = PAGE_SIZE_DEFAULT,
|
@@ -6525,6 +6526,7 @@ class Client(metaclass=ClientMetaClass):
|
|
6525
6526
|
"""Get model versions by filter from Model Control Plane.
|
6526
6527
|
|
6527
6528
|
Args:
|
6529
|
+
model: The model to filter by.
|
6528
6530
|
model_name_or_id: name or id of the model containing the model
|
6529
6531
|
version.
|
6530
6532
|
sort_by: The column to sort by
|
@@ -6548,6 +6550,19 @@ class Client(metaclass=ClientMetaClass):
|
|
6548
6550
|
Returns:
|
6549
6551
|
A page object with all model versions.
|
6550
6552
|
"""
|
6553
|
+
if model_name_or_id:
|
6554
|
+
logger.warning(
|
6555
|
+
"The `model_name_or_id` argument is deprecated. "
|
6556
|
+
"Please use the `model` argument instead."
|
6557
|
+
)
|
6558
|
+
if model is None:
|
6559
|
+
model = model_name_or_id
|
6560
|
+
else:
|
6561
|
+
logger.warning(
|
6562
|
+
"Ignoring `model_name_or_id` argument as `model` argument "
|
6563
|
+
"was also provided."
|
6564
|
+
)
|
6565
|
+
|
6551
6566
|
model_version_filter_model = ModelVersionFilter(
|
6552
6567
|
page=page,
|
6553
6568
|
size=size,
|
@@ -6563,7 +6578,7 @@ class Client(metaclass=ClientMetaClass):
|
|
6563
6578
|
tag=tag,
|
6564
6579
|
tags=tags,
|
6565
6580
|
user=user,
|
6566
|
-
model=
|
6581
|
+
model=model,
|
6567
6582
|
project=project or self.active_project.id,
|
6568
6583
|
)
|
6569
6584
|
|
@@ -95,6 +95,10 @@ class BuildConfiguration(BaseModel):
|
|
95
95
|
for _, requirements, _ in requirements_files:
|
96
96
|
hash_.update(requirements.encode())
|
97
97
|
|
98
|
+
if self.settings.dockerfile:
|
99
|
+
with open(self.settings.dockerfile, "rb") as f:
|
100
|
+
hash_.update(f.read())
|
101
|
+
|
98
102
|
return hash_.hexdigest()
|
99
103
|
|
100
104
|
def should_include_files(
|
zenml/config/docker_settings.py
CHANGED
@@ -274,7 +274,7 @@ class BaseEntrypointConfiguration(ABC):
|
|
274
274
|
download_dir = os.path.join(
|
275
275
|
code_repo_root, code_reference.subdirectory
|
276
276
|
)
|
277
|
-
os.makedirs(download_dir)
|
277
|
+
os.makedirs(download_dir, exist_ok=True)
|
278
278
|
repo.download_files(
|
279
279
|
commit=code_reference.commit,
|
280
280
|
directory=download_dir,
|
zenml/environment.py
CHANGED
@@ -15,12 +15,11 @@
|
|
15
15
|
|
16
16
|
import os
|
17
17
|
import platform
|
18
|
-
|
19
|
-
from typing import Dict
|
18
|
+
import subprocess
|
19
|
+
from typing import Any, Dict, List
|
20
20
|
|
21
21
|
import distro
|
22
22
|
|
23
|
-
from zenml import __version__
|
24
23
|
from zenml.constants import INSIDE_ZENML_CONTAINER
|
25
24
|
from zenml.enums import EnvironmentType
|
26
25
|
from zenml.logger import get_logger
|
@@ -29,7 +28,7 @@ from zenml.utils.singleton import SingletonMetaClass
|
|
29
28
|
logger = get_logger(__name__)
|
30
29
|
|
31
30
|
|
32
|
-
def get_run_environment_dict() -> Dict[str,
|
31
|
+
def get_run_environment_dict() -> Dict[str, Any]:
|
33
32
|
"""Returns a dictionary of the current run environment.
|
34
33
|
|
35
34
|
Everything that is returned here will be saved in the DB as
|
@@ -40,12 +39,24 @@ def get_run_environment_dict() -> Dict[str, str]:
|
|
40
39
|
Returns:
|
41
40
|
A dictionary of the current run environment.
|
42
41
|
"""
|
43
|
-
|
44
|
-
"environment": get_environment(),
|
42
|
+
env_dict: Dict[str, Any] = {
|
43
|
+
"environment": str(get_environment()),
|
45
44
|
**Environment.get_system_info(),
|
46
45
|
"python_version": Environment.python_version(),
|
47
46
|
}
|
48
47
|
|
48
|
+
try:
|
49
|
+
python_packages = Environment.get_python_packages()
|
50
|
+
except RuntimeError:
|
51
|
+
logger.warning("Failed to get list of installed Python packages")
|
52
|
+
else:
|
53
|
+
# TODO: We send the python packages as a string right now to keep
|
54
|
+
# backwards compatibility with old versions. We should update this to
|
55
|
+
# be a list of strings eventually.
|
56
|
+
env_dict["python_packages"] = "\n".join(python_packages)
|
57
|
+
|
58
|
+
return env_dict
|
59
|
+
|
49
60
|
|
50
61
|
def get_environment() -> str:
|
51
62
|
"""Returns a string representing the execution environment of the pipeline.
|
@@ -88,35 +99,8 @@ def get_environment() -> str:
|
|
88
99
|
return EnvironmentType.NATIVE
|
89
100
|
|
90
101
|
|
91
|
-
def get_system_details() -> str:
|
92
|
-
"""Returns OS, python and ZenML information.
|
93
|
-
|
94
|
-
Returns:
|
95
|
-
str: OS, python and ZenML information
|
96
|
-
"""
|
97
|
-
from zenml.integrations.registry import integration_registry
|
98
|
-
|
99
|
-
info = {
|
100
|
-
"ZenML version": __version__,
|
101
|
-
"Install path": Path(__file__).resolve().parent,
|
102
|
-
"Python version": Environment.python_version(),
|
103
|
-
"Platform information": Environment.get_system_info(),
|
104
|
-
"Environment": get_environment(),
|
105
|
-
"Integrations": integration_registry.get_installed_integrations(),
|
106
|
-
}
|
107
|
-
return "\n".join(
|
108
|
-
"{:>10} {}".format(k + ":", str(v).replace("\n", " "))
|
109
|
-
for k, v in info.items()
|
110
|
-
)
|
111
|
-
|
112
|
-
|
113
102
|
class Environment(metaclass=SingletonMetaClass):
|
114
|
-
"""Provides environment information.
|
115
|
-
|
116
|
-
Individual environment components can be registered separately to extend
|
117
|
-
the global Environment object with additional information (see
|
118
|
-
`BaseEnvironmentComponent`).
|
119
|
-
"""
|
103
|
+
"""Provides environment information."""
|
120
104
|
|
121
105
|
def __init__(self) -> None:
|
122
106
|
"""Initializes an Environment instance.
|
@@ -366,3 +350,22 @@ class Environment(metaclass=SingletonMetaClass):
|
|
366
350
|
"LIGHTNING_CLOUD_URL" in os.environ
|
367
351
|
and "LIGHTNING_CLOUDSPACE_HOST" in os.environ
|
368
352
|
)
|
353
|
+
|
354
|
+
@staticmethod
|
355
|
+
def get_python_packages() -> List[str]:
|
356
|
+
"""Returns a list of installed Python packages.
|
357
|
+
|
358
|
+
Raises:
|
359
|
+
RuntimeError: If the process to get the list of installed packages
|
360
|
+
fails.
|
361
|
+
|
362
|
+
Returns:
|
363
|
+
List of installed packages in pip freeze format.
|
364
|
+
"""
|
365
|
+
try:
|
366
|
+
output = subprocess.check_output(["pip", "freeze"]).decode()
|
367
|
+
return output.strip().split("\n")
|
368
|
+
except subprocess.CalledProcessError:
|
369
|
+
raise RuntimeError(
|
370
|
+
"Failed to get list of installed Python packages"
|
371
|
+
)
|
zenml/exceptions.py
CHANGED
@@ -70,40 +70,6 @@ class DoesNotExistException(ZenMLBaseException):
|
|
70
70
|
super().__init__(message)
|
71
71
|
|
72
72
|
|
73
|
-
class PipelineNotSucceededException(ZenMLBaseException):
|
74
|
-
"""Raises exception when trying to fetch artifacts from a not succeeded pipeline."""
|
75
|
-
|
76
|
-
def __init__(
|
77
|
-
self,
|
78
|
-
name: str = "",
|
79
|
-
message: str = "{} is not yet completed successfully.",
|
80
|
-
):
|
81
|
-
"""Initializes the exception.
|
82
|
-
|
83
|
-
Args:
|
84
|
-
name: Name of the pipeline.
|
85
|
-
message: Message with details of exception.
|
86
|
-
"""
|
87
|
-
super().__init__(message.format(name))
|
88
|
-
|
89
|
-
|
90
|
-
class GitException(ZenMLBaseException):
|
91
|
-
"""Raises exception when a problem occurs in git resolution."""
|
92
|
-
|
93
|
-
def __init__(
|
94
|
-
self,
|
95
|
-
message: str = "There is a problem with git resolution. "
|
96
|
-
"Please make sure that all relevant files "
|
97
|
-
"are committed.",
|
98
|
-
):
|
99
|
-
"""Initializes the exception.
|
100
|
-
|
101
|
-
Args:
|
102
|
-
message: Message with details of exception.
|
103
|
-
"""
|
104
|
-
super().__init__(message)
|
105
|
-
|
106
|
-
|
107
73
|
class StepInterfaceError(ZenMLBaseException):
|
108
74
|
"""Raises exception when interacting with the Step interface in an unsupported way."""
|
109
75
|
|
@@ -116,50 +82,18 @@ class StepContextError(ZenMLBaseException):
|
|
116
82
|
"""Raises exception when interacting with a StepContext in an unsupported way."""
|
117
83
|
|
118
84
|
|
119
|
-
class PipelineInterfaceError(ZenMLBaseException):
|
120
|
-
"""Raises exception when interacting with the Pipeline interface in an unsupported way."""
|
121
|
-
|
122
|
-
|
123
|
-
class ArtifactInterfaceError(ZenMLBaseException):
|
124
|
-
"""Raises exception when interacting with the Artifact interface in an unsupported way."""
|
125
|
-
|
126
|
-
|
127
85
|
class StackComponentInterfaceError(ZenMLBaseException):
|
128
86
|
"""Raises exception when interacting with the stack components in an unsupported way."""
|
129
87
|
|
130
88
|
|
131
|
-
class StackComponentDeploymentError(ZenMLBaseException):
|
132
|
-
"""Raises exception when deploying a stack component fails."""
|
133
|
-
|
134
|
-
|
135
89
|
class ArtifactStoreInterfaceError(ZenMLBaseException):
|
136
90
|
"""Raises exception when interacting with the Artifact Store interface in an unsupported way."""
|
137
91
|
|
138
92
|
|
139
|
-
class PipelineConfigurationError(ZenMLBaseException):
|
140
|
-
"""Raises exceptions when a pipeline configuration contains invalid values."""
|
141
|
-
|
142
|
-
|
143
93
|
class IntegrationError(ZenMLBaseException):
|
144
94
|
"""Raises exceptions when a requested integration can not be activated."""
|
145
95
|
|
146
96
|
|
147
|
-
class DuplicateRunNameError(RuntimeError):
|
148
|
-
"""Raises exception when a run with the same name already exists."""
|
149
|
-
|
150
|
-
def __init__(
|
151
|
-
self,
|
152
|
-
message: str = "Unable to run a pipeline with a run name that "
|
153
|
-
"already exists.",
|
154
|
-
):
|
155
|
-
"""Initializes the exception.
|
156
|
-
|
157
|
-
Args:
|
158
|
-
message: Message with details of exception.
|
159
|
-
"""
|
160
|
-
super().__init__(message)
|
161
|
-
|
162
|
-
|
163
97
|
class ValidationError(ZenMLBaseException):
|
164
98
|
"""Raised when the Model passed to the ZenStore."""
|
165
99
|
|
@@ -180,22 +114,10 @@ class StackValidationError(ZenMLBaseException):
|
|
180
114
|
"""Raised when a stack configuration is not valid."""
|
181
115
|
|
182
116
|
|
183
|
-
class StackComponentValidationError(ZenMLBaseException):
|
184
|
-
"""Raised when a stack component configuration is not valid."""
|
185
|
-
|
186
|
-
|
187
|
-
class ProvisioningError(ZenMLBaseException):
|
188
|
-
"""Raised when an error occurs when provisioning resources for a StackComponent."""
|
189
|
-
|
190
|
-
|
191
117
|
class GitNotFoundError(ImportError):
|
192
118
|
"""Raised when ZenML CLI is used to interact with examples on a machine with no git installation."""
|
193
119
|
|
194
120
|
|
195
|
-
class DuplicatedConfigurationError(ZenMLBaseException):
|
196
|
-
"""Raised when a configuration parameter is set twice."""
|
197
|
-
|
198
|
-
|
199
121
|
class IllegalOperationError(ZenMLBaseException):
|
200
122
|
"""Raised when an illegal operation is attempted."""
|
201
123
|
|
@@ -56,6 +56,7 @@ class EvidentlyIntegration(Integration):
|
|
56
56
|
REQUIREMENTS = [
|
57
57
|
"evidently>=0.4.16,<=0.4.22",
|
58
58
|
"tenacity!=8.4.0", # https://github.com/jd/tenacity/issues/471
|
59
|
+
"numpy<2.0.0", # evidently is not compatible with NumPy 2.0
|
59
60
|
]
|
60
61
|
REQUIREMENTS_IGNORED_ON_UNINSTALL = ["tenacity", "pandas"]
|
61
62
|
|
@@ -112,6 +112,11 @@ class VertexOrchestratorConfig(
|
|
112
112
|
network: the full name of the Compute Engine Network to which the job
|
113
113
|
should be peered. For example, `projects/12345/global/networks/myVPC`
|
114
114
|
If not provided, the job will not be peered with any network.
|
115
|
+
private_service_connect: the full name of a Private Service Connect
|
116
|
+
endpoint to which the job should be peered. For example,
|
117
|
+
`projects/12345/regions/us-central1/networkAttachments/NETWORK_ATTACHMENT_NAME`
|
118
|
+
If not provided, the job will not be peered with any private service
|
119
|
+
connect endpoint.
|
115
120
|
cpu_limit: The maximum CPU limit for this operator. This string value
|
116
121
|
can be a number (integer value for number of CPUs) as string,
|
117
122
|
or a number followed by "m", which means 1/1000. You can specify
|
@@ -130,6 +135,7 @@ class VertexOrchestratorConfig(
|
|
130
135
|
encryption_spec_key_name: Optional[str] = None
|
131
136
|
workload_service_account: Optional[str] = None
|
132
137
|
network: Optional[str] = None
|
138
|
+
private_service_connect: Optional[str] = None
|
133
139
|
|
134
140
|
# Deprecated
|
135
141
|
cpu_limit: Optional[str] = None
|
@@ -48,7 +48,15 @@ from uuid import UUID
|
|
48
48
|
|
49
49
|
from google.api_core import exceptions as google_exceptions
|
50
50
|
from google.cloud import aiplatform
|
51
|
+
from google.cloud.aiplatform.compat.services import (
|
52
|
+
pipeline_service_client_v1beta1,
|
53
|
+
)
|
54
|
+
from google.cloud.aiplatform.compat.types import pipeline_job_v1beta1
|
51
55
|
from google.cloud.aiplatform_v1.types import PipelineState
|
56
|
+
from google.cloud.aiplatform_v1beta1.types.service_networking import (
|
57
|
+
PscInterfaceConfig,
|
58
|
+
)
|
59
|
+
from google.protobuf import json_format
|
52
60
|
from google_cloud_pipeline_components.v1.custom_job.utils import (
|
53
61
|
create_custom_training_job_from_component,
|
54
62
|
)
|
@@ -495,36 +503,16 @@ class VertexOrchestrator(ContainerizedOrchestrator, GoogleCredentialsMixin):
|
|
495
503
|
)
|
496
504
|
pod_settings = step_settings.pod_settings
|
497
505
|
if pod_settings:
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
)
|
503
|
-
if pod_settings.affinity:
|
504
|
-
logger.warning(
|
505
|
-
"Affinity is set but not supported in Vertex with "
|
506
|
-
"Kubeflow Pipelines 2.x. Ignoring..."
|
507
|
-
)
|
508
|
-
if pod_settings.tolerations:
|
509
|
-
logger.warning(
|
510
|
-
"Tolerations are set but not supported in "
|
511
|
-
"Vertex with Kubeflow Pipelines 2.x. Ignoring..."
|
512
|
-
)
|
513
|
-
if pod_settings.volumes:
|
514
|
-
logger.warning(
|
515
|
-
"Volumes are set but not supported in Vertex with "
|
516
|
-
"Kubeflow Pipelines 2.x. Ignoring..."
|
517
|
-
)
|
518
|
-
if pod_settings.volume_mounts:
|
519
|
-
logger.warning(
|
520
|
-
"Volume mounts are set but not supported in "
|
521
|
-
"Vertex with Kubeflow Pipelines 2.x. Ignoring..."
|
522
|
-
)
|
523
|
-
if pod_settings.env or pod_settings.env_from:
|
506
|
+
ignored_fields = pod_settings.model_fields_set - {
|
507
|
+
"node_selectors"
|
508
|
+
}
|
509
|
+
if ignored_fields:
|
524
510
|
logger.warning(
|
525
|
-
"
|
526
|
-
"
|
511
|
+
f"The following pod settings are not supported in "
|
512
|
+
f"Vertex with Vertex Pipelines 2.x and will be "
|
513
|
+
f"ignored: {list(ignored_fields)}."
|
527
514
|
)
|
515
|
+
|
528
516
|
for key in pod_settings.node_selectors:
|
529
517
|
if (
|
530
518
|
key
|
@@ -737,6 +725,39 @@ class VertexOrchestrator(ContainerizedOrchestrator, GoogleCredentialsMixin):
|
|
737
725
|
self.config.network,
|
738
726
|
)
|
739
727
|
|
728
|
+
if self.config.private_service_connect:
|
729
|
+
# The PSC setting isn't yet part of the stable v1 API. We need to
|
730
|
+
# temporarily hack the aiplatform.PipelineJob object in two places:
|
731
|
+
# * to use the v1beta1 PipelineJob primitive which supports the
|
732
|
+
# psc_interface_config field instead of the v1 PipelineJob
|
733
|
+
# primitive.
|
734
|
+
# * to use the v1beta1 PipelineServiceClient instead of the v1
|
735
|
+
# PipelineServiceClient.
|
736
|
+
#
|
737
|
+
# We achieve the first by converting the v1 PipelineJob to a
|
738
|
+
# v1beta1 PipelineJob and the second by replacing the v1
|
739
|
+
# PipelineServiceClient with a v1beta1 PipelineServiceClient.
|
740
|
+
#
|
741
|
+
# TODO: Remove this once the v1 stable API is updated to support
|
742
|
+
# the PSC setting.
|
743
|
+
pipeline_job_dict = json_format.MessageToDict(
|
744
|
+
run._gca_resource._pb, preserving_proto_field_name=True
|
745
|
+
)
|
746
|
+
run._gca_resource = pipeline_job_v1beta1.PipelineJob(
|
747
|
+
**pipeline_job_dict,
|
748
|
+
psc_interface_config=PscInterfaceConfig(
|
749
|
+
network_attachment=self.config.private_service_connect,
|
750
|
+
),
|
751
|
+
)
|
752
|
+
run.api_client = (
|
753
|
+
pipeline_service_client_v1beta1.PipelineServiceClient(
|
754
|
+
credentials=run.credentials,
|
755
|
+
client_options={
|
756
|
+
"api_endpoint": run.api_client.api_endpoint,
|
757
|
+
},
|
758
|
+
)
|
759
|
+
)
|
760
|
+
|
740
761
|
try:
|
741
762
|
if schedule:
|
742
763
|
logger.info(
|
@@ -555,36 +555,14 @@ class KubeflowOrchestrator(ContainerizedOrchestrator):
|
|
555
555
|
)
|
556
556
|
pod_settings = step_settings.pod_settings
|
557
557
|
if pod_settings:
|
558
|
-
|
558
|
+
ignored_fields = pod_settings.model_fields_set - {
|
559
|
+
"node_selectors"
|
560
|
+
}
|
561
|
+
if ignored_fields:
|
559
562
|
logger.warning(
|
560
|
-
"
|
561
|
-
"
|
562
|
-
|
563
|
-
if pod_settings.affinity:
|
564
|
-
logger.warning(
|
565
|
-
"Affinity is set but not supported in Kubeflow with "
|
566
|
-
"Kubeflow Pipelines 2.x. Ignoring..."
|
567
|
-
)
|
568
|
-
if pod_settings.tolerations:
|
569
|
-
logger.warning(
|
570
|
-
"Tolerations are set but not supported in "
|
571
|
-
"Kubeflow with Kubeflow Pipelines 2.x. Ignoring..."
|
572
|
-
)
|
573
|
-
if pod_settings.volumes:
|
574
|
-
logger.warning(
|
575
|
-
"Volumes are set but not supported in Kubeflow with "
|
576
|
-
"Kubeflow Pipelines 2.x. Ignoring..."
|
577
|
-
)
|
578
|
-
if pod_settings.volume_mounts:
|
579
|
-
logger.warning(
|
580
|
-
"Volume mounts are set but not supported in "
|
581
|
-
"Kubeflow with Kubeflow Pipelines 2.x. Ignoring..."
|
582
|
-
)
|
583
|
-
if pod_settings.env or pod_settings.env_from:
|
584
|
-
logger.warning(
|
585
|
-
"Environment variables are set but not supported "
|
586
|
-
"in Kubeflow with Kubeflow Pipelines 2.x. "
|
587
|
-
"Ignoring..."
|
563
|
+
f"The following pod settings are not supported in "
|
564
|
+
f"Kubeflow with Kubeflow Pipelines 2.x and will be "
|
565
|
+
f"ignored: {list(ignored_fields)}."
|
588
566
|
)
|
589
567
|
|
590
568
|
# apply pod settings
|
@@ -15,6 +15,8 @@
|
|
15
15
|
|
16
16
|
from typing import TYPE_CHECKING, Optional, Type
|
17
17
|
|
18
|
+
from pydantic import PositiveInt
|
19
|
+
|
18
20
|
from zenml.config.base_settings import BaseSettings
|
19
21
|
from zenml.constants import KUBERNETES_CLUSTER_RESOURCE_TYPE
|
20
22
|
from zenml.integrations.kubernetes import KUBERNETES_ORCHESTRATOR_FLAVOR
|
@@ -47,6 +49,7 @@ class KubernetesOrchestratorSettings(BaseSettings):
|
|
47
49
|
pod_settings: Pod settings to apply to pods executing the steps.
|
48
50
|
orchestrator_pod_settings: Pod settings to apply to the pod which is
|
49
51
|
launching the actual steps.
|
52
|
+
pod_name_prefix: Prefix to use for the pod name.
|
50
53
|
pod_startup_timeout: The maximum time to wait for a pending step pod to
|
51
54
|
start (in seconds).
|
52
55
|
pod_failure_max_retries: The maximum number of times to retry a step
|
@@ -55,6 +58,7 @@ class KubernetesOrchestratorSettings(BaseSettings):
|
|
55
58
|
failure retries and pod startup retries (in seconds)
|
56
59
|
pod_failure_backoff: The backoff factor for pod failure retries and
|
57
60
|
pod startup retries.
|
61
|
+
max_parallelism: Maximum number of steps to run in parallel.
|
58
62
|
"""
|
59
63
|
|
60
64
|
synchronous: bool = True
|
@@ -64,10 +68,12 @@ class KubernetesOrchestratorSettings(BaseSettings):
|
|
64
68
|
privileged: bool = False
|
65
69
|
pod_settings: Optional[KubernetesPodSettings] = None
|
66
70
|
orchestrator_pod_settings: Optional[KubernetesPodSettings] = None
|
71
|
+
pod_name_prefix: Optional[str] = None
|
67
72
|
pod_startup_timeout: int = 60 * 10 # Default 10 minutes
|
68
73
|
pod_failure_max_retries: int = 3
|
69
74
|
pod_failure_retry_delay: int = 10
|
70
75
|
pod_failure_backoff: float = 1.0
|
76
|
+
max_parallelism: Optional[PositiveInt] = None
|
71
77
|
|
72
78
|
|
73
79
|
class KubernetesOrchestratorConfig(
|
@@ -417,6 +417,9 @@ class KubernetesOrchestrator(ContainerizedOrchestrator):
|
|
417
417
|
)
|
418
418
|
|
419
419
|
pipeline_name = deployment.pipeline_configuration.name
|
420
|
+
settings = cast(
|
421
|
+
KubernetesOrchestratorSettings, self.get_settings(deployment)
|
422
|
+
)
|
420
423
|
|
421
424
|
# We already make sure the orchestrator run name has the correct length
|
422
425
|
# to make sure we don't cut off the randomized suffix later when
|
@@ -427,8 +430,16 @@ class KubernetesOrchestrator(ContainerizedOrchestrator):
|
|
427
430
|
orchestrator_run_name = get_orchestrator_run_name(
|
428
431
|
pipeline_name, max_length=max_length
|
429
432
|
)
|
433
|
+
|
434
|
+
if settings.pod_name_prefix:
|
435
|
+
pod_name = get_orchestrator_run_name(
|
436
|
+
settings.pod_name_prefix, max_length=max_length
|
437
|
+
)
|
438
|
+
else:
|
439
|
+
pod_name = orchestrator_run_name
|
440
|
+
|
430
441
|
pod_name = kube_utils.sanitize_pod_name(
|
431
|
-
|
442
|
+
pod_name, namespace=self.config.kubernetes_namespace
|
432
443
|
)
|
433
444
|
|
434
445
|
assert stack.container_registry
|
@@ -455,10 +466,6 @@ class KubernetesOrchestrator(ContainerizedOrchestrator):
|
|
455
466
|
run_id=placeholder_run.id if placeholder_run else None,
|
456
467
|
)
|
457
468
|
|
458
|
-
settings = cast(
|
459
|
-
KubernetesOrchestratorSettings, self.get_settings(deployment)
|
460
|
-
)
|
461
|
-
|
462
469
|
# Authorize pod to run Kubernetes commands inside the cluster.
|
463
470
|
service_account_name = self._get_service_account_name(settings)
|
464
471
|
|