ob-metaflow-extensions 1.1.151__py2.py3-none-any.whl → 1.6.2__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 (92) hide show
  1. metaflow_extensions/outerbounds/__init__.py +1 -1
  2. metaflow_extensions/outerbounds/plugins/__init__.py +24 -3
  3. metaflow_extensions/outerbounds/plugins/apps/app_cli.py +0 -0
  4. metaflow_extensions/outerbounds/plugins/apps/core/__init__.py +16 -0
  5. metaflow_extensions/outerbounds/plugins/apps/core/_state_machine.py +506 -0
  6. metaflow_extensions/outerbounds/plugins/apps/core/_vendor/__init__.py +0 -0
  7. metaflow_extensions/outerbounds/plugins/apps/core/_vendor/spinner/__init__.py +4 -0
  8. metaflow_extensions/outerbounds/plugins/apps/core/_vendor/spinner/spinners.py +478 -0
  9. metaflow_extensions/outerbounds/plugins/apps/core/app_config.py +128 -0
  10. metaflow_extensions/outerbounds/plugins/apps/core/app_deploy_decorator.py +333 -0
  11. metaflow_extensions/outerbounds/plugins/apps/core/artifacts.py +0 -0
  12. metaflow_extensions/outerbounds/plugins/apps/core/capsule.py +1029 -0
  13. metaflow_extensions/outerbounds/plugins/apps/core/click_importer.py +24 -0
  14. metaflow_extensions/outerbounds/plugins/apps/core/code_package/__init__.py +3 -0
  15. metaflow_extensions/outerbounds/plugins/apps/core/code_package/code_packager.py +618 -0
  16. metaflow_extensions/outerbounds/plugins/apps/core/code_package/examples.py +125 -0
  17. metaflow_extensions/outerbounds/plugins/apps/core/config/__init__.py +15 -0
  18. metaflow_extensions/outerbounds/plugins/apps/core/config/cli_generator.py +165 -0
  19. metaflow_extensions/outerbounds/plugins/apps/core/config/config_utils.py +966 -0
  20. metaflow_extensions/outerbounds/plugins/apps/core/config/schema_export.py +299 -0
  21. metaflow_extensions/outerbounds/plugins/apps/core/config/typed_configs.py +233 -0
  22. metaflow_extensions/outerbounds/plugins/apps/core/config/typed_init_generator.py +537 -0
  23. metaflow_extensions/outerbounds/plugins/apps/core/config/unified_config.py +1125 -0
  24. metaflow_extensions/outerbounds/plugins/apps/core/config_schema.yaml +337 -0
  25. metaflow_extensions/outerbounds/plugins/apps/core/dependencies.py +115 -0
  26. metaflow_extensions/outerbounds/plugins/apps/core/deployer.py +1300 -0
  27. metaflow_extensions/outerbounds/plugins/apps/core/exceptions.py +341 -0
  28. metaflow_extensions/outerbounds/plugins/apps/core/experimental/__init__.py +89 -0
  29. metaflow_extensions/outerbounds/plugins/apps/core/perimeters.py +123 -0
  30. metaflow_extensions/outerbounds/plugins/apps/core/secrets.py +164 -0
  31. metaflow_extensions/outerbounds/plugins/apps/core/utils.py +233 -0
  32. metaflow_extensions/outerbounds/plugins/apps/core/validations.py +17 -0
  33. metaflow_extensions/outerbounds/plugins/aws/__init__.py +4 -0
  34. metaflow_extensions/outerbounds/plugins/aws/assume_role.py +3 -0
  35. metaflow_extensions/outerbounds/plugins/aws/assume_role_decorator.py +118 -0
  36. metaflow_extensions/outerbounds/plugins/checkpoint_datastores/coreweave.py +9 -77
  37. metaflow_extensions/outerbounds/plugins/checkpoint_datastores/external_chckpt.py +85 -0
  38. metaflow_extensions/outerbounds/plugins/checkpoint_datastores/nebius.py +7 -78
  39. metaflow_extensions/outerbounds/plugins/fast_bakery/baker.py +119 -0
  40. metaflow_extensions/outerbounds/plugins/fast_bakery/docker_environment.py +17 -3
  41. metaflow_extensions/outerbounds/plugins/fast_bakery/fast_bakery.py +1 -0
  42. metaflow_extensions/outerbounds/plugins/kubernetes/kubernetes_client.py +18 -44
  43. metaflow_extensions/outerbounds/plugins/kubernetes/pod_killer.py +374 -0
  44. metaflow_extensions/outerbounds/plugins/nim/card.py +1 -6
  45. metaflow_extensions/outerbounds/plugins/nim/{__init__.py → nim_decorator.py} +13 -49
  46. metaflow_extensions/outerbounds/plugins/nim/nim_manager.py +294 -233
  47. metaflow_extensions/outerbounds/plugins/nim/utils.py +36 -0
  48. metaflow_extensions/outerbounds/plugins/nvcf/constants.py +2 -2
  49. metaflow_extensions/outerbounds/plugins/nvct/nvct_decorator.py +32 -8
  50. metaflow_extensions/outerbounds/plugins/nvct/nvct_runner.py +1 -1
  51. metaflow_extensions/outerbounds/plugins/ollama/__init__.py +171 -16
  52. metaflow_extensions/outerbounds/plugins/ollama/constants.py +1 -0
  53. metaflow_extensions/outerbounds/plugins/ollama/exceptions.py +22 -0
  54. metaflow_extensions/outerbounds/plugins/ollama/ollama.py +1710 -114
  55. metaflow_extensions/outerbounds/plugins/ollama/status_card.py +292 -0
  56. metaflow_extensions/outerbounds/plugins/optuna/__init__.py +49 -0
  57. metaflow_extensions/outerbounds/plugins/profilers/simple_card_decorator.py +96 -0
  58. metaflow_extensions/outerbounds/plugins/s3_proxy/__init__.py +7 -0
  59. metaflow_extensions/outerbounds/plugins/s3_proxy/binary_caller.py +132 -0
  60. metaflow_extensions/outerbounds/plugins/s3_proxy/constants.py +11 -0
  61. metaflow_extensions/outerbounds/plugins/s3_proxy/exceptions.py +13 -0
  62. metaflow_extensions/outerbounds/plugins/s3_proxy/proxy_bootstrap.py +59 -0
  63. metaflow_extensions/outerbounds/plugins/s3_proxy/s3_proxy_api.py +93 -0
  64. metaflow_extensions/outerbounds/plugins/s3_proxy/s3_proxy_decorator.py +250 -0
  65. metaflow_extensions/outerbounds/plugins/s3_proxy/s3_proxy_manager.py +225 -0
  66. metaflow_extensions/outerbounds/plugins/snowflake/snowflake.py +37 -7
  67. metaflow_extensions/outerbounds/plugins/snowpark/snowpark.py +18 -8
  68. metaflow_extensions/outerbounds/plugins/snowpark/snowpark_cli.py +6 -0
  69. metaflow_extensions/outerbounds/plugins/snowpark/snowpark_client.py +45 -18
  70. metaflow_extensions/outerbounds/plugins/snowpark/snowpark_decorator.py +18 -9
  71. metaflow_extensions/outerbounds/plugins/snowpark/snowpark_job.py +10 -4
  72. metaflow_extensions/outerbounds/plugins/torchtune/__init__.py +163 -0
  73. metaflow_extensions/outerbounds/plugins/vllm/__init__.py +255 -0
  74. metaflow_extensions/outerbounds/plugins/vllm/constants.py +1 -0
  75. metaflow_extensions/outerbounds/plugins/vllm/exceptions.py +1 -0
  76. metaflow_extensions/outerbounds/plugins/vllm/status_card.py +352 -0
  77. metaflow_extensions/outerbounds/plugins/vllm/vllm_manager.py +621 -0
  78. metaflow_extensions/outerbounds/remote_config.py +46 -9
  79. metaflow_extensions/outerbounds/toplevel/apps/__init__.py +9 -0
  80. metaflow_extensions/outerbounds/toplevel/apps/exceptions.py +11 -0
  81. metaflow_extensions/outerbounds/toplevel/global_aliases_for_metaflow_package.py +86 -2
  82. metaflow_extensions/outerbounds/toplevel/ob_internal.py +4 -0
  83. metaflow_extensions/outerbounds/toplevel/plugins/optuna/__init__.py +1 -0
  84. metaflow_extensions/outerbounds/toplevel/plugins/torchtune/__init__.py +1 -0
  85. metaflow_extensions/outerbounds/toplevel/plugins/vllm/__init__.py +1 -0
  86. metaflow_extensions/outerbounds/toplevel/s3_proxy.py +88 -0
  87. {ob_metaflow_extensions-1.1.151.dist-info → ob_metaflow_extensions-1.6.2.dist-info}/METADATA +2 -2
  88. ob_metaflow_extensions-1.6.2.dist-info/RECORD +136 -0
  89. metaflow_extensions/outerbounds/plugins/nim/utilities.py +0 -5
  90. ob_metaflow_extensions-1.1.151.dist-info/RECORD +0 -74
  91. {ob_metaflow_extensions-1.1.151.dist-info → ob_metaflow_extensions-1.6.2.dist-info}/WHEEL +0 -0
  92. {ob_metaflow_extensions-1.1.151.dist-info → ob_metaflow_extensions-1.6.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,337 @@
1
+ $schema: https://json-schema.org/draft/2020-12/schema
2
+ title: CoreConfig
3
+ description: |
4
+ Schema for defining Outerbounds Apps configuration. This schema is what we will end up using on the CLI/programmatic interface.
5
+ How to read this schema:
6
+ 1. If the a property has `mutation_behavior` set to `union` then it will allow overrides of values at runtime from the CLI.
7
+ 2. If the property has `mutation_behavior`set to `not_allowed` then either the CLI or the config file value will be used (which ever is not None). If the user supplies something in both then an error will be raised.
8
+ 3. If a property has `experimental` set to true then a lot its validations may-be skipped and parsing handled somewhere else.
9
+ type: object
10
+ required:
11
+ - name
12
+ - port
13
+ - commands
14
+ properties:
15
+ name:
16
+ description: The name of the app to deploy. (validation applied)
17
+ type: string
18
+ example: myapp
19
+ mutation_behavior: union
20
+ cli_option: --name
21
+ port:
22
+ description: |-
23
+ Port where the app is hosted. When deployed this will be port on which we will deploy the app. (validation applied)
24
+ type: integer
25
+ example: 8000
26
+ mutation_behavior: union
27
+ cli_option: --port
28
+ description:
29
+ description: The description of the app to deploy.
30
+ type: string
31
+ example: This is a description of my app.
32
+ mutation_behavior: union
33
+ cli_option: --description
34
+ app_type:
35
+ description: The User defined type of app to deploy. Its only used for bookkeeping purposes.
36
+ type: string
37
+ example: MyCustomAgent
38
+ mutation_behavior: union
39
+ cli_option: --app-type
40
+ image:
41
+ description: The Docker image to deploy with the App.
42
+ type: string
43
+ example: python:3.10-slim
44
+ mutation_behavior: union
45
+ cli_option: --image
46
+ tags:
47
+ description: The tags of the app to deploy. (validation applied)
48
+ type: array
49
+ items:
50
+ type: string
51
+ example:
52
+ - foo: bar
53
+ - x: y
54
+ mutation_behavior: union
55
+ cli_option: --tag
56
+ secrets:
57
+ description: |-
58
+ Outerbounds integrations to attach to the app. You can use the value you set in the `@secrets` decorator in your code. (validation applied)
59
+ type: array
60
+ items:
61
+ type: string
62
+ example:
63
+ - hf-token
64
+ mutation_behavior: union
65
+ cli_option: --secret
66
+ compute_pools:
67
+ description: A list of compute pools to deploy the app to.
68
+ type: array
69
+ items:
70
+ type: string
71
+ example:
72
+ - default
73
+ - large
74
+ mutation_behavior: union
75
+ cli_option: --compute-pools
76
+ environment:
77
+ description: Environment variables to deploy with the App.
78
+ type: object
79
+ additionalProperties: true
80
+ example:
81
+ DEBUG: true
82
+ DATABASE_CONFIG:
83
+ host: localhost
84
+ port: 5432
85
+ ALLOWED_ORIGINS:
86
+ - http://localhost:3000
87
+ - https://myapp.com
88
+ mutation_behavior: union
89
+ cli_option: --env
90
+ commands:
91
+ description: A list of commands to run the app with.
92
+ type: array
93
+ items:
94
+ type: string
95
+ example:
96
+ - python app.py
97
+ - python app.py --foo bar
98
+ mutation_behavior: not_allowed
99
+ resources:
100
+ title: ResourceConfig
101
+ description: Resource configuration for the app.
102
+ type: object
103
+ required: []
104
+ properties:
105
+ cpu:
106
+ description: CPU requests (validation applied)
107
+ type: string
108
+ default: '1'
109
+ example: 500m
110
+ mutation_behavior: union
111
+ cli_option: --cpu
112
+ memory:
113
+ description: Memory requests (validation applied)
114
+ type: string
115
+ default: 4Gi
116
+ example: 512Mi
117
+ mutation_behavior: union
118
+ cli_option: --memory
119
+ gpu:
120
+ description: GPU requests (validation applied)
121
+ type: string
122
+ example: '1'
123
+ mutation_behavior: union
124
+ cli_option: --gpu
125
+ disk:
126
+ description: Storage disk size. (validation applied)
127
+ type: string
128
+ default: 20Gi
129
+ example: 1Gi
130
+ mutation_behavior: union
131
+ cli_option: --disk
132
+ shared_memory:
133
+ description: Shared memory (validation applied)
134
+ type: string
135
+ example: 1Gi
136
+ mutation_behavior: union
137
+ cli_option: --shared-memory
138
+ mutation_behavior: union
139
+ auth:
140
+ title: AuthConfig
141
+ description: Authentication configuration.
142
+ type: object
143
+ required: []
144
+ properties:
145
+ type:
146
+ description: The type of authentication to use for the app.
147
+ type: string
148
+ default: Browser
149
+ enum:
150
+ - Browser
151
+ - API
152
+ - BrowserAndApi
153
+ example: Browser
154
+ mutation_behavior: union
155
+ cli_option: --auth-type
156
+ public:
157
+ description: Whether the app is public or not.
158
+ type: boolean
159
+ default: true
160
+ example: true
161
+ mutation_behavior: union
162
+ cli_option: --public-access/--private-access
163
+ mutation_behavior: union
164
+ replicas:
165
+ title: ReplicaConfig
166
+ description: Replica configuration.
167
+ type: object
168
+ required: []
169
+ properties:
170
+ fixed:
171
+ description: |-
172
+ The fixed number of replicas to deploy the app with. If min and max are set, this will raise an error.
173
+ type: integer
174
+ example: 1
175
+ mutation_behavior: union
176
+ cli_option: --fixed-replicas
177
+ min:
178
+ description: The minimum number of replicas to deploy the app with.
179
+ type: integer
180
+ example: 1
181
+ mutation_behavior: union
182
+ cli_option: --min-replicas
183
+ max:
184
+ description: The maximum number of replicas to deploy the app with.
185
+ type: integer
186
+ example: 10
187
+ mutation_behavior: union
188
+ cli_option: --max-replicas
189
+ scaling_policy:
190
+ title: ScalingPolicyConfig
191
+ description: |-
192
+ Policies for autoscaling replicas. Available policies:
193
+ - Request based Autoscaling (rpm)
194
+ type: object
195
+ required: []
196
+ properties:
197
+ rpm:
198
+ description: |-
199
+ Scale up replicas when the requests per minute crosses this threshold. If nothing is provided and the replicas.max and replicas.min is set then the default rpm would be 60.
200
+ type: integer
201
+ default: 60
202
+ mutation_behavior: union
203
+ cli_option: --scaling-rpm
204
+ mutation_behavior: union
205
+ mutation_behavior: union
206
+ dependencies:
207
+ title: DependencyConfig
208
+ description: Dependency configuration.
209
+ type: object
210
+ required: []
211
+ properties:
212
+ from_requirements_file:
213
+ description: The path to the requirements.txt file to attach to the app.
214
+ type: string
215
+ example: requirements.txt
216
+ mutation_behavior: not_allowed
217
+ cli_option: --dep-from-requirements
218
+ from_pyproject_toml:
219
+ description: The path to the pyproject.toml file to attach to the app.
220
+ type: string
221
+ example: pyproject.toml
222
+ mutation_behavior: not_allowed
223
+ cli_option: --dep-from-pyproject
224
+ python:
225
+ description: The Python version to use for the app.
226
+ type: string
227
+ example: '3.10'
228
+ mutation_behavior: union
229
+ cli_option: --python
230
+ pypi:
231
+ description: |-
232
+ A dictionary of pypi dependencies to attach to the app. The key is the package name and the value is the version.
233
+ type: object
234
+ additionalProperties: true
235
+ example:
236
+ numpy: 1.23.0
237
+ pandas: ''
238
+ mutation_behavior: not_allowed
239
+ cli_option: --pypi
240
+ conda:
241
+ description: |-
242
+ A dictionary of conda dependencies to attach to the app. The key is the package name and the value is the version.
243
+ type: object
244
+ additionalProperties: true
245
+ example:
246
+ numpy: 1.23.0
247
+ pandas: ''
248
+ mutation_behavior: not_allowed
249
+ cli_option: --conda
250
+ mutation_behavior: union
251
+ package:
252
+ title: PackageConfig
253
+ description: Package configuration.
254
+ type: object
255
+ required: []
256
+ properties:
257
+ src_paths:
258
+ description: The path to the source code to deploy with the App.
259
+ type: array
260
+ items:
261
+ type: string
262
+ example:
263
+ - ./
264
+ mutation_behavior: union
265
+ cli_option: --package-src-path
266
+ suffixes:
267
+ description: A list of suffixes to add to the source code to deploy with the App.
268
+ type: array
269
+ items:
270
+ type: string
271
+ example:
272
+ - .py
273
+ - .ipynb
274
+ mutation_behavior: union
275
+ cli_option: --package-suffixes
276
+ mutation_behavior: union
277
+ no_deps:
278
+ description: Do not bake any dependencies. Directly used the image provided
279
+ type: boolean
280
+ default: false
281
+ mutation_behavior: union
282
+ cli_option: --no-deps
283
+ force_upgrade:
284
+ description: Force upgrade the app even if it is currently being upgraded.
285
+ type: boolean
286
+ default: false
287
+ mutation_behavior: union
288
+ cli_option: --force-upgrade
289
+ persistence:
290
+ description: The persistence mode to deploy the app with. (validation applied)
291
+ type: string
292
+ default: none
293
+ enum:
294
+ - none
295
+ - postgres
296
+ example: postgres
297
+ experimental: true
298
+ mutation_behavior: union
299
+ cli_option: --persistence
300
+ project:
301
+ description: The project name to deploy the app to.
302
+ type: string
303
+ example: my-project
304
+ experimental: true
305
+ mutation_behavior: union
306
+ cli_option: --project
307
+ branch:
308
+ description: The branch name to deploy the app to.
309
+ type: string
310
+ example: main
311
+ experimental: true
312
+ mutation_behavior: union
313
+ cli_option: --branch
314
+ models:
315
+ type: array
316
+ items:
317
+ type: string
318
+ example:
319
+ - asset_id: model-123
320
+ asset_instance_id: instance-456
321
+ experimental: true
322
+ mutation_behavior: union
323
+ data:
324
+ type: array
325
+ items:
326
+ type: string
327
+ example:
328
+ - asset_id: data-789
329
+ asset_instance_id: instance-101
330
+ experimental: true
331
+ mutation_behavior: union
332
+ generate_static_url:
333
+ description: Generate a static URL for the app based on its name.
334
+ type: boolean
335
+ default: false
336
+ mutation_behavior: union
337
+ cli_option: --generate-static-url
@@ -0,0 +1,115 @@
1
+ import copy
2
+ import json
3
+ import os
4
+ import shutil
5
+ import sys
6
+ import tempfile
7
+ from hashlib import sha256
8
+ from typing import List, Optional, Callable, Any
9
+ from .app_config import AppConfig
10
+ from .utils import TODOException
11
+ from metaflow.metaflow_config import (
12
+ get_pinned_conda_libs,
13
+ DEFAULT_DATASTORE,
14
+ KUBERNETES_CONTAINER_IMAGE,
15
+ )
16
+ from collections import namedtuple
17
+
18
+ BakingStatus = namedtuple(
19
+ "BakingStatus", ["image_should_be_baked", "python_path", "resolved_image"]
20
+ )
21
+
22
+
23
+ class ImageBakingException(Exception):
24
+ pass
25
+
26
+
27
+ def _safe_open_file(path: str):
28
+ if not os.path.exists(path):
29
+ raise ImageBakingException(f"File does not exist: {path}")
30
+ try:
31
+ with open(path, "r") as f:
32
+ return f.read()
33
+ except Exception as e:
34
+ raise ImageBakingException(f"Failed to open file: {e}")
35
+
36
+
37
+ def bake_deployment_image(
38
+ app_config: AppConfig,
39
+ cache_file_path: str,
40
+ logger: Optional[Callable[[str], Any]] = None,
41
+ ) -> BakingStatus:
42
+ # When do we bake an image?
43
+ # 1. When the user has specified something like `pypi`/`conda`
44
+ # 2, When the user has specified something like `from_requirements`/ `from_pyproject`
45
+ # TODO: add parsers for the pyproject/requirements stuff.
46
+ from metaflow.ob_internal import internal_bake_image # type: ignore
47
+ from metaflow.plugins.pypi.parsers import (
48
+ requirements_txt_parser,
49
+ pyproject_toml_parser,
50
+ )
51
+
52
+ image = app_config.get("image", KUBERNETES_CONTAINER_IMAGE)
53
+ python_version = "%d.%d.%d" % sys.version_info[:3]
54
+
55
+ dependencies = app_config.get_state("dependencies", {})
56
+ pypi_packages = {}
57
+ conda_packages = {}
58
+
59
+ parsed_packages = {}
60
+
61
+ if dependencies.get("from_requirements_file"):
62
+ parsed_packages = requirements_txt_parser(
63
+ _safe_open_file(dependencies.get("from_requirements_file"))
64
+ )
65
+ pypi_packages = parsed_packages.get("packages", {})
66
+ python_version = parsed_packages.get("python_version", python_version)
67
+
68
+ elif dependencies.get("from_pyproject_toml"):
69
+ parsed_packages = pyproject_toml_parser(
70
+ _safe_open_file(dependencies.get("from_pyproject_toml"))
71
+ )
72
+ pypi_packages = parsed_packages.get("packages", {})
73
+ python_version = parsed_packages.get("python_version", python_version)
74
+
75
+ elif "pypi" in dependencies:
76
+ pypi_packages = dependencies.get("pypi", {}) or {}
77
+
78
+ if "conda" in dependencies:
79
+ conda_packages = dependencies.get("conda", {}) or {}
80
+ if "python" in dependencies:
81
+ python_version = dependencies.get("python", python_version) or python_version
82
+
83
+ python_packages_exist = len(pypi_packages) > 0 or len(conda_packages) > 0
84
+ if (not python_packages_exist) or app_config.get_state("skip_dependencies", False):
85
+ # Inform the user that no dependencies are being used.
86
+ if app_config.get_state("skip_dependencies", False) and logger:
87
+ logger(
88
+ "⏭️ Skipping baking dependencies into the image based on the --no-deps flag."
89
+ )
90
+ # TODO: Handle this a little more nicely.
91
+ return BakingStatus(
92
+ image_should_be_baked=False, resolved_image=image, python_path="python"
93
+ )
94
+
95
+ pinned_conda_libs = get_pinned_conda_libs(python_version, DEFAULT_DATASTORE)
96
+ pypi_packages.update(pinned_conda_libs)
97
+ _reference = app_config.get("name", "default")
98
+ # `image` cannot be None. If by chance it is none, FB will fart.
99
+ fb_response = internal_bake_image(
100
+ cache_file_path=cache_file_path,
101
+ pypi_packages=pypi_packages,
102
+ conda_packages=conda_packages,
103
+ ref=_reference,
104
+ python=python_version,
105
+ base_image=image,
106
+ logger=logger,
107
+ )
108
+ if fb_response.failure:
109
+ raise ImageBakingException(f"Failed to bake image: {fb_response.response}")
110
+
111
+ return BakingStatus(
112
+ image_should_be_baked=True,
113
+ resolved_image=fb_response.container_image,
114
+ python_path=fb_response.python_path,
115
+ )