zenml-nightly 0.70.0.dev20241201__py3-none-any.whl → 0.71.0.dev20241223__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.
- README.md +4 -4
- RELEASE_NOTES.md +112 -0
- zenml/VERSION +1 -1
- zenml/artifacts/artifact_config.py +8 -5
- zenml/artifacts/utils.py +3 -1
- zenml/cli/__init__.py +4 -4
- zenml/cli/base.py +1 -1
- zenml/cli/pipeline.py +48 -79
- zenml/cli/server.py +19 -19
- zenml/client.py +54 -2
- zenml/config/secret_reference_mixin.py +1 -1
- zenml/config/server_config.py +4 -0
- zenml/constants.py +10 -0
- zenml/image_builders/base_image_builder.py +5 -2
- zenml/image_builders/build_context.py +7 -16
- zenml/integrations/aws/__init__.py +3 -0
- zenml/integrations/aws/flavors/__init__.py +6 -0
- zenml/integrations/aws/flavors/aws_image_builder_flavor.py +146 -0
- zenml/integrations/aws/image_builders/__init__.py +20 -0
- zenml/integrations/aws/image_builders/aws_image_builder.py +307 -0
- zenml/integrations/gcp/orchestrators/vertex_orchestrator.py +1 -1
- zenml/integrations/kaniko/image_builders/kaniko_image_builder.py +2 -1
- zenml/integrations/kubernetes/flavors/kubernetes_orchestrator_flavor.py +11 -0
- zenml/integrations/kubernetes/step_operators/kubernetes_step_operator.py +0 -1
- zenml/integrations/lightning/flavors/lightning_orchestrator_flavor.py +11 -0
- zenml/integrations/neptune/experiment_trackers/neptune_experiment_tracker.py +7 -5
- zenml/integrations/neptune/experiment_trackers/run_state.py +69 -53
- zenml/integrations/registry.py +2 -2
- zenml/integrations/skypilot/flavors/skypilot_orchestrator_base_vm_config.py +12 -0
- zenml/integrations/wandb/flavors/wandb_experiment_tracker_flavor.py +13 -5
- zenml/materializers/built_in_materializer.py +1 -1
- zenml/model/model.py +12 -16
- zenml/model/utils.py +3 -1
- zenml/models/v2/base/filter.py +26 -30
- zenml/models/v2/base/scoped.py +258 -5
- zenml/models/v2/core/artifact_version.py +15 -26
- zenml/models/v2/core/code_repository.py +1 -12
- zenml/models/v2/core/component.py +5 -46
- zenml/models/v2/core/flavor.py +1 -11
- zenml/models/v2/core/model.py +1 -57
- zenml/models/v2/core/model_version.py +5 -33
- zenml/models/v2/core/model_version_artifact.py +11 -3
- zenml/models/v2/core/model_version_pipeline_run.py +14 -3
- zenml/models/v2/core/pipeline.py +47 -55
- zenml/models/v2/core/pipeline_build.py +67 -12
- zenml/models/v2/core/pipeline_deployment.py +0 -10
- zenml/models/v2/core/pipeline_run.py +91 -29
- zenml/models/v2/core/run_template.py +21 -29
- zenml/models/v2/core/schedule.py +0 -10
- zenml/models/v2/core/secret.py +0 -14
- zenml/models/v2/core/service.py +9 -16
- zenml/models/v2/core/service_connector.py +0 -11
- zenml/models/v2/core/stack.py +21 -30
- zenml/models/v2/core/step_run.py +18 -14
- zenml/models/v2/core/trigger.py +19 -3
- zenml/orchestrators/base_orchestrator.py +13 -1
- zenml/orchestrators/output_utils.py +5 -1
- zenml/orchestrators/step_launcher.py +9 -13
- zenml/orchestrators/step_run_utils.py +8 -204
- zenml/orchestrators/utils.py +55 -27
- zenml/pipelines/build_utils.py +12 -0
- zenml/service_connectors/service_connector_utils.py +3 -9
- zenml/stack/stack_component.py +1 -1
- zenml/stack_deployments/aws_stack_deployment.py +22 -0
- zenml/utils/archivable.py +65 -36
- zenml/utils/code_utils.py +8 -4
- zenml/utils/docker_utils.py +9 -0
- zenml/zen_server/auth.py +9 -10
- zenml/zen_server/dashboard/assets/{404-NVXKFp-x.js → 404-Cqu3EDCm.js} +1 -1
- zenml/zen_server/dashboard/assets/{@reactflow-CK0KJUen.js → @reactflow-D2Y7BWwz.js} +1 -1
- zenml/zen_server/dashboard/assets/{AlertDialogDropdownItem-DezXKmDf.js → AlertDialogDropdownItem-BHd71pVS.js} +1 -1
- zenml/zen_server/dashboard/assets/{CodeSnippet-JzR8CEtw.js → CodeSnippet-DIonwetW.js} +1 -1
- zenml/zen_server/dashboard/assets/{CollapsibleCard-DQW_ktMO.js → CollapsibleCard-CDnC97pB.js} +1 -1
- zenml/zen_server/dashboard/assets/{Commands-DL2kwkRd.js → Commands-BVEXKAOj.js} +1 -1
- zenml/zen_server/dashboard/assets/{ComponentBadge-D_g62Wv8.js → ComponentBadge-CrRvovox.js} +1 -1
- zenml/zen_server/dashboard/assets/{CopyButton-LNcWaa14.js → CopyButton-B6wGAhQv.js} +1 -1
- zenml/zen_server/dashboard/assets/{CsvVizualization-DknpE5ej.js → CsvVizualization-CjcT7LMm.js} +5 -5
- zenml/zen_server/dashboard/assets/DeleteAlertDialog-D2ELtM2W.js +1 -0
- zenml/zen_server/dashboard/assets/{DialogItem-Bxf8FuAT.js → DialogItem-DXIMhBgU.js} +1 -1
- zenml/zen_server/dashboard/assets/{Error-DYflYyps.js → Error-B8uUfTpL.js} +1 -1
- zenml/zen_server/dashboard/assets/{ExecutionStatus-C7zyIQKZ.js → ExecutionStatus-ibAdY-dG.js} +1 -1
- zenml/zen_server/dashboard/assets/{Helpbox-oYSGpLqd.js → Helpbox-BfAfhKHw.js} +1 -1
- zenml/zen_server/dashboard/assets/{Infobox-Cx4xGoXR.js → Infobox-M_SMOu96.js} +1 -1
- zenml/zen_server/dashboard/assets/{InlineAvatar-DiGOWNKF.js → InlineAvatar-DBA0a0-a.js} +1 -1
- zenml/zen_server/dashboard/assets/{NestedCollapsible-DYbgyKxK.js → NestedCollapsible-DpgmEFKw.js} +1 -1
- zenml/zen_server/dashboard/assets/{Partials-03iZf8-N.js → Partials-D_ldD9if.js} +1 -1
- zenml/zen_server/dashboard/assets/{ProBadge-D_EB8HNo.js → ProBadge-DQbfFotM.js} +1 -1
- zenml/zen_server/dashboard/assets/{ProCta-DqNS4v3x.js → ProCta-Bcpb4rcY.js} +1 -1
- zenml/zen_server/dashboard/assets/{ProviderIcon-Bki2aw8w.js → ProviderIcon-BZpgPigN.js} +1 -1
- zenml/zen_server/dashboard/assets/{ProviderRadio-8f43sPD4.js → ProviderRadio-DWPnMuQ1.js} +1 -1
- zenml/zen_server/dashboard/assets/RunSelector-DgRGaAc6.js +1 -0
- zenml/zen_server/dashboard/assets/{RunsBody-07YEO7qI.js → RunsBody-KecfSkjY.js} +1 -1
- zenml/zen_server/dashboard/assets/{SearchField-lp1KgU4e.js → SearchField-n-ILHnaP.js} +1 -1
- zenml/zen_server/dashboard/assets/{SecretTooltip-CgnbyeOx.js → SecretTooltip-B8MrX5yu.js} +1 -1
- zenml/zen_server/dashboard/assets/{SetPassword-CpP418A2.js → SetPassword-B_IVq_wg.js} +1 -1
- zenml/zen_server/dashboard/assets/StackList-TWPBYnkF.js +1 -0
- zenml/zen_server/dashboard/assets/{Tabs-BktHkCJJ.js → Tabs-Rg857zmd.js} +1 -1
- zenml/zen_server/dashboard/assets/{Tick-BlMoIlJT.js → Tick-COg4A-xo.js} +1 -1
- zenml/zen_server/dashboard/assets/{UpdatePasswordSchemas-Sc0A0pP-.js → UpdatePasswordSchemas-C6Aj3hm6.js} +1 -1
- zenml/zen_server/dashboard/assets/{UsageReason-YYduL4fj.js → UsageReason-BTLbx7w4.js} +1 -1
- zenml/zen_server/dashboard/assets/{WizardFooter-dgmizSJC.js → WizardFooter-BCAj69Vj.js} +1 -1
- zenml/zen_server/dashboard/assets/{all-pipeline-runs-query-D-c2G6lV.js → all-pipeline-runs-query-DMXkDrV2.js} +1 -1
- zenml/zen_server/dashboard/assets/code-snippets-CqONne41.js +13 -0
- zenml/zen_server/dashboard/assets/{create-stack-DM_JPgef.js → create-stack-HfdbhLs4.js} +1 -1
- zenml/zen_server/dashboard/assets/dates-3pMLCNrD.js +1 -0
- zenml/zen_server/dashboard/assets/delete-run-DZ4hIXff.js +1 -0
- zenml/zen_server/dashboard/assets/{form-schemas-K6FYKjwa.js → form-schemas-B0AVEd9b.js} +1 -1
- zenml/zen_server/dashboard/assets/{index-BAkC7FXi.js → index-DPqSWjug.js} +1 -1
- zenml/zen_server/dashboard/assets/{index-CEV4Cvaf.js → index-DScjfBRb.js} +1 -1
- zenml/zen_server/dashboard/assets/index-DXvT1_Um.css +1 -0
- zenml/zen_server/dashboard/assets/{index-CCOPpudF.js → index-FO-p0GU7.js} +5 -5
- zenml/zen_server/dashboard/assets/{index-B1mVPYxf.js → index-I3bKUGUj.js} +1 -1
- zenml/zen_server/dashboard/assets/key-icon-aH-QIa5R.js +1 -0
- zenml/zen_server/dashboard/assets/login-command-CkqxPtV3.js +1 -0
- zenml/zen_server/dashboard/assets/{login-mutation-hf-lK87O.js → login-mutation-BQeo4wTY.js} +1 -1
- zenml/zen_server/dashboard/assets/{not-found-BGirLjU-.js → not-found-gAJ5aDdR.js} +1 -1
- zenml/zen_server/dashboard/assets/page-9Y9-gig0.js +1 -0
- zenml/zen_server/dashboard/assets/{page-DjRJCGb3.js → page-AUwiQ14W.js} +1 -1
- zenml/zen_server/dashboard/assets/page-B6XU7yYT.js +2 -0
- zenml/zen_server/dashboard/assets/{page-C00YAkaB.js → page-BKZYc2Zv.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-CdMWnQak.js → page-BU9FG4sR.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-D7S3aCbF.js → page-B_Apk3xg.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-Djikxq_S.js → page-BdowiCbr.js} +1 -1
- zenml/zen_server/dashboard/assets/page-Bg8OjTRe.js +1 -0
- zenml/zen_server/dashboard/assets/page-BxL4qD4_.js +1 -0
- zenml/zen_server/dashboard/assets/{page-DakHVWXF.js → page-CWxT5K5J.js} +1 -1
- zenml/zen_server/dashboard/assets/page-CXuQufSe.js +1 -0
- zenml/zen_server/dashboard/assets/{page-DLC-bNBP.js → page-CcQr8CPP.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-CD-DcWoy.js → page-Ce4Hrjnr.js} +1 -1
- zenml/zen_server/dashboard/assets/page-CiYxgZP_.js +1 -0
- zenml/zen_server/dashboard/assets/page-Cldq1mpe.js +1 -0
- zenml/zen_server/dashboard/assets/{page-BDigxVpo.js → page-D4wdonLm.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-D6uU2ax4.js → page-D8ObrbH8.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-DXSTpqRD.js → page-DFuAUGt4.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-CbpvrsDL.js → page-DGazBpuP.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-COXXJj1k.js → page-DO1UcqPX.js} +1 -1
- zenml/zen_server/dashboard/assets/page-DRYXdL5o.js +1 -0
- zenml/zen_server/dashboard/assets/{page-Df-Fw0aq.js → page-DYEquBC2.js} +1 -1
- zenml/zen_server/dashboard/assets/page-Dk32IeZm.js +1 -0
- zenml/zen_server/dashboard/assets/{page-yYC9OI-E.js → page-I3nKFGie.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-6m6yHHlE.js → page-M0w-n6vn.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-Vcxara9U.js → page-R5dx3xGF.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-BR68V0V1.js → page-bT5pOvcB.js} +1 -1
- zenml/zen_server/dashboard/assets/page-hUqK889I.js +6 -0
- zenml/zen_server/dashboard/assets/{page-CjGdWY13.js → page-h_Stveon.js} +1 -1
- zenml/zen_server/dashboard/assets/{page-D01JhjQB.js → page-r8XK5vR7.js} +1 -1
- zenml/zen_server/dashboard/assets/page-u_-ZXBKb.js +1 -0
- zenml/zen_server/dashboard/assets/page-zaMqB_ao.js +1 -0
- zenml/zen_server/dashboard/assets/{persist-GjC8PZoC.js → persist-AppN1B0J.js} +1 -1
- zenml/zen_server/dashboard/assets/{persist-Coz7ZWvz.js → persist-DAUi_3za.js} +1 -1
- zenml/zen_server/dashboard/assets/service-BqqeXLEe.js +2 -0
- zenml/zen_server/dashboard/assets/{sharedSchema-CQb14VSr.js → sharedSchema-uXN9FLLk.js} +1 -1
- zenml/zen_server/dashboard/assets/{stack-detail-query-OPEW-cDJ.js → stack-detail-query-XfZBiBP2.js} +1 -1
- zenml/zen_server/dashboard/assets/{update-server-settings-mutation-LwuQfHYn.js → update-server-settings-mutation-BWmgVJwA.js} +1 -1
- zenml/zen_server/dashboard/assets/{url-CkvKAnwF.js → url-BLwMbzES.js} +1 -1
- zenml/zen_server/dashboard/index.html +4 -4
- zenml/zen_server/deploy/helm/Chart.yaml +1 -1
- zenml/zen_server/deploy/helm/README.md +2 -2
- zenml/zen_server/rbac/rbac_sql_zen_store.py +173 -0
- zenml/zen_server/routers/auth_endpoints.py +22 -11
- zenml/zen_server/routers/steps_endpoints.py +7 -1
- zenml/zen_server/template_execution/utils.py +3 -1
- zenml/zen_server/utils.py +4 -3
- zenml/zen_stores/base_zen_store.py +10 -2
- zenml/zen_stores/migrations/versions/0.71.0_release.py +23 -0
- zenml/zen_stores/migrations/versions/26351d482b9e_add_step_run_unique_constraint.py +37 -0
- zenml/zen_stores/migrations/versions/a1237ba94fd8_add_model_version_producer_run_unique_.py +68 -0
- zenml/zen_stores/rest_zen_store.py +76 -43
- zenml/zen_stores/schemas/model_schemas.py +42 -6
- zenml/zen_stores/schemas/pipeline_deployment_schemas.py +7 -7
- zenml/zen_stores/schemas/pipeline_run_schemas.py +12 -6
- zenml/zen_stores/schemas/pipeline_schemas.py +5 -0
- zenml/zen_stores/schemas/step_run_schemas.py +8 -1
- zenml/zen_stores/sql_zen_store.py +332 -100
- {zenml_nightly-0.70.0.dev20241201.dist-info → zenml_nightly-0.71.0.dev20241223.dist-info}/METADATA +5 -5
- {zenml_nightly-0.70.0.dev20241201.dist-info → zenml_nightly-0.71.0.dev20241223.dist-info}/RECORD +179 -164
- zenml/zen_server/dashboard/assets/RunSelector-DkPiIiNr.js +0 -1
- zenml/zen_server/dashboard/assets/StackList-WvuKQusZ.js +0 -1
- zenml/zen_server/dashboard/assets/delete-run-CJdh1P_h.js +0 -1
- zenml/zen_server/dashboard/assets/index-DlGvJQPn.css +0 -1
- zenml/zen_server/dashboard/assets/page-0JE_-Ec1.js +0 -1
- zenml/zen_server/dashboard/assets/page-BRLpxOt0.js +0 -1
- zenml/zen_server/dashboard/assets/page-BU7huvKw.js +0 -6
- zenml/zen_server/dashboard/assets/page-BvqLv2Ky.js +0 -1
- zenml/zen_server/dashboard/assets/page-CwxrFarU.js +0 -1
- zenml/zen_server/dashboard/assets/page-DfbXf_8s.js +0 -1
- zenml/zen_server/dashboard/assets/page-Dnovpa0i.js +0 -3
- zenml/zen_server/dashboard/assets/page-Dot3LPmL.js +0 -1
- zenml/zen_server/dashboard/assets/page-Xynx4btY.js +0 -14
- zenml/zen_server/dashboard/assets/page-YpKAqVSa.js +0 -1
- {zenml_nightly-0.70.0.dev20241201.dist-info → zenml_nightly-0.71.0.dev20241223.dist-info}/LICENSE +0 -0
- {zenml_nightly-0.70.0.dev20241201.dist-info → zenml_nightly-0.71.0.dev20241223.dist-info}/WHEEL +0 -0
- {zenml_nightly-0.70.0.dev20241201.dist-info → zenml_nightly-0.71.0.dev20241223.dist-info}/entry_points.txt +0 -0
@@ -55,7 +55,7 @@ from pydantic import (
|
|
55
55
|
field_validator,
|
56
56
|
model_validator,
|
57
57
|
)
|
58
|
-
from sqlalchemy import
|
58
|
+
from sqlalchemy import func
|
59
59
|
from sqlalchemy.engine import URL, Engine, make_url
|
60
60
|
from sqlalchemy.exc import (
|
61
61
|
ArgumentError,
|
@@ -71,6 +71,7 @@ from sqlmodel import (
|
|
71
71
|
col,
|
72
72
|
create_engine,
|
73
73
|
delete,
|
74
|
+
desc,
|
74
75
|
or_,
|
75
76
|
select,
|
76
77
|
)
|
@@ -100,7 +101,6 @@ from zenml.constants import (
|
|
100
101
|
ENV_ZENML_SERVER,
|
101
102
|
FINISHED_ONBOARDING_SURVEY_KEY,
|
102
103
|
MAX_RETRIES_FOR_VERSIONED_ENTITY_CREATION,
|
103
|
-
SORT_PIPELINES_BY_LATEST_RUN_KEY,
|
104
104
|
SQL_STORE_BACKUP_DIRECTORY_NAME,
|
105
105
|
TEXT_FIELD_MAX_LENGTH,
|
106
106
|
handle_bool_env_var,
|
@@ -117,7 +117,6 @@ from zenml.enums import (
|
|
117
117
|
OnboardingStep,
|
118
118
|
SecretScope,
|
119
119
|
SecretsStoreType,
|
120
|
-
SorterOps,
|
121
120
|
StackComponentType,
|
122
121
|
StackDeploymentProvider,
|
123
122
|
StepRunInputArtifactType,
|
@@ -298,7 +297,11 @@ from zenml.utils.networking_utils import (
|
|
298
297
|
replace_localhost_with_internal_hostname,
|
299
298
|
)
|
300
299
|
from zenml.utils.pydantic_utils import before_validator_handler
|
301
|
-
from zenml.utils.string_utils import
|
300
|
+
from zenml.utils.string_utils import (
|
301
|
+
format_name_template,
|
302
|
+
random_str,
|
303
|
+
validate_name,
|
304
|
+
)
|
302
305
|
from zenml.zen_stores import template_utils
|
303
306
|
from zenml.zen_stores.base_zen_store import (
|
304
307
|
BaseZenStore,
|
@@ -4358,69 +4361,14 @@ class SqlZenStore(BaseZenStore):
|
|
4358
4361
|
Returns:
|
4359
4362
|
A list of all pipelines matching the filter criteria.
|
4360
4363
|
"""
|
4361
|
-
query: Union[Select[Any], SelectOfScalar[Any]] = select(PipelineSchema)
|
4362
|
-
_custom_conversion: Optional[Callable[[Any], PipelineResponse]] = None
|
4363
|
-
|
4364
|
-
column, operand = pipeline_filter_model.sorting_params
|
4365
|
-
if column == SORT_PIPELINES_BY_LATEST_RUN_KEY:
|
4366
|
-
with Session(self.engine) as session:
|
4367
|
-
max_date_subquery = (
|
4368
|
-
# If no run exists for the pipeline yet, we use the pipeline
|
4369
|
-
# creation date as a fallback, otherwise newly created
|
4370
|
-
# pipeline would always be at the top/bottom
|
4371
|
-
select(
|
4372
|
-
PipelineSchema.id,
|
4373
|
-
case(
|
4374
|
-
(
|
4375
|
-
func.max(PipelineRunSchema.created).is_(None),
|
4376
|
-
PipelineSchema.created,
|
4377
|
-
),
|
4378
|
-
else_=func.max(PipelineRunSchema.created),
|
4379
|
-
).label("run_or_created"),
|
4380
|
-
)
|
4381
|
-
.outerjoin(
|
4382
|
-
PipelineRunSchema,
|
4383
|
-
PipelineSchema.id == PipelineRunSchema.pipeline_id, # type: ignore[arg-type]
|
4384
|
-
)
|
4385
|
-
.group_by(col(PipelineSchema.id))
|
4386
|
-
.subquery()
|
4387
|
-
)
|
4388
|
-
|
4389
|
-
if operand == SorterOps.DESCENDING:
|
4390
|
-
sort_clause = desc
|
4391
|
-
else:
|
4392
|
-
sort_clause = asc
|
4393
|
-
|
4394
|
-
query = (
|
4395
|
-
# We need to include the subquery in the select here to
|
4396
|
-
# make this query work with the distinct statement. This
|
4397
|
-
# result will be removed in the custom conversion function
|
4398
|
-
# applied later
|
4399
|
-
select(PipelineSchema, max_date_subquery.c.run_or_created)
|
4400
|
-
.where(PipelineSchema.id == max_date_subquery.c.id)
|
4401
|
-
.order_by(sort_clause(max_date_subquery.c.run_or_created))
|
4402
|
-
# We always add the `id` column as a tiebreaker to ensure a
|
4403
|
-
# stable, repeatable order of items, otherwise subsequent
|
4404
|
-
# pages might contain the same items.
|
4405
|
-
.order_by(col(PipelineSchema.id))
|
4406
|
-
)
|
4407
|
-
|
4408
|
-
def _custom_conversion(row: Any) -> PipelineResponse:
|
4409
|
-
return cast(
|
4410
|
-
PipelineResponse,
|
4411
|
-
row[0].to_model(
|
4412
|
-
include_metadata=hydrate, include_resources=True
|
4413
|
-
),
|
4414
|
-
)
|
4415
|
-
|
4416
4364
|
with Session(self.engine) as session:
|
4365
|
+
query = select(PipelineSchema)
|
4417
4366
|
return self.filter_and_paginate(
|
4418
4367
|
session=session,
|
4419
4368
|
query=query,
|
4420
4369
|
table=PipelineSchema,
|
4421
4370
|
filter_model=pipeline_filter_model,
|
4422
4371
|
hydrate=hydrate,
|
4423
|
-
custom_schema_to_model_conversion=_custom_conversion,
|
4424
4372
|
)
|
4425
4373
|
|
4426
4374
|
def count_pipelines(self, filter_model: Optional[PipelineFilter]) -> int:
|
@@ -5211,6 +5159,20 @@ class SqlZenStore(BaseZenStore):
|
|
5211
5159
|
"already exists."
|
5212
5160
|
)
|
5213
5161
|
|
5162
|
+
if model_version_id := self._get_or_create_model_version_for_run(
|
5163
|
+
new_run
|
5164
|
+
):
|
5165
|
+
new_run.model_version_id = model_version_id
|
5166
|
+
session.add(new_run)
|
5167
|
+
session.commit()
|
5168
|
+
|
5169
|
+
self.create_model_version_pipeline_run_link(
|
5170
|
+
ModelVersionPipelineRunRequest(
|
5171
|
+
model_version=model_version_id, pipeline_run=new_run.id
|
5172
|
+
)
|
5173
|
+
)
|
5174
|
+
session.refresh(new_run)
|
5175
|
+
|
5214
5176
|
return new_run.to_model(
|
5215
5177
|
include_metadata=True, include_resources=True
|
5216
5178
|
)
|
@@ -8167,25 +8129,17 @@ class SqlZenStore(BaseZenStore):
|
|
8167
8129
|
f"with ID '{step_run.pipeline_run_id}' found."
|
8168
8130
|
)
|
8169
8131
|
|
8170
|
-
|
8171
|
-
|
8172
|
-
|
8173
|
-
.
|
8174
|
-
|
8175
|
-
StepRunSchema.pipeline_run_id == step_run.pipeline_run_id
|
8176
|
-
)
|
8177
|
-
).first()
|
8178
|
-
if existing_step_run is not None:
|
8132
|
+
step_schema = StepRunSchema.from_request(step_run)
|
8133
|
+
session.add(step_schema)
|
8134
|
+
try:
|
8135
|
+
session.commit()
|
8136
|
+
except IntegrityError:
|
8179
8137
|
raise EntityExistsError(
|
8180
8138
|
f"Unable to create step `{step_run.name}`: A step with "
|
8181
8139
|
f"this name already exists in the pipeline run with ID "
|
8182
8140
|
f"'{step_run.pipeline_run_id}'."
|
8183
8141
|
)
|
8184
8142
|
|
8185
|
-
# Create the step
|
8186
|
-
step_schema = StepRunSchema.from_request(step_run)
|
8187
|
-
session.add(step_schema)
|
8188
|
-
|
8189
8143
|
# Add logs entry for the step if exists
|
8190
8144
|
if step_run.logs is not None:
|
8191
8145
|
log_entry = LogsSchema(
|
@@ -8281,6 +8235,21 @@ class SqlZenStore(BaseZenStore):
|
|
8281
8235
|
session.commit()
|
8282
8236
|
session.refresh(step_schema)
|
8283
8237
|
|
8238
|
+
if model_version_id := self._get_or_create_model_version_for_run(
|
8239
|
+
step_schema
|
8240
|
+
):
|
8241
|
+
step_schema.model_version_id = model_version_id
|
8242
|
+
session.add(step_schema)
|
8243
|
+
session.commit()
|
8244
|
+
|
8245
|
+
self.create_model_version_pipeline_run_link(
|
8246
|
+
ModelVersionPipelineRunRequest(
|
8247
|
+
model_version=model_version_id,
|
8248
|
+
pipeline_run=step_schema.pipeline_run_id,
|
8249
|
+
)
|
8250
|
+
)
|
8251
|
+
session.refresh(step_schema)
|
8252
|
+
|
8284
8253
|
return step_schema.to_model(
|
8285
8254
|
include_metadata=True, include_resources=True
|
8286
8255
|
)
|
@@ -8633,7 +8602,11 @@ class SqlZenStore(BaseZenStore):
|
|
8633
8602
|
|
8634
8603
|
# Deployment always exists for pipeline runs of newer versions
|
8635
8604
|
assert pipeline_run.deployment
|
8636
|
-
num_steps = len(
|
8605
|
+
num_steps = len(
|
8606
|
+
pipeline_run.deployment.to_model(
|
8607
|
+
include_metadata=True
|
8608
|
+
).step_configurations
|
8609
|
+
)
|
8637
8610
|
new_status = get_pipeline_run_status(
|
8638
8611
|
step_statuses=[
|
8639
8612
|
ExecutionStatus(step_run.status) for step_run in step_runs
|
@@ -10279,6 +10252,22 @@ class SqlZenStore(BaseZenStore):
|
|
10279
10252
|
|
10280
10253
|
# ----------------------------- Model Versions -----------------------------
|
10281
10254
|
|
10255
|
+
def _get_or_create_model(
|
10256
|
+
self, model_request: ModelRequest
|
10257
|
+
) -> Tuple[bool, ModelResponse]:
|
10258
|
+
"""Get or create a model.
|
10259
|
+
|
10260
|
+
Args:
|
10261
|
+
model_request: The model request.
|
10262
|
+
|
10263
|
+
Returns:
|
10264
|
+
A boolean whether the model was created or not, and the model.
|
10265
|
+
"""
|
10266
|
+
try:
|
10267
|
+
return True, self.create_model(model_request)
|
10268
|
+
except EntityExistsError:
|
10269
|
+
return False, self.get_model(model_request.name)
|
10270
|
+
|
10282
10271
|
def _get_next_numeric_version_for_model(
|
10283
10272
|
self, session: Session, model_id: UUID
|
10284
10273
|
) -> int:
|
@@ -10303,55 +10292,276 @@ class SqlZenStore(BaseZenStore):
|
|
10303
10292
|
else:
|
10304
10293
|
return int(current_max_version) + 1
|
10305
10294
|
|
10306
|
-
def _model_version_exists(
|
10295
|
+
def _model_version_exists(
|
10296
|
+
self,
|
10297
|
+
model_id: UUID,
|
10298
|
+
version: Optional[str] = None,
|
10299
|
+
producer_run_id: Optional[UUID] = None,
|
10300
|
+
) -> bool:
|
10307
10301
|
"""Check if a model version with a certain version exists.
|
10308
10302
|
|
10309
10303
|
Args:
|
10310
10304
|
model_id: The model ID of the version.
|
10311
10305
|
version: The version name.
|
10306
|
+
producer_run_id: The producer run ID. If given, checks if a numeric
|
10307
|
+
version for the producer run exists.
|
10312
10308
|
|
10313
10309
|
Returns:
|
10314
|
-
If a model version
|
10310
|
+
If a model version for the given arguments exists.
|
10315
10311
|
"""
|
10312
|
+
query = select(ModelVersionSchema.id).where(
|
10313
|
+
ModelVersionSchema.model_id == model_id
|
10314
|
+
)
|
10315
|
+
|
10316
|
+
if version:
|
10317
|
+
query = query.where(ModelVersionSchema.name == version)
|
10318
|
+
|
10319
|
+
if producer_run_id:
|
10320
|
+
query = query.where(
|
10321
|
+
ModelVersionSchema.producer_run_id_if_numeric
|
10322
|
+
== producer_run_id,
|
10323
|
+
)
|
10324
|
+
|
10316
10325
|
with Session(self.engine) as session:
|
10317
|
-
return (
|
10318
|
-
|
10319
|
-
|
10320
|
-
|
10321
|
-
|
10322
|
-
|
10323
|
-
|
10326
|
+
return session.exec(query).first() is not None
|
10327
|
+
|
10328
|
+
def _get_model_version(
|
10329
|
+
self,
|
10330
|
+
model_id: UUID,
|
10331
|
+
version_name: Optional[str] = None,
|
10332
|
+
producer_run_id: Optional[UUID] = None,
|
10333
|
+
) -> ModelVersionResponse:
|
10334
|
+
"""Get a model version.
|
10335
|
+
|
10336
|
+
Args:
|
10337
|
+
model_id: The ID of the model.
|
10338
|
+
version_name: The name of the model version.
|
10339
|
+
producer_run_id: The ID of the producer pipeline run. If this is
|
10340
|
+
set, only numeric versions created as part of the pipeline run
|
10341
|
+
will be returned.
|
10342
|
+
|
10343
|
+
Raises:
|
10344
|
+
ValueError: If no version name or producer run ID was provided.
|
10345
|
+
KeyError: If no model version was found.
|
10346
|
+
|
10347
|
+
Returns:
|
10348
|
+
The model version.
|
10349
|
+
"""
|
10350
|
+
query = select(ModelVersionSchema).where(
|
10351
|
+
ModelVersionSchema.model_id == model_id
|
10352
|
+
)
|
10353
|
+
|
10354
|
+
if version_name:
|
10355
|
+
if version_name.isnumeric():
|
10356
|
+
query = query.where(
|
10357
|
+
ModelVersionSchema.number == int(version_name)
|
10358
|
+
)
|
10359
|
+
error_text = (
|
10360
|
+
f"No version with number {version_name} found "
|
10361
|
+
f"for model {model_id}."
|
10362
|
+
)
|
10363
|
+
elif version_name in ModelStages.values():
|
10364
|
+
if version_name == ModelStages.LATEST:
|
10365
|
+
query = query.order_by(
|
10366
|
+
desc(col(ModelVersionSchema.number))
|
10367
|
+
).limit(1)
|
10368
|
+
else:
|
10369
|
+
query = query.where(
|
10370
|
+
ModelVersionSchema.stage == version_name
|
10371
|
+
)
|
10372
|
+
error_text = (
|
10373
|
+
f"No {version_name} stage version found for "
|
10374
|
+
f"model {model_id}."
|
10375
|
+
)
|
10376
|
+
else:
|
10377
|
+
query = query.where(ModelVersionSchema.name == version_name)
|
10378
|
+
error_text = (
|
10379
|
+
f"No {version_name} version found for model {model_id}."
|
10380
|
+
)
|
10381
|
+
|
10382
|
+
elif producer_run_id:
|
10383
|
+
query = query.where(
|
10384
|
+
ModelVersionSchema.producer_run_id_if_numeric
|
10385
|
+
== producer_run_id,
|
10386
|
+
)
|
10387
|
+
error_text = (
|
10388
|
+
f"No numeric model version found for model {model_id} "
|
10389
|
+
f"and producer run {producer_run_id}."
|
10390
|
+
)
|
10391
|
+
else:
|
10392
|
+
raise ValueError(
|
10393
|
+
"Version name or producer run id need to be specified."
|
10324
10394
|
)
|
10325
10395
|
|
10326
|
-
|
10327
|
-
|
10328
|
-
|
10396
|
+
with Session(self.engine) as session:
|
10397
|
+
schema = session.exec(query).one_or_none()
|
10398
|
+
|
10399
|
+
if not schema:
|
10400
|
+
raise KeyError(error_text)
|
10401
|
+
|
10402
|
+
return schema.to_model(
|
10403
|
+
include_metadata=True, include_resources=True
|
10404
|
+
)
|
10405
|
+
|
10406
|
+
def _get_or_create_model_version(
|
10407
|
+
self,
|
10408
|
+
model_version_request: ModelVersionRequest,
|
10409
|
+
producer_run_id: Optional[UUID] = None,
|
10410
|
+
) -> Tuple[bool, ModelVersionResponse]:
|
10411
|
+
"""Get or create a model version.
|
10412
|
+
|
10413
|
+
Args:
|
10414
|
+
model_version_request: The model version request.
|
10415
|
+
producer_run_id: ID of the producer pipeline run.
|
10416
|
+
|
10417
|
+
Raises:
|
10418
|
+
EntityCreationError: If the model version creation failed.
|
10419
|
+
|
10420
|
+
Returns:
|
10421
|
+
A boolean whether the model version was created or not, and the
|
10422
|
+
model version.
|
10423
|
+
"""
|
10424
|
+
try:
|
10425
|
+
model_version = self._create_model_version(
|
10426
|
+
model_version=model_version_request,
|
10427
|
+
producer_run_id=producer_run_id,
|
10428
|
+
)
|
10429
|
+
track(event=AnalyticsEvent.CREATED_MODEL_VERSION)
|
10430
|
+
return True, model_version
|
10431
|
+
except EntityCreationError:
|
10432
|
+
# Need to explicitly re-raise this here as otherwise the catching
|
10433
|
+
# of the RuntimeError would include this
|
10434
|
+
raise
|
10435
|
+
except RuntimeError:
|
10436
|
+
return False, self._get_model_version(
|
10437
|
+
model_id=model_version_request.model,
|
10438
|
+
producer_run_id=producer_run_id,
|
10439
|
+
)
|
10440
|
+
except EntityExistsError:
|
10441
|
+
return False, self._get_model_version(
|
10442
|
+
model_id=model_version_request.model,
|
10443
|
+
version_name=model_version_request.name,
|
10444
|
+
)
|
10445
|
+
|
10446
|
+
def _get_or_create_model_version_for_run(
|
10447
|
+
self, pipeline_or_step_run: Union[PipelineRunSchema, StepRunSchema]
|
10448
|
+
) -> Optional[UUID]:
|
10449
|
+
"""Get or create a model version for a pipeline or step run.
|
10450
|
+
|
10451
|
+
Args:
|
10452
|
+
pipeline_or_step_run: The pipeline or step run for which to create
|
10453
|
+
the model version.
|
10454
|
+
|
10455
|
+
Returns:
|
10456
|
+
The model version.
|
10457
|
+
"""
|
10458
|
+
if isinstance(pipeline_or_step_run, PipelineRunSchema):
|
10459
|
+
producer_run_id = pipeline_or_step_run.id
|
10460
|
+
pipeline_run = pipeline_or_step_run.to_model(include_metadata=True)
|
10461
|
+
configured_model = pipeline_run.config.model
|
10462
|
+
substitutions = pipeline_run.config.substitutions
|
10463
|
+
else:
|
10464
|
+
producer_run_id = pipeline_or_step_run.pipeline_run_id
|
10465
|
+
step_run = pipeline_or_step_run.to_model(include_metadata=True)
|
10466
|
+
configured_model = step_run.config.model
|
10467
|
+
substitutions = step_run.config.substitutions
|
10468
|
+
|
10469
|
+
if not configured_model:
|
10470
|
+
return None
|
10471
|
+
|
10472
|
+
model_request = ModelRequest(
|
10473
|
+
name=format_name_template(
|
10474
|
+
configured_model.name, substitutions=substitutions
|
10475
|
+
),
|
10476
|
+
license=configured_model.license,
|
10477
|
+
description=configured_model.description,
|
10478
|
+
audience=configured_model.audience,
|
10479
|
+
use_cases=configured_model.use_cases,
|
10480
|
+
limitations=configured_model.limitations,
|
10481
|
+
trade_offs=configured_model.trade_offs,
|
10482
|
+
ethics=configured_model.ethics,
|
10483
|
+
save_models_to_registry=configured_model.save_models_to_registry,
|
10484
|
+
user=pipeline_or_step_run.user_id,
|
10485
|
+
workspace=pipeline_or_step_run.workspace_id,
|
10486
|
+
)
|
10487
|
+
|
10488
|
+
_, model_response = self._get_or_create_model(
|
10489
|
+
model_request=model_request
|
10490
|
+
)
|
10491
|
+
|
10492
|
+
version_name = None
|
10493
|
+
if configured_model.version is not None:
|
10494
|
+
version_name = format_name_template(
|
10495
|
+
str(configured_model.version), substitutions=substitutions
|
10496
|
+
)
|
10497
|
+
|
10498
|
+
# If the model version was specified to be a numeric version or
|
10499
|
+
# stage we don't try to create it (which will fail because it is not
|
10500
|
+
# allowed) but try to fetch it immediately
|
10501
|
+
if (
|
10502
|
+
version_name.isnumeric()
|
10503
|
+
or version_name in ModelStages.values()
|
10504
|
+
):
|
10505
|
+
return self._get_model_version(
|
10506
|
+
model_id=model_response.id, version_name=version_name
|
10507
|
+
).id
|
10508
|
+
|
10509
|
+
model_version_request = ModelVersionRequest(
|
10510
|
+
model=model_response.id,
|
10511
|
+
name=version_name,
|
10512
|
+
description=configured_model.description,
|
10513
|
+
tags=configured_model.tags,
|
10514
|
+
user=pipeline_or_step_run.user_id,
|
10515
|
+
workspace=pipeline_or_step_run.workspace_id,
|
10516
|
+
)
|
10517
|
+
|
10518
|
+
_, model_version_response = self._get_or_create_model_version(
|
10519
|
+
model_version_request=model_version_request,
|
10520
|
+
producer_run_id=producer_run_id,
|
10521
|
+
)
|
10522
|
+
return model_version_response.id
|
10523
|
+
|
10524
|
+
def _create_model_version(
|
10525
|
+
self,
|
10526
|
+
model_version: ModelVersionRequest,
|
10527
|
+
producer_run_id: Optional[UUID] = None,
|
10329
10528
|
) -> ModelVersionResponse:
|
10330
10529
|
"""Creates a new model version.
|
10331
10530
|
|
10332
10531
|
Args:
|
10333
10532
|
model_version: the Model Version to be created.
|
10533
|
+
producer_run_id: ID of the pipeline run that produced this model
|
10534
|
+
version.
|
10334
10535
|
|
10335
10536
|
Returns:
|
10336
10537
|
The newly created model version.
|
10337
10538
|
|
10338
10539
|
Raises:
|
10339
|
-
ValueError: If
|
10540
|
+
ValueError: If the requested version name is invalid.
|
10340
10541
|
EntityExistsError: If a model version with the given name already
|
10341
10542
|
exists.
|
10342
10543
|
EntityCreationError: If the model version creation failed.
|
10544
|
+
RuntimeError: If an auto-incremented model version already exists
|
10545
|
+
for the producer run.
|
10343
10546
|
"""
|
10344
|
-
|
10345
|
-
|
10346
|
-
|
10347
|
-
)
|
10547
|
+
has_custom_name = False
|
10548
|
+
if model_version.name:
|
10549
|
+
has_custom_name = True
|
10550
|
+
validate_name(model_version)
|
10348
10551
|
|
10349
|
-
|
10552
|
+
if model_version.name.isnumeric():
|
10553
|
+
raise ValueError(
|
10554
|
+
"Can't create model version with custom numeric model "
|
10555
|
+
"version name."
|
10556
|
+
)
|
10350
10557
|
|
10351
|
-
|
10352
|
-
|
10353
|
-
|
10558
|
+
if str(model_version.name).lower() in ModelStages.values():
|
10559
|
+
raise ValueError(
|
10560
|
+
"Can't create model version with a name that is used as a "
|
10561
|
+
f"model version stage ({ModelStages.values()})."
|
10562
|
+
)
|
10354
10563
|
|
10564
|
+
model = self.get_model(model_version.model)
|
10355
10565
|
model_version_id = None
|
10356
10566
|
|
10357
10567
|
remaining_tries = MAX_RETRIES_FOR_VERSIONED_ENTITY_CREATION
|
@@ -10359,17 +10569,19 @@ class SqlZenStore(BaseZenStore):
|
|
10359
10569
|
remaining_tries -= 1
|
10360
10570
|
try:
|
10361
10571
|
with Session(self.engine) as session:
|
10362
|
-
|
10572
|
+
model_version_number = (
|
10363
10573
|
self._get_next_numeric_version_for_model(
|
10364
10574
|
session=session,
|
10365
10575
|
model_id=model.id,
|
10366
10576
|
)
|
10367
10577
|
)
|
10368
10578
|
if not has_custom_name:
|
10369
|
-
model_version.name = str(
|
10579
|
+
model_version.name = str(model_version_number)
|
10370
10580
|
|
10371
10581
|
model_version_schema = ModelVersionSchema.from_request(
|
10372
|
-
model_version
|
10582
|
+
model_version,
|
10583
|
+
model_version_number=model_version_number,
|
10584
|
+
producer_run_id=producer_run_id,
|
10373
10585
|
)
|
10374
10586
|
session.add(model_version_schema)
|
10375
10587
|
session.commit()
|
@@ -10390,6 +10602,13 @@ class SqlZenStore(BaseZenStore):
|
|
10390
10602
|
f"{model_version.name}): A model with the "
|
10391
10603
|
"same name and version already exists."
|
10392
10604
|
)
|
10605
|
+
elif producer_run_id and self._model_version_exists(
|
10606
|
+
model_id=model.id, producer_run_id=producer_run_id
|
10607
|
+
):
|
10608
|
+
raise RuntimeError(
|
10609
|
+
"Auto-incremented model version already exists for "
|
10610
|
+
f"producer run {producer_run_id}."
|
10611
|
+
)
|
10393
10612
|
elif remaining_tries == 0:
|
10394
10613
|
raise EntityCreationError(
|
10395
10614
|
f"Failed to create version for model "
|
@@ -10408,10 +10627,9 @@ class SqlZenStore(BaseZenStore):
|
|
10408
10627
|
)
|
10409
10628
|
logger.debug(
|
10410
10629
|
"Failed to create model version %s "
|
10411
|
-
"
|
10630
|
+
"due to an integrity error. "
|
10412
10631
|
"Retrying in %f seconds.",
|
10413
10632
|
model.name,
|
10414
|
-
model_version.number,
|
10415
10633
|
sleep_duration,
|
10416
10634
|
)
|
10417
10635
|
time.sleep(sleep_duration)
|
@@ -10426,6 +10644,20 @@ class SqlZenStore(BaseZenStore):
|
|
10426
10644
|
|
10427
10645
|
return self.get_model_version(model_version_id)
|
10428
10646
|
|
10647
|
+
@track_decorator(AnalyticsEvent.CREATED_MODEL_VERSION)
|
10648
|
+
def create_model_version(
|
10649
|
+
self, model_version: ModelVersionRequest
|
10650
|
+
) -> ModelVersionResponse:
|
10651
|
+
"""Creates a new model version.
|
10652
|
+
|
10653
|
+
Args:
|
10654
|
+
model_version: the Model Version to be created.
|
10655
|
+
|
10656
|
+
Returns:
|
10657
|
+
The newly created model version.
|
10658
|
+
"""
|
10659
|
+
return self._create_model_version(model_version=model_version)
|
10660
|
+
|
10429
10661
|
def get_model_version(
|
10430
10662
|
self, model_version_id: UUID, hydrate: bool = True
|
10431
10663
|
) -> ModelVersionResponse:
|
{zenml_nightly-0.70.0.dev20241201.dist-info → zenml_nightly-0.71.0.dev20241223.dist-info}/METADATA
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: zenml-nightly
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.71.0.dev20241223
|
4
4
|
Summary: ZenML: Write production-ready ML code.
|
5
5
|
Home-page: https://zenml.io
|
6
6
|
License: Apache-2.0
|
@@ -288,7 +288,7 @@ Or, through our CLI command:
|
|
288
288
|
zenml stack deploy --provider aws
|
289
289
|
```
|
290
290
|
|
291
|
-
Alternatively, if the necessary pieces of infrastructure
|
291
|
+
Alternatively, if the necessary pieces of infrastructure are already deployed, you can register a cloud stack seamlessly through the stack wizard:
|
292
292
|
|
293
293
|
```bash
|
294
294
|
zenml stack register <STACK_NAME> --provider aws
|
@@ -336,9 +336,9 @@ def trainer(training_df: pd.DataFrame) -> Annotated["model", torch.nn.Module]:
|
|
336
336
|
|
337
337
|

|
338
338
|
|
339
|
-
### Purpose built for machine learning with
|
339
|
+
### Purpose built for machine learning with integrations to your favorite tools
|
340
340
|
|
341
|
-
While ZenML brings a lot of value of the box, it also integrates into your existing tooling and infrastructure without you having to be locked in.
|
341
|
+
While ZenML brings a lot of value out of the box, it also integrates into your existing tooling and infrastructure without you having to be locked in.
|
342
342
|
|
343
343
|
```python
|
344
344
|
from bentoml._internal.bento import bento
|
@@ -474,7 +474,7 @@ the Apache License Version 2.0.
|
|
474
474
|
<a href="https://github.com/zenml-io/zenml-projects">Projects Showcase</a>
|
475
475
|
<br />
|
476
476
|
<br />
|
477
|
-
🎉 Version 0.
|
477
|
+
🎉 Version 0.71.0 is out. Check out the release notes
|
478
478
|
<a href="https://github.com/zenml-io/zenml/releases">here</a>.
|
479
479
|
<br />
|
480
480
|
🖥️ Download our VS Code Extension <a href="https://marketplace.visualstudio.com/items?itemName=ZenML.zenml-vscode">here</a>.
|