ob-metaflow-stubs 6.0.3.156__py2.py3-none-any.whl → 6.0.3.157__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. metaflow-stubs/__init__.pyi +721 -606
  2. metaflow-stubs/cards.pyi +2 -2
  3. metaflow-stubs/cli.pyi +2 -2
  4. metaflow-stubs/cli_components/__init__.pyi +2 -2
  5. metaflow-stubs/cli_components/utils.pyi +2 -2
  6. metaflow-stubs/client/__init__.pyi +2 -2
  7. metaflow-stubs/client/core.pyi +5 -5
  8. metaflow-stubs/client/filecache.pyi +2 -2
  9. metaflow-stubs/events.pyi +3 -3
  10. metaflow-stubs/exception.pyi +2 -2
  11. metaflow-stubs/flowspec.pyi +5 -5
  12. metaflow-stubs/generated_for.txt +1 -1
  13. metaflow-stubs/includefile.pyi +4 -4
  14. metaflow-stubs/info_file.pyi +2 -2
  15. metaflow-stubs/metadata_provider/__init__.pyi +2 -2
  16. metaflow-stubs/metadata_provider/heartbeat.pyi +2 -2
  17. metaflow-stubs/metadata_provider/metadata.pyi +3 -3
  18. metaflow-stubs/metadata_provider/util.pyi +2 -2
  19. metaflow-stubs/metaflow_config.pyi +2 -2
  20. metaflow-stubs/metaflow_current.pyi +87 -87
  21. metaflow-stubs/mf_extensions/__init__.pyi +2 -2
  22. metaflow-stubs/mf_extensions/obcheckpoint/__init__.pyi +2 -2
  23. metaflow-stubs/mf_extensions/obcheckpoint/plugins/__init__.pyi +2 -2
  24. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/__init__.pyi +2 -2
  25. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/card_utils/__init__.pyi +2 -2
  26. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/card_utils/async_cards.pyi +3 -3
  27. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/card_utils/deco_injection_mixin.pyi +2 -2
  28. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/card_utils/extra_components.pyi +4 -4
  29. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/__init__.pyi +2 -2
  30. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/cards/__init__.pyi +2 -2
  31. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/cards/checkpoint_lister.pyi +6 -6
  32. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/cards/lineage_card.pyi +2 -2
  33. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/checkpoint_storage.pyi +7 -5
  34. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/constructors.pyi +2 -2
  35. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/core.pyi +11 -5
  36. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/decorator.pyi +6 -5
  37. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/exceptions.pyi +2 -2
  38. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/final_api.pyi +5 -3
  39. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/lineage.pyi +2 -2
  40. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/datastore/__init__.pyi +2 -2
  41. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/datastore/context.pyi +95 -0
  42. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/datastore/core.pyi +7 -9
  43. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/datastore/decorator.pyi +135 -0
  44. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/datastore/exceptions.pyi +2 -2
  45. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/datastore/task_utils.pyi +33 -5
  46. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/datastore/utils.pyi +2 -2
  47. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/datastructures.pyi +3 -3
  48. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/exceptions.pyi +2 -2
  49. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/hf_hub/__init__.pyi +2 -2
  50. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/hf_hub/decorator.pyi +3 -3
  51. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/modeling_utils/__init__.pyi +2 -2
  52. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/modeling_utils/core.pyi +3 -3
  53. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/modeling_utils/exceptions.pyi +2 -2
  54. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/modeling_utils/model_storage.pyi +4 -4
  55. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/utils/__init__.pyi +2 -2
  56. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/utils/flowspec_utils.pyi +2 -2
  57. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/utils/general.pyi +2 -2
  58. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/utils/identity_utils.pyi +3 -3
  59. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/utils/serialization_handler/__init__.pyi +2 -2
  60. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/utils/serialization_handler/base.pyi +2 -2
  61. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/utils/serialization_handler/tar.pyi +3 -3
  62. metaflow-stubs/mf_extensions/obcheckpoint/plugins/machine_learning_utilities/utils/tar_utils.pyi +3 -3
  63. metaflow-stubs/mf_extensions/outerbounds/__init__.pyi +2 -2
  64. metaflow-stubs/mf_extensions/outerbounds/plugins/__init__.pyi +2 -2
  65. metaflow-stubs/mf_extensions/outerbounds/plugins/card_utilities/__init__.pyi +2 -2
  66. metaflow-stubs/mf_extensions/outerbounds/plugins/card_utilities/injector.pyi +2 -2
  67. metaflow-stubs/mf_extensions/outerbounds/plugins/ollama/__init__.pyi +2 -2
  68. metaflow-stubs/mf_extensions/outerbounds/plugins/ollama/ollama.pyi +2 -2
  69. metaflow-stubs/mf_extensions/outerbounds/plugins/snowflake/__init__.pyi +2 -2
  70. metaflow-stubs/mf_extensions/outerbounds/plugins/snowflake/snowflake.pyi +2 -2
  71. metaflow-stubs/mf_extensions/outerbounds/profilers/__init__.pyi +2 -2
  72. metaflow-stubs/mf_extensions/outerbounds/profilers/gpu.pyi +2 -2
  73. metaflow-stubs/mf_extensions/outerbounds/remote_config.pyi +2 -2
  74. metaflow-stubs/mf_extensions/outerbounds/toplevel/__init__.pyi +2 -2
  75. metaflow-stubs/mf_extensions/outerbounds/toplevel/global_aliases_for_metaflow_package.pyi +2 -2
  76. metaflow-stubs/multicore_utils.pyi +2 -2
  77. metaflow-stubs/parameters.pyi +4 -4
  78. metaflow-stubs/plugins/__init__.pyi +11 -11
  79. metaflow-stubs/plugins/airflow/__init__.pyi +2 -2
  80. metaflow-stubs/plugins/airflow/airflow_utils.pyi +2 -2
  81. metaflow-stubs/plugins/airflow/exception.pyi +2 -2
  82. metaflow-stubs/plugins/airflow/sensors/__init__.pyi +2 -2
  83. metaflow-stubs/plugins/airflow/sensors/base_sensor.pyi +2 -2
  84. metaflow-stubs/plugins/airflow/sensors/external_task_sensor.pyi +2 -2
  85. metaflow-stubs/plugins/airflow/sensors/s3_sensor.pyi +2 -2
  86. metaflow-stubs/plugins/argo/__init__.pyi +2 -2
  87. metaflow-stubs/plugins/argo/argo_client.pyi +2 -2
  88. metaflow-stubs/plugins/argo/argo_events.pyi +2 -2
  89. metaflow-stubs/plugins/argo/argo_workflows.pyi +4 -4
  90. metaflow-stubs/plugins/argo/argo_workflows_decorator.pyi +3 -3
  91. metaflow-stubs/plugins/argo/argo_workflows_deployer.pyi +3 -3
  92. metaflow-stubs/plugins/argo/argo_workflows_deployer_objects.pyi +4 -4
  93. metaflow-stubs/plugins/aws/__init__.pyi +2 -2
  94. metaflow-stubs/plugins/aws/aws_client.pyi +2 -2
  95. metaflow-stubs/plugins/aws/aws_utils.pyi +2 -2
  96. metaflow-stubs/plugins/aws/batch/__init__.pyi +2 -2
  97. metaflow-stubs/plugins/aws/batch/batch.pyi +2 -2
  98. metaflow-stubs/plugins/aws/batch/batch_client.pyi +2 -2
  99. metaflow-stubs/plugins/aws/batch/batch_decorator.pyi +2 -2
  100. metaflow-stubs/plugins/aws/secrets_manager/__init__.pyi +2 -2
  101. metaflow-stubs/plugins/aws/secrets_manager/aws_secrets_manager_secrets_provider.pyi +4 -4
  102. metaflow-stubs/plugins/aws/step_functions/__init__.pyi +2 -2
  103. metaflow-stubs/plugins/aws/step_functions/event_bridge_client.pyi +2 -2
  104. metaflow-stubs/plugins/aws/step_functions/schedule_decorator.pyi +2 -2
  105. metaflow-stubs/plugins/aws/step_functions/step_functions.pyi +2 -2
  106. metaflow-stubs/plugins/aws/step_functions/step_functions_client.pyi +2 -2
  107. metaflow-stubs/plugins/aws/step_functions/step_functions_deployer.pyi +4 -4
  108. metaflow-stubs/plugins/aws/step_functions/step_functions_deployer_objects.pyi +4 -4
  109. metaflow-stubs/plugins/azure/__init__.pyi +2 -2
  110. metaflow-stubs/plugins/azure/azure_credential.pyi +2 -2
  111. metaflow-stubs/plugins/azure/azure_exceptions.pyi +2 -2
  112. metaflow-stubs/plugins/azure/azure_secret_manager_secrets_provider.pyi +4 -4
  113. metaflow-stubs/plugins/azure/azure_utils.pyi +2 -2
  114. metaflow-stubs/plugins/azure/blob_service_client_factory.pyi +2 -2
  115. metaflow-stubs/plugins/azure/includefile_support.pyi +2 -2
  116. metaflow-stubs/plugins/cards/__init__.pyi +2 -2
  117. metaflow-stubs/plugins/cards/card_client.pyi +3 -3
  118. metaflow-stubs/plugins/cards/card_creator.pyi +2 -2
  119. metaflow-stubs/plugins/cards/card_datastore.pyi +2 -2
  120. metaflow-stubs/plugins/cards/card_decorator.pyi +2 -2
  121. metaflow-stubs/plugins/cards/card_modules/__init__.pyi +2 -2
  122. metaflow-stubs/plugins/cards/card_modules/basic.pyi +3 -3
  123. metaflow-stubs/plugins/cards/card_modules/card.pyi +2 -2
  124. metaflow-stubs/plugins/cards/card_modules/components.pyi +4 -4
  125. metaflow-stubs/plugins/cards/card_modules/convert_to_native_type.pyi +2 -2
  126. metaflow-stubs/plugins/cards/card_modules/renderer_tools.pyi +2 -2
  127. metaflow-stubs/plugins/cards/card_modules/test_cards.pyi +2 -2
  128. metaflow-stubs/plugins/cards/card_resolver.pyi +2 -2
  129. metaflow-stubs/plugins/cards/component_serializer.pyi +2 -2
  130. metaflow-stubs/plugins/cards/exception.pyi +2 -2
  131. metaflow-stubs/plugins/catch_decorator.pyi +2 -2
  132. metaflow-stubs/plugins/datatools/__init__.pyi +2 -2
  133. metaflow-stubs/plugins/datatools/local.pyi +2 -2
  134. metaflow-stubs/plugins/datatools/s3/__init__.pyi +2 -2
  135. metaflow-stubs/plugins/datatools/s3/s3.pyi +4 -4
  136. metaflow-stubs/plugins/datatools/s3/s3tail.pyi +2 -2
  137. metaflow-stubs/plugins/datatools/s3/s3util.pyi +2 -2
  138. metaflow-stubs/plugins/debug_logger.pyi +2 -2
  139. metaflow-stubs/plugins/debug_monitor.pyi +2 -2
  140. metaflow-stubs/plugins/environment_decorator.pyi +2 -2
  141. metaflow-stubs/plugins/events_decorator.pyi +2 -2
  142. metaflow-stubs/plugins/frameworks/__init__.pyi +2 -2
  143. metaflow-stubs/plugins/frameworks/pytorch.pyi +2 -2
  144. metaflow-stubs/plugins/gcp/__init__.pyi +2 -2
  145. metaflow-stubs/plugins/gcp/gcp_secret_manager_secrets_provider.pyi +4 -4
  146. metaflow-stubs/plugins/gcp/gs_exceptions.pyi +2 -2
  147. metaflow-stubs/plugins/gcp/gs_storage_client_factory.pyi +2 -2
  148. metaflow-stubs/plugins/gcp/gs_utils.pyi +2 -2
  149. metaflow-stubs/plugins/gcp/includefile_support.pyi +2 -2
  150. metaflow-stubs/plugins/kubernetes/__init__.pyi +2 -2
  151. metaflow-stubs/plugins/kubernetes/kube_utils.pyi +3 -3
  152. metaflow-stubs/plugins/kubernetes/kubernetes.pyi +2 -2
  153. metaflow-stubs/plugins/kubernetes/kubernetes_client.pyi +2 -2
  154. metaflow-stubs/plugins/kubernetes/kubernetes_decorator.pyi +2 -2
  155. metaflow-stubs/plugins/kubernetes/kubernetes_jobsets.pyi +2 -2
  156. metaflow-stubs/plugins/kubernetes/spot_monitor_sidecar.pyi +2 -2
  157. metaflow-stubs/plugins/ollama/__init__.pyi +3 -3
  158. metaflow-stubs/plugins/parallel_decorator.pyi +2 -2
  159. metaflow-stubs/plugins/perimeters.pyi +2 -2
  160. metaflow-stubs/plugins/project_decorator.pyi +2 -2
  161. metaflow-stubs/plugins/pypi/__init__.pyi +3 -3
  162. metaflow-stubs/plugins/pypi/conda_decorator.pyi +2 -2
  163. metaflow-stubs/plugins/pypi/conda_environment.pyi +5 -5
  164. metaflow-stubs/plugins/pypi/parsers.pyi +2 -2
  165. metaflow-stubs/plugins/pypi/pypi_decorator.pyi +2 -2
  166. metaflow-stubs/plugins/pypi/pypi_environment.pyi +2 -2
  167. metaflow-stubs/plugins/pypi/utils.pyi +2 -2
  168. metaflow-stubs/plugins/resources_decorator.pyi +2 -2
  169. metaflow-stubs/plugins/retry_decorator.pyi +2 -2
  170. metaflow-stubs/plugins/secrets/__init__.pyi +2 -2
  171. metaflow-stubs/plugins/secrets/inline_secrets_provider.pyi +3 -3
  172. metaflow-stubs/plugins/secrets/secrets_decorator.pyi +2 -2
  173. metaflow-stubs/plugins/snowflake/__init__.pyi +2 -2
  174. metaflow-stubs/plugins/storage_executor.pyi +2 -2
  175. metaflow-stubs/plugins/test_unbounded_foreach_decorator.pyi +2 -2
  176. metaflow-stubs/plugins/timeout_decorator.pyi +2 -2
  177. metaflow-stubs/profilers/__init__.pyi +2 -2
  178. metaflow-stubs/pylint_wrapper.pyi +2 -2
  179. metaflow-stubs/runner/__init__.pyi +2 -2
  180. metaflow-stubs/runner/deployer.pyi +30 -30
  181. metaflow-stubs/runner/deployer_impl.pyi +3 -3
  182. metaflow-stubs/runner/metaflow_runner.pyi +4 -4
  183. metaflow-stubs/runner/nbdeploy.pyi +2 -2
  184. metaflow-stubs/runner/nbrun.pyi +2 -2
  185. metaflow-stubs/runner/subprocess_manager.pyi +2 -2
  186. metaflow-stubs/runner/utils.pyi +3 -3
  187. metaflow-stubs/system/__init__.pyi +2 -2
  188. metaflow-stubs/system/system_logger.pyi +3 -3
  189. metaflow-stubs/system/system_monitor.pyi +2 -2
  190. metaflow-stubs/tagging_util.pyi +2 -2
  191. metaflow-stubs/tuple_util.pyi +2 -2
  192. metaflow-stubs/user_configs/__init__.pyi +2 -2
  193. metaflow-stubs/user_configs/config_decorators.pyi +6 -6
  194. metaflow-stubs/user_configs/config_options.pyi +4 -4
  195. metaflow-stubs/user_configs/config_parameters.pyi +6 -6
  196. {ob_metaflow_stubs-6.0.3.156.dist-info → ob_metaflow_stubs-6.0.3.157.dist-info}/METADATA +1 -1
  197. ob_metaflow_stubs-6.0.3.157.dist-info/RECORD +200 -0
  198. ob_metaflow_stubs-6.0.3.156.dist-info/RECORD +0 -198
  199. {ob_metaflow_stubs-6.0.3.156.dist-info → ob_metaflow_stubs-6.0.3.157.dist-info}/WHEEL +0 -0
  200. {ob_metaflow_stubs-6.0.3.156.dist-info → ob_metaflow_stubs-6.0.3.157.dist-info}/top_level.txt +0 -0
@@ -1,15 +1,15 @@
1
1
  ######################################################################################################
2
2
  # Auto-generated Metaflow stub file #
3
- # MF version: 2.15.7.2+obcheckpoint(0.1.9);ob(v1) #
4
- # Generated on 2025-04-16T21:50:24.175279 #
3
+ # MF version: 2.15.7.2+obcheckpoint(0.2.1);ob(v1) #
4
+ # Generated on 2025-04-17T01:41:06.563175 #
5
5
  ######################################################################################################
6
6
 
7
7
  from __future__ import annotations
8
8
 
9
9
  import typing
10
10
  if typing.TYPE_CHECKING:
11
- import datetime
12
11
  import typing
12
+ import datetime
13
13
  FlowSpecDerived = typing.TypeVar("FlowSpecDerived", bound="FlowSpec", contravariant=False, covariant=False)
14
14
  StepFlag = typing.NewType("StepFlag", bool)
15
15
 
@@ -35,17 +35,17 @@ from .user_configs.config_parameters import ConfigValue as ConfigValue
35
35
  from .user_configs.config_parameters import config_expr as config_expr
36
36
  from .user_configs.config_decorators import CustomFlowDecorator as CustomFlowDecorator
37
37
  from .user_configs.config_decorators import CustomStepDecorator as CustomStepDecorator
38
+ from . import events as events
38
39
  from . import tuple_util as tuple_util
39
40
  from . import cards as cards
40
- from . import events as events
41
41
  from . import runner as runner
42
42
  from . import plugins as plugins
43
43
  from .mf_extensions.outerbounds.toplevel.global_aliases_for_metaflow_package import S3 as S3
44
44
  from . import includefile as includefile
45
45
  from .includefile import IncludeFile as IncludeFile
46
+ from .plugins.pypi.parsers import pyproject_toml_parser as pyproject_toml_parser
46
47
  from .plugins.pypi.parsers import requirements_txt_parser as requirements_txt_parser
47
48
  from .plugins.pypi.parsers import conda_environment_yml_parser as conda_environment_yml_parser
48
- from .plugins.pypi.parsers import pyproject_toml_parser as pyproject_toml_parser
49
49
  from . import client as client
50
50
  from .client.core import namespace as namespace
51
51
  from .client.core import get_namespace as get_namespace
@@ -66,6 +66,7 @@ from .runner.deployer import DeployedFlow as DeployedFlow
66
66
  from .runner.nbdeploy import NBDeployer as NBDeployer
67
67
  from .mf_extensions.obcheckpoint.plugins.machine_learning_utilities.checkpoints.final_api import Checkpoint as Checkpoint
68
68
  from .mf_extensions.obcheckpoint.plugins.machine_learning_utilities.datastructures import load_model as load_model
69
+ from .mf_extensions.obcheckpoint.plugins.machine_learning_utilities.datastore.context import artifact_store_from as artifact_store_from
69
70
  from .mf_extensions.outerbounds.toplevel.global_aliases_for_metaflow_package import get_aws_client as get_aws_client
70
71
  from .mf_extensions.outerbounds.plugins.snowflake.snowflake import Snowflake as Snowflake
71
72
  from . import cli_components as cli_components
@@ -149,206 +150,188 @@ def step(f: typing.Union[typing.Callable[[FlowSpecDerived], None], typing.Callab
149
150
  """
150
151
  ...
151
152
 
152
- def nvidia(*, gpu: int, gpu_type: str, queue_timeout: int) -> typing.Callable[[typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]], typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]]:
153
+ def huggingface_hub(*, temp_dir_root: typing.Optional[str] = None, load: typing.Union[typing.List[str], typing.List[typing.Tuple[typing.Dict, str]], typing.List[typing.Tuple[str, str]], typing.List[typing.Dict], None]) -> typing.Callable[[typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]], typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]]:
153
154
  """
154
- Specifies that this step should execute on DGX cloud.
155
+ Decorator that helps cache, version and store models/datasets from huggingface hub.
155
156
 
156
157
 
157
158
  Parameters
158
159
  ----------
159
- gpu : int
160
- Number of GPUs to use.
161
- gpu_type : str
162
- Type of Nvidia GPU to use.
163
- queue_timeout : int
164
- Time to keep the job in NVCF's queue.
160
+ temp_dir_root : str, optional
161
+ The root directory that will hold the temporary directory where objects will be downloaded.
162
+
163
+ load: Union[List[str], List[Tuple[Dict, str]], List[Tuple[str, str]], List[Dict], None]
164
+ The list of repos (models/datasets) to load.
165
+
166
+ Loaded repos can be accessed via `current.huggingface_hub.loaded`. If load is set, then the following happens:
167
+
168
+ - If repo (model/dataset) is not found in the datastore:
169
+ - Downloads the repo from Hugging Face Hub to a temporary directory (or uses specified path) for local access
170
+ - Stores it in Metaflow's datastore (s3/gcs/azure etc.) with a unique name based on repo_type/repo_id
171
+ - All HF models loaded for a `@step` will be cached separately under flow/step/namespace.
172
+
173
+ - If repo is found in the datastore:
174
+ - Loads it directly from datastore to local path (can be temporary directory or specified path)
165
175
  """
166
176
  ...
167
177
 
168
178
  @typing.overload
169
- def catch(*, var: typing.Optional[str] = None, print_exception: bool = True) -> typing.Callable[[typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]], typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]]:
179
+ def model(*, load: typing.Union[typing.List[str], str, typing.List[typing.Tuple[str, typing.Optional[str]]]] = None, temp_dir_root: str = None) -> typing.Callable[[typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]], typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]]:
170
180
  """
171
- Specifies that the step will success under all circumstances.
181
+ Enables loading / saving of models within a step.
172
182
 
173
- The decorator will create an optional artifact, specified by `var`, which
174
- contains the exception raised. You can use it to detect the presence
175
- of errors, indicating that all happy-path artifacts produced by the step
176
- are missing.
177
183
 
178
184
 
179
185
  Parameters
180
186
  ----------
181
- var : str, optional, default None
182
- Name of the artifact in which to store the caught exception.
183
- If not specified, the exception is not stored.
184
- print_exception : bool, default True
185
- Determines whether or not the exception is printed to
186
- stdout when caught.
187
+ load : Union[List[str],str,List[Tuple[str,Union[str,None]]]], default: None
188
+ Artifact name/s referencing the models/checkpoints to load. Artifact names refer to the names of the instance variables set to `self`.
189
+ These artifact names give to `load` be reference objects or reference `key` string's from objects created by:
190
+ - `current.checkpoint`
191
+ - `current.model`
192
+ - `current.huggingface_hub`
193
+
194
+ If a list of tuples is provided, the first element is the artifact name and the second element is the path the artifact needs be unpacked on
195
+ the local filesystem. If the second element is None, the artifact will be unpacked in the current working directory.
196
+ If a string is provided, then the artifact corresponding to that name will be loaded in the current working directory.
197
+
198
+ temp_dir_root : str, default: None
199
+ The root directory under which `current.model.loaded` will store loaded models
187
200
  """
188
201
  ...
189
202
 
190
203
  @typing.overload
191
- def catch(f: typing.Callable[[FlowSpecDerived, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, StepFlag], None]:
204
+ def model(f: typing.Callable[[FlowSpecDerived, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, StepFlag], None]:
192
205
  ...
193
206
 
194
207
  @typing.overload
195
- def catch(f: typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]:
208
+ def model(f: typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]:
196
209
  ...
197
210
 
198
- def catch(f: typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None], None] = None, *, var: typing.Optional[str] = None, print_exception: bool = True):
211
+ def model(f: typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None], None] = None, *, load: typing.Union[typing.List[str], str, typing.List[typing.Tuple[str, typing.Optional[str]]]] = None, temp_dir_root: str = None):
199
212
  """
200
- Specifies that the step will success under all circumstances.
213
+ Enables loading / saving of models within a step.
201
214
 
202
- The decorator will create an optional artifact, specified by `var`, which
203
- contains the exception raised. You can use it to detect the presence
204
- of errors, indicating that all happy-path artifacts produced by the step
205
- are missing.
206
215
 
207
216
 
208
217
  Parameters
209
218
  ----------
210
- var : str, optional, default None
211
- Name of the artifact in which to store the caught exception.
212
- If not specified, the exception is not stored.
213
- print_exception : bool, default True
214
- Determines whether or not the exception is printed to
215
- stdout when caught.
219
+ load : Union[List[str],str,List[Tuple[str,Union[str,None]]]], default: None
220
+ Artifact name/s referencing the models/checkpoints to load. Artifact names refer to the names of the instance variables set to `self`.
221
+ These artifact names give to `load` be reference objects or reference `key` string's from objects created by:
222
+ - `current.checkpoint`
223
+ - `current.model`
224
+ - `current.huggingface_hub`
225
+
226
+ If a list of tuples is provided, the first element is the artifact name and the second element is the path the artifact needs be unpacked on
227
+ the local filesystem. If the second element is None, the artifact will be unpacked in the current working directory.
228
+ If a string is provided, then the artifact corresponding to that name will be loaded in the current working directory.
229
+
230
+ temp_dir_root : str, default: None
231
+ The root directory under which `current.model.loaded` will store loaded models
216
232
  """
217
233
  ...
218
234
 
219
235
  @typing.overload
220
- def resources(*, cpu: int = 1, gpu: typing.Optional[int] = None, disk: typing.Optional[int] = None, memory: int = 4096, shared_memory: typing.Optional[int] = None) -> typing.Callable[[typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]], typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]]:
236
+ def pypi(*, packages: typing.Dict[str, str] = {}, python: typing.Optional[str] = None) -> typing.Callable[[typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]], typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]]:
221
237
  """
222
- Specifies the resources needed when executing this step.
223
-
224
- Use `@resources` to specify the resource requirements
225
- independently of the specific compute layer (`@batch`, `@kubernetes`).
238
+ Specifies the PyPI packages for the step.
226
239
 
227
- You can choose the compute layer on the command line by executing e.g.
228
- ```
229
- python myflow.py run --with batch
230
- ```
231
- or
232
- ```
233
- python myflow.py run --with kubernetes
234
- ```
235
- which executes the flow on the desired system using the
236
- requirements specified in `@resources`.
240
+ Information in this decorator will augment any
241
+ attributes set in the `@pyi_base` flow-level decorator. Hence,
242
+ you can use `@pypi_base` to set packages required by all
243
+ steps and use `@pypi` to specify step-specific overrides.
237
244
 
238
245
 
239
246
  Parameters
240
247
  ----------
241
- cpu : int, default 1
242
- Number of CPUs required for this step.
243
- gpu : int, optional, default None
244
- Number of GPUs required for this step.
245
- disk : int, optional, default None
246
- Disk size (in MB) required for this step. Only applies on Kubernetes.
247
- memory : int, default 4096
248
- Memory size (in MB) required for this step.
249
- shared_memory : int, optional, default None
250
- The value for the size (in MiB) of the /dev/shm volume for this step.
251
- This parameter maps to the `--shm-size` option in Docker.
248
+ packages : Dict[str, str], default: {}
249
+ Packages to use for this step. The key is the name of the package
250
+ and the value is the version to use.
251
+ python : str, optional, default: None
252
+ Version of Python to use, e.g. '3.7.4'. A default value of None implies
253
+ that the version used will correspond to the version of the Python interpreter used to start the run.
252
254
  """
253
255
  ...
254
256
 
255
257
  @typing.overload
256
- def resources(f: typing.Callable[[FlowSpecDerived, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, StepFlag], None]:
258
+ def pypi(f: typing.Callable[[FlowSpecDerived, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, StepFlag], None]:
257
259
  ...
258
260
 
259
261
  @typing.overload
260
- def resources(f: typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]:
262
+ def pypi(f: typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]:
261
263
  ...
262
264
 
263
- def resources(f: typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None], None] = None, *, cpu: int = 1, gpu: typing.Optional[int] = None, disk: typing.Optional[int] = None, memory: int = 4096, shared_memory: typing.Optional[int] = None):
265
+ def pypi(f: typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None], None] = None, *, packages: typing.Dict[str, str] = {}, python: typing.Optional[str] = None):
264
266
  """
265
- Specifies the resources needed when executing this step.
266
-
267
- Use `@resources` to specify the resource requirements
268
- independently of the specific compute layer (`@batch`, `@kubernetes`).
267
+ Specifies the PyPI packages for the step.
269
268
 
270
- You can choose the compute layer on the command line by executing e.g.
271
- ```
272
- python myflow.py run --with batch
273
- ```
274
- or
275
- ```
276
- python myflow.py run --with kubernetes
277
- ```
278
- which executes the flow on the desired system using the
279
- requirements specified in `@resources`.
269
+ Information in this decorator will augment any
270
+ attributes set in the `@pyi_base` flow-level decorator. Hence,
271
+ you can use `@pypi_base` to set packages required by all
272
+ steps and use `@pypi` to specify step-specific overrides.
280
273
 
281
274
 
282
275
  Parameters
283
276
  ----------
284
- cpu : int, default 1
285
- Number of CPUs required for this step.
286
- gpu : int, optional, default None
287
- Number of GPUs required for this step.
288
- disk : int, optional, default None
289
- Disk size (in MB) required for this step. Only applies on Kubernetes.
290
- memory : int, default 4096
291
- Memory size (in MB) required for this step.
292
- shared_memory : int, optional, default None
293
- The value for the size (in MiB) of the /dev/shm volume for this step.
294
- This parameter maps to the `--shm-size` option in Docker.
277
+ packages : Dict[str, str], default: {}
278
+ Packages to use for this step. The key is the name of the package
279
+ and the value is the version to use.
280
+ python : str, optional, default: None
281
+ Version of Python to use, e.g. '3.7.4'. A default value of None implies
282
+ that the version used will correspond to the version of the Python interpreter used to start the run.
295
283
  """
296
284
  ...
297
285
 
298
- @typing.overload
299
- def checkpoint(*, load_policy: str = 'fresh', temp_dir_root: str = None) -> typing.Callable[[typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]], typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]]:
286
+ def nim(*, models: "list[NIM]", backend: str, queue_timeout: int) -> typing.Callable[[typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]], typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]]:
300
287
  """
301
- Enables checkpointing for a step.
288
+ This decorator is used to run NIM containers in Metaflow tasks as sidecars.
289
+
290
+ User code call
291
+ -----------
292
+ @nim(
293
+ models=['meta/llama3-8b-instruct', 'meta/llama3-70b-instruct'],
294
+ backend='managed'
295
+ )
296
+
297
+ Valid backend options
298
+ ---------------------
299
+ - 'managed': Outerbounds selects a compute provider based on the model.
302
300
 
301
+ Valid model options
302
+ ----------------
303
+ - 'meta/llama3-8b-instruct': 8B parameter model
304
+ - 'meta/llama3-70b-instruct': 70B parameter model
305
+ - any model here: https://nvcf.ngc.nvidia.com/functions?filter=nvidia-functions
303
306
 
304
307
 
305
308
  Parameters
306
309
  ----------
307
- load_policy : str, default: "fresh"
308
- The policy for loading the checkpoint. The following policies are supported:
309
- - "eager": Loads the the latest available checkpoint within the namespace.
310
- With this mode, the latest checkpoint written by any previous task (can be even a different run) of the step
311
- will be loaded at the start of the task.
312
- - "none": Do not load any checkpoint
313
- - "fresh": Loads the lastest checkpoint created within the running Task.
314
- This mode helps loading checkpoints across various retry attempts of the same task.
315
- With this mode, no checkpoint will be loaded at the start of a task but any checkpoints
316
- created within the task will be loaded when the task is retries execution on failure.
317
-
318
- temp_dir_root : str, default: None
319
- The root directory under which `current.checkpoint.directory` will be created.
310
+ models: list[NIM]
311
+ List of NIM containers running models in sidecars.
312
+ backend: str
313
+ Compute provider to run the NIM container.
314
+ queue_timeout : int
315
+ Time to keep the job in NVCF's queue.
320
316
  """
321
317
  ...
322
318
 
323
319
  @typing.overload
324
- def checkpoint(f: typing.Callable[[FlowSpecDerived, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, StepFlag], None]:
320
+ def parallel(f: typing.Callable[[FlowSpecDerived, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, StepFlag], None]:
321
+ """
322
+ Decorator prototype for all step decorators. This function gets specialized
323
+ and imported for all decorators types by _import_plugin_decorators().
324
+ """
325
325
  ...
326
326
 
327
327
  @typing.overload
328
- def checkpoint(f: typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]:
328
+ def parallel(f: typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]:
329
329
  ...
330
330
 
331
- def checkpoint(f: typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None], None] = None, *, load_policy: str = 'fresh', temp_dir_root: str = None):
331
+ def parallel(f: typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None], None] = None):
332
332
  """
333
- Enables checkpointing for a step.
334
-
335
-
336
-
337
- Parameters
338
- ----------
339
- load_policy : str, default: "fresh"
340
- The policy for loading the checkpoint. The following policies are supported:
341
- - "eager": Loads the the latest available checkpoint within the namespace.
342
- With this mode, the latest checkpoint written by any previous task (can be even a different run) of the step
343
- will be loaded at the start of the task.
344
- - "none": Do not load any checkpoint
345
- - "fresh": Loads the lastest checkpoint created within the running Task.
346
- This mode helps loading checkpoints across various retry attempts of the same task.
347
- With this mode, no checkpoint will be loaded at the start of a task but any checkpoints
348
- created within the task will be loaded when the task is retries execution on failure.
349
-
350
- temp_dir_root : str, default: None
351
- The root directory under which `current.checkpoint.directory` will be created.
333
+ Decorator prototype for all step decorators. This function gets specialized
334
+ and imported for all decorators types by _import_plugin_decorators().
352
335
  """
353
336
  ...
354
337
 
@@ -411,484 +394,355 @@ def timeout(f: typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None],
411
394
  """
412
395
  ...
413
396
 
414
- @typing.overload
415
- def fast_bakery_internal(f: typing.Callable[[FlowSpecDerived, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, StepFlag], None]:
397
+ def nvidia(*, gpu: int, gpu_type: str, queue_timeout: int) -> typing.Callable[[typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]], typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]]:
416
398
  """
417
- Internal decorator to support Fast bakery
399
+ Specifies that this step should execute on DGX cloud.
400
+
401
+
402
+ Parameters
403
+ ----------
404
+ gpu : int
405
+ Number of GPUs to use.
406
+ gpu_type : str
407
+ Type of Nvidia GPU to use.
408
+ queue_timeout : int
409
+ Time to keep the job in NVCF's queue.
418
410
  """
419
411
  ...
420
412
 
421
413
  @typing.overload
422
- def fast_bakery_internal(f: typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]:
423
- ...
424
-
425
- def fast_bakery_internal(f: typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None], None] = None):
426
- """
427
- Internal decorator to support Fast bakery
428
- """
429
- ...
430
-
431
- def huggingface_hub(*, temp_dir_root: typing.Optional[str] = None, load: typing.Union[typing.List[str], typing.List[typing.Tuple[typing.Dict, str]], typing.List[typing.Tuple[str, str]], typing.List[typing.Dict], None]) -> typing.Callable[[typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]], typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]]:
432
- """
433
- Decorator that helps cache, version and store models/datasets from huggingface hub.
434
-
435
-
436
- Parameters
437
- ----------
438
- temp_dir_root : str, optional
439
- The root directory that will hold the temporary directory where objects will be downloaded.
440
-
441
- load: Union[List[str], List[Tuple[Dict, str]], List[Tuple[str, str]], List[Dict], None]
442
- The list of repos (models/datasets) to load.
443
-
444
- Loaded repos can be accessed via `current.huggingface_hub.loaded`. If load is set, then the following happens:
445
-
446
- - If repo (model/dataset) is not found in the datastore:
447
- - Downloads the repo from Hugging Face Hub to a temporary directory (or uses specified path) for local access
448
- - Stores it in Metaflow's datastore (s3/gcs/azure etc.) with a unique name based on repo_type/repo_id
449
- - All HF models loaded for a `@step` will be cached separately under flow/step/namespace.
450
-
451
- - If repo is found in the datastore:
452
- - Loads it directly from datastore to local path (can be temporary directory or specified path)
453
- """
454
- ...
455
-
456
- @typing.overload
457
- def card(*, type: str = 'default', id: typing.Optional[str] = None, options: typing.Dict[str, typing.Any] = {}, timeout: int = 45) -> typing.Callable[[typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]], typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]]:
414
+ def checkpoint(*, load_policy: str = 'fresh', temp_dir_root: str = None) -> typing.Callable[[typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]], typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]]:
458
415
  """
459
- Creates a human-readable report, a Metaflow Card, after this step completes.
416
+ Enables checkpointing for a step.
460
417
 
461
- Note that you may add multiple `@card` decorators in a step with different parameters.
462
418
 
463
419
 
464
420
  Parameters
465
421
  ----------
466
- type : str, default 'default'
467
- Card type.
468
- id : str, optional, default None
469
- If multiple cards are present, use this id to identify this card.
470
- options : Dict[str, Any], default {}
471
- Options passed to the card. The contents depend on the card type.
472
- timeout : int, default 45
473
- Interrupt reporting if it takes more than this many seconds.
422
+ load_policy : str, default: "fresh"
423
+ The policy for loading the checkpoint. The following policies are supported:
424
+ - "eager": Loads the the latest available checkpoint within the namespace.
425
+ With this mode, the latest checkpoint written by any previous task (can be even a different run) of the step
426
+ will be loaded at the start of the task.
427
+ - "none": Do not load any checkpoint
428
+ - "fresh": Loads the lastest checkpoint created within the running Task.
429
+ This mode helps loading checkpoints across various retry attempts of the same task.
430
+ With this mode, no checkpoint will be loaded at the start of a task but any checkpoints
431
+ created within the task will be loaded when the task is retries execution on failure.
432
+
433
+ temp_dir_root : str, default: None
434
+ The root directory under which `current.checkpoint.directory` will be created.
474
435
  """
475
436
  ...
476
437
 
477
438
  @typing.overload
478
- def card(f: typing.Callable[[FlowSpecDerived, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, StepFlag], None]:
439
+ def checkpoint(f: typing.Callable[[FlowSpecDerived, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, StepFlag], None]:
479
440
  ...
480
441
 
481
442
  @typing.overload
482
- def card(f: typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]:
483
- ...
484
-
485
- def card(f: typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None], None] = None, *, type: str = 'default', id: typing.Optional[str] = None, options: typing.Dict[str, typing.Any] = {}, timeout: int = 45):
486
- """
487
- Creates a human-readable report, a Metaflow Card, after this step completes.
488
-
489
- Note that you may add multiple `@card` decorators in a step with different parameters.
490
-
491
-
492
- Parameters
493
- ----------
494
- type : str, default 'default'
495
- Card type.
496
- id : str, optional, default None
497
- If multiple cards are present, use this id to identify this card.
498
- options : Dict[str, Any], default {}
499
- Options passed to the card. The contents depend on the card type.
500
- timeout : int, default 45
501
- Interrupt reporting if it takes more than this many seconds.
502
- """
443
+ def checkpoint(f: typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]:
503
444
  ...
504
445
 
505
- @typing.overload
506
- def model(*, load: typing.Union[typing.List[str], str, typing.List[typing.Tuple[str, typing.Optional[str]]]] = None, temp_dir_root: str = None) -> typing.Callable[[typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]], typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]]:
446
+ def checkpoint(f: typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None], None] = None, *, load_policy: str = 'fresh', temp_dir_root: str = None):
507
447
  """
508
- Enables loading / saving of models within a step.
448
+ Enables checkpointing for a step.
509
449
 
510
450
 
511
451
 
512
452
  Parameters
513
453
  ----------
514
- load : Union[List[str],str,List[Tuple[str,Union[str,None]]]], default: None
515
- Artifact name/s referencing the models/checkpoints to load. Artifact names refer to the names of the instance variables set to `self`.
516
- These artifact names give to `load` be reference objects or reference `key` string's from objects created by:
517
- - `current.checkpoint`
518
- - `current.model`
519
- - `current.huggingface_hub`
520
-
521
- If a list of tuples is provided, the first element is the artifact name and the second element is the path the artifact needs be unpacked on
522
- the local filesystem. If the second element is None, the artifact will be unpacked in the current working directory.
523
- If a string is provided, then the artifact corresponding to that name will be loaded in the current working directory.
454
+ load_policy : str, default: "fresh"
455
+ The policy for loading the checkpoint. The following policies are supported:
456
+ - "eager": Loads the the latest available checkpoint within the namespace.
457
+ With this mode, the latest checkpoint written by any previous task (can be even a different run) of the step
458
+ will be loaded at the start of the task.
459
+ - "none": Do not load any checkpoint
460
+ - "fresh": Loads the lastest checkpoint created within the running Task.
461
+ This mode helps loading checkpoints across various retry attempts of the same task.
462
+ With this mode, no checkpoint will be loaded at the start of a task but any checkpoints
463
+ created within the task will be loaded when the task is retries execution on failure.
524
464
 
525
465
  temp_dir_root : str, default: None
526
- The root directory under which `current.model.loaded` will store loaded models
466
+ The root directory under which `current.checkpoint.directory` will be created.
527
467
  """
528
468
  ...
529
469
 
530
470
  @typing.overload
531
- def model(f: typing.Callable[[FlowSpecDerived, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, StepFlag], None]:
532
- ...
533
-
534
- @typing.overload
535
- def model(f: typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]:
536
- ...
537
-
538
- def model(f: typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None], None] = None, *, load: typing.Union[typing.List[str], str, typing.List[typing.Tuple[str, typing.Optional[str]]]] = None, temp_dir_root: str = None):
471
+ def environment(*, vars: typing.Dict[str, str] = {}) -> typing.Callable[[typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]], typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]]:
539
472
  """
540
- Enables loading / saving of models within a step.
541
-
473
+ Specifies environment variables to be set prior to the execution of a step.
542
474
 
543
475
 
544
476
  Parameters
545
477
  ----------
546
- load : Union[List[str],str,List[Tuple[str,Union[str,None]]]], default: None
547
- Artifact name/s referencing the models/checkpoints to load. Artifact names refer to the names of the instance variables set to `self`.
548
- These artifact names give to `load` be reference objects or reference `key` string's from objects created by:
549
- - `current.checkpoint`
550
- - `current.model`
551
- - `current.huggingface_hub`
552
-
553
- If a list of tuples is provided, the first element is the artifact name and the second element is the path the artifact needs be unpacked on
554
- the local filesystem. If the second element is None, the artifact will be unpacked in the current working directory.
555
- If a string is provided, then the artifact corresponding to that name will be loaded in the current working directory.
556
-
557
- temp_dir_root : str, default: None
558
- The root directory under which `current.model.loaded` will store loaded models
478
+ vars : Dict[str, str], default {}
479
+ Dictionary of environment variables to set.
559
480
  """
560
481
  ...
561
482
 
562
- def app_deploy(*, app_port: int, app_name: str) -> typing.Callable[[typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]], typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]]:
563
- """
564
- Specifies that this step is used to deploy an instance of the app.
565
- Requires that self.app_name, self.app_port, self.entrypoint and self.deployDir is set.
566
-
567
-
568
- Parameters
569
- ----------
570
- app_port : int
571
- Number of GPUs to use.
572
- app_name : str
573
- Name of the app to deploy.
574
- """
483
+ @typing.overload
484
+ def environment(f: typing.Callable[[FlowSpecDerived, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, StepFlag], None]:
575
485
  ...
576
486
 
577
- def ollama(*, models: "list[Ollama]", backend: str) -> typing.Callable[[typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]], typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]]:
578
- """
579
- This decorator is used to run Ollama APIs as Metaflow task sidecars.
580
-
581
- User code call
582
- -----------
583
- @ollama(
584
- models=['meta/llama3-8b-instruct', 'meta/llama3-70b-instruct'],
585
- backend='local'
586
- )
587
-
588
- Valid backend options
589
- ---------------------
590
- - 'local': Run as a separate process on the local task machine.
591
- - (TODO) 'managed': Outerbounds hosts and selects compute provider.
592
- - (TODO) 'remote': Spin up separate instance to serve Ollama models.
593
-
594
- Valid model options
595
- ----------------
596
- - 'llama3.2'
597
- - 'llama3.3'
598
- - any model here https://ollama.com/search
599
-
600
-
601
- Parameters
602
- ----------
603
- models: list[Ollama]
604
- List of Ollama containers running models in sidecars.
605
- backend: str
606
- Determines where and how to run the Ollama process.
607
- """
487
+ @typing.overload
488
+ def environment(f: typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]:
608
489
  ...
609
490
 
610
- def nim(*, models: "list[NIM]", backend: str, queue_timeout: int) -> typing.Callable[[typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]], typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]]:
491
+ def environment(f: typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None], None] = None, *, vars: typing.Dict[str, str] = {}):
611
492
  """
612
- This decorator is used to run NIM containers in Metaflow tasks as sidecars.
613
-
614
- User code call
615
- -----------
616
- @nim(
617
- models=['meta/llama3-8b-instruct', 'meta/llama3-70b-instruct'],
618
- backend='managed'
619
- )
620
-
621
- Valid backend options
622
- ---------------------
623
- - 'managed': Outerbounds selects a compute provider based on the model.
624
-
625
- Valid model options
626
- ----------------
627
- - 'meta/llama3-8b-instruct': 8B parameter model
628
- - 'meta/llama3-70b-instruct': 70B parameter model
629
- - any model here: https://nvcf.ngc.nvidia.com/functions?filter=nvidia-functions
493
+ Specifies environment variables to be set prior to the execution of a step.
630
494
 
631
495
 
632
496
  Parameters
633
497
  ----------
634
- models: list[NIM]
635
- List of NIM containers running models in sidecars.
636
- backend: str
637
- Compute provider to run the NIM container.
638
- queue_timeout : int
639
- Time to keep the job in NVCF's queue.
498
+ vars : Dict[str, str], default {}
499
+ Dictionary of environment variables to set.
640
500
  """
641
501
  ...
642
502
 
643
503
  @typing.overload
644
- def secrets(*, sources: typing.List[typing.Union[str, typing.Dict[str, typing.Any]]] = []) -> typing.Callable[[typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]], typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]]:
504
+ def catch(*, var: typing.Optional[str] = None, print_exception: bool = True) -> typing.Callable[[typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]], typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]]:
645
505
  """
646
- Specifies secrets to be retrieved and injected as environment variables prior to
647
- the execution of a step.
506
+ Specifies that the step will success under all circumstances.
507
+
508
+ The decorator will create an optional artifact, specified by `var`, which
509
+ contains the exception raised. You can use it to detect the presence
510
+ of errors, indicating that all happy-path artifacts produced by the step
511
+ are missing.
648
512
 
649
513
 
650
514
  Parameters
651
515
  ----------
652
- sources : List[Union[str, Dict[str, Any]]], default: []
653
- List of secret specs, defining how the secrets are to be retrieved
516
+ var : str, optional, default None
517
+ Name of the artifact in which to store the caught exception.
518
+ If not specified, the exception is not stored.
519
+ print_exception : bool, default True
520
+ Determines whether or not the exception is printed to
521
+ stdout when caught.
654
522
  """
655
523
  ...
656
524
 
657
525
  @typing.overload
658
- def secrets(f: typing.Callable[[FlowSpecDerived, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, StepFlag], None]:
526
+ def catch(f: typing.Callable[[FlowSpecDerived, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, StepFlag], None]:
659
527
  ...
660
528
 
661
529
  @typing.overload
662
- def secrets(f: typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]:
530
+ def catch(f: typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]:
663
531
  ...
664
532
 
665
- def secrets(f: typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None], None] = None, *, sources: typing.List[typing.Union[str, typing.Dict[str, typing.Any]]] = []):
533
+ def catch(f: typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None], None] = None, *, var: typing.Optional[str] = None, print_exception: bool = True):
666
534
  """
667
- Specifies secrets to be retrieved and injected as environment variables prior to
668
- the execution of a step.
535
+ Specifies that the step will success under all circumstances.
536
+
537
+ The decorator will create an optional artifact, specified by `var`, which
538
+ contains the exception raised. You can use it to detect the presence
539
+ of errors, indicating that all happy-path artifacts produced by the step
540
+ are missing.
669
541
 
670
542
 
671
543
  Parameters
672
544
  ----------
673
- sources : List[Union[str, Dict[str, Any]]], default: []
674
- List of secret specs, defining how the secrets are to be retrieved
545
+ var : str, optional, default None
546
+ Name of the artifact in which to store the caught exception.
547
+ If not specified, the exception is not stored.
548
+ print_exception : bool, default True
549
+ Determines whether or not the exception is printed to
550
+ stdout when caught.
675
551
  """
676
552
  ...
677
553
 
678
554
  @typing.overload
679
- def conda(*, packages: typing.Dict[str, str] = {}, libraries: typing.Dict[str, str] = {}, python: typing.Optional[str] = None, disabled: bool = False) -> typing.Callable[[typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]], typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]]:
555
+ def card(*, type: str = 'default', id: typing.Optional[str] = None, options: typing.Dict[str, typing.Any] = {}, timeout: int = 45) -> typing.Callable[[typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]], typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]]:
680
556
  """
681
- Specifies the Conda environment for the step.
557
+ Creates a human-readable report, a Metaflow Card, after this step completes.
682
558
 
683
- Information in this decorator will augment any
684
- attributes set in the `@conda_base` flow-level decorator. Hence,
685
- you can use `@conda_base` to set packages required by all
686
- steps and use `@conda` to specify step-specific overrides.
559
+ Note that you may add multiple `@card` decorators in a step with different parameters.
687
560
 
688
561
 
689
562
  Parameters
690
563
  ----------
691
- packages : Dict[str, str], default {}
692
- Packages to use for this step. The key is the name of the package
693
- and the value is the version to use.
694
- libraries : Dict[str, str], default {}
695
- Supported for backward compatibility. When used with packages, packages will take precedence.
696
- python : str, optional, default None
697
- Version of Python to use, e.g. '3.7.4'. A default value of None implies
698
- that the version used will correspond to the version of the Python interpreter used to start the run.
699
- disabled : bool, default False
700
- If set to True, disables @conda.
564
+ type : str, default 'default'
565
+ Card type.
566
+ id : str, optional, default None
567
+ If multiple cards are present, use this id to identify this card.
568
+ options : Dict[str, Any], default {}
569
+ Options passed to the card. The contents depend on the card type.
570
+ timeout : int, default 45
571
+ Interrupt reporting if it takes more than this many seconds.
701
572
  """
702
573
  ...
703
574
 
704
575
  @typing.overload
705
- def conda(f: typing.Callable[[FlowSpecDerived, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, StepFlag], None]:
576
+ def card(f: typing.Callable[[FlowSpecDerived, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, StepFlag], None]:
706
577
  ...
707
578
 
708
579
  @typing.overload
709
- def conda(f: typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]:
580
+ def card(f: typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]:
710
581
  ...
711
582
 
712
- def conda(f: typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None], None] = None, *, packages: typing.Dict[str, str] = {}, libraries: typing.Dict[str, str] = {}, python: typing.Optional[str] = None, disabled: bool = False):
583
+ def card(f: typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None], None] = None, *, type: str = 'default', id: typing.Optional[str] = None, options: typing.Dict[str, typing.Any] = {}, timeout: int = 45):
713
584
  """
714
- Specifies the Conda environment for the step.
585
+ Creates a human-readable report, a Metaflow Card, after this step completes.
715
586
 
716
- Information in this decorator will augment any
717
- attributes set in the `@conda_base` flow-level decorator. Hence,
718
- you can use `@conda_base` to set packages required by all
719
- steps and use `@conda` to specify step-specific overrides.
587
+ Note that you may add multiple `@card` decorators in a step with different parameters.
720
588
 
721
589
 
722
590
  Parameters
723
591
  ----------
724
- packages : Dict[str, str], default {}
725
- Packages to use for this step. The key is the name of the package
726
- and the value is the version to use.
727
- libraries : Dict[str, str], default {}
728
- Supported for backward compatibility. When used with packages, packages will take precedence.
729
- python : str, optional, default None
730
- Version of Python to use, e.g. '3.7.4'. A default value of None implies
731
- that the version used will correspond to the version of the Python interpreter used to start the run.
732
- disabled : bool, default False
733
- If set to True, disables @conda.
592
+ type : str, default 'default'
593
+ Card type.
594
+ id : str, optional, default None
595
+ If multiple cards are present, use this id to identify this card.
596
+ options : Dict[str, Any], default {}
597
+ Options passed to the card. The contents depend on the card type.
598
+ timeout : int, default 45
599
+ Interrupt reporting if it takes more than this many seconds.
734
600
  """
735
601
  ...
736
602
 
737
- @typing.overload
738
- def pypi(*, packages: typing.Dict[str, str] = {}, python: typing.Optional[str] = None) -> typing.Callable[[typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]], typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]]:
603
+ def app_deploy(*, app_port: int, app_name: str) -> typing.Callable[[typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]], typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]]:
739
604
  """
740
- Specifies the PyPI packages for the step.
741
-
742
- Information in this decorator will augment any
743
- attributes set in the `@pyi_base` flow-level decorator. Hence,
744
- you can use `@pypi_base` to set packages required by all
745
- steps and use `@pypi` to specify step-specific overrides.
605
+ Specifies that this step is used to deploy an instance of the app.
606
+ Requires that self.app_name, self.app_port, self.entrypoint and self.deployDir is set.
746
607
 
747
608
 
748
609
  Parameters
749
610
  ----------
750
- packages : Dict[str, str], default: {}
751
- Packages to use for this step. The key is the name of the package
752
- and the value is the version to use.
753
- python : str, optional, default: None
754
- Version of Python to use, e.g. '3.7.4'. A default value of None implies
755
- that the version used will correspond to the version of the Python interpreter used to start the run.
611
+ app_port : int
612
+ Number of GPUs to use.
613
+ app_name : str
614
+ Name of the app to deploy.
756
615
  """
757
616
  ...
758
617
 
759
618
  @typing.overload
760
- def pypi(f: typing.Callable[[FlowSpecDerived, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, StepFlag], None]:
619
+ def fast_bakery_internal(f: typing.Callable[[FlowSpecDerived, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, StepFlag], None]:
620
+ """
621
+ Internal decorator to support Fast bakery
622
+ """
761
623
  ...
762
624
 
763
625
  @typing.overload
764
- def pypi(f: typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]:
626
+ def fast_bakery_internal(f: typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]:
765
627
  ...
766
628
 
767
- def pypi(f: typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None], None] = None, *, packages: typing.Dict[str, str] = {}, python: typing.Optional[str] = None):
629
+ def fast_bakery_internal(f: typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None], None] = None):
768
630
  """
769
- Specifies the PyPI packages for the step.
770
-
771
- Information in this decorator will augment any
772
- attributes set in the `@pyi_base` flow-level decorator. Hence,
773
- you can use `@pypi_base` to set packages required by all
774
- steps and use `@pypi` to specify step-specific overrides.
775
-
776
-
777
- Parameters
778
- ----------
779
- packages : Dict[str, str], default: {}
780
- Packages to use for this step. The key is the name of the package
781
- and the value is the version to use.
782
- python : str, optional, default: None
783
- Version of Python to use, e.g. '3.7.4'. A default value of None implies
784
- that the version used will correspond to the version of the Python interpreter used to start the run.
631
+ Internal decorator to support Fast bakery
785
632
  """
786
633
  ...
787
634
 
788
635
  @typing.overload
789
- def environment(*, vars: typing.Dict[str, str] = {}) -> typing.Callable[[typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]], typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]]:
636
+ def secrets(*, sources: typing.List[typing.Union[str, typing.Dict[str, typing.Any]]] = []) -> typing.Callable[[typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]], typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]]:
790
637
  """
791
- Specifies environment variables to be set prior to the execution of a step.
638
+ Specifies secrets to be retrieved and injected as environment variables prior to
639
+ the execution of a step.
792
640
 
793
641
 
794
642
  Parameters
795
643
  ----------
796
- vars : Dict[str, str], default {}
797
- Dictionary of environment variables to set.
644
+ sources : List[Union[str, Dict[str, Any]]], default: []
645
+ List of secret specs, defining how the secrets are to be retrieved
798
646
  """
799
647
  ...
800
648
 
801
649
  @typing.overload
802
- def environment(f: typing.Callable[[FlowSpecDerived, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, StepFlag], None]:
650
+ def secrets(f: typing.Callable[[FlowSpecDerived, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, StepFlag], None]:
803
651
  ...
804
652
 
805
653
  @typing.overload
806
- def environment(f: typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]:
654
+ def secrets(f: typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]:
807
655
  ...
808
656
 
809
- def environment(f: typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None], None] = None, *, vars: typing.Dict[str, str] = {}):
657
+ def secrets(f: typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None], None] = None, *, sources: typing.List[typing.Union[str, typing.Dict[str, typing.Any]]] = []):
810
658
  """
811
- Specifies environment variables to be set prior to the execution of a step.
659
+ Specifies secrets to be retrieved and injected as environment variables prior to
660
+ the execution of a step.
812
661
 
813
662
 
814
663
  Parameters
815
664
  ----------
816
- vars : Dict[str, str], default {}
817
- Dictionary of environment variables to set.
818
- """
819
- ...
820
-
821
- @typing.overload
822
- def parallel(f: typing.Callable[[FlowSpecDerived, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, StepFlag], None]:
823
- """
824
- Decorator prototype for all step decorators. This function gets specialized
825
- and imported for all decorators types by _import_plugin_decorators().
826
- """
827
- ...
828
-
829
- @typing.overload
830
- def parallel(f: typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]:
831
- ...
832
-
833
- def parallel(f: typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None], None] = None):
834
- """
835
- Decorator prototype for all step decorators. This function gets specialized
836
- and imported for all decorators types by _import_plugin_decorators().
665
+ sources : List[Union[str, Dict[str, Any]]], default: []
666
+ List of secret specs, defining how the secrets are to be retrieved
837
667
  """
838
668
  ...
839
669
 
840
670
  @typing.overload
841
- def retry(*, times: int = 3, minutes_between_retries: int = 2) -> typing.Callable[[typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]], typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]]:
671
+ def resources(*, cpu: int = 1, gpu: typing.Optional[int] = None, disk: typing.Optional[int] = None, memory: int = 4096, shared_memory: typing.Optional[int] = None) -> typing.Callable[[typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]], typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]]:
842
672
  """
843
- Specifies the number of times the task corresponding
844
- to a step needs to be retried.
673
+ Specifies the resources needed when executing this step.
845
674
 
846
- This decorator is useful for handling transient errors, such as networking issues.
847
- If your task contains operations that can't be retried safely, e.g. database updates,
848
- it is advisable to annotate it with `@retry(times=0)`.
675
+ Use `@resources` to specify the resource requirements
676
+ independently of the specific compute layer (`@batch`, `@kubernetes`).
849
677
 
850
- This can be used in conjunction with the `@catch` decorator. The `@catch`
851
- decorator will execute a no-op task after all retries have been exhausted,
852
- ensuring that the flow execution can continue.
678
+ You can choose the compute layer on the command line by executing e.g.
679
+ ```
680
+ python myflow.py run --with batch
681
+ ```
682
+ or
683
+ ```
684
+ python myflow.py run --with kubernetes
685
+ ```
686
+ which executes the flow on the desired system using the
687
+ requirements specified in `@resources`.
853
688
 
854
689
 
855
690
  Parameters
856
691
  ----------
857
- times : int, default 3
858
- Number of times to retry this task.
859
- minutes_between_retries : int, default 2
860
- Number of minutes between retries.
692
+ cpu : int, default 1
693
+ Number of CPUs required for this step.
694
+ gpu : int, optional, default None
695
+ Number of GPUs required for this step.
696
+ disk : int, optional, default None
697
+ Disk size (in MB) required for this step. Only applies on Kubernetes.
698
+ memory : int, default 4096
699
+ Memory size (in MB) required for this step.
700
+ shared_memory : int, optional, default None
701
+ The value for the size (in MiB) of the /dev/shm volume for this step.
702
+ This parameter maps to the `--shm-size` option in Docker.
861
703
  """
862
704
  ...
863
705
 
864
706
  @typing.overload
865
- def retry(f: typing.Callable[[FlowSpecDerived, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, StepFlag], None]:
707
+ def resources(f: typing.Callable[[FlowSpecDerived, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, StepFlag], None]:
866
708
  ...
867
709
 
868
710
  @typing.overload
869
- def retry(f: typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]:
711
+ def resources(f: typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]:
870
712
  ...
871
713
 
872
- def retry(f: typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None], None] = None, *, times: int = 3, minutes_between_retries: int = 2):
714
+ def resources(f: typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None], None] = None, *, cpu: int = 1, gpu: typing.Optional[int] = None, disk: typing.Optional[int] = None, memory: int = 4096, shared_memory: typing.Optional[int] = None):
873
715
  """
874
- Specifies the number of times the task corresponding
875
- to a step needs to be retried.
876
-
877
- This decorator is useful for handling transient errors, such as networking issues.
878
- If your task contains operations that can't be retried safely, e.g. database updates,
879
- it is advisable to annotate it with `@retry(times=0)`.
716
+ Specifies the resources needed when executing this step.
880
717
 
881
- This can be used in conjunction with the `@catch` decorator. The `@catch`
882
- decorator will execute a no-op task after all retries have been exhausted,
883
- ensuring that the flow execution can continue.
718
+ Use `@resources` to specify the resource requirements
719
+ independently of the specific compute layer (`@batch`, `@kubernetes`).
720
+
721
+ You can choose the compute layer on the command line by executing e.g.
722
+ ```
723
+ python myflow.py run --with batch
724
+ ```
725
+ or
726
+ ```
727
+ python myflow.py run --with kubernetes
728
+ ```
729
+ which executes the flow on the desired system using the
730
+ requirements specified in `@resources`.
884
731
 
885
732
 
886
733
  Parameters
887
734
  ----------
888
- times : int, default 3
889
- Number of times to retry this task.
890
- minutes_between_retries : int, default 2
891
- Number of minutes between retries.
735
+ cpu : int, default 1
736
+ Number of CPUs required for this step.
737
+ gpu : int, optional, default None
738
+ Number of GPUs required for this step.
739
+ disk : int, optional, default None
740
+ Disk size (in MB) required for this step. Only applies on Kubernetes.
741
+ memory : int, default 4096
742
+ Memory size (in MB) required for this step.
743
+ shared_memory : int, optional, default None
744
+ The value for the size (in MiB) of the /dev/shm volume for this step.
745
+ This parameter maps to the `--shm-size` option in Docker.
892
746
  """
893
747
  ...
894
748
 
@@ -970,94 +824,149 @@ def kubernetes(*, cpu: int = 1, memory: int = 4096, disk: int = 10240, image: ty
970
824
  ...
971
825
 
972
826
  @typing.overload
973
- def pypi_base(*, packages: typing.Dict[str, str] = {}, python: typing.Optional[str] = None) -> typing.Callable[[typing.Type[FlowSpecDerived]], typing.Type[FlowSpecDerived]]:
827
+ def conda(*, packages: typing.Dict[str, str] = {}, libraries: typing.Dict[str, str] = {}, python: typing.Optional[str] = None, disabled: bool = False) -> typing.Callable[[typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]], typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]]:
974
828
  """
975
- Specifies the PyPI packages for all steps of the flow.
829
+ Specifies the Conda environment for the step.
830
+
831
+ Information in this decorator will augment any
832
+ attributes set in the `@conda_base` flow-level decorator. Hence,
833
+ you can use `@conda_base` to set packages required by all
834
+ steps and use `@conda` to specify step-specific overrides.
976
835
 
977
- Use `@pypi_base` to set common packages required by all
978
- steps and use `@pypi` to specify step-specific overrides.
979
836
 
980
837
  Parameters
981
838
  ----------
982
- packages : Dict[str, str], default: {}
983
- Packages to use for this flow. The key is the name of the package
839
+ packages : Dict[str, str], default {}
840
+ Packages to use for this step. The key is the name of the package
984
841
  and the value is the version to use.
985
- python : str, optional, default: None
842
+ libraries : Dict[str, str], default {}
843
+ Supported for backward compatibility. When used with packages, packages will take precedence.
844
+ python : str, optional, default None
986
845
  Version of Python to use, e.g. '3.7.4'. A default value of None implies
987
846
  that the version used will correspond to the version of the Python interpreter used to start the run.
847
+ disabled : bool, default False
848
+ If set to True, disables @conda.
988
849
  """
989
850
  ...
990
851
 
991
852
  @typing.overload
992
- def pypi_base(f: typing.Type[FlowSpecDerived]) -> typing.Type[FlowSpecDerived]:
853
+ def conda(f: typing.Callable[[FlowSpecDerived, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, StepFlag], None]:
993
854
  ...
994
855
 
995
- def pypi_base(f: typing.Optional[typing.Type[FlowSpecDerived]] = None, *, packages: typing.Dict[str, str] = {}, python: typing.Optional[str] = None):
856
+ @typing.overload
857
+ def conda(f: typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]:
858
+ ...
859
+
860
+ def conda(f: typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None], None] = None, *, packages: typing.Dict[str, str] = {}, libraries: typing.Dict[str, str] = {}, python: typing.Optional[str] = None, disabled: bool = False):
996
861
  """
997
- Specifies the PyPI packages for all steps of the flow.
862
+ Specifies the Conda environment for the step.
863
+
864
+ Information in this decorator will augment any
865
+ attributes set in the `@conda_base` flow-level decorator. Hence,
866
+ you can use `@conda_base` to set packages required by all
867
+ steps and use `@conda` to specify step-specific overrides.
998
868
 
999
- Use `@pypi_base` to set common packages required by all
1000
- steps and use `@pypi` to specify step-specific overrides.
1001
869
 
1002
870
  Parameters
1003
871
  ----------
1004
- packages : Dict[str, str], default: {}
1005
- Packages to use for this flow. The key is the name of the package
872
+ packages : Dict[str, str], default {}
873
+ Packages to use for this step. The key is the name of the package
1006
874
  and the value is the version to use.
1007
- python : str, optional, default: None
875
+ libraries : Dict[str, str], default {}
876
+ Supported for backward compatibility. When used with packages, packages will take precedence.
877
+ python : str, optional, default None
1008
878
  Version of Python to use, e.g. '3.7.4'. A default value of None implies
1009
879
  that the version used will correspond to the version of the Python interpreter used to start the run.
880
+ disabled : bool, default False
881
+ If set to True, disables @conda.
1010
882
  """
1011
883
  ...
1012
884
 
1013
885
  @typing.overload
1014
- def conda_base(*, packages: typing.Dict[str, str] = {}, libraries: typing.Dict[str, str] = {}, python: typing.Optional[str] = None, disabled: bool = False) -> typing.Callable[[typing.Type[FlowSpecDerived]], typing.Type[FlowSpecDerived]]:
886
+ def retry(*, times: int = 3, minutes_between_retries: int = 2) -> typing.Callable[[typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]], typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]]:
1015
887
  """
1016
- Specifies the Conda environment for all steps of the flow.
888
+ Specifies the number of times the task corresponding
889
+ to a step needs to be retried.
1017
890
 
1018
- Use `@conda_base` to set common libraries required by all
1019
- steps and use `@conda` to specify step-specific additions.
891
+ This decorator is useful for handling transient errors, such as networking issues.
892
+ If your task contains operations that can't be retried safely, e.g. database updates,
893
+ it is advisable to annotate it with `@retry(times=0)`.
894
+
895
+ This can be used in conjunction with the `@catch` decorator. The `@catch`
896
+ decorator will execute a no-op task after all retries have been exhausted,
897
+ ensuring that the flow execution can continue.
1020
898
 
1021
899
 
1022
900
  Parameters
1023
901
  ----------
1024
- packages : Dict[str, str], default {}
1025
- Packages to use for this flow. The key is the name of the package
1026
- and the value is the version to use.
1027
- libraries : Dict[str, str], default {}
1028
- Supported for backward compatibility. When used with packages, packages will take precedence.
1029
- python : str, optional, default None
1030
- Version of Python to use, e.g. '3.7.4'. A default value of None implies
1031
- that the version used will correspond to the version of the Python interpreter used to start the run.
1032
- disabled : bool, default False
1033
- If set to True, disables Conda.
902
+ times : int, default 3
903
+ Number of times to retry this task.
904
+ minutes_between_retries : int, default 2
905
+ Number of minutes between retries.
1034
906
  """
1035
907
  ...
1036
908
 
1037
909
  @typing.overload
1038
- def conda_base(f: typing.Type[FlowSpecDerived]) -> typing.Type[FlowSpecDerived]:
910
+ def retry(f: typing.Callable[[FlowSpecDerived, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, StepFlag], None]:
1039
911
  ...
1040
912
 
1041
- def conda_base(f: typing.Optional[typing.Type[FlowSpecDerived]] = None, *, packages: typing.Dict[str, str] = {}, libraries: typing.Dict[str, str] = {}, python: typing.Optional[str] = None, disabled: bool = False):
913
+ @typing.overload
914
+ def retry(f: typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]) -> typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]:
915
+ ...
916
+
917
+ def retry(f: typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None], None] = None, *, times: int = 3, minutes_between_retries: int = 2):
1042
918
  """
1043
- Specifies the Conda environment for all steps of the flow.
919
+ Specifies the number of times the task corresponding
920
+ to a step needs to be retried.
1044
921
 
1045
- Use `@conda_base` to set common libraries required by all
1046
- steps and use `@conda` to specify step-specific additions.
922
+ This decorator is useful for handling transient errors, such as networking issues.
923
+ If your task contains operations that can't be retried safely, e.g. database updates,
924
+ it is advisable to annotate it with `@retry(times=0)`.
925
+
926
+ This can be used in conjunction with the `@catch` decorator. The `@catch`
927
+ decorator will execute a no-op task after all retries have been exhausted,
928
+ ensuring that the flow execution can continue.
1047
929
 
1048
930
 
1049
931
  Parameters
1050
932
  ----------
1051
- packages : Dict[str, str], default {}
1052
- Packages to use for this flow. The key is the name of the package
1053
- and the value is the version to use.
1054
- libraries : Dict[str, str], default {}
1055
- Supported for backward compatibility. When used with packages, packages will take precedence.
1056
- python : str, optional, default None
1057
- Version of Python to use, e.g. '3.7.4'. A default value of None implies
1058
- that the version used will correspond to the version of the Python interpreter used to start the run.
1059
- disabled : bool, default False
1060
- If set to True, disables Conda.
933
+ times : int, default 3
934
+ Number of times to retry this task.
935
+ minutes_between_retries : int, default 2
936
+ Number of minutes between retries.
937
+ """
938
+ ...
939
+
940
+ def ollama(*, models: "list[Ollama]", backend: str) -> typing.Callable[[typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]], typing.Union[typing.Callable[[FlowSpecDerived, StepFlag], None], typing.Callable[[FlowSpecDerived, typing.Any, StepFlag], None]]]:
941
+ """
942
+ This decorator is used to run Ollama APIs as Metaflow task sidecars.
943
+
944
+ User code call
945
+ -----------
946
+ @ollama(
947
+ models=['meta/llama3-8b-instruct', 'meta/llama3-70b-instruct'],
948
+ backend='local'
949
+ )
950
+
951
+ Valid backend options
952
+ ---------------------
953
+ - 'local': Run as a separate process on the local task machine.
954
+ - (TODO) 'managed': Outerbounds hosts and selects compute provider.
955
+ - (TODO) 'remote': Spin up separate instance to serve Ollama models.
956
+
957
+ Valid model options
958
+ ----------------
959
+ - 'llama3.2'
960
+ - 'llama3.3'
961
+ - any model here https://ollama.com/search
962
+
963
+
964
+ Parameters
965
+ ----------
966
+ models: list[Ollama]
967
+ List of Ollama containers running models in sidecars.
968
+ backend: str
969
+ Determines where and how to run the Ollama process.
1061
970
  """
1062
971
  ...
1063
972
 
@@ -1097,98 +1006,198 @@ def project(*, name: str, branch: typing.Optional[str] = None, production: bool
1097
1006
  ...
1098
1007
 
1099
1008
  @typing.overload
1100
- def trigger(*, event: typing.Union[str, typing.Dict[str, typing.Any], None] = None, events: typing.List[typing.Union[str, typing.Dict[str, typing.Any]]] = [], options: typing.Dict[str, typing.Any] = {}) -> typing.Callable[[typing.Type[FlowSpecDerived]], typing.Type[FlowSpecDerived]]:
1009
+ def pypi_base(*, packages: typing.Dict[str, str] = {}, python: typing.Optional[str] = None) -> typing.Callable[[typing.Type[FlowSpecDerived]], typing.Type[FlowSpecDerived]]:
1101
1010
  """
1102
- Specifies the event(s) that this flow depends on.
1011
+ Specifies the PyPI packages for all steps of the flow.
1012
+
1013
+ Use `@pypi_base` to set common packages required by all
1014
+ steps and use `@pypi` to specify step-specific overrides.
1015
+
1016
+ Parameters
1017
+ ----------
1018
+ packages : Dict[str, str], default: {}
1019
+ Packages to use for this flow. The key is the name of the package
1020
+ and the value is the version to use.
1021
+ python : str, optional, default: None
1022
+ Version of Python to use, e.g. '3.7.4'. A default value of None implies
1023
+ that the version used will correspond to the version of the Python interpreter used to start the run.
1024
+ """
1025
+ ...
1026
+
1027
+ @typing.overload
1028
+ def pypi_base(f: typing.Type[FlowSpecDerived]) -> typing.Type[FlowSpecDerived]:
1029
+ ...
1030
+
1031
+ def pypi_base(f: typing.Optional[typing.Type[FlowSpecDerived]] = None, *, packages: typing.Dict[str, str] = {}, python: typing.Optional[str] = None):
1032
+ """
1033
+ Specifies the PyPI packages for all steps of the flow.
1034
+
1035
+ Use `@pypi_base` to set common packages required by all
1036
+ steps and use `@pypi` to specify step-specific overrides.
1037
+
1038
+ Parameters
1039
+ ----------
1040
+ packages : Dict[str, str], default: {}
1041
+ Packages to use for this flow. The key is the name of the package
1042
+ and the value is the version to use.
1043
+ python : str, optional, default: None
1044
+ Version of Python to use, e.g. '3.7.4'. A default value of None implies
1045
+ that the version used will correspond to the version of the Python interpreter used to start the run.
1046
+ """
1047
+ ...
1048
+
1049
+ @typing.overload
1050
+ def trigger_on_finish(*, flow: typing.Union[typing.Dict[str, str], str, None] = None, flows: typing.List[typing.Union[str, typing.Dict[str, str]]] = [], options: typing.Dict[str, typing.Any] = {}) -> typing.Callable[[typing.Type[FlowSpecDerived]], typing.Type[FlowSpecDerived]]:
1051
+ """
1052
+ Specifies the flow(s) that this flow depends on.
1103
1053
 
1104
1054
  ```
1105
- @trigger(event='foo')
1055
+ @trigger_on_finish(flow='FooFlow')
1106
1056
  ```
1107
1057
  or
1108
1058
  ```
1109
- @trigger(events=['foo', 'bar'])
1059
+ @trigger_on_finish(flows=['FooFlow', 'BarFlow'])
1110
1060
  ```
1061
+ This decorator respects the @project decorator and triggers the flow
1062
+ when upstream runs within the same namespace complete successfully
1111
1063
 
1112
- Additionally, you can specify the parameter mappings
1113
- to map event payload to Metaflow parameters for the flow.
1064
+ Additionally, you can specify project aware upstream flow dependencies
1065
+ by specifying the fully qualified project_flow_name.
1114
1066
  ```
1115
- @trigger(event={'name':'foo', 'parameters':{'flow_param': 'event_field'}})
1067
+ @trigger_on_finish(flow='my_project.branch.my_branch.FooFlow')
1116
1068
  ```
1117
1069
  or
1118
1070
  ```
1119
- @trigger(events=[{'name':'foo', 'parameters':{'flow_param_1': 'event_field_1'},
1120
- {'name':'bar', 'parameters':{'flow_param_2': 'event_field_2'}])
1071
+ @trigger_on_finish(flows=['my_project.branch.my_branch.FooFlow', 'BarFlow'])
1121
1072
  ```
1122
1073
 
1123
- 'parameters' can also be a list of strings and tuples like so:
1124
- ```
1125
- @trigger(event={'name':'foo', 'parameters':['common_name', ('flow_param', 'event_field')]})
1126
- ```
1127
- This is equivalent to:
1074
+ You can also specify just the project or project branch (other values will be
1075
+ inferred from the current project or project branch):
1128
1076
  ```
1129
- @trigger(event={'name':'foo', 'parameters':{'common_name': 'common_name', 'flow_param': 'event_field'}})
1077
+ @trigger_on_finish(flow={"name": "FooFlow", "project": "my_project", "project_branch": "branch"})
1130
1078
  ```
1131
1079
 
1080
+ Note that `branch` is typically one of:
1081
+ - `prod`
1082
+ - `user.bob`
1083
+ - `test.my_experiment`
1084
+ - `prod.staging`
1085
+
1132
1086
 
1133
1087
  Parameters
1134
1088
  ----------
1135
- event : Union[str, Dict[str, Any]], optional, default None
1136
- Event dependency for this flow.
1137
- events : List[Union[str, Dict[str, Any]]], default []
1138
- Events dependency for this flow.
1089
+ flow : Union[str, Dict[str, str]], optional, default None
1090
+ Upstream flow dependency for this flow.
1091
+ flows : List[Union[str, Dict[str, str]]], default []
1092
+ Upstream flow dependencies for this flow.
1139
1093
  options : Dict[str, Any], default {}
1140
1094
  Backend-specific configuration for tuning eventing behavior.
1141
1095
  """
1142
1096
  ...
1143
1097
 
1144
1098
  @typing.overload
1145
- def trigger(f: typing.Type[FlowSpecDerived]) -> typing.Type[FlowSpecDerived]:
1099
+ def trigger_on_finish(f: typing.Type[FlowSpecDerived]) -> typing.Type[FlowSpecDerived]:
1146
1100
  ...
1147
1101
 
1148
- def trigger(f: typing.Optional[typing.Type[FlowSpecDerived]] = None, *, event: typing.Union[str, typing.Dict[str, typing.Any], None] = None, events: typing.List[typing.Union[str, typing.Dict[str, typing.Any]]] = [], options: typing.Dict[str, typing.Any] = {}):
1102
+ def trigger_on_finish(f: typing.Optional[typing.Type[FlowSpecDerived]] = None, *, flow: typing.Union[typing.Dict[str, str], str, None] = None, flows: typing.List[typing.Union[str, typing.Dict[str, str]]] = [], options: typing.Dict[str, typing.Any] = {}):
1149
1103
  """
1150
- Specifies the event(s) that this flow depends on.
1104
+ Specifies the flow(s) that this flow depends on.
1151
1105
 
1152
1106
  ```
1153
- @trigger(event='foo')
1107
+ @trigger_on_finish(flow='FooFlow')
1154
1108
  ```
1155
1109
  or
1156
1110
  ```
1157
- @trigger(events=['foo', 'bar'])
1111
+ @trigger_on_finish(flows=['FooFlow', 'BarFlow'])
1158
1112
  ```
1113
+ This decorator respects the @project decorator and triggers the flow
1114
+ when upstream runs within the same namespace complete successfully
1159
1115
 
1160
- Additionally, you can specify the parameter mappings
1161
- to map event payload to Metaflow parameters for the flow.
1116
+ Additionally, you can specify project aware upstream flow dependencies
1117
+ by specifying the fully qualified project_flow_name.
1162
1118
  ```
1163
- @trigger(event={'name':'foo', 'parameters':{'flow_param': 'event_field'}})
1119
+ @trigger_on_finish(flow='my_project.branch.my_branch.FooFlow')
1164
1120
  ```
1165
1121
  or
1166
1122
  ```
1167
- @trigger(events=[{'name':'foo', 'parameters':{'flow_param_1': 'event_field_1'},
1168
- {'name':'bar', 'parameters':{'flow_param_2': 'event_field_2'}])
1123
+ @trigger_on_finish(flows=['my_project.branch.my_branch.FooFlow', 'BarFlow'])
1169
1124
  ```
1170
1125
 
1171
- 'parameters' can also be a list of strings and tuples like so:
1172
- ```
1173
- @trigger(event={'name':'foo', 'parameters':['common_name', ('flow_param', 'event_field')]})
1174
- ```
1175
- This is equivalent to:
1126
+ You can also specify just the project or project branch (other values will be
1127
+ inferred from the current project or project branch):
1176
1128
  ```
1177
- @trigger(event={'name':'foo', 'parameters':{'common_name': 'common_name', 'flow_param': 'event_field'}})
1129
+ @trigger_on_finish(flow={"name": "FooFlow", "project": "my_project", "project_branch": "branch"})
1178
1130
  ```
1179
1131
 
1132
+ Note that `branch` is typically one of:
1133
+ - `prod`
1134
+ - `user.bob`
1135
+ - `test.my_experiment`
1136
+ - `prod.staging`
1137
+
1180
1138
 
1181
1139
  Parameters
1182
1140
  ----------
1183
- event : Union[str, Dict[str, Any]], optional, default None
1184
- Event dependency for this flow.
1185
- events : List[Union[str, Dict[str, Any]]], default []
1186
- Events dependency for this flow.
1141
+ flow : Union[str, Dict[str, str]], optional, default None
1142
+ Upstream flow dependency for this flow.
1143
+ flows : List[Union[str, Dict[str, str]]], default []
1144
+ Upstream flow dependencies for this flow.
1187
1145
  options : Dict[str, Any], default {}
1188
1146
  Backend-specific configuration for tuning eventing behavior.
1189
1147
  """
1190
1148
  ...
1191
1149
 
1150
+ @typing.overload
1151
+ def schedule(*, hourly: bool = False, daily: bool = True, weekly: bool = False, cron: typing.Optional[str] = None, timezone: typing.Optional[str] = None) -> typing.Callable[[typing.Type[FlowSpecDerived]], typing.Type[FlowSpecDerived]]:
1152
+ """
1153
+ Specifies the times when the flow should be run when running on a
1154
+ production scheduler.
1155
+
1156
+
1157
+ Parameters
1158
+ ----------
1159
+ hourly : bool, default False
1160
+ Run the workflow hourly.
1161
+ daily : bool, default True
1162
+ Run the workflow daily.
1163
+ weekly : bool, default False
1164
+ Run the workflow weekly.
1165
+ cron : str, optional, default None
1166
+ Run the workflow at [a custom Cron schedule](https://docs.aws.amazon.com/eventbridge/latest/userguide/scheduled-events.html#cron-expressions)
1167
+ specified by this expression.
1168
+ timezone : str, optional, default None
1169
+ Timezone on which the schedule runs (default: None). Currently supported only for Argo workflows,
1170
+ which accepts timezones in [IANA format](https://nodatime.org/TimeZones).
1171
+ """
1172
+ ...
1173
+
1174
+ @typing.overload
1175
+ def schedule(f: typing.Type[FlowSpecDerived]) -> typing.Type[FlowSpecDerived]:
1176
+ ...
1177
+
1178
+ def schedule(f: typing.Optional[typing.Type[FlowSpecDerived]] = None, *, hourly: bool = False, daily: bool = True, weekly: bool = False, cron: typing.Optional[str] = None, timezone: typing.Optional[str] = None):
1179
+ """
1180
+ Specifies the times when the flow should be run when running on a
1181
+ production scheduler.
1182
+
1183
+
1184
+ Parameters
1185
+ ----------
1186
+ hourly : bool, default False
1187
+ Run the workflow hourly.
1188
+ daily : bool, default True
1189
+ Run the workflow daily.
1190
+ weekly : bool, default False
1191
+ Run the workflow weekly.
1192
+ cron : str, optional, default None
1193
+ Run the workflow at [a custom Cron schedule](https://docs.aws.amazon.com/eventbridge/latest/userguide/scheduled-events.html#cron-expressions)
1194
+ specified by this expression.
1195
+ timezone : str, optional, default None
1196
+ Timezone on which the schedule runs (default: None). Currently supported only for Argo workflows,
1197
+ which accepts timezones in [IANA format](https://nodatime.org/TimeZones).
1198
+ """
1199
+ ...
1200
+
1192
1201
  def airflow_external_task_sensor(*, timeout: int, poke_interval: int, mode: str, exponential_backoff: bool, pool: str, soft_fail: bool, name: str, description: str, external_dag_id: str, external_task_ids: typing.List[str], allowed_states: typing.List[str], failed_states: typing.List[str], execution_delta: "datetime.timedelta", check_existence: bool) -> typing.Callable[[typing.Type[FlowSpecDerived]], typing.Type[FlowSpecDerived]]:
1193
1202
  """
1194
1203
  The `@airflow_external_task_sensor` decorator attaches a Airflow [ExternalTaskSensor](https://airflow.apache.org/docs/apache-airflow/stable/_api/airflow/sensors/external_task/index.html#airflow.sensors.external_task.ExternalTaskSensor) before the start step of the flow.
@@ -1233,101 +1242,93 @@ def airflow_external_task_sensor(*, timeout: int, poke_interval: int, mode: str,
1233
1242
  ...
1234
1243
 
1235
1244
  @typing.overload
1236
- def trigger_on_finish(*, flow: typing.Union[typing.Dict[str, str], str, None] = None, flows: typing.List[typing.Union[str, typing.Dict[str, str]]] = [], options: typing.Dict[str, typing.Any] = {}) -> typing.Callable[[typing.Type[FlowSpecDerived]], typing.Type[FlowSpecDerived]]:
1245
+ def trigger(*, event: typing.Union[str, typing.Dict[str, typing.Any], None] = None, events: typing.List[typing.Union[str, typing.Dict[str, typing.Any]]] = [], options: typing.Dict[str, typing.Any] = {}) -> typing.Callable[[typing.Type[FlowSpecDerived]], typing.Type[FlowSpecDerived]]:
1237
1246
  """
1238
- Specifies the flow(s) that this flow depends on.
1247
+ Specifies the event(s) that this flow depends on.
1239
1248
 
1240
1249
  ```
1241
- @trigger_on_finish(flow='FooFlow')
1250
+ @trigger(event='foo')
1242
1251
  ```
1243
1252
  or
1244
1253
  ```
1245
- @trigger_on_finish(flows=['FooFlow', 'BarFlow'])
1254
+ @trigger(events=['foo', 'bar'])
1246
1255
  ```
1247
- This decorator respects the @project decorator and triggers the flow
1248
- when upstream runs within the same namespace complete successfully
1249
1256
 
1250
- Additionally, you can specify project aware upstream flow dependencies
1251
- by specifying the fully qualified project_flow_name.
1257
+ Additionally, you can specify the parameter mappings
1258
+ to map event payload to Metaflow parameters for the flow.
1252
1259
  ```
1253
- @trigger_on_finish(flow='my_project.branch.my_branch.FooFlow')
1260
+ @trigger(event={'name':'foo', 'parameters':{'flow_param': 'event_field'}})
1254
1261
  ```
1255
1262
  or
1256
1263
  ```
1257
- @trigger_on_finish(flows=['my_project.branch.my_branch.FooFlow', 'BarFlow'])
1264
+ @trigger(events=[{'name':'foo', 'parameters':{'flow_param_1': 'event_field_1'},
1265
+ {'name':'bar', 'parameters':{'flow_param_2': 'event_field_2'}])
1258
1266
  ```
1259
1267
 
1260
- You can also specify just the project or project branch (other values will be
1261
- inferred from the current project or project branch):
1268
+ 'parameters' can also be a list of strings and tuples like so:
1262
1269
  ```
1263
- @trigger_on_finish(flow={"name": "FooFlow", "project": "my_project", "project_branch": "branch"})
1270
+ @trigger(event={'name':'foo', 'parameters':['common_name', ('flow_param', 'event_field')]})
1271
+ ```
1272
+ This is equivalent to:
1273
+ ```
1274
+ @trigger(event={'name':'foo', 'parameters':{'common_name': 'common_name', 'flow_param': 'event_field'}})
1264
1275
  ```
1265
-
1266
- Note that `branch` is typically one of:
1267
- - `prod`
1268
- - `user.bob`
1269
- - `test.my_experiment`
1270
- - `prod.staging`
1271
1276
 
1272
1277
 
1273
1278
  Parameters
1274
1279
  ----------
1275
- flow : Union[str, Dict[str, str]], optional, default None
1276
- Upstream flow dependency for this flow.
1277
- flows : List[Union[str, Dict[str, str]]], default []
1278
- Upstream flow dependencies for this flow.
1280
+ event : Union[str, Dict[str, Any]], optional, default None
1281
+ Event dependency for this flow.
1282
+ events : List[Union[str, Dict[str, Any]]], default []
1283
+ Events dependency for this flow.
1279
1284
  options : Dict[str, Any], default {}
1280
1285
  Backend-specific configuration for tuning eventing behavior.
1281
1286
  """
1282
1287
  ...
1283
1288
 
1284
1289
  @typing.overload
1285
- def trigger_on_finish(f: typing.Type[FlowSpecDerived]) -> typing.Type[FlowSpecDerived]:
1290
+ def trigger(f: typing.Type[FlowSpecDerived]) -> typing.Type[FlowSpecDerived]:
1286
1291
  ...
1287
1292
 
1288
- def trigger_on_finish(f: typing.Optional[typing.Type[FlowSpecDerived]] = None, *, flow: typing.Union[typing.Dict[str, str], str, None] = None, flows: typing.List[typing.Union[str, typing.Dict[str, str]]] = [], options: typing.Dict[str, typing.Any] = {}):
1293
+ def trigger(f: typing.Optional[typing.Type[FlowSpecDerived]] = None, *, event: typing.Union[str, typing.Dict[str, typing.Any], None] = None, events: typing.List[typing.Union[str, typing.Dict[str, typing.Any]]] = [], options: typing.Dict[str, typing.Any] = {}):
1289
1294
  """
1290
- Specifies the flow(s) that this flow depends on.
1295
+ Specifies the event(s) that this flow depends on.
1291
1296
 
1292
1297
  ```
1293
- @trigger_on_finish(flow='FooFlow')
1298
+ @trigger(event='foo')
1294
1299
  ```
1295
1300
  or
1296
1301
  ```
1297
- @trigger_on_finish(flows=['FooFlow', 'BarFlow'])
1302
+ @trigger(events=['foo', 'bar'])
1298
1303
  ```
1299
- This decorator respects the @project decorator and triggers the flow
1300
- when upstream runs within the same namespace complete successfully
1301
1304
 
1302
- Additionally, you can specify project aware upstream flow dependencies
1303
- by specifying the fully qualified project_flow_name.
1305
+ Additionally, you can specify the parameter mappings
1306
+ to map event payload to Metaflow parameters for the flow.
1304
1307
  ```
1305
- @trigger_on_finish(flow='my_project.branch.my_branch.FooFlow')
1308
+ @trigger(event={'name':'foo', 'parameters':{'flow_param': 'event_field'}})
1306
1309
  ```
1307
1310
  or
1308
1311
  ```
1309
- @trigger_on_finish(flows=['my_project.branch.my_branch.FooFlow', 'BarFlow'])
1312
+ @trigger(events=[{'name':'foo', 'parameters':{'flow_param_1': 'event_field_1'},
1313
+ {'name':'bar', 'parameters':{'flow_param_2': 'event_field_2'}])
1310
1314
  ```
1311
1315
 
1312
- You can also specify just the project or project branch (other values will be
1313
- inferred from the current project or project branch):
1316
+ 'parameters' can also be a list of strings and tuples like so:
1314
1317
  ```
1315
- @trigger_on_finish(flow={"name": "FooFlow", "project": "my_project", "project_branch": "branch"})
1318
+ @trigger(event={'name':'foo', 'parameters':['common_name', ('flow_param', 'event_field')]})
1319
+ ```
1320
+ This is equivalent to:
1321
+ ```
1322
+ @trigger(event={'name':'foo', 'parameters':{'common_name': 'common_name', 'flow_param': 'event_field'}})
1316
1323
  ```
1317
-
1318
- Note that `branch` is typically one of:
1319
- - `prod`
1320
- - `user.bob`
1321
- - `test.my_experiment`
1322
- - `prod.staging`
1323
1324
 
1324
1325
 
1325
1326
  Parameters
1326
1327
  ----------
1327
- flow : Union[str, Dict[str, str]], optional, default None
1328
- Upstream flow dependency for this flow.
1329
- flows : List[Union[str, Dict[str, str]]], default []
1330
- Upstream flow dependencies for this flow.
1328
+ event : Union[str, Dict[str, Any]], optional, default None
1329
+ Event dependency for this flow.
1330
+ events : List[Union[str, Dict[str, Any]]], default []
1331
+ Events dependency for this flow.
1331
1332
  options : Dict[str, Any], default {}
1332
1333
  Backend-specific configuration for tuning eventing behavior.
1333
1334
  """
@@ -1376,54 +1377,168 @@ def airflow_s3_key_sensor(*, timeout: int, poke_interval: int, mode: str, expone
1376
1377
  """
1377
1378
  ...
1378
1379
 
1380
+ def with_artifact_store(f: typing.Optional[typing.Type[FlowSpecDerived]] = None):
1381
+ """
1382
+ Allows setting external datastores to save data for the
1383
+ `@checkpoint`/`@model`/`@huggingface_hub` decorators.
1384
+
1385
+ This decorator is useful when users wish to save data to a different datastore
1386
+ than what is configured in Metaflow. This can be for variety of reasons:
1387
+
1388
+ 1. Data security: The objects needs to be stored in a bucket (object storage) that is not accessible by other flows.
1389
+ 2. Data Locality: The location where the task is executing is not located in the same region as the datastore.
1390
+ - Example: Metaflow datastore lives in US East, but the task is executing in Finland datacenters.
1391
+ 3. Data Lifecycle Policies: The objects need to be archived / managed separately from the Metaflow managed objects.
1392
+ - Example: Flow is training very large models that need to be stored separately and will be deleted more aggressively than the Metaflow managed objects.
1393
+
1394
+ Usage:
1395
+ ----------
1396
+
1397
+ - Using a custom IAM role to access the datastore.
1398
+
1399
+ ```python
1400
+ @with_artifact_store(
1401
+ type="s3",
1402
+ config=lambda: {
1403
+ "root": "s3://my-bucket-foo/path/to/root",
1404
+ "role_arn": ROLE,
1405
+ },
1406
+ )
1407
+ class MyFlow(FlowSpec):
1408
+
1409
+ @checkpoint
1410
+ @step
1411
+ def start(self):
1412
+ with open("my_file.txt", "w") as f:
1413
+ f.write("Hello, World!")
1414
+ self.external_bucket_checkpoint = current.checkpoint.save("my_file.txt")
1415
+ self.next(self.end)
1416
+
1417
+ ```
1418
+
1419
+ - Using credentials to access the s3-compatible datastore.
1420
+
1421
+ ```python
1422
+ @with_artifact_store(
1423
+ type="s3",
1424
+ config=lambda: {
1425
+ "root": "s3://my-bucket-foo/path/to/root",
1426
+ "client_params": {
1427
+ "aws_access_key_id": os.environ.get("MY_CUSTOM_ACCESS_KEY"),
1428
+ "aws_secret_access_key": os.environ.get("MY_CUSTOM_SECRET_KEY"),
1429
+ },
1430
+ },
1431
+ )
1432
+ class MyFlow(FlowSpec):
1433
+
1434
+ @checkpoint
1435
+ @step
1436
+ def start(self):
1437
+ with open("my_file.txt", "w") as f:
1438
+ f.write("Hello, World!")
1439
+ self.external_bucket_checkpoint = current.checkpoint.save("my_file.txt")
1440
+ self.next(self.end)
1441
+
1442
+ ```
1443
+
1444
+ - Accessing objects stored in external datastores after task execution.
1445
+
1446
+ ```python
1447
+ run = Run("CheckpointsTestsFlow/8992")
1448
+ with artifact_store_from(run=run, config={
1449
+ "client_params": {
1450
+ "aws_access_key_id": os.environ.get("MY_CUSTOM_ACCESS_KEY"),
1451
+ "aws_secret_access_key": os.environ.get("MY_CUSTOM_SECRET_KEY"),
1452
+ },
1453
+ }):
1454
+ with Checkpoint() as cp:
1455
+ latest = cp.list(
1456
+ task=run["start"].task
1457
+ )[0]
1458
+ print(latest)
1459
+ cp.load(
1460
+ latest,
1461
+ "test-checkpoints"
1462
+ )
1463
+
1464
+ task = Task("TorchTuneFlow/8484/train/53673")
1465
+ with artifact_store_from(run=run, config={
1466
+ "client_params": {
1467
+ "aws_access_key_id": os.environ.get("MY_CUSTOM_ACCESS_KEY"),
1468
+ "aws_secret_access_key": os.environ.get("MY_CUSTOM_SECRET_KEY"),
1469
+ },
1470
+ }):
1471
+ load_model(
1472
+ task.data.model_ref,
1473
+ "test-models"
1474
+ )
1475
+ ```
1476
+ Parameters:
1477
+ ----------
1478
+
1479
+ type: str
1480
+ The type of the datastore. Can be one of 's3', 'gcs', 'azure' or any other supported metaflow Datastore.
1481
+
1482
+ config: dict or Callable
1483
+ Dictionary of configuration options for the datastore. The following keys are required:
1484
+ - root: The root path in the datastore where the data will be saved. (needs to be in the format expected by the datastore)
1485
+ - example: 's3://bucket-name/path/to/root'
1486
+ - example: 'gs://bucket-name/path/to/root'
1487
+ - example: 'https://myblockacc.blob.core.windows.net/metaflow/'
1488
+ - role_arn (optional): AWS IAM role to access s3 bucket (only when `type` is 's3')
1489
+ - session_vars (optional): AWS session variables to access s3 bucket (only when `type` is 's3')
1490
+ - client_params (optional): AWS client parameters to access s3 bucket (only when `type` is 's3')
1491
+ """
1492
+ ...
1493
+
1379
1494
  @typing.overload
1380
- def schedule(*, hourly: bool = False, daily: bool = True, weekly: bool = False, cron: typing.Optional[str] = None, timezone: typing.Optional[str] = None) -> typing.Callable[[typing.Type[FlowSpecDerived]], typing.Type[FlowSpecDerived]]:
1495
+ def conda_base(*, packages: typing.Dict[str, str] = {}, libraries: typing.Dict[str, str] = {}, python: typing.Optional[str] = None, disabled: bool = False) -> typing.Callable[[typing.Type[FlowSpecDerived]], typing.Type[FlowSpecDerived]]:
1381
1496
  """
1382
- Specifies the times when the flow should be run when running on a
1383
- production scheduler.
1497
+ Specifies the Conda environment for all steps of the flow.
1498
+
1499
+ Use `@conda_base` to set common libraries required by all
1500
+ steps and use `@conda` to specify step-specific additions.
1384
1501
 
1385
1502
 
1386
1503
  Parameters
1387
1504
  ----------
1388
- hourly : bool, default False
1389
- Run the workflow hourly.
1390
- daily : bool, default True
1391
- Run the workflow daily.
1392
- weekly : bool, default False
1393
- Run the workflow weekly.
1394
- cron : str, optional, default None
1395
- Run the workflow at [a custom Cron schedule](https://docs.aws.amazon.com/eventbridge/latest/userguide/scheduled-events.html#cron-expressions)
1396
- specified by this expression.
1397
- timezone : str, optional, default None
1398
- Timezone on which the schedule runs (default: None). Currently supported only for Argo workflows,
1399
- which accepts timezones in [IANA format](https://nodatime.org/TimeZones).
1505
+ packages : Dict[str, str], default {}
1506
+ Packages to use for this flow. The key is the name of the package
1507
+ and the value is the version to use.
1508
+ libraries : Dict[str, str], default {}
1509
+ Supported for backward compatibility. When used with packages, packages will take precedence.
1510
+ python : str, optional, default None
1511
+ Version of Python to use, e.g. '3.7.4'. A default value of None implies
1512
+ that the version used will correspond to the version of the Python interpreter used to start the run.
1513
+ disabled : bool, default False
1514
+ If set to True, disables Conda.
1400
1515
  """
1401
1516
  ...
1402
1517
 
1403
1518
  @typing.overload
1404
- def schedule(f: typing.Type[FlowSpecDerived]) -> typing.Type[FlowSpecDerived]:
1519
+ def conda_base(f: typing.Type[FlowSpecDerived]) -> typing.Type[FlowSpecDerived]:
1405
1520
  ...
1406
1521
 
1407
- def schedule(f: typing.Optional[typing.Type[FlowSpecDerived]] = None, *, hourly: bool = False, daily: bool = True, weekly: bool = False, cron: typing.Optional[str] = None, timezone: typing.Optional[str] = None):
1522
+ def conda_base(f: typing.Optional[typing.Type[FlowSpecDerived]] = None, *, packages: typing.Dict[str, str] = {}, libraries: typing.Dict[str, str] = {}, python: typing.Optional[str] = None, disabled: bool = False):
1408
1523
  """
1409
- Specifies the times when the flow should be run when running on a
1410
- production scheduler.
1524
+ Specifies the Conda environment for all steps of the flow.
1525
+
1526
+ Use `@conda_base` to set common libraries required by all
1527
+ steps and use `@conda` to specify step-specific additions.
1411
1528
 
1412
1529
 
1413
1530
  Parameters
1414
1531
  ----------
1415
- hourly : bool, default False
1416
- Run the workflow hourly.
1417
- daily : bool, default True
1418
- Run the workflow daily.
1419
- weekly : bool, default False
1420
- Run the workflow weekly.
1421
- cron : str, optional, default None
1422
- Run the workflow at [a custom Cron schedule](https://docs.aws.amazon.com/eventbridge/latest/userguide/scheduled-events.html#cron-expressions)
1423
- specified by this expression.
1424
- timezone : str, optional, default None
1425
- Timezone on which the schedule runs (default: None). Currently supported only for Argo workflows,
1426
- which accepts timezones in [IANA format](https://nodatime.org/TimeZones).
1532
+ packages : Dict[str, str], default {}
1533
+ Packages to use for this flow. The key is the name of the package
1534
+ and the value is the version to use.
1535
+ libraries : Dict[str, str], default {}
1536
+ Supported for backward compatibility. When used with packages, packages will take precedence.
1537
+ python : str, optional, default None
1538
+ Version of Python to use, e.g. '3.7.4'. A default value of None implies
1539
+ that the version used will correspond to the version of the Python interpreter used to start the run.
1540
+ disabled : bool, default False
1541
+ If set to True, disables Conda.
1427
1542
  """
1428
1543
  ...
1429
1544