truefoundry 0.3.4rc1__py3-none-any.whl → 0.4.0__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.
Potentially problematic release.
This version of truefoundry might be problematic. Click here for more details.
- truefoundry/__init__.py +2 -0
- truefoundry/autodeploy/agents/developer.py +1 -1
- truefoundry/autodeploy/agents/project_identifier.py +2 -2
- truefoundry/autodeploy/agents/tester.py +1 -1
- truefoundry/autodeploy/cli.py +1 -1
- truefoundry/autodeploy/tools/list_files.py +1 -1
- truefoundry/cli/__main__.py +3 -17
- truefoundry/common/__init__.py +0 -0
- truefoundry/{deploy/lib/auth → common}/auth_service_client.py +50 -40
- truefoundry/common/constants.py +12 -0
- truefoundry/{deploy/lib/auth → common}/credential_file_manager.py +7 -7
- truefoundry/{deploy/lib/auth → common}/credential_provider.py +10 -23
- truefoundry/common/entities.py +124 -0
- truefoundry/common/exceptions.py +12 -0
- truefoundry/common/request_utils.py +84 -0
- truefoundry/common/servicefoundry_client.py +91 -0
- truefoundry/common/utils.py +56 -0
- truefoundry/deploy/auto_gen/models.py +4 -6
- truefoundry/deploy/cli/cli.py +3 -1
- truefoundry/deploy/cli/commands/apply_command.py +1 -1
- truefoundry/deploy/cli/commands/build_command.py +1 -1
- truefoundry/deploy/cli/commands/deploy_command.py +1 -1
- truefoundry/deploy/cli/commands/login_command.py +2 -2
- truefoundry/deploy/cli/commands/patch_application_command.py +1 -1
- truefoundry/deploy/cli/commands/patch_command.py +1 -1
- truefoundry/deploy/cli/commands/terminate_comand.py +1 -1
- truefoundry/deploy/cli/util.py +1 -1
- truefoundry/deploy/function_service/remote/remote.py +1 -1
- truefoundry/deploy/lib/auth/servicefoundry_session.py +2 -2
- truefoundry/deploy/lib/clients/servicefoundry_client.py +120 -159
- truefoundry/deploy/lib/const.py +1 -35
- truefoundry/deploy/lib/exceptions.py +0 -16
- truefoundry/deploy/lib/model/entity.py +1 -112
- truefoundry/deploy/lib/session.py +14 -42
- truefoundry/deploy/lib/util.py +0 -37
- truefoundry/{python_deploy_codegen.py → deploy/python_deploy_codegen.py} +2 -2
- truefoundry/deploy/v2/lib/deploy.py +3 -3
- truefoundry/deploy/v2/lib/deployable_patched_models.py +1 -1
- truefoundry/langchain/truefoundry_chat.py +1 -1
- truefoundry/langchain/truefoundry_embeddings.py +1 -1
- truefoundry/langchain/truefoundry_llm.py +1 -1
- truefoundry/langchain/utils.py +0 -41
- truefoundry/ml/__init__.py +37 -6
- truefoundry/ml/artifact/__init__.py +0 -0
- truefoundry/ml/artifact/truefoundry_artifact_repo.py +1161 -0
- truefoundry/ml/autogen/__init__.py +0 -0
- truefoundry/ml/autogen/client/__init__.py +370 -0
- truefoundry/ml/autogen/client/api/__init__.py +16 -0
- truefoundry/ml/autogen/client/api/auth_api.py +184 -0
- truefoundry/ml/autogen/client/api/deprecated_api.py +605 -0
- truefoundry/ml/autogen/client/api/experiments_api.py +1944 -0
- truefoundry/ml/autogen/client/api/health_api.py +299 -0
- truefoundry/ml/autogen/client/api/metrics_api.py +371 -0
- truefoundry/ml/autogen/client/api/mlfoundry_artifacts_api.py +7213 -0
- truefoundry/ml/autogen/client/api/python_deployment_config_api.py +201 -0
- truefoundry/ml/autogen/client/api/run_artifacts_api.py +231 -0
- truefoundry/ml/autogen/client/api/runs_api.py +2919 -0
- truefoundry/ml/autogen/client/api_client.py +822 -0
- truefoundry/ml/autogen/client/api_response.py +30 -0
- truefoundry/ml/autogen/client/configuration.py +489 -0
- truefoundry/ml/autogen/client/exceptions.py +161 -0
- truefoundry/ml/autogen/client/models/__init__.py +341 -0
- truefoundry/ml/autogen/client/models/add_custom_metrics_to_model_version_request_dto.py +69 -0
- truefoundry/ml/autogen/client/models/add_features_to_model_version_request_dto.py +83 -0
- truefoundry/ml/autogen/client/models/agent.py +125 -0
- truefoundry/ml/autogen/client/models/agent_app.py +118 -0
- truefoundry/ml/autogen/client/models/agent_open_api_tool.py +143 -0
- truefoundry/ml/autogen/client/models/agent_open_api_tool_with_fqn.py +144 -0
- truefoundry/ml/autogen/client/models/agent_with_fqn.py +127 -0
- truefoundry/ml/autogen/client/models/artifact_dto.py +115 -0
- truefoundry/ml/autogen/client/models/artifact_response_dto.py +75 -0
- truefoundry/ml/autogen/client/models/artifact_type.py +39 -0
- truefoundry/ml/autogen/client/models/artifact_version_dto.py +141 -0
- truefoundry/ml/autogen/client/models/artifact_version_response_dto.py +77 -0
- truefoundry/ml/autogen/client/models/artifact_version_status.py +35 -0
- truefoundry/ml/autogen/client/models/assistant_message.py +89 -0
- truefoundry/ml/autogen/client/models/authorize_user_for_model_request_dto.py +69 -0
- truefoundry/ml/autogen/client/models/authorize_user_for_model_version_request_dto.py +69 -0
- truefoundry/ml/autogen/client/models/blob_storage_reference.py +93 -0
- truefoundry/ml/autogen/client/models/body_get_search_runs_get.py +72 -0
- truefoundry/ml/autogen/client/models/chat_prompt.py +156 -0
- truefoundry/ml/autogen/client/models/chat_prompt_messages_inner.py +171 -0
- truefoundry/ml/autogen/client/models/columns_dto.py +73 -0
- truefoundry/ml/autogen/client/models/content.py +153 -0
- truefoundry/ml/autogen/client/models/content1.py +153 -0
- truefoundry/ml/autogen/client/models/content2.py +174 -0
- truefoundry/ml/autogen/client/models/content2_any_of_inner.py +150 -0
- truefoundry/ml/autogen/client/models/create_artifact_request_dto.py +74 -0
- truefoundry/ml/autogen/client/models/create_artifact_response_dto.py +65 -0
- truefoundry/ml/autogen/client/models/create_artifact_version_request_dto.py +74 -0
- truefoundry/ml/autogen/client/models/create_artifact_version_response_dto.py +65 -0
- truefoundry/ml/autogen/client/models/create_dataset_request_dto.py +76 -0
- truefoundry/ml/autogen/client/models/create_experiment_request_dto.py +94 -0
- truefoundry/ml/autogen/client/models/create_experiment_response_dto.py +67 -0
- truefoundry/ml/autogen/client/models/create_model_version_request_dto.py +95 -0
- truefoundry/ml/autogen/client/models/create_multi_part_upload_for_dataset_request_dto.py +73 -0
- truefoundry/ml/autogen/client/models/create_multi_part_upload_for_dataset_response_dto.py +79 -0
- truefoundry/ml/autogen/client/models/create_multi_part_upload_request_dto.py +73 -0
- truefoundry/ml/autogen/client/models/create_python_deployment_config_request_dto.py +72 -0
- truefoundry/ml/autogen/client/models/create_python_deployment_config_response_dto.py +67 -0
- truefoundry/ml/autogen/client/models/create_run_request_dto.py +97 -0
- truefoundry/ml/autogen/client/models/create_run_response_dto.py +75 -0
- truefoundry/ml/autogen/client/models/dataset_dto.py +112 -0
- truefoundry/ml/autogen/client/models/dataset_response_dto.py +75 -0
- truefoundry/ml/autogen/client/models/delete_artifact_versions_request_dto.py +65 -0
- truefoundry/ml/autogen/client/models/delete_dataset_request_dto.py +74 -0
- truefoundry/ml/autogen/client/models/delete_model_version_request_dto.py +65 -0
- truefoundry/ml/autogen/client/models/delete_run_request.py +65 -0
- truefoundry/ml/autogen/client/models/delete_tag_request_dto.py +68 -0
- truefoundry/ml/autogen/client/models/experiment_dto.py +127 -0
- truefoundry/ml/autogen/client/models/experiment_id_request_dto.py +67 -0
- truefoundry/ml/autogen/client/models/experiment_response_dto.py +75 -0
- truefoundry/ml/autogen/client/models/experiment_tag_dto.py +69 -0
- truefoundry/ml/autogen/client/models/feature_dto.py +68 -0
- truefoundry/ml/autogen/client/models/feature_value_type.py +35 -0
- truefoundry/ml/autogen/client/models/file_info_dto.py +76 -0
- truefoundry/ml/autogen/client/models/finalize_artifact_version_request_dto.py +101 -0
- truefoundry/ml/autogen/client/models/get_experiment_response_dto.py +88 -0
- truefoundry/ml/autogen/client/models/get_latest_run_log_response_dto.py +75 -0
- truefoundry/ml/autogen/client/models/get_metric_history_response.py +79 -0
- truefoundry/ml/autogen/client/models/get_signed_url_for_dataset_write_request_dto.py +68 -0
- truefoundry/ml/autogen/client/models/get_signed_urls_for_artifact_version_read_request_dto.py +68 -0
- truefoundry/ml/autogen/client/models/get_signed_urls_for_artifact_version_read_response_dto.py +81 -0
- truefoundry/ml/autogen/client/models/get_signed_urls_for_artifact_version_write_request_dto.py +69 -0
- truefoundry/ml/autogen/client/models/get_signed_urls_for_artifact_version_write_response_dto.py +83 -0
- truefoundry/ml/autogen/client/models/get_signed_urls_for_dataset_read_request_dto.py +68 -0
- truefoundry/ml/autogen/client/models/get_signed_urls_for_dataset_read_response_dto.py +81 -0
- truefoundry/ml/autogen/client/models/get_signed_urls_for_dataset_write_response_dto.py +81 -0
- truefoundry/ml/autogen/client/models/get_tenant_id_response_dto.py +73 -0
- truefoundry/ml/autogen/client/models/http_validation_error.py +82 -0
- truefoundry/ml/autogen/client/models/image_content_part.py +87 -0
- truefoundry/ml/autogen/client/models/image_url.py +75 -0
- truefoundry/ml/autogen/client/models/internal_metadata.py +180 -0
- truefoundry/ml/autogen/client/models/latest_run_log_dto.py +78 -0
- truefoundry/ml/autogen/client/models/list_artifact_versions_request_dto.py +107 -0
- truefoundry/ml/autogen/client/models/list_artifact_versions_response_dto.py +87 -0
- truefoundry/ml/autogen/client/models/list_artifacts_request_dto.py +96 -0
- truefoundry/ml/autogen/client/models/list_artifacts_response_dto.py +86 -0
- truefoundry/ml/autogen/client/models/list_colums_response_dto.py +75 -0
- truefoundry/ml/autogen/client/models/list_datasets_request_dto.py +78 -0
- truefoundry/ml/autogen/client/models/list_datasets_response_dto.py +86 -0
- truefoundry/ml/autogen/client/models/list_experiments_response_dto.py +86 -0
- truefoundry/ml/autogen/client/models/list_files_for_artifact_version_request_dto.py +76 -0
- truefoundry/ml/autogen/client/models/list_files_for_artifact_versions_response_dto.py +82 -0
- truefoundry/ml/autogen/client/models/list_files_for_dataset_request_dto.py +76 -0
- truefoundry/ml/autogen/client/models/list_files_for_dataset_response_dto.py +82 -0
- truefoundry/ml/autogen/client/models/list_latest_run_logs_response_dto.py +82 -0
- truefoundry/ml/autogen/client/models/list_metric_history_request_dto.py +69 -0
- truefoundry/ml/autogen/client/models/list_metric_history_response_dto.py +84 -0
- truefoundry/ml/autogen/client/models/list_model_version_response_dto.py +87 -0
- truefoundry/ml/autogen/client/models/list_model_versions_request_dto.py +93 -0
- truefoundry/ml/autogen/client/models/list_models_request_dto.py +89 -0
- truefoundry/ml/autogen/client/models/list_models_response_dto.py +84 -0
- truefoundry/ml/autogen/client/models/list_run_artifacts_response_dto.py +84 -0
- truefoundry/ml/autogen/client/models/list_run_logs_response_dto.py +82 -0
- truefoundry/ml/autogen/client/models/list_seed_experiments_response_dto.py +81 -0
- truefoundry/ml/autogen/client/models/log_batch_request_dto.py +106 -0
- truefoundry/ml/autogen/client/models/log_metric_request_dto.py +80 -0
- truefoundry/ml/autogen/client/models/log_param_request_dto.py +76 -0
- truefoundry/ml/autogen/client/models/method.py +37 -0
- truefoundry/ml/autogen/client/models/metric_collection_dto.py +82 -0
- truefoundry/ml/autogen/client/models/metric_dto.py +76 -0
- truefoundry/ml/autogen/client/models/mime_type.py +37 -0
- truefoundry/ml/autogen/client/models/model_configuration.py +103 -0
- truefoundry/ml/autogen/client/models/model_dto.py +122 -0
- truefoundry/ml/autogen/client/models/model_response_dto.py +75 -0
- truefoundry/ml/autogen/client/models/model_schema_dto.py +85 -0
- truefoundry/ml/autogen/client/models/model_version_dto.py +170 -0
- truefoundry/ml/autogen/client/models/model_version_response_dto.py +75 -0
- truefoundry/ml/autogen/client/models/multi_part_upload_dto.py +107 -0
- truefoundry/ml/autogen/client/models/multi_part_upload_response_dto.py +79 -0
- truefoundry/ml/autogen/client/models/multi_part_upload_storage_provider.py +34 -0
- truefoundry/ml/autogen/client/models/notify_artifact_version_failure_dto.py +65 -0
- truefoundry/ml/autogen/client/models/openapi_spec.py +152 -0
- truefoundry/ml/autogen/client/models/param_dto.py +66 -0
- truefoundry/ml/autogen/client/models/parameters.py +84 -0
- truefoundry/ml/autogen/client/models/prediction_type.py +34 -0
- truefoundry/ml/autogen/client/models/resolve_agent_app_response_dto.py +75 -0
- truefoundry/ml/autogen/client/models/restore_run_request_dto.py +65 -0
- truefoundry/ml/autogen/client/models/run_data_dto.py +104 -0
- truefoundry/ml/autogen/client/models/run_dto.py +84 -0
- truefoundry/ml/autogen/client/models/run_info_dto.py +105 -0
- truefoundry/ml/autogen/client/models/run_log_dto.py +90 -0
- truefoundry/ml/autogen/client/models/run_log_input_dto.py +80 -0
- truefoundry/ml/autogen/client/models/run_response_dto.py +75 -0
- truefoundry/ml/autogen/client/models/run_tag_dto.py +66 -0
- truefoundry/ml/autogen/client/models/search_runs_request_dto.py +94 -0
- truefoundry/ml/autogen/client/models/search_runs_response_dto.py +84 -0
- truefoundry/ml/autogen/client/models/set_experiment_tag_request_dto.py +73 -0
- truefoundry/ml/autogen/client/models/set_tag_request_dto.py +76 -0
- truefoundry/ml/autogen/client/models/signed_url_dto.py +69 -0
- truefoundry/ml/autogen/client/models/stop.py +152 -0
- truefoundry/ml/autogen/client/models/store_run_logs_request_dto.py +83 -0
- truefoundry/ml/autogen/client/models/system_message.py +89 -0
- truefoundry/ml/autogen/client/models/text.py +153 -0
- truefoundry/ml/autogen/client/models/text_content_part.py +84 -0
- truefoundry/ml/autogen/client/models/update_artifact_version_request_dto.py +74 -0
- truefoundry/ml/autogen/client/models/update_dataset_request_dto.py +74 -0
- truefoundry/ml/autogen/client/models/update_experiment_request_dto.py +74 -0
- truefoundry/ml/autogen/client/models/update_model_version_request_dto.py +93 -0
- truefoundry/ml/autogen/client/models/update_run_request_dto.py +78 -0
- truefoundry/ml/autogen/client/models/update_run_response_dto.py +75 -0
- truefoundry/ml/autogen/client/models/url.py +153 -0
- truefoundry/ml/autogen/client/models/user_message.py +89 -0
- truefoundry/ml/autogen/client/models/validation_error.py +87 -0
- truefoundry/ml/autogen/client/models/validation_error_loc_inner.py +154 -0
- truefoundry/ml/autogen/client/rest.py +426 -0
- truefoundry/ml/autogen/client_README.md +320 -0
- truefoundry/ml/cli/__init__.py +0 -0
- truefoundry/ml/cli/cli.py +18 -0
- truefoundry/ml/cli/commands/__init__.py +3 -0
- truefoundry/ml/cli/commands/download.py +87 -0
- truefoundry/ml/clients/__init__.py +0 -0
- truefoundry/ml/clients/entities.py +8 -0
- truefoundry/ml/clients/servicefoundry_client.py +45 -0
- truefoundry/ml/clients/utils.py +122 -0
- truefoundry/ml/constants.py +84 -0
- truefoundry/ml/entities.py +62 -0
- truefoundry/ml/enums.py +70 -0
- truefoundry/ml/env_vars.py +9 -0
- truefoundry/ml/exceptions.py +8 -0
- truefoundry/ml/git_info.py +60 -0
- truefoundry/ml/internal_namespace.py +52 -0
- truefoundry/ml/log_types/__init__.py +4 -0
- truefoundry/ml/log_types/artifacts/artifact.py +431 -0
- truefoundry/ml/log_types/artifacts/constants.py +33 -0
- truefoundry/ml/log_types/artifacts/dataset.py +384 -0
- truefoundry/ml/log_types/artifacts/general_artifact.py +110 -0
- truefoundry/ml/log_types/artifacts/model.py +611 -0
- truefoundry/ml/log_types/artifacts/model_extras.py +48 -0
- truefoundry/ml/log_types/artifacts/utils.py +161 -0
- truefoundry/ml/log_types/image/__init__.py +3 -0
- truefoundry/ml/log_types/image/constants.py +8 -0
- truefoundry/ml/log_types/image/image.py +357 -0
- truefoundry/ml/log_types/image/image_normalizer.py +102 -0
- truefoundry/ml/log_types/image/types.py +68 -0
- truefoundry/ml/log_types/plot.py +281 -0
- truefoundry/ml/log_types/pydantic_base.py +10 -0
- truefoundry/ml/log_types/utils.py +12 -0
- truefoundry/ml/logger.py +17 -0
- truefoundry/ml/mlfoundry_api.py +1575 -0
- truefoundry/ml/mlfoundry_run.py +1203 -0
- truefoundry/ml/run_utils.py +93 -0
- truefoundry/ml/session.py +168 -0
- truefoundry/ml/validation_utils.py +346 -0
- truefoundry/pydantic_v1.py +8 -1
- truefoundry/workflow/__init__.py +16 -1
- {truefoundry-0.3.4rc1.dist-info → truefoundry-0.4.0.dist-info}/METADATA +21 -14
- truefoundry-0.4.0.dist-info/RECORD +344 -0
- truefoundry/deploy/lib/clients/utils.py +0 -41
- truefoundry-0.3.4rc1.dist-info/RECORD +0 -136
- {truefoundry-0.3.4rc1.dist-info → truefoundry-0.4.0.dist-info}/WHEEL +0 -0
- {truefoundry-0.3.4rc1.dist-info → truefoundry-0.4.0.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,611 @@
|
|
|
1
|
+
import copy
|
|
2
|
+
import datetime
|
|
3
|
+
import json
|
|
4
|
+
import logging
|
|
5
|
+
import os.path
|
|
6
|
+
import tempfile
|
|
7
|
+
import uuid
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Sequence, Tuple, Union
|
|
10
|
+
|
|
11
|
+
from truefoundry.ml.artifact.truefoundry_artifact_repo import (
|
|
12
|
+
ArtifactIdentifier,
|
|
13
|
+
MlFoundryArtifactsRepository,
|
|
14
|
+
)
|
|
15
|
+
from truefoundry.ml.autogen.client import ( # type: ignore[attr-defined]
|
|
16
|
+
AddCustomMetricsToModelVersionRequestDto,
|
|
17
|
+
ArtifactType,
|
|
18
|
+
CreateArtifactVersionRequestDto,
|
|
19
|
+
CreateModelVersionRequestDto,
|
|
20
|
+
DeleteArtifactVersionsRequestDto,
|
|
21
|
+
FinalizeArtifactVersionRequestDto,
|
|
22
|
+
MetricDto,
|
|
23
|
+
MlfoundryArtifactsApi,
|
|
24
|
+
ModelDto,
|
|
25
|
+
ModelVersionDto,
|
|
26
|
+
NotifyArtifactVersionFailureDto,
|
|
27
|
+
UpdateModelVersionRequestDto,
|
|
28
|
+
)
|
|
29
|
+
from truefoundry.ml.autogen.client import ( # type: ignore[attr-defined]
|
|
30
|
+
InternalMetadata as InternalMetadataDto,
|
|
31
|
+
)
|
|
32
|
+
from truefoundry.ml.enums import ModelFramework
|
|
33
|
+
from truefoundry.ml.exceptions import MlFoundryException
|
|
34
|
+
from truefoundry.ml.log_types.artifacts.constants import (
|
|
35
|
+
FILES_DIR,
|
|
36
|
+
INTERNAL_METADATA_PATH,
|
|
37
|
+
MODEL_DIR_NAME,
|
|
38
|
+
MODEL_SCHEMA_UPDATE_FAILURE_HELP,
|
|
39
|
+
)
|
|
40
|
+
from truefoundry.ml.log_types.artifacts.model_extras import CustomMetric, ModelSchema
|
|
41
|
+
from truefoundry.ml.log_types.artifacts.utils import (
|
|
42
|
+
_copy_additional_files,
|
|
43
|
+
_validate_artifact_metadata,
|
|
44
|
+
_validate_description,
|
|
45
|
+
)
|
|
46
|
+
from truefoundry.ml.session import _get_api_client
|
|
47
|
+
from truefoundry.pydantic_v1 import BaseModel, Extra
|
|
48
|
+
from truefoundry.version import __version__
|
|
49
|
+
|
|
50
|
+
if TYPE_CHECKING:
|
|
51
|
+
from truefoundry.ml.mlfoundry_run import MlFoundryRun
|
|
52
|
+
|
|
53
|
+
logger = logging.getLogger("truefoundry.ml")
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
# TODO: Support async download and upload
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class ModelVersionInternalMetadata(BaseModel):
|
|
60
|
+
class Config:
|
|
61
|
+
extra = Extra.allow
|
|
62
|
+
|
|
63
|
+
files_dir: str # relative to root
|
|
64
|
+
model_dir: str # relative to `files_dir`
|
|
65
|
+
model_is_null: bool = False
|
|
66
|
+
framework: ModelFramework = ModelFramework.UNKNOWN
|
|
67
|
+
transformers_pipeline_task: Optional[str] = None
|
|
68
|
+
model_filename: Optional[str] = None
|
|
69
|
+
mlfoundry_version: Optional[str] = None
|
|
70
|
+
truefoundry_version: Optional[str] = None
|
|
71
|
+
|
|
72
|
+
def dict(self, *args, **kwargs):
|
|
73
|
+
dct = super().dict(*args, **kwargs)
|
|
74
|
+
dct["framework"] = dct["framework"].value
|
|
75
|
+
return dct
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class ModelVersionDownloadInfo(BaseModel):
|
|
79
|
+
download_dir: str
|
|
80
|
+
model_dir: str
|
|
81
|
+
model_framework: ModelFramework = ModelFramework.UNKNOWN
|
|
82
|
+
model_filename: Optional[str] = None
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class ModelVersion:
|
|
86
|
+
def __init__(
|
|
87
|
+
self,
|
|
88
|
+
model_version: ModelVersionDto,
|
|
89
|
+
model: ModelDto,
|
|
90
|
+
) -> None:
|
|
91
|
+
self._api_client = _get_api_client()
|
|
92
|
+
self._mlfoundry_artifacts_api = MlfoundryArtifactsApi(
|
|
93
|
+
api_client=self._api_client
|
|
94
|
+
)
|
|
95
|
+
self._model_version = model_version
|
|
96
|
+
self._model = model
|
|
97
|
+
self._deleted = False
|
|
98
|
+
self._description: str = ""
|
|
99
|
+
self._metadata: Dict[str, Any] = {}
|
|
100
|
+
self._metrics: List[MetricDto] = []
|
|
101
|
+
self._set_metrics_attr()
|
|
102
|
+
self._set_mutable_attrs()
|
|
103
|
+
|
|
104
|
+
@classmethod
|
|
105
|
+
def from_fqn(cls, fqn: str) -> "ModelVersion":
|
|
106
|
+
"""
|
|
107
|
+
Get the version of a model to download contents or load them in memory
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
fqn (str): Fully qualified name of the model version.
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
ModelVersion: An ModelVersion instance of the Model
|
|
114
|
+
|
|
115
|
+
Examples:
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
from truefoundry.ml import get_client, ModelVersion
|
|
119
|
+
|
|
120
|
+
client = get_client()
|
|
121
|
+
model_version = ModelVersion.from_fqn(fqn="<your-model-fqn>")
|
|
122
|
+
```
|
|
123
|
+
"""
|
|
124
|
+
api_client = _get_api_client()
|
|
125
|
+
mlfoundry_artifacts_api = MlfoundryArtifactsApi(api_client=api_client)
|
|
126
|
+
_model_version = mlfoundry_artifacts_api.get_model_version_by_fqn_get(fqn=fqn)
|
|
127
|
+
model_version = _model_version.model_version
|
|
128
|
+
_model = mlfoundry_artifacts_api.get_model_get(id=model_version.model_id)
|
|
129
|
+
model = _model.model
|
|
130
|
+
instance = cls(model_version=model_version, model=model)
|
|
131
|
+
return instance
|
|
132
|
+
|
|
133
|
+
def _ensure_not_deleted(self):
|
|
134
|
+
if self._deleted:
|
|
135
|
+
raise MlFoundryException(
|
|
136
|
+
"Model Version was deleted, cannot perform updates on a deleted version"
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
def _set_metrics_attr(self):
|
|
140
|
+
self._metrics = sorted(
|
|
141
|
+
self._model_version.metrics or [], key=lambda m: m.timestamp
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
def _set_mutable_attrs(self):
|
|
145
|
+
self._description = self._model_version.description or ""
|
|
146
|
+
self._metadata = copy.deepcopy(self._model_version.artifact_metadata)
|
|
147
|
+
|
|
148
|
+
def _refetch_model_version(self):
|
|
149
|
+
_model_version = self._mlfoundry_artifacts_api.get_model_version_get(
|
|
150
|
+
id=self._model_version.id
|
|
151
|
+
)
|
|
152
|
+
self._model_version = _model_version.model_version
|
|
153
|
+
self._set_metrics_attr()
|
|
154
|
+
self._set_mutable_attrs()
|
|
155
|
+
|
|
156
|
+
def __repr__(self):
|
|
157
|
+
return f"{self.__class__.__name__}(fqn={self.fqn!r})"
|
|
158
|
+
|
|
159
|
+
def _get_artifacts_repo(self):
|
|
160
|
+
return MlFoundryArtifactsRepository(
|
|
161
|
+
artifact_identifier=ArtifactIdentifier(
|
|
162
|
+
artifact_version_id=uuid.UUID(self._model_version.id)
|
|
163
|
+
),
|
|
164
|
+
api_client=self._api_client,
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
@property
|
|
168
|
+
def name(self) -> str:
|
|
169
|
+
"""Get the name of the model"""
|
|
170
|
+
return self._model.name
|
|
171
|
+
|
|
172
|
+
@property
|
|
173
|
+
def model_fqn(self) -> str:
|
|
174
|
+
"""Get fqn of the model"""
|
|
175
|
+
return self._model.fqn
|
|
176
|
+
|
|
177
|
+
@property
|
|
178
|
+
def version(self) -> int:
|
|
179
|
+
"""Get version information of the model"""
|
|
180
|
+
return self._model_version.version
|
|
181
|
+
|
|
182
|
+
@property
|
|
183
|
+
def fqn(self) -> str:
|
|
184
|
+
"""Get fqn of the current model version"""
|
|
185
|
+
return self._model_version.fqn
|
|
186
|
+
|
|
187
|
+
@property
|
|
188
|
+
def step(self) -> int:
|
|
189
|
+
"""Get the step in which model was created"""
|
|
190
|
+
return self._model_version.step
|
|
191
|
+
|
|
192
|
+
@property
|
|
193
|
+
def description(self) -> Optional[str]:
|
|
194
|
+
"""Get description of the model"""
|
|
195
|
+
return self._description
|
|
196
|
+
|
|
197
|
+
@description.setter
|
|
198
|
+
def description(self, value: str):
|
|
199
|
+
"""set the description of the model"""
|
|
200
|
+
_validate_description(value)
|
|
201
|
+
self._description = value
|
|
202
|
+
|
|
203
|
+
@property
|
|
204
|
+
def metadata(self) -> Dict[str, Any]:
|
|
205
|
+
"""Get metadata for the current model"""
|
|
206
|
+
return self._metadata
|
|
207
|
+
|
|
208
|
+
@metadata.setter
|
|
209
|
+
def metadata(self, value: Dict[str, Any]):
|
|
210
|
+
"""set the metadata for current model"""
|
|
211
|
+
_validate_artifact_metadata(value)
|
|
212
|
+
self._metadata = value
|
|
213
|
+
|
|
214
|
+
@property
|
|
215
|
+
def metrics(self) -> Dict[str, Union[float, int]]:
|
|
216
|
+
"""get the metrics for the current version of the model"""
|
|
217
|
+
metrics_as_kv: Dict[str, Union[float, int]] = {}
|
|
218
|
+
for metric in self._metrics:
|
|
219
|
+
metrics_as_kv[metric.key] = metric.value
|
|
220
|
+
return metrics_as_kv
|
|
221
|
+
|
|
222
|
+
@property
|
|
223
|
+
def created_by(self) -> str:
|
|
224
|
+
"""Get the information about who created the model version"""
|
|
225
|
+
return self._model_version.created_by
|
|
226
|
+
|
|
227
|
+
@property
|
|
228
|
+
def created_at(self) -> datetime.datetime:
|
|
229
|
+
"""Get the time at which model version was created"""
|
|
230
|
+
return self._model_version.created_at
|
|
231
|
+
|
|
232
|
+
@property
|
|
233
|
+
def updated_at(self) -> datetime.datetime:
|
|
234
|
+
"""Get the information about when the model version was updated"""
|
|
235
|
+
return self._model_version.updated_at
|
|
236
|
+
|
|
237
|
+
def raw_download(
|
|
238
|
+
self,
|
|
239
|
+
path: Optional[Union[str, Path]],
|
|
240
|
+
overwrite: bool = False,
|
|
241
|
+
progress: Optional[bool] = None,
|
|
242
|
+
) -> str:
|
|
243
|
+
"""
|
|
244
|
+
Download a model file or directory to a local directory if applicable, and return a
|
|
245
|
+
local path for it.
|
|
246
|
+
|
|
247
|
+
Args:
|
|
248
|
+
path (str): Absolute path of the local filesystem destination directory to which to
|
|
249
|
+
download the specified models. This directory must already exist.
|
|
250
|
+
If unspecified, the models will either be downloaded to a new
|
|
251
|
+
uniquely-named directory on the local filesystem.
|
|
252
|
+
overwrite (bool): If True it will overwrite the file if it is already present in the download directory else
|
|
253
|
+
it will throw an error
|
|
254
|
+
progress (bool): value to show progress bar, defaults to None.
|
|
255
|
+
|
|
256
|
+
Returns:
|
|
257
|
+
path: Absolute path of the local filesystem location containing the desired models.
|
|
258
|
+
|
|
259
|
+
Examples:
|
|
260
|
+
|
|
261
|
+
```python
|
|
262
|
+
from truefoundry.ml import get_client
|
|
263
|
+
|
|
264
|
+
client = get_client()
|
|
265
|
+
model_version = client.get_model_version_by_fqn(fqn="<your-model-fqn>")
|
|
266
|
+
model_version.raw_download(path="<your-desired-download-path>")
|
|
267
|
+
```
|
|
268
|
+
"""
|
|
269
|
+
logger.info("Downloading model version contents, this might take a while ...")
|
|
270
|
+
artifacts_repo = self._get_artifacts_repo()
|
|
271
|
+
return artifacts_repo.download_artifacts(
|
|
272
|
+
artifact_path="", dst_path=path, overwrite=overwrite, progress=progress
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
def _download(
|
|
276
|
+
self,
|
|
277
|
+
path: Optional[Union[str, Path]],
|
|
278
|
+
overwrite: bool = False,
|
|
279
|
+
progress: Optional[bool] = None,
|
|
280
|
+
) -> Tuple[ModelVersionInternalMetadata, ModelVersionDownloadInfo]:
|
|
281
|
+
self._ensure_not_deleted()
|
|
282
|
+
download_dir = self.raw_download(
|
|
283
|
+
path=path, overwrite=overwrite, progress=progress
|
|
284
|
+
)
|
|
285
|
+
internal_metadata_path = os.path.join(download_dir, INTERNAL_METADATA_PATH)
|
|
286
|
+
if not os.path.exists(internal_metadata_path):
|
|
287
|
+
raise MlFoundryException(
|
|
288
|
+
"Model version seems to be corrupted or in invalid format due to missing model metadata. "
|
|
289
|
+
"You can still use .raw_download(path='/your/path/here') to download and inspect files."
|
|
290
|
+
)
|
|
291
|
+
with open(internal_metadata_path) as f:
|
|
292
|
+
internal_metadata = ModelVersionInternalMetadata.parse_obj(json.load(f))
|
|
293
|
+
download_info = ModelVersionDownloadInfo(
|
|
294
|
+
download_dir=os.path.join(download_dir, internal_metadata.files_dir),
|
|
295
|
+
model_dir=os.path.join(
|
|
296
|
+
download_dir, internal_metadata.files_dir, internal_metadata.model_dir
|
|
297
|
+
),
|
|
298
|
+
model_framework=internal_metadata.framework,
|
|
299
|
+
model_filename=internal_metadata.model_filename,
|
|
300
|
+
)
|
|
301
|
+
return internal_metadata, download_info
|
|
302
|
+
|
|
303
|
+
def download(
|
|
304
|
+
self,
|
|
305
|
+
path: Optional[Union[str, Path]],
|
|
306
|
+
overwrite: bool = False,
|
|
307
|
+
progress: Optional[bool] = None,
|
|
308
|
+
) -> ModelVersionDownloadInfo:
|
|
309
|
+
"""
|
|
310
|
+
Download a model file or directory to a local directory if applicable, and return download info
|
|
311
|
+
containing `model_dir` - local path where model was downloaded
|
|
312
|
+
|
|
313
|
+
Args:
|
|
314
|
+
path (str): Absolute path of the local filesystem destination directory to which to
|
|
315
|
+
download the specified models. This directory must already exist.
|
|
316
|
+
If unspecified, the models will either be downloaded to a new
|
|
317
|
+
uniquely-named directory on the local filesystem.
|
|
318
|
+
overwrite (bool): If True it will overwrite the file if it is already present in the download directory else
|
|
319
|
+
it will throw an error
|
|
320
|
+
progress (bool): value to show progress bar, defaults to None.
|
|
321
|
+
|
|
322
|
+
Returns:
|
|
323
|
+
ModelVersionDownloadInfo: Download Info instance containing
|
|
324
|
+
`model_dir` (path to downloaded model folder) and other metadata
|
|
325
|
+
|
|
326
|
+
Examples:
|
|
327
|
+
|
|
328
|
+
```python
|
|
329
|
+
from truefoundry.ml import get_client
|
|
330
|
+
|
|
331
|
+
client = get_client()
|
|
332
|
+
model_version = client.get_model_version_by_fqn(fqn="<your-model-fqn>")
|
|
333
|
+
download_info = model_version.download(path="<your-desired-download-path>")
|
|
334
|
+
print(download_info.model_dir)
|
|
335
|
+
```
|
|
336
|
+
"""
|
|
337
|
+
_, download_info = self._download(
|
|
338
|
+
path=path, overwrite=overwrite, progress=progress
|
|
339
|
+
)
|
|
340
|
+
return download_info
|
|
341
|
+
|
|
342
|
+
def delete(self) -> bool:
|
|
343
|
+
"""
|
|
344
|
+
Deletes the current instance of the ModelVersion hence deleting the current version.
|
|
345
|
+
|
|
346
|
+
Returns:
|
|
347
|
+
True if model was deleted successfully
|
|
348
|
+
|
|
349
|
+
Examples:
|
|
350
|
+
|
|
351
|
+
```python
|
|
352
|
+
from truefoundry.ml import get_client
|
|
353
|
+
|
|
354
|
+
client = get_client()
|
|
355
|
+
model_version = client.get_model_version_by_fqn(fqn="<your-model-fqn>")
|
|
356
|
+
model_version.delete()
|
|
357
|
+
```
|
|
358
|
+
"""
|
|
359
|
+
self._ensure_not_deleted()
|
|
360
|
+
self._mlfoundry_artifacts_api.delete_artifact_version_post(
|
|
361
|
+
delete_artifact_versions_request_dto=DeleteArtifactVersionsRequestDto(
|
|
362
|
+
id=self._model_version.id
|
|
363
|
+
)
|
|
364
|
+
)
|
|
365
|
+
self._deleted = True
|
|
366
|
+
return True
|
|
367
|
+
|
|
368
|
+
def update(self):
|
|
369
|
+
"""
|
|
370
|
+
Updates the current instance of the ModelVersion hence updating the current version.
|
|
371
|
+
|
|
372
|
+
Examples:
|
|
373
|
+
|
|
374
|
+
```python
|
|
375
|
+
from truefoundry.ml import get_client
|
|
376
|
+
|
|
377
|
+
client = get_client()
|
|
378
|
+
model_version = client.get_model_version_by_fqn(fqn="<your-model-fqn>")
|
|
379
|
+
model_version.description = 'This is the new description'
|
|
380
|
+
model_version.update()
|
|
381
|
+
```
|
|
382
|
+
"""
|
|
383
|
+
self._ensure_not_deleted()
|
|
384
|
+
_model_version = self._mlfoundry_artifacts_api.update_model_version_post(
|
|
385
|
+
update_model_version_request_dto=UpdateModelVersionRequestDto(
|
|
386
|
+
id=self._model_version.id,
|
|
387
|
+
description=self.description,
|
|
388
|
+
artifact_metadata=self.metadata,
|
|
389
|
+
)
|
|
390
|
+
)
|
|
391
|
+
self._model_version = _model_version.model_version
|
|
392
|
+
self._set_metrics_attr()
|
|
393
|
+
self._set_mutable_attrs()
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
def calculate_model_size(artifact_dir: tempfile.TemporaryDirectory):
|
|
397
|
+
"""
|
|
398
|
+
Tells about the size of the model
|
|
399
|
+
|
|
400
|
+
Args:
|
|
401
|
+
artifact_dir (str): directory in which model is present.
|
|
402
|
+
|
|
403
|
+
Returns:
|
|
404
|
+
total size of the model
|
|
405
|
+
"""
|
|
406
|
+
total_size = 0
|
|
407
|
+
for path, _dirs, files in os.walk(artifact_dir.name):
|
|
408
|
+
for f in files:
|
|
409
|
+
file_path = os.path.join(path, f)
|
|
410
|
+
total_size += os.stat(file_path).st_size
|
|
411
|
+
return total_size
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
def _log_model_version( # noqa: C901
|
|
415
|
+
run: Optional["MlFoundryRun"],
|
|
416
|
+
name: str,
|
|
417
|
+
model_file_or_folder: str,
|
|
418
|
+
framework: Optional[Union[ModelFramework, str]],
|
|
419
|
+
mlfoundry_artifacts_api: Optional[MlfoundryArtifactsApi] = None,
|
|
420
|
+
ml_repo_id: Optional[str] = None,
|
|
421
|
+
additional_files: Sequence[Tuple[Union[str, Path], Optional[str]]] = (),
|
|
422
|
+
description: Optional[str] = None,
|
|
423
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
424
|
+
model_schema: Optional[Union[Dict[str, Any], ModelSchema]] = None,
|
|
425
|
+
custom_metrics: Optional[List[Union[CustomMetric, Dict[str, Any]]]] = None,
|
|
426
|
+
step: Optional[int] = 0,
|
|
427
|
+
progress: Optional[bool] = None,
|
|
428
|
+
) -> ModelVersion:
|
|
429
|
+
if (run and mlfoundry_artifacts_api) or (not run and not mlfoundry_artifacts_api):
|
|
430
|
+
raise MlFoundryException(
|
|
431
|
+
"Exactly one of run, mlfoundry_artifacts_api should be passed"
|
|
432
|
+
)
|
|
433
|
+
if mlfoundry_artifacts_api and not ml_repo_id:
|
|
434
|
+
raise MlFoundryException(
|
|
435
|
+
"If mlfoundry_artifacts_api is passed, ml_repo_id must also be passed"
|
|
436
|
+
)
|
|
437
|
+
if run:
|
|
438
|
+
mlfoundry_artifacts_api = run._mlfoundry_artifacts_api
|
|
439
|
+
|
|
440
|
+
assert mlfoundry_artifacts_api is not None
|
|
441
|
+
|
|
442
|
+
custom_metrics = custom_metrics or []
|
|
443
|
+
metadata = metadata or {}
|
|
444
|
+
additional_files = additional_files or {}
|
|
445
|
+
step = step or 0
|
|
446
|
+
|
|
447
|
+
# validations
|
|
448
|
+
if framework is None:
|
|
449
|
+
framework = ModelFramework.UNKNOWN
|
|
450
|
+
elif not isinstance(framework, ModelFramework):
|
|
451
|
+
framework = ModelFramework(framework)
|
|
452
|
+
|
|
453
|
+
_validate_description(description)
|
|
454
|
+
_validate_artifact_metadata(metadata)
|
|
455
|
+
|
|
456
|
+
if model_schema is not None and not isinstance(model_schema, ModelSchema):
|
|
457
|
+
model_schema = ModelSchema.parse_obj(model_schema)
|
|
458
|
+
|
|
459
|
+
if custom_metrics and not model_schema:
|
|
460
|
+
raise MlFoundryException(
|
|
461
|
+
"Custom Metrics defined without adding the Model Schema"
|
|
462
|
+
)
|
|
463
|
+
custom_metrics = [
|
|
464
|
+
CustomMetric.parse_obj(cm) if not isinstance(cm, CustomMetric) else cm
|
|
465
|
+
for cm in custom_metrics
|
|
466
|
+
]
|
|
467
|
+
|
|
468
|
+
logger.info("Logging model and additional files, this might take a while ...")
|
|
469
|
+
temp_dir = tempfile.TemporaryDirectory(prefix="truefoundry-")
|
|
470
|
+
|
|
471
|
+
internal_metadata = ModelVersionInternalMetadata(
|
|
472
|
+
framework=framework,
|
|
473
|
+
files_dir=FILES_DIR,
|
|
474
|
+
model_dir=MODEL_DIR_NAME,
|
|
475
|
+
model_filename=(
|
|
476
|
+
os.path.basename(model_file_or_folder)
|
|
477
|
+
if model_file_or_folder and os.path.isfile(model_file_or_folder)
|
|
478
|
+
else None
|
|
479
|
+
),
|
|
480
|
+
mlfoundry_version=__version__,
|
|
481
|
+
truefoundry_version=__version__,
|
|
482
|
+
)
|
|
483
|
+
|
|
484
|
+
try:
|
|
485
|
+
local_files_dir = os.path.join(temp_dir.name, internal_metadata.files_dir)
|
|
486
|
+
os.makedirs(local_files_dir, exist_ok=True)
|
|
487
|
+
# in case model was None, we still create an empty dir
|
|
488
|
+
local_model_dir = os.path.join(local_files_dir, internal_metadata.model_dir)
|
|
489
|
+
os.makedirs(local_model_dir, exist_ok=True)
|
|
490
|
+
|
|
491
|
+
logger.info("Adding model file/folder to model version content")
|
|
492
|
+
model_file_or_folder = [
|
|
493
|
+
(model_file_or_folder, MODEL_DIR_NAME.rstrip(os.sep) + os.sep)
|
|
494
|
+
]
|
|
495
|
+
_copy_additional_files(
|
|
496
|
+
root_dir=temp_dir.name,
|
|
497
|
+
files_dir=internal_metadata.files_dir,
|
|
498
|
+
model_dir=internal_metadata.model_dir,
|
|
499
|
+
additional_files=model_file_or_folder,
|
|
500
|
+
ignore_model_dir_dest_conflict=True,
|
|
501
|
+
)
|
|
502
|
+
|
|
503
|
+
# verify additional files and paths, copy additional files
|
|
504
|
+
if additional_files:
|
|
505
|
+
logger.info("Adding `additional_files` to model version contents")
|
|
506
|
+
_copy_additional_files(
|
|
507
|
+
root_dir=temp_dir.name,
|
|
508
|
+
files_dir=internal_metadata.files_dir,
|
|
509
|
+
model_dir=internal_metadata.model_dir,
|
|
510
|
+
additional_files=additional_files,
|
|
511
|
+
ignore_model_dir_dest_conflict=False,
|
|
512
|
+
)
|
|
513
|
+
|
|
514
|
+
except Exception as e:
|
|
515
|
+
temp_dir.cleanup()
|
|
516
|
+
raise MlFoundryException("Failed to log model") from e
|
|
517
|
+
|
|
518
|
+
# save internal metadata
|
|
519
|
+
local_internal_metadata_path = os.path.join(temp_dir.name, INTERNAL_METADATA_PATH)
|
|
520
|
+
os.makedirs(os.path.dirname(local_internal_metadata_path), exist_ok=True)
|
|
521
|
+
with open(local_internal_metadata_path, "w") as f:
|
|
522
|
+
json.dump(internal_metadata.dict(), f)
|
|
523
|
+
|
|
524
|
+
# create entry
|
|
525
|
+
_create_artifact_version_response = (
|
|
526
|
+
mlfoundry_artifacts_api.create_artifact_version_post(
|
|
527
|
+
create_artifact_version_request_dto=CreateArtifactVersionRequestDto(
|
|
528
|
+
experiment_id=int(run._experiment_id if run else ml_repo_id),
|
|
529
|
+
artifact_type=ArtifactType.MODEL,
|
|
530
|
+
name=name,
|
|
531
|
+
)
|
|
532
|
+
)
|
|
533
|
+
)
|
|
534
|
+
version_id = _create_artifact_version_response.id
|
|
535
|
+
artifacts_repo = MlFoundryArtifactsRepository(
|
|
536
|
+
artifact_identifier=ArtifactIdentifier(
|
|
537
|
+
artifact_version_id=uuid.UUID(version_id)
|
|
538
|
+
),
|
|
539
|
+
api_client=mlfoundry_artifacts_api.api_client,
|
|
540
|
+
)
|
|
541
|
+
model_size = calculate_model_size(temp_dir)
|
|
542
|
+
try:
|
|
543
|
+
logger.info(
|
|
544
|
+
"Packaging and uploading files to remote with Total Size: %.6f MB",
|
|
545
|
+
model_size / 1000000.0,
|
|
546
|
+
)
|
|
547
|
+
artifacts_repo.log_artifacts(
|
|
548
|
+
local_dir=temp_dir.name, artifact_path=None, progress=progress
|
|
549
|
+
)
|
|
550
|
+
except Exception as e:
|
|
551
|
+
mlfoundry_artifacts_api.notify_failure_post(
|
|
552
|
+
notify_artifact_version_failure_dto=NotifyArtifactVersionFailureDto(
|
|
553
|
+
id=version_id
|
|
554
|
+
)
|
|
555
|
+
)
|
|
556
|
+
raise MlFoundryException("Failed to log model") from e
|
|
557
|
+
finally:
|
|
558
|
+
temp_dir.cleanup()
|
|
559
|
+
|
|
560
|
+
# Note: Here we call from_dict instead of directly passing in init and relying on it
|
|
561
|
+
# to convert because the complicated union of types generates a custom type to handle casting
|
|
562
|
+
# Check the source of `InternalMetadataDto` to see the generated code
|
|
563
|
+
internal_metadata_dto = InternalMetadataDto.from_dict(
|
|
564
|
+
internal_metadata.dict() if internal_metadata is not None else {}
|
|
565
|
+
)
|
|
566
|
+
mlfoundry_artifacts_api.finalize_artifact_version_post(
|
|
567
|
+
finalize_artifact_version_request_dto=FinalizeArtifactVersionRequestDto(
|
|
568
|
+
id=version_id,
|
|
569
|
+
run_uuid=run.run_id if run else None,
|
|
570
|
+
artifact_size=model_size,
|
|
571
|
+
internal_metadata=internal_metadata_dto,
|
|
572
|
+
step=step if run else None,
|
|
573
|
+
)
|
|
574
|
+
)
|
|
575
|
+
_model_version = mlfoundry_artifacts_api.create_model_version_post(
|
|
576
|
+
create_model_version_request_dto=CreateModelVersionRequestDto(
|
|
577
|
+
artifact_version_id=version_id,
|
|
578
|
+
description=description,
|
|
579
|
+
artifact_metadata=metadata,
|
|
580
|
+
internal_metadata=internal_metadata_dto,
|
|
581
|
+
data_path=INTERNAL_METADATA_PATH,
|
|
582
|
+
step=step if run else None,
|
|
583
|
+
)
|
|
584
|
+
)
|
|
585
|
+
model_version = _model_version.model_version
|
|
586
|
+
|
|
587
|
+
# update model schema at end
|
|
588
|
+
update_args: Dict[str, Any] = {
|
|
589
|
+
"id": version_id,
|
|
590
|
+
"model_framework": framework.value,
|
|
591
|
+
}
|
|
592
|
+
if model_schema:
|
|
593
|
+
update_args["model_schema"] = model_schema
|
|
594
|
+
|
|
595
|
+
try:
|
|
596
|
+
_model_version = mlfoundry_artifacts_api.update_model_version_post(
|
|
597
|
+
update_model_version_request_dto=UpdateModelVersionRequestDto(**update_args)
|
|
598
|
+
)
|
|
599
|
+
model_version = _model_version.model_version
|
|
600
|
+
if model_schema:
|
|
601
|
+
_model_version = mlfoundry_artifacts_api.add_custom_metrics_to_model_version_post(
|
|
602
|
+
add_custom_metrics_to_model_version_request_dto=AddCustomMetricsToModelVersionRequestDto(
|
|
603
|
+
id=version_id, custom_metrics=custom_metrics
|
|
604
|
+
)
|
|
605
|
+
)
|
|
606
|
+
model_version = _model_version.model_version
|
|
607
|
+
except Exception:
|
|
608
|
+
# TODO (chiragjn): what is the best exception to catch here?
|
|
609
|
+
logger.error(MODEL_SCHEMA_UPDATE_FAILURE_HELP.format(fqn=model_version.fqn))
|
|
610
|
+
|
|
611
|
+
return ModelVersion.from_fqn(fqn=model_version.fqn)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import enum
|
|
2
|
+
from typing import List, Type, TypeVar
|
|
3
|
+
|
|
4
|
+
from truefoundry.ml.autogen.client import ( # type: ignore[attr-defined]
|
|
5
|
+
ModelSchemaDto,
|
|
6
|
+
)
|
|
7
|
+
from truefoundry.ml.exceptions import MlFoundryException
|
|
8
|
+
from truefoundry.pydantic_v1 import BaseModel
|
|
9
|
+
|
|
10
|
+
T = TypeVar("T")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class BaseEnum(enum.Enum):
|
|
14
|
+
@classmethod
|
|
15
|
+
def values(cls: Type[T]) -> List[T]:
|
|
16
|
+
return [member.value for member in cls]
|
|
17
|
+
|
|
18
|
+
@classmethod
|
|
19
|
+
def _missing_(cls: Type[T], value: object):
|
|
20
|
+
raise MlFoundryException(
|
|
21
|
+
f"Unknown value for type {cls.__name__}: {value}", status_code=400
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@enum.unique
|
|
26
|
+
class CustomMetricValueType(str, BaseEnum):
|
|
27
|
+
FLOAT = "float"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@enum.unique
|
|
31
|
+
class CustomMetricType(str, BaseEnum):
|
|
32
|
+
METRIC = "metric"
|
|
33
|
+
PROJECTION = "projection"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class CustomMetric(BaseModel):
|
|
37
|
+
class Config:
|
|
38
|
+
validate_assignment = True
|
|
39
|
+
use_enum_values = True
|
|
40
|
+
extra = "allow"
|
|
41
|
+
|
|
42
|
+
name: str
|
|
43
|
+
value_type: CustomMetricValueType
|
|
44
|
+
type: CustomMetricType
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class ModelSchema(ModelSchemaDto):
|
|
48
|
+
pass
|