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.
- flyteplugins/trackio/__init__.py +52 -0
- flyteplugins/trackio/_context.py +241 -0
- flyteplugins/trackio/_decorator.py +173 -0
- flyteplugins/trackio/_link.py +86 -0
- flyteplugins_trackio-2.6.11.dist-info/METADATA +124 -0
- flyteplugins_trackio-2.6.11.dist-info/RECORD +8 -0
- flyteplugins_trackio-2.6.11.dist-info/WHEEL +5 -0
- flyteplugins_trackio-2.6.11.dist-info/top_level.txt +1 -0
|
@@ -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 @@
|
|
|
1
|
+
flyteplugins
|