flyteplugins-trackio 2.6.11__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.
@@ -0,0 +1,52 @@
1
+ """
2
+ Flyte Trackio plugin.
3
+
4
+ Provides seamless Trackio experiment tracking for Flyte tasks through the
5
+ `@trackio_init` decorator.
6
+
7
+ Basic usage:
8
+
9
+ from flyteplugins.trackio import (
10
+ get_trackio_run,
11
+ trackio_init,
12
+ )
13
+
14
+ @trackio_init(project="my-project")
15
+ @env.task
16
+ async def train():
17
+ run = get_trackio_run()
18
+ run.log({"loss": 0.123})
19
+ return run.id
20
+
21
+ Configuration can also be provided via `trackio_config()`:
22
+
23
+ r = flyte.with_runcontext(
24
+ custom_context=trackio_config(
25
+ project="my-project",
26
+ group="baseline",
27
+ config={"learning_rate": 1e-3},
28
+ )
29
+ ).run(train)
30
+ """
31
+
32
+ from __future__ import annotations
33
+
34
+ from ._context import (
35
+ get_trackio_context,
36
+ get_trackio_run,
37
+ trackio_config,
38
+ )
39
+ from ._decorator import (
40
+ trackio_init,
41
+ )
42
+ from ._link import Trackio
43
+
44
+ __version__ = "0.1.0"
45
+
46
+ __all__ = [
47
+ "Trackio",
48
+ "get_trackio_context",
49
+ "get_trackio_run",
50
+ "trackio_config",
51
+ "trackio_init",
52
+ ]
@@ -0,0 +1,241 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ from dataclasses import asdict, dataclass
5
+ from typing import Any, Optional
6
+
7
+ import flyte
8
+
9
+ import trackio
10
+
11
+ _TRACKIO_RUN_KEY = "_trackio_run"
12
+ _TRACKIO_CONTEXT_PREFIX = "trackio"
13
+
14
+
15
+ def _to_dict_helper(obj, prefix: str) -> dict[str, str]:
16
+ """Serialize a dataclass into Flyte custom_context."""
17
+
18
+ result: dict[str, str] = {}
19
+
20
+ for key, value in asdict(obj).items():
21
+ if value is None:
22
+ continue
23
+
24
+ if isinstance(value, (dict, list, bool)):
25
+ result[f"{prefix}_{key}"] = json.dumps(value)
26
+ else:
27
+ result[f"{prefix}_{key}"] = str(value)
28
+
29
+ return result
30
+
31
+
32
+ def _from_dict_helper(cls, d: dict[str, str], prefix: str):
33
+ """Deserialize a dataclass from Flyte custom_context."""
34
+
35
+ kwargs = {}
36
+
37
+ prefix = f"{prefix}_"
38
+
39
+ for key, value in d.items():
40
+ if not key.startswith(prefix):
41
+ continue
42
+
43
+ field = key[len(prefix) :]
44
+
45
+ try:
46
+ kwargs[field] = json.loads(value)
47
+ except Exception:
48
+ kwargs[field] = value
49
+
50
+ return cls(**kwargs)
51
+
52
+
53
+ def _context_manager_enter(obj, prefix: str):
54
+ ctx = flyte.ctx()
55
+
56
+ saved = {}
57
+
58
+ if ctx and ctx.custom_context:
59
+ for key in list(ctx.custom_context.keys()):
60
+ if key.startswith(f"{prefix}_"):
61
+ saved[key] = ctx.custom_context[key]
62
+
63
+ ctx_mgr = flyte.custom_context(**obj)
64
+
65
+ ctx_mgr.__enter__()
66
+
67
+ return saved, ctx_mgr
68
+
69
+
70
+ def _context_manager_exit(ctx_mgr, saved: dict, prefix: str, *args):
71
+ if ctx_mgr:
72
+ ctx_mgr.__exit__(*args)
73
+
74
+ ctx = flyte.ctx()
75
+
76
+ if ctx and ctx.custom_context:
77
+ for key in list(ctx.custom_context.keys()):
78
+ if key.startswith(f"{prefix}_"):
79
+ del ctx.custom_context[key]
80
+
81
+ ctx.custom_context.update(saved)
82
+
83
+
84
+ @dataclass
85
+ class _TrackioConfig:
86
+ """
87
+ Trackio configuration stored inside the Flyte custom_context.
88
+ Mirrors the supported subset of `trackio.init()`.
89
+ """
90
+
91
+ project: Optional[str] = None
92
+
93
+ name: Optional[str] = None
94
+
95
+ group: Optional[str] = None
96
+
97
+ space_id: Optional[str] = None
98
+
99
+ dataset_id: Optional[str] = None
100
+
101
+ bucket_id: Optional[str] = None
102
+
103
+ server_url: Optional[str] = None
104
+
105
+ config: Optional[dict[str, Any]] = None
106
+
107
+ resume: str = "never"
108
+
109
+ auto_log_gpu: Optional[bool] = None
110
+
111
+ gpu_log_interval: float = 10.0
112
+
113
+ auto_log_cpu: Optional[bool] = None
114
+
115
+ cpu_log_interval: float = 10.0
116
+
117
+ def to_trackio_init(self) -> dict[str, Any]:
118
+ """Convert to arguments for `trackio.init()`."""
119
+
120
+ return {k: v for k, v in asdict(self).items() if v is not None}
121
+
122
+ def to_dict(self) -> dict[str, str]:
123
+ return _to_dict_helper(self, _TRACKIO_CONTEXT_PREFIX)
124
+
125
+ @classmethod
126
+ def from_dict(cls, d: dict[str, str]):
127
+ return _from_dict_helper(cls, d, _TRACKIO_CONTEXT_PREFIX)
128
+
129
+ def __enter__(self):
130
+ self._saved, self._ctx = _context_manager_enter(
131
+ self,
132
+ _TRACKIO_CONTEXT_PREFIX,
133
+ )
134
+ return self
135
+
136
+ def __exit__(self, *args):
137
+ _context_manager_exit(
138
+ self._ctx,
139
+ self._saved,
140
+ _TRACKIO_CONTEXT_PREFIX,
141
+ *args,
142
+ )
143
+
144
+
145
+ def get_trackio_context() -> Optional[_TrackioConfig]:
146
+ """
147
+ Return the current Trackio configuration.
148
+ """
149
+
150
+ ctx = flyte.ctx()
151
+
152
+ if not ctx or not ctx.custom_context:
153
+ return None
154
+
155
+ prefix = f"{_TRACKIO_CONTEXT_PREFIX}_"
156
+
157
+ if not any(k.startswith(prefix) for k in ctx.custom_context):
158
+ return None
159
+
160
+ return _TrackioConfig.from_dict(ctx.custom_context)
161
+
162
+
163
+ def trackio_config(
164
+ *,
165
+ project: str | None = None,
166
+ name: str | None = None,
167
+ group: str | None = None,
168
+ space_id: str | None = None,
169
+ dataset_id: str | None = None,
170
+ bucket_id: str | None = None,
171
+ server_url: str | None = None,
172
+ config: dict[str, Any] | None = None,
173
+ resume: str = "never",
174
+ auto_log_gpu: bool | None = None,
175
+ gpu_log_interval: float = 10.0,
176
+ auto_log_cpu: bool | None = None,
177
+ cpu_log_interval: float = 10.0,
178
+ ) -> _TrackioConfig:
179
+ """
180
+ Create Trackio configuration for Flyte.
181
+ """
182
+
183
+ return _TrackioConfig(
184
+ project=project,
185
+ name=name,
186
+ group=group,
187
+ space_id=space_id,
188
+ dataset_id=dataset_id,
189
+ bucket_id=bucket_id,
190
+ server_url=server_url,
191
+ config=config,
192
+ resume=resume,
193
+ auto_log_gpu=auto_log_gpu,
194
+ gpu_log_interval=gpu_log_interval,
195
+ auto_log_cpu=auto_log_cpu,
196
+ cpu_log_interval=cpu_log_interval,
197
+ )
198
+
199
+
200
+ def set_trackio_run(run) -> None:
201
+ """Store the active Trackio run in the Flyte context."""
202
+
203
+ ctx = flyte.ctx()
204
+
205
+ if not ctx:
206
+ return
207
+
208
+ if ctx.data is None:
209
+ ctx.data = {}
210
+
211
+ ctx.data[_TRACKIO_RUN_KEY] = run
212
+
213
+
214
+ def get_trackio_run():
215
+ """
216
+ Return the active Trackio run.
217
+
218
+ If called inside a `@trackio_init` decorated Flyte task, this returns the
219
+ Trackio run managed by the plugin. Otherwise it falls back to Trackio's
220
+ globally active run (if one exists).
221
+
222
+ Returns:
223
+ trackio.Run | None: The active Trackio run.
224
+ """
225
+ ctx = flyte.ctx()
226
+
227
+ if ctx and ctx.data:
228
+ run = ctx.data.get(_TRACKIO_RUN_KEY)
229
+ if run is not None:
230
+ return run
231
+
232
+ return getattr(trackio, "run", None)
233
+
234
+
235
+ def clear_trackio_run() -> None:
236
+ """Remove the Trackio run from the Flyte context."""
237
+
238
+ ctx = flyte.ctx()
239
+
240
+ if ctx and ctx.data:
241
+ ctx.data.pop(_TRACKIO_RUN_KEY, None)
@@ -0,0 +1,173 @@
1
+ from __future__ import annotations
2
+
3
+ import functools
4
+ import logging
5
+ from contextlib import contextmanager
6
+ from inspect import iscoroutinefunction
7
+ from typing import Any, Callable, Optional, TypeVar, cast
8
+
9
+ import flyte
10
+ from flyte._task import AsyncFunctionTaskTemplate
11
+
12
+ import trackio
13
+
14
+ from ._context import (
15
+ _TRACKIO_RUN_KEY,
16
+ clear_trackio_run,
17
+ get_trackio_context,
18
+ set_trackio_run,
19
+ )
20
+ from ._link import Trackio
21
+
22
+ logger = logging.getLogger(__name__)
23
+
24
+ F = TypeVar("F", bound=Callable[..., Any])
25
+
26
+
27
+ def _build_init_kwargs(
28
+ decorator_kwargs: dict[str, Any],
29
+ ) -> dict[str, Any]:
30
+ """
31
+ Build arguments for `trackio.init()`.
32
+
33
+ Values from the current Trackio configuration are used as defaults and are
34
+ overridden by non-`None` decorator arguments.
35
+
36
+ Args:
37
+ decorator_kwargs:
38
+ Keyword arguments supplied to `@trackio_init`.
39
+
40
+ Returns:
41
+ A dictionary of resolved keyword arguments to pass to
42
+ `trackio.init()`.
43
+ """
44
+ ctx = get_trackio_context()
45
+
46
+ init_kwargs = ctx.to_trackio_init() if ctx else {}
47
+
48
+ init_kwargs.update({k: v for k, v in decorator_kwargs.items() if v is not None})
49
+
50
+ return init_kwargs
51
+
52
+
53
+ @contextmanager
54
+ def _trackio_run(**decorator_kwargs):
55
+ """
56
+ Context manager responsible for Trackio run lifecycle.
57
+
58
+ If a parent Trackio run already exists, it is reused.
59
+ Otherwise a new Trackio run is created for the duration
60
+ of the task.
61
+ """
62
+
63
+ flyte_ctx = flyte.ctx()
64
+
65
+ if not flyte_ctx:
66
+ run = trackio.init(**decorator_kwargs)
67
+
68
+ try:
69
+ yield run
70
+ finally:
71
+ run.finish()
72
+
73
+ return
74
+
75
+ if flyte_ctx.data is None:
76
+ flyte_ctx.data = {}
77
+
78
+ saved_run = flyte_ctx.data.get(_TRACKIO_RUN_KEY)
79
+
80
+ if saved_run is not None:
81
+ yield saved_run
82
+ return
83
+
84
+ init_kwargs = _build_init_kwargs(decorator_kwargs)
85
+
86
+ run = trackio.init(**init_kwargs)
87
+
88
+ set_trackio_run(run)
89
+
90
+ try:
91
+ yield run
92
+ finally:
93
+ try:
94
+ run.finish()
95
+ except Exception:
96
+ logger.exception("Failed to finish Trackio run.")
97
+ finally:
98
+ clear_trackio_run()
99
+
100
+
101
+ def trackio_init(
102
+ _func: Optional[F] = None,
103
+ **decorator_kwargs: Any,
104
+ ) -> F:
105
+ """
106
+ Initialize a Trackio run around a Flyte task.
107
+
108
+ Usage
109
+ -----
110
+
111
+ @trackio_init
112
+ @env.task
113
+ async def train():
114
+ ...
115
+
116
+ @trackio_init(
117
+ project="vision",
118
+ space_id="user/demo",
119
+ )
120
+ @env.task
121
+ async def train():
122
+ ...
123
+ """
124
+
125
+ def decorator(task: F) -> F:
126
+
127
+ if isinstance(task, AsyncFunctionTaskTemplate):
128
+ existing_links = getattr(task, "links", ())
129
+
130
+ task = task.override(
131
+ links=(
132
+ *existing_links,
133
+ Trackio(
134
+ project=decorator_kwargs.get("project"),
135
+ server_url=decorator_kwargs.get("server_url"),
136
+ space_id=decorator_kwargs.get("space_id"),
137
+ ),
138
+ )
139
+ )
140
+
141
+ original_execute = task.execute
142
+
143
+ async def wrapped_execute(*args, **kwargs):
144
+
145
+ with _trackio_run(**decorator_kwargs):
146
+ return await original_execute(*args, **kwargs)
147
+
148
+ task.execute = wrapped_execute
149
+
150
+ return cast(F, task)
151
+
152
+ if iscoroutinefunction(task):
153
+
154
+ @functools.wraps(task)
155
+ async def async_wrapper(*args, **kwargs):
156
+
157
+ with _trackio_run(**decorator_kwargs):
158
+ return await task(*args, **kwargs)
159
+
160
+ return cast(F, async_wrapper)
161
+
162
+ @functools.wraps(task)
163
+ def sync_wrapper(*args, **kwargs):
164
+
165
+ with _trackio_run(**decorator_kwargs):
166
+ return task(*args, **kwargs)
167
+
168
+ return cast(F, sync_wrapper)
169
+
170
+ if _func is None:
171
+ return decorator
172
+
173
+ return decorator(_func)
@@ -0,0 +1,86 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from typing import Dict, Optional
5
+
6
+ from flyte import Link
7
+
8
+ from ._context import get_trackio_context
9
+
10
+
11
+ @dataclass
12
+ class Trackio(Link):
13
+ """
14
+ Generates a Trackio dashboard link for Flyte.
15
+
16
+ The link resolution order is:
17
+
18
+ 1. Explicit server_url (self or context)
19
+ 2. Hugging Face Space (space_id)
20
+ 3. Hugging Face Trackio documentation
21
+
22
+ Args:
23
+ host:
24
+ Base Hugging Face host.
25
+
26
+ project:
27
+ Trackio project name.
28
+
29
+ server_url:
30
+ Base URL of a self-hosted Trackio instance.
31
+
32
+ space_id:
33
+ Hugging Face Space hosting the Trackio dashboard.
34
+
35
+ name:
36
+ Display name in the Flyte UI.
37
+ """
38
+
39
+ host: str = "https://huggingface.co"
40
+
41
+ project: Optional[str] = None
42
+
43
+ server_url: Optional[str] = None
44
+
45
+ space_id: Optional[str] = None
46
+
47
+ name: str = "Trackio"
48
+
49
+ def get_link(
50
+ self,
51
+ run_name: str,
52
+ project: str,
53
+ domain: str,
54
+ context: Dict[str, str],
55
+ parent_action_name: str,
56
+ action_name: str,
57
+ pod_name: str,
58
+ **kwargs,
59
+ ) -> str:
60
+ """
61
+ Resolve the Trackio dashboard URL.
62
+ """
63
+
64
+ cfg = get_trackio_context()
65
+
66
+ project_name = self.project
67
+ server_url = self.server_url
68
+ space_id = self.space_id
69
+
70
+ if cfg is not None:
71
+ project_name = project_name or cfg.project
72
+ server_url = server_url or cfg.server_url
73
+ space_id = space_id or cfg.space_id
74
+
75
+ if server_url:
76
+ server_url = server_url.rstrip("/")
77
+
78
+ if project_name:
79
+ return f"{server_url}/projects/{project_name}"
80
+
81
+ return server_url
82
+
83
+ if space_id:
84
+ return f"{self.host}/spaces/{space_id}"
85
+
86
+ return f"{self.host}/docs/trackio"
@@ -0,0 +1,124 @@
1
+ Metadata-Version: 2.4
2
+ Name: flyteplugins-trackio
3
+ Version: 2.6.11
4
+ Summary: Trackio plugin for Flyte
5
+ Author-email: Parag Ekbote <23150020.dypsst@dpu.edu.in>
6
+ Requires-Python: >=3.10
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: trackio
9
+ Requires-Dist: flyte
10
+
11
+ # Flyte Trackio Plugin
12
+
13
+ Native Flyte support for Trackio experiment tracking.
14
+
15
+ This plugin makes it easy to manage Trackio runs inside Flyte tasks, log metrics from within task code or callbacks, and expose a Trackio dashboard link in the Flyte UI.
16
+
17
+ ## Deploying a Trackio Server
18
+
19
+ This plugin works with Trackio's local-first design. By default, Trackio stores experiment data locally and can optionally send metrics to a self-hosted Trackio server or a Hugging Face Space by configuring the appropriate `server_url` or `space_id`.
20
+
21
+ For deployment instructions, please refer to the official Trackio documentation:
22
+
23
+ - Self-host a Trackio server: https://huggingface.co/docs/trackio/self_hosted_server
24
+ - Deploy and embed Trackio dashboards: https://huggingface.co/docs/trackio/deploy_embed
25
+
26
+ ## What it provides
27
+
28
+ - `@trackio_init` decorator to initialize and manage a Trackio run for a Flyte task.
29
+ - `trackio_config(...)` helper to store Trackio initialization settings in Flyte `custom_context`.
30
+ - `get_trackio_run()` to access the active Trackio run from task code or callback code.
31
+ - Optional Flyte task link support via the `Trackio` link class.
32
+
33
+ ## Installation
34
+
35
+ ```bash
36
+ pip install flyteplugins-trackio
37
+ ```
38
+
39
+ ## Quick start
40
+
41
+ ```python
42
+ import flyte
43
+ from flyteplugins.trackio import (
44
+ get_trackio_run,
45
+ trackio_config,
46
+ trackio_init,
47
+ )
48
+
49
+ env = flyte.TaskEnvironment(name="trackio")
50
+
51
+ @trackio_init
52
+ @env.task
53
+ def train() -> dict[str, float]:
54
+ run = get_trackio_run()
55
+ run.log({"accuracy": 0.92})
56
+ return {"accuracy": 0.92}
57
+
58
+ cfg = trackio_config(
59
+ project="my-project",
60
+ space_id="my-org/my-trackio-space",
61
+ bucket_id="my-bucket",
62
+ auto_log_cpu=True,
63
+ )
64
+
65
+ flyte.with_runcontext(custom_context=cfg.to_dict()).run(train)
66
+ ```
67
+
68
+ ## Key APIs
69
+
70
+ ### `trackio_init`
71
+
72
+ Decorates a Flyte task or plain Python function to create a Trackio run for the decorated execution.
73
+
74
+ - Works with Flyte task functions.
75
+ - Works with plain synchronous or asynchronous functions outside of Flyte.
76
+ - Reuses an existing Trackio run if one is already present in the Flyte context.
77
+
78
+ ### `trackio_config(...)`
79
+
80
+ Returns a configuration object with Trackio initialization options such as:
81
+
82
+ - `project`
83
+ - `name`
84
+ - `group`
85
+ - `space_id`
86
+ - `dataset_id`
87
+ - `bucket_id`
88
+ - `server_url`
89
+ - `config`
90
+ - `resume`
91
+ - `auto_log_gpu`
92
+ - `gpu_log_interval`
93
+ - `auto_log_cpu`
94
+ - `cpu_log_interval`
95
+
96
+ Use `cfg.to_dict()` to store these settings in Flyte `custom_context`, then run the task with `flyte.with_runcontext(...)`.
97
+
98
+ ### `get_trackio_run()`
99
+
100
+ Returns the active Trackio run from the current Flyte context, or falls back to Trackio's global active run when running outside of Flyte.
101
+
102
+ ### `Trackio`
103
+
104
+ A Flyte `Link` implementation that resolves a Trackio dashboard URL based on:
105
+
106
+ - explicit `server_url`
107
+ - `space_id` for Hugging Face Space deployments
108
+ - plugin `project`/context values
109
+
110
+ This link can be attached automatically by `trackio_init` for Flyte tasks.
111
+
112
+ ## Usage notes
113
+
114
+ - The plugin manages the Trackio run lifecycle automatically: `trackio_init` creates and finishes the run around the decorated execution.
115
+ - Custom context values from `trackio_config` are merged with decorator-level overrides.
116
+ - Use `get_trackio_run()` in callbacks or training loops to log metrics incrementally.
117
+
118
+ ## Examples
119
+
120
+ See [distilbert_text_classification.py](https://github.com/flyteorg/flyte-sdk/tree/main/plugins/trackio/examples) and [vit_image_classification.py](https://github.com/flyteorg/flyte-sdk/tree/main/plugins/trackio/examples) for full usage patterns with Hugging Face training and callback-based metric logging. Before running the examples, please install the required dependencies:
121
+
122
+ ```bash
123
+ pip install datasets transformers accelerate evaluate psutil
124
+ ```
@@ -0,0 +1,8 @@
1
+ flyteplugins/trackio/__init__.py,sha256=H9YHuhiBHQedE7q_7AUATlMKlEGwtnzNdMR5lNYg45s,1017
2
+ flyteplugins/trackio/_context.py,sha256=ANJdp_lSVwcXVxTFKrajs2byl084A95RC-QMsyktc2g,5547
3
+ flyteplugins/trackio/_decorator.py,sha256=EYELNYEMIjPi7QvFw5krVF1ikvxLGfNZMYUPTUjAVM0,3938
4
+ flyteplugins/trackio/_link.py,sha256=K-Z22Riy0a0e2x66B3J_j2sueeiPHY9yxE6cUyLY9QM,1906
5
+ flyteplugins_trackio-2.6.11.dist-info/METADATA,sha256=xYl5KpG7rA5b_IijgOiLZv9sV7OTsxiXKDTVIxVR-E0,3995
6
+ flyteplugins_trackio-2.6.11.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
7
+ flyteplugins_trackio-2.6.11.dist-info/top_level.txt,sha256=cgd779rPu9EsvdtuYgUxNHHgElaQvPn74KhB5XSeMBE,13
8
+ flyteplugins_trackio-2.6.11.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ flyteplugins