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.

Files changed (253) hide show
  1. truefoundry/__init__.py +2 -0
  2. truefoundry/autodeploy/agents/developer.py +1 -1
  3. truefoundry/autodeploy/agents/project_identifier.py +2 -2
  4. truefoundry/autodeploy/agents/tester.py +1 -1
  5. truefoundry/autodeploy/cli.py +1 -1
  6. truefoundry/autodeploy/tools/list_files.py +1 -1
  7. truefoundry/cli/__main__.py +3 -17
  8. truefoundry/common/__init__.py +0 -0
  9. truefoundry/{deploy/lib/auth → common}/auth_service_client.py +50 -40
  10. truefoundry/common/constants.py +12 -0
  11. truefoundry/{deploy/lib/auth → common}/credential_file_manager.py +7 -7
  12. truefoundry/{deploy/lib/auth → common}/credential_provider.py +10 -23
  13. truefoundry/common/entities.py +124 -0
  14. truefoundry/common/exceptions.py +12 -0
  15. truefoundry/common/request_utils.py +84 -0
  16. truefoundry/common/servicefoundry_client.py +91 -0
  17. truefoundry/common/utils.py +56 -0
  18. truefoundry/deploy/auto_gen/models.py +4 -6
  19. truefoundry/deploy/cli/cli.py +3 -1
  20. truefoundry/deploy/cli/commands/apply_command.py +1 -1
  21. truefoundry/deploy/cli/commands/build_command.py +1 -1
  22. truefoundry/deploy/cli/commands/deploy_command.py +1 -1
  23. truefoundry/deploy/cli/commands/login_command.py +2 -2
  24. truefoundry/deploy/cli/commands/patch_application_command.py +1 -1
  25. truefoundry/deploy/cli/commands/patch_command.py +1 -1
  26. truefoundry/deploy/cli/commands/terminate_comand.py +1 -1
  27. truefoundry/deploy/cli/util.py +1 -1
  28. truefoundry/deploy/function_service/remote/remote.py +1 -1
  29. truefoundry/deploy/lib/auth/servicefoundry_session.py +2 -2
  30. truefoundry/deploy/lib/clients/servicefoundry_client.py +120 -159
  31. truefoundry/deploy/lib/const.py +1 -35
  32. truefoundry/deploy/lib/exceptions.py +0 -16
  33. truefoundry/deploy/lib/model/entity.py +1 -112
  34. truefoundry/deploy/lib/session.py +14 -42
  35. truefoundry/deploy/lib/util.py +0 -37
  36. truefoundry/{python_deploy_codegen.py → deploy/python_deploy_codegen.py} +2 -2
  37. truefoundry/deploy/v2/lib/deploy.py +3 -3
  38. truefoundry/deploy/v2/lib/deployable_patched_models.py +1 -1
  39. truefoundry/langchain/truefoundry_chat.py +1 -1
  40. truefoundry/langchain/truefoundry_embeddings.py +1 -1
  41. truefoundry/langchain/truefoundry_llm.py +1 -1
  42. truefoundry/langchain/utils.py +0 -41
  43. truefoundry/ml/__init__.py +37 -6
  44. truefoundry/ml/artifact/__init__.py +0 -0
  45. truefoundry/ml/artifact/truefoundry_artifact_repo.py +1161 -0
  46. truefoundry/ml/autogen/__init__.py +0 -0
  47. truefoundry/ml/autogen/client/__init__.py +370 -0
  48. truefoundry/ml/autogen/client/api/__init__.py +16 -0
  49. truefoundry/ml/autogen/client/api/auth_api.py +184 -0
  50. truefoundry/ml/autogen/client/api/deprecated_api.py +605 -0
  51. truefoundry/ml/autogen/client/api/experiments_api.py +1944 -0
  52. truefoundry/ml/autogen/client/api/health_api.py +299 -0
  53. truefoundry/ml/autogen/client/api/metrics_api.py +371 -0
  54. truefoundry/ml/autogen/client/api/mlfoundry_artifacts_api.py +7213 -0
  55. truefoundry/ml/autogen/client/api/python_deployment_config_api.py +201 -0
  56. truefoundry/ml/autogen/client/api/run_artifacts_api.py +231 -0
  57. truefoundry/ml/autogen/client/api/runs_api.py +2919 -0
  58. truefoundry/ml/autogen/client/api_client.py +822 -0
  59. truefoundry/ml/autogen/client/api_response.py +30 -0
  60. truefoundry/ml/autogen/client/configuration.py +489 -0
  61. truefoundry/ml/autogen/client/exceptions.py +161 -0
  62. truefoundry/ml/autogen/client/models/__init__.py +341 -0
  63. truefoundry/ml/autogen/client/models/add_custom_metrics_to_model_version_request_dto.py +69 -0
  64. truefoundry/ml/autogen/client/models/add_features_to_model_version_request_dto.py +83 -0
  65. truefoundry/ml/autogen/client/models/agent.py +125 -0
  66. truefoundry/ml/autogen/client/models/agent_app.py +118 -0
  67. truefoundry/ml/autogen/client/models/agent_open_api_tool.py +143 -0
  68. truefoundry/ml/autogen/client/models/agent_open_api_tool_with_fqn.py +144 -0
  69. truefoundry/ml/autogen/client/models/agent_with_fqn.py +127 -0
  70. truefoundry/ml/autogen/client/models/artifact_dto.py +115 -0
  71. truefoundry/ml/autogen/client/models/artifact_response_dto.py +75 -0
  72. truefoundry/ml/autogen/client/models/artifact_type.py +39 -0
  73. truefoundry/ml/autogen/client/models/artifact_version_dto.py +141 -0
  74. truefoundry/ml/autogen/client/models/artifact_version_response_dto.py +77 -0
  75. truefoundry/ml/autogen/client/models/artifact_version_status.py +35 -0
  76. truefoundry/ml/autogen/client/models/assistant_message.py +89 -0
  77. truefoundry/ml/autogen/client/models/authorize_user_for_model_request_dto.py +69 -0
  78. truefoundry/ml/autogen/client/models/authorize_user_for_model_version_request_dto.py +69 -0
  79. truefoundry/ml/autogen/client/models/blob_storage_reference.py +93 -0
  80. truefoundry/ml/autogen/client/models/body_get_search_runs_get.py +72 -0
  81. truefoundry/ml/autogen/client/models/chat_prompt.py +156 -0
  82. truefoundry/ml/autogen/client/models/chat_prompt_messages_inner.py +171 -0
  83. truefoundry/ml/autogen/client/models/columns_dto.py +73 -0
  84. truefoundry/ml/autogen/client/models/content.py +153 -0
  85. truefoundry/ml/autogen/client/models/content1.py +153 -0
  86. truefoundry/ml/autogen/client/models/content2.py +174 -0
  87. truefoundry/ml/autogen/client/models/content2_any_of_inner.py +150 -0
  88. truefoundry/ml/autogen/client/models/create_artifact_request_dto.py +74 -0
  89. truefoundry/ml/autogen/client/models/create_artifact_response_dto.py +65 -0
  90. truefoundry/ml/autogen/client/models/create_artifact_version_request_dto.py +74 -0
  91. truefoundry/ml/autogen/client/models/create_artifact_version_response_dto.py +65 -0
  92. truefoundry/ml/autogen/client/models/create_dataset_request_dto.py +76 -0
  93. truefoundry/ml/autogen/client/models/create_experiment_request_dto.py +94 -0
  94. truefoundry/ml/autogen/client/models/create_experiment_response_dto.py +67 -0
  95. truefoundry/ml/autogen/client/models/create_model_version_request_dto.py +95 -0
  96. truefoundry/ml/autogen/client/models/create_multi_part_upload_for_dataset_request_dto.py +73 -0
  97. truefoundry/ml/autogen/client/models/create_multi_part_upload_for_dataset_response_dto.py +79 -0
  98. truefoundry/ml/autogen/client/models/create_multi_part_upload_request_dto.py +73 -0
  99. truefoundry/ml/autogen/client/models/create_python_deployment_config_request_dto.py +72 -0
  100. truefoundry/ml/autogen/client/models/create_python_deployment_config_response_dto.py +67 -0
  101. truefoundry/ml/autogen/client/models/create_run_request_dto.py +97 -0
  102. truefoundry/ml/autogen/client/models/create_run_response_dto.py +75 -0
  103. truefoundry/ml/autogen/client/models/dataset_dto.py +112 -0
  104. truefoundry/ml/autogen/client/models/dataset_response_dto.py +75 -0
  105. truefoundry/ml/autogen/client/models/delete_artifact_versions_request_dto.py +65 -0
  106. truefoundry/ml/autogen/client/models/delete_dataset_request_dto.py +74 -0
  107. truefoundry/ml/autogen/client/models/delete_model_version_request_dto.py +65 -0
  108. truefoundry/ml/autogen/client/models/delete_run_request.py +65 -0
  109. truefoundry/ml/autogen/client/models/delete_tag_request_dto.py +68 -0
  110. truefoundry/ml/autogen/client/models/experiment_dto.py +127 -0
  111. truefoundry/ml/autogen/client/models/experiment_id_request_dto.py +67 -0
  112. truefoundry/ml/autogen/client/models/experiment_response_dto.py +75 -0
  113. truefoundry/ml/autogen/client/models/experiment_tag_dto.py +69 -0
  114. truefoundry/ml/autogen/client/models/feature_dto.py +68 -0
  115. truefoundry/ml/autogen/client/models/feature_value_type.py +35 -0
  116. truefoundry/ml/autogen/client/models/file_info_dto.py +76 -0
  117. truefoundry/ml/autogen/client/models/finalize_artifact_version_request_dto.py +101 -0
  118. truefoundry/ml/autogen/client/models/get_experiment_response_dto.py +88 -0
  119. truefoundry/ml/autogen/client/models/get_latest_run_log_response_dto.py +75 -0
  120. truefoundry/ml/autogen/client/models/get_metric_history_response.py +79 -0
  121. truefoundry/ml/autogen/client/models/get_signed_url_for_dataset_write_request_dto.py +68 -0
  122. truefoundry/ml/autogen/client/models/get_signed_urls_for_artifact_version_read_request_dto.py +68 -0
  123. truefoundry/ml/autogen/client/models/get_signed_urls_for_artifact_version_read_response_dto.py +81 -0
  124. truefoundry/ml/autogen/client/models/get_signed_urls_for_artifact_version_write_request_dto.py +69 -0
  125. truefoundry/ml/autogen/client/models/get_signed_urls_for_artifact_version_write_response_dto.py +83 -0
  126. truefoundry/ml/autogen/client/models/get_signed_urls_for_dataset_read_request_dto.py +68 -0
  127. truefoundry/ml/autogen/client/models/get_signed_urls_for_dataset_read_response_dto.py +81 -0
  128. truefoundry/ml/autogen/client/models/get_signed_urls_for_dataset_write_response_dto.py +81 -0
  129. truefoundry/ml/autogen/client/models/get_tenant_id_response_dto.py +73 -0
  130. truefoundry/ml/autogen/client/models/http_validation_error.py +82 -0
  131. truefoundry/ml/autogen/client/models/image_content_part.py +87 -0
  132. truefoundry/ml/autogen/client/models/image_url.py +75 -0
  133. truefoundry/ml/autogen/client/models/internal_metadata.py +180 -0
  134. truefoundry/ml/autogen/client/models/latest_run_log_dto.py +78 -0
  135. truefoundry/ml/autogen/client/models/list_artifact_versions_request_dto.py +107 -0
  136. truefoundry/ml/autogen/client/models/list_artifact_versions_response_dto.py +87 -0
  137. truefoundry/ml/autogen/client/models/list_artifacts_request_dto.py +96 -0
  138. truefoundry/ml/autogen/client/models/list_artifacts_response_dto.py +86 -0
  139. truefoundry/ml/autogen/client/models/list_colums_response_dto.py +75 -0
  140. truefoundry/ml/autogen/client/models/list_datasets_request_dto.py +78 -0
  141. truefoundry/ml/autogen/client/models/list_datasets_response_dto.py +86 -0
  142. truefoundry/ml/autogen/client/models/list_experiments_response_dto.py +86 -0
  143. truefoundry/ml/autogen/client/models/list_files_for_artifact_version_request_dto.py +76 -0
  144. truefoundry/ml/autogen/client/models/list_files_for_artifact_versions_response_dto.py +82 -0
  145. truefoundry/ml/autogen/client/models/list_files_for_dataset_request_dto.py +76 -0
  146. truefoundry/ml/autogen/client/models/list_files_for_dataset_response_dto.py +82 -0
  147. truefoundry/ml/autogen/client/models/list_latest_run_logs_response_dto.py +82 -0
  148. truefoundry/ml/autogen/client/models/list_metric_history_request_dto.py +69 -0
  149. truefoundry/ml/autogen/client/models/list_metric_history_response_dto.py +84 -0
  150. truefoundry/ml/autogen/client/models/list_model_version_response_dto.py +87 -0
  151. truefoundry/ml/autogen/client/models/list_model_versions_request_dto.py +93 -0
  152. truefoundry/ml/autogen/client/models/list_models_request_dto.py +89 -0
  153. truefoundry/ml/autogen/client/models/list_models_response_dto.py +84 -0
  154. truefoundry/ml/autogen/client/models/list_run_artifacts_response_dto.py +84 -0
  155. truefoundry/ml/autogen/client/models/list_run_logs_response_dto.py +82 -0
  156. truefoundry/ml/autogen/client/models/list_seed_experiments_response_dto.py +81 -0
  157. truefoundry/ml/autogen/client/models/log_batch_request_dto.py +106 -0
  158. truefoundry/ml/autogen/client/models/log_metric_request_dto.py +80 -0
  159. truefoundry/ml/autogen/client/models/log_param_request_dto.py +76 -0
  160. truefoundry/ml/autogen/client/models/method.py +37 -0
  161. truefoundry/ml/autogen/client/models/metric_collection_dto.py +82 -0
  162. truefoundry/ml/autogen/client/models/metric_dto.py +76 -0
  163. truefoundry/ml/autogen/client/models/mime_type.py +37 -0
  164. truefoundry/ml/autogen/client/models/model_configuration.py +103 -0
  165. truefoundry/ml/autogen/client/models/model_dto.py +122 -0
  166. truefoundry/ml/autogen/client/models/model_response_dto.py +75 -0
  167. truefoundry/ml/autogen/client/models/model_schema_dto.py +85 -0
  168. truefoundry/ml/autogen/client/models/model_version_dto.py +170 -0
  169. truefoundry/ml/autogen/client/models/model_version_response_dto.py +75 -0
  170. truefoundry/ml/autogen/client/models/multi_part_upload_dto.py +107 -0
  171. truefoundry/ml/autogen/client/models/multi_part_upload_response_dto.py +79 -0
  172. truefoundry/ml/autogen/client/models/multi_part_upload_storage_provider.py +34 -0
  173. truefoundry/ml/autogen/client/models/notify_artifact_version_failure_dto.py +65 -0
  174. truefoundry/ml/autogen/client/models/openapi_spec.py +152 -0
  175. truefoundry/ml/autogen/client/models/param_dto.py +66 -0
  176. truefoundry/ml/autogen/client/models/parameters.py +84 -0
  177. truefoundry/ml/autogen/client/models/prediction_type.py +34 -0
  178. truefoundry/ml/autogen/client/models/resolve_agent_app_response_dto.py +75 -0
  179. truefoundry/ml/autogen/client/models/restore_run_request_dto.py +65 -0
  180. truefoundry/ml/autogen/client/models/run_data_dto.py +104 -0
  181. truefoundry/ml/autogen/client/models/run_dto.py +84 -0
  182. truefoundry/ml/autogen/client/models/run_info_dto.py +105 -0
  183. truefoundry/ml/autogen/client/models/run_log_dto.py +90 -0
  184. truefoundry/ml/autogen/client/models/run_log_input_dto.py +80 -0
  185. truefoundry/ml/autogen/client/models/run_response_dto.py +75 -0
  186. truefoundry/ml/autogen/client/models/run_tag_dto.py +66 -0
  187. truefoundry/ml/autogen/client/models/search_runs_request_dto.py +94 -0
  188. truefoundry/ml/autogen/client/models/search_runs_response_dto.py +84 -0
  189. truefoundry/ml/autogen/client/models/set_experiment_tag_request_dto.py +73 -0
  190. truefoundry/ml/autogen/client/models/set_tag_request_dto.py +76 -0
  191. truefoundry/ml/autogen/client/models/signed_url_dto.py +69 -0
  192. truefoundry/ml/autogen/client/models/stop.py +152 -0
  193. truefoundry/ml/autogen/client/models/store_run_logs_request_dto.py +83 -0
  194. truefoundry/ml/autogen/client/models/system_message.py +89 -0
  195. truefoundry/ml/autogen/client/models/text.py +153 -0
  196. truefoundry/ml/autogen/client/models/text_content_part.py +84 -0
  197. truefoundry/ml/autogen/client/models/update_artifact_version_request_dto.py +74 -0
  198. truefoundry/ml/autogen/client/models/update_dataset_request_dto.py +74 -0
  199. truefoundry/ml/autogen/client/models/update_experiment_request_dto.py +74 -0
  200. truefoundry/ml/autogen/client/models/update_model_version_request_dto.py +93 -0
  201. truefoundry/ml/autogen/client/models/update_run_request_dto.py +78 -0
  202. truefoundry/ml/autogen/client/models/update_run_response_dto.py +75 -0
  203. truefoundry/ml/autogen/client/models/url.py +153 -0
  204. truefoundry/ml/autogen/client/models/user_message.py +89 -0
  205. truefoundry/ml/autogen/client/models/validation_error.py +87 -0
  206. truefoundry/ml/autogen/client/models/validation_error_loc_inner.py +154 -0
  207. truefoundry/ml/autogen/client/rest.py +426 -0
  208. truefoundry/ml/autogen/client_README.md +320 -0
  209. truefoundry/ml/cli/__init__.py +0 -0
  210. truefoundry/ml/cli/cli.py +18 -0
  211. truefoundry/ml/cli/commands/__init__.py +3 -0
  212. truefoundry/ml/cli/commands/download.py +87 -0
  213. truefoundry/ml/clients/__init__.py +0 -0
  214. truefoundry/ml/clients/entities.py +8 -0
  215. truefoundry/ml/clients/servicefoundry_client.py +45 -0
  216. truefoundry/ml/clients/utils.py +122 -0
  217. truefoundry/ml/constants.py +84 -0
  218. truefoundry/ml/entities.py +62 -0
  219. truefoundry/ml/enums.py +70 -0
  220. truefoundry/ml/env_vars.py +9 -0
  221. truefoundry/ml/exceptions.py +8 -0
  222. truefoundry/ml/git_info.py +60 -0
  223. truefoundry/ml/internal_namespace.py +52 -0
  224. truefoundry/ml/log_types/__init__.py +4 -0
  225. truefoundry/ml/log_types/artifacts/artifact.py +431 -0
  226. truefoundry/ml/log_types/artifacts/constants.py +33 -0
  227. truefoundry/ml/log_types/artifacts/dataset.py +384 -0
  228. truefoundry/ml/log_types/artifacts/general_artifact.py +110 -0
  229. truefoundry/ml/log_types/artifacts/model.py +611 -0
  230. truefoundry/ml/log_types/artifacts/model_extras.py +48 -0
  231. truefoundry/ml/log_types/artifacts/utils.py +161 -0
  232. truefoundry/ml/log_types/image/__init__.py +3 -0
  233. truefoundry/ml/log_types/image/constants.py +8 -0
  234. truefoundry/ml/log_types/image/image.py +357 -0
  235. truefoundry/ml/log_types/image/image_normalizer.py +102 -0
  236. truefoundry/ml/log_types/image/types.py +68 -0
  237. truefoundry/ml/log_types/plot.py +281 -0
  238. truefoundry/ml/log_types/pydantic_base.py +10 -0
  239. truefoundry/ml/log_types/utils.py +12 -0
  240. truefoundry/ml/logger.py +17 -0
  241. truefoundry/ml/mlfoundry_api.py +1575 -0
  242. truefoundry/ml/mlfoundry_run.py +1203 -0
  243. truefoundry/ml/run_utils.py +93 -0
  244. truefoundry/ml/session.py +168 -0
  245. truefoundry/ml/validation_utils.py +346 -0
  246. truefoundry/pydantic_v1.py +8 -1
  247. truefoundry/workflow/__init__.py +16 -1
  248. {truefoundry-0.3.4rc1.dist-info → truefoundry-0.4.0.dist-info}/METADATA +21 -14
  249. truefoundry-0.4.0.dist-info/RECORD +344 -0
  250. truefoundry/deploy/lib/clients/utils.py +0 -41
  251. truefoundry-0.3.4rc1.dist-info/RECORD +0 -136
  252. {truefoundry-0.3.4rc1.dist-info → truefoundry-0.4.0.dist-info}/WHEEL +0 -0
  253. {truefoundry-0.3.4rc1.dist-info → truefoundry-0.4.0.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,281 @@
1
+ import enum
2
+ import json
3
+ import os
4
+ import posixpath
5
+ import sys
6
+ import tempfile
7
+ from typing import TYPE_CHECKING, Union
8
+
9
+ from truefoundry.ml.autogen.client import ( # type: ignore[attr-defined]
10
+ ArtifactType,
11
+ )
12
+ from truefoundry.ml.exceptions import MlFoundryException
13
+ from truefoundry.ml.log_types.artifacts.artifact import (
14
+ ArtifactVersionInternalMetadata,
15
+ _log_artifact_version_helper,
16
+ )
17
+ from truefoundry.ml.log_types.artifacts.constants import (
18
+ FILES_DIR,
19
+ INTERNAL_METADATA_PATH,
20
+ )
21
+ from truefoundry.ml.log_types.pydantic_base import PydanticBase
22
+ from truefoundry.ml.log_types.utils import validate_key_name
23
+ from truefoundry.pydantic_v1 import BaseModel
24
+
25
+ if TYPE_CHECKING:
26
+ import matplotlib.figure
27
+ import matplotlib.pyplot
28
+ import plotly.graph_objects
29
+
30
+ from truefoundry.ml import MlFoundryRun
31
+
32
+ PlotObjType = Union[
33
+ "matplotlib.figure.Figure",
34
+ "plotly.graph_objects.Figure",
35
+ "matplotlib.pyplot",
36
+ ]
37
+
38
+
39
+ @enum.unique
40
+ class Format(enum.Enum):
41
+ SVG = "SVG"
42
+ HTML = "HTML"
43
+ PNG = "PNG"
44
+
45
+
46
+ def _is_matplotlib_figure(fig) -> bool:
47
+ if "matplotlib" not in sys.modules:
48
+ return False
49
+ import matplotlib
50
+
51
+ return isinstance(fig, matplotlib.figure.Figure)
52
+
53
+
54
+ def _is_matplotlib_plt(plt) -> bool:
55
+ if "matplotlib" not in sys.modules:
56
+ return False
57
+ return getattr(plt, "__name__", "") == "matplotlib.pyplot"
58
+
59
+
60
+ def _is_plotly_figure(fig) -> bool:
61
+ if "plotly" not in sys.modules:
62
+ return False
63
+
64
+ import plotly
65
+
66
+ return isinstance(fig, plotly.graph_objects.Figure)
67
+
68
+
69
+ def get_plot_file_name(format: Format) -> str:
70
+ return f"plot.{format.value.lower()}"
71
+
72
+
73
+ class PlotArtifact(BaseModel):
74
+ artifact_file: str
75
+ format: Format
76
+
77
+ class Config:
78
+ allow_mutation = False
79
+ use_enum_values = True
80
+
81
+
82
+ def _save_matplotlib_figure(
83
+ figure: "matplotlib.figure.Figure",
84
+ key: str,
85
+ step: int,
86
+ local_dir: str,
87
+ ) -> PlotArtifact:
88
+ supported_formats = figure.canvas.get_supported_filetypes().keys()
89
+ if "svg" in supported_formats:
90
+ format_ = Format.SVG
91
+ elif "png" in supported_formats:
92
+ format_ = Format.PNG
93
+ else:
94
+ raise MlFoundryException(
95
+ f"Could not save {key} {figure} matplotlib figure"
96
+ "in either SVG or PNG format"
97
+ )
98
+ file_path = get_plot_file_name(format=format_)
99
+ local_path = os.path.join(local_dir, file_path)
100
+ figure.savefig(local_path)
101
+ return PlotArtifact(artifact_file=file_path, format=format_)
102
+
103
+
104
+ def _save_matplotlib_plt(
105
+ plt: "matplotlib.pyplot",
106
+ key: str,
107
+ step: int,
108
+ local_dir: str,
109
+ ) -> PlotArtifact:
110
+ figure = plt.gcf()
111
+ return _save_matplotlib_figure(
112
+ figure=figure, key=key, step=step, local_dir=local_dir
113
+ )
114
+
115
+
116
+ def _save_plotly_figure(
117
+ figure: "plotly.graph_objects.Figure",
118
+ key: str,
119
+ step: int,
120
+ local_dir: str,
121
+ ) -> PlotArtifact:
122
+ format_ = Format.HTML
123
+ file_path = get_plot_file_name(format=format_)
124
+ local_path = os.path.join(local_dir, file_path)
125
+ figure.write_html(local_path, include_plotlyjs="cdn", auto_open=False)
126
+ return PlotArtifact(artifact_file=file_path, format=format_)
127
+
128
+
129
+ class Plot:
130
+ def __init__(self, plot_obj: PlotObjType):
131
+ self._plot_obj = plot_obj
132
+
133
+ def _save_plot(self, key: str, step: int, local_dir: str) -> PlotArtifact:
134
+ if _is_matplotlib_plt(self._plot_obj):
135
+ return _save_matplotlib_plt(
136
+ plt=self._plot_obj, key=key, step=step, local_dir=local_dir
137
+ )
138
+
139
+ if _is_matplotlib_figure(self._plot_obj):
140
+ return _save_matplotlib_figure(
141
+ figure=self._plot_obj, key=key, step=step, local_dir=local_dir
142
+ )
143
+
144
+ if _is_plotly_figure(self._plot_obj):
145
+ return _save_plotly_figure(
146
+ figure=self._plot_obj, key=key, step=step, local_dir=local_dir
147
+ )
148
+
149
+ raise MlFoundryException(
150
+ f"Unknown type: {type(self._plot_obj)}"
151
+ "Supported types are, matplotlib.figure.Figure, matplotlib.pyplot"
152
+ " and plotly.graph_objects.Figure"
153
+ )
154
+
155
+ def save(
156
+ self,
157
+ run: "MlFoundryRun",
158
+ key: str,
159
+ step: int = 0,
160
+ ):
161
+ validate_key_name(key)
162
+
163
+ # creating a temp dir which will be logged
164
+ temp_dir = tempfile.TemporaryDirectory(prefix="truefoundry-")
165
+ local_files_dir = os.path.join(temp_dir.name, FILES_DIR)
166
+ os.makedirs(local_files_dir, exist_ok=True)
167
+
168
+ # save plot locally
169
+ plot_artifact = self._save_plot(key=key, step=step, local_dir=local_files_dir)
170
+
171
+ # save internal metadata
172
+ internal_metadata = PlotVersionInternalMetadata(
173
+ files_dir=FILES_DIR,
174
+ plot_file=posixpath.join(FILES_DIR, plot_artifact.artifact_file),
175
+ )
176
+ local_internal_metadata_path = os.path.join(
177
+ temp_dir.name, INTERNAL_METADATA_PATH
178
+ )
179
+ os.makedirs(os.path.dirname(local_internal_metadata_path), exist_ok=True)
180
+ with open(local_internal_metadata_path, "w") as f:
181
+ json.dump(internal_metadata.dict(), f)
182
+
183
+ # log the artifact
184
+ _log_artifact_version_helper(
185
+ run=run,
186
+ name=key,
187
+ artifact_type=ArtifactType.PLOT,
188
+ artifact_dir=temp_dir,
189
+ internal_metadata=internal_metadata,
190
+ step=step,
191
+ )
192
+
193
+
194
+ class PlotRunLogType(PydanticBase):
195
+ value: PlotArtifact
196
+
197
+ @staticmethod
198
+ def get_log_type() -> str:
199
+ return "plot"
200
+
201
+
202
+ class PlotVersionInternalMetadata(ArtifactVersionInternalMetadata):
203
+ plot_file: str
204
+
205
+
206
+ if __name__ == "__main__":
207
+ import matplotlib.pyplot as plt
208
+ import numpy as np
209
+ import plotly.express as px
210
+
211
+ from truefoundry.ml import get_client
212
+
213
+ client = get_client()
214
+
215
+ run = client.create_run(ml_repo="plot-test1")
216
+
217
+ df = px.data.iris()
218
+ fig = px.scatter(
219
+ df,
220
+ x="sepal_width",
221
+ y="sepal_length",
222
+ color="species",
223
+ size="petal_length",
224
+ hover_data=["petal_width"],
225
+ )
226
+ Plot(fig).save(run, "foo")
227
+
228
+ df = px.data.tips()
229
+ fig = px.histogram(
230
+ df,
231
+ x="total_bill",
232
+ y="tip",
233
+ color="sex",
234
+ marginal="rug",
235
+ hover_data=df.columns,
236
+ )
237
+ Plot(fig).save(run, "foo", step=1)
238
+
239
+ names = ["group_a", "group_b", "group_c"]
240
+ values = [1, 10, 100]
241
+ plt.figure(figsize=(9, 3))
242
+ plt.subplot(131)
243
+ plt.bar(names, values)
244
+ plt.subplot(132)
245
+ plt.scatter(names, values)
246
+ plt.subplot(133)
247
+ plt.plot(names, values)
248
+ plt.suptitle("Categorical Plotting")
249
+
250
+ Plot(plt).save(run, "bar")
251
+
252
+ plt.clf()
253
+
254
+ data = {
255
+ "a": np.arange(50),
256
+ "c": np.random.randint(0, 50, 50),
257
+ "d": np.random.randn(50),
258
+ }
259
+ data["b"] = data["a"] + 10 * np.random.randn(50)
260
+ data["d"] = np.abs(data["d"]) * 100
261
+ plt.scatter("a", "b", c="c", s="d", data=data)
262
+ plt.xlabel("entry a")
263
+ plt.ylabel("entry b")
264
+ Plot(plt).save(run, "bar", 2)
265
+
266
+ plt.clf()
267
+
268
+ ax = plt.subplot()
269
+ t = np.arange(0.0, 5.0, 0.01)
270
+ s = np.cos(2 * np.pi * t)
271
+ (line,) = plt.plot(t, s, lw=2)
272
+
273
+ plt.annotate(
274
+ "local max",
275
+ xy=(2, 1),
276
+ xytext=(3, 1.5),
277
+ arrowprops={"facecolor": "black", "shrink": 0.05},
278
+ )
279
+
280
+ plt.ylim(-2, 2)
281
+ Plot(plt.gcf()).save(run, "bar", 3)
@@ -0,0 +1,10 @@
1
+ from truefoundry.pydantic_v1 import BaseModel
2
+
3
+
4
+ class PydanticBase(BaseModel):
5
+ # I can make this a property,
6
+ # but <3.9, it is difficult to access
7
+ # property from classmethod
8
+ @staticmethod
9
+ def get_log_type() -> str:
10
+ raise NotImplementedError()
@@ -0,0 +1,12 @@
1
+ import re
2
+
3
+ from truefoundry.ml.exceptions import MlFoundryException
4
+
5
+ KEY_REGEX = re.compile(r"^[a-zA-Z0-9-_]+$")
6
+
7
+
8
+ def validate_key_name(key: str):
9
+ if not key or not KEY_REGEX.match(key):
10
+ raise MlFoundryException(
11
+ f"Invalid run image key: {key} should only contain alphanumeric, hyphen or underscore"
12
+ )
@@ -0,0 +1,17 @@
1
+ import logging
2
+ import sys
3
+
4
+ logger = logging.getLogger("truefoundry.ml")
5
+
6
+
7
+ def init_logger(level=logging.INFO):
8
+ handler = logging.StreamHandler(sys.stdout)
9
+ handler.setLevel(level)
10
+ formatter = logging.Formatter(
11
+ "[%(name)s] %(asctime)s %(levelname)s %(message)s",
12
+ datefmt="%Y-%m-%dT%H:%M:%S%z",
13
+ )
14
+ handler.setFormatter(formatter)
15
+ logger.addHandler(handler)
16
+ logger.setLevel(logging.DEBUG)
17
+ logger.propagate = False