ml-dash 0.6.1__py3-none-any.whl → 0.6.2rc1__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.
- ml_dash/__init__.py +2 -0
- ml_dash/experiment.py +83 -36
- ml_dash/files.py +932 -336
- ml_dash/run.py +85 -0
- ml_dash/storage.py +4 -2
- {ml_dash-0.6.1.dist-info → ml_dash-0.6.2rc1.dist-info}/METADATA +42 -15
- {ml_dash-0.6.1.dist-info → ml_dash-0.6.2rc1.dist-info}/RECORD +9 -8
- {ml_dash-0.6.1.dist-info → ml_dash-0.6.2rc1.dist-info}/WHEEL +1 -1
- {ml_dash-0.6.1.dist-info → ml_dash-0.6.2rc1.dist-info}/entry_points.txt +0 -0
ml_dash/__init__.py
CHANGED
|
@@ -51,6 +51,7 @@ from .client import RemoteClient
|
|
|
51
51
|
from .storage import LocalStorage
|
|
52
52
|
from .log import LogLevel, LogBuilder
|
|
53
53
|
from .params import ParametersBuilder
|
|
54
|
+
from .run import RUN
|
|
54
55
|
from .auto_start import dxp
|
|
55
56
|
|
|
56
57
|
__version__ = "0.1.0"
|
|
@@ -65,6 +66,7 @@ __all__ = [
|
|
|
65
66
|
"LogLevel",
|
|
66
67
|
"LogBuilder",
|
|
67
68
|
"ParametersBuilder",
|
|
69
|
+
"RUN",
|
|
68
70
|
"dxp",
|
|
69
71
|
]
|
|
70
72
|
|
ml_dash/experiment.py
CHANGED
|
@@ -17,7 +17,8 @@ from .client import RemoteClient
|
|
|
17
17
|
from .storage import LocalStorage
|
|
18
18
|
from .log import LogLevel, LogBuilder
|
|
19
19
|
from .params import ParametersBuilder
|
|
20
|
-
from .files import
|
|
20
|
+
from .files import FilesAccessor, BindrsBuilder
|
|
21
|
+
from .run import RUN
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
class OperationMode(Enum):
|
|
@@ -121,28 +122,13 @@ class RunManager:
|
|
|
121
122
|
"Set folder before calling start() or entering 'with' block."
|
|
122
123
|
)
|
|
123
124
|
|
|
124
|
-
#
|
|
125
|
+
# Check if this is a template (contains {RUN.) or static folder
|
|
125
126
|
if value and '{RUN.' in value:
|
|
126
|
-
#
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
# Supports: {RUN.name}, {RUN.project}, {RUN.id}, {RUN.timestamp}
|
|
132
|
-
replacements = {
|
|
133
|
-
'{RUN.name}': f"{self._experiment.name}_{run_timestamp}", # Unique name with timestamp
|
|
134
|
-
'{RUN.project}': self._experiment.project,
|
|
135
|
-
'{RUN.id}': run_timestamp, # Just the timestamp
|
|
136
|
-
'{RUN.timestamp}': run_timestamp, # Alias for id
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
# Replace all template variables
|
|
140
|
-
for template, replacement in replacements.items():
|
|
141
|
-
if template in value:
|
|
142
|
-
value = value.replace(template, replacement)
|
|
143
|
-
|
|
144
|
-
# Update the folder on the experiment
|
|
145
|
-
self._experiment.folder = value
|
|
127
|
+
# Store the template - it will be formatted when the run starts
|
|
128
|
+
self._experiment._folder_template = value
|
|
129
|
+
else:
|
|
130
|
+
# Static folder - set directly
|
|
131
|
+
self._experiment.folder = value
|
|
146
132
|
|
|
147
133
|
def __enter__(self) -> "Experiment":
|
|
148
134
|
"""Context manager entry - starts the experiment."""
|
|
@@ -240,7 +226,7 @@ class Experiment:
|
|
|
240
226
|
self.project = project
|
|
241
227
|
self.description = description
|
|
242
228
|
self.tags = tags
|
|
243
|
-
self.
|
|
229
|
+
self._bindrs_list = bindrs
|
|
244
230
|
self.folder = folder
|
|
245
231
|
self._write_protected = _write_protected
|
|
246
232
|
self.metadata = metadata
|
|
@@ -264,6 +250,7 @@ class Experiment:
|
|
|
264
250
|
self._experiment_data: Optional[Dict[str, Any]] = None
|
|
265
251
|
self._is_open = False
|
|
266
252
|
self._metrics_manager: Optional['MetricsManager'] = None # Cached metrics manager
|
|
253
|
+
self._folder_template: Optional[str] = None # Template for folder path
|
|
267
254
|
|
|
268
255
|
if self.mode in (OperationMode.REMOTE, OperationMode.HYBRID):
|
|
269
256
|
# api_key can be None - RemoteClient will auto-load from storage
|
|
@@ -284,6 +271,16 @@ class Experiment:
|
|
|
284
271
|
if self._is_open:
|
|
285
272
|
return self
|
|
286
273
|
|
|
274
|
+
# Initialize RUN with experiment values
|
|
275
|
+
RUN.name = self.name
|
|
276
|
+
RUN.project = self.project
|
|
277
|
+
RUN.description = self.description
|
|
278
|
+
RUN._init_run() # Generate id and timestamp
|
|
279
|
+
|
|
280
|
+
# Format folder template if present
|
|
281
|
+
if self._folder_template:
|
|
282
|
+
self.folder = RUN._format(self._folder_template)
|
|
283
|
+
|
|
287
284
|
if self._client:
|
|
288
285
|
# Remote mode: create/update experiment via API
|
|
289
286
|
response = self._client.create_or_update_experiment(
|
|
@@ -291,7 +288,7 @@ class Experiment:
|
|
|
291
288
|
name=self.name,
|
|
292
289
|
description=self.description,
|
|
293
290
|
tags=self.tags,
|
|
294
|
-
bindrs=self.
|
|
291
|
+
bindrs=self._bindrs_list,
|
|
295
292
|
folder=self.folder,
|
|
296
293
|
write_protected=self._write_protected,
|
|
297
294
|
metadata=self.metadata,
|
|
@@ -306,7 +303,7 @@ class Experiment:
|
|
|
306
303
|
name=self.name,
|
|
307
304
|
description=self.description,
|
|
308
305
|
tags=self.tags,
|
|
309
|
-
bindrs=self.
|
|
306
|
+
bindrs=self._bindrs_list,
|
|
310
307
|
folder=self.folder,
|
|
311
308
|
metadata=self.metadata,
|
|
312
309
|
)
|
|
@@ -341,6 +338,9 @@ class Experiment:
|
|
|
341
338
|
|
|
342
339
|
self._is_open = False
|
|
343
340
|
|
|
341
|
+
# Reset RUN for next experiment
|
|
342
|
+
RUN._reset()
|
|
343
|
+
|
|
344
344
|
@property
|
|
345
345
|
def run(self) -> RunManager:
|
|
346
346
|
"""
|
|
@@ -545,39 +545,86 @@ class Experiment:
|
|
|
545
545
|
else:
|
|
546
546
|
print(formatted_message, file=sys.stdout)
|
|
547
547
|
|
|
548
|
-
|
|
548
|
+
@property
|
|
549
|
+
def files(self) -> FilesAccessor:
|
|
549
550
|
"""
|
|
550
|
-
Get a
|
|
551
|
+
Get a FilesAccessor for fluent file operations.
|
|
551
552
|
|
|
552
553
|
Returns:
|
|
553
|
-
|
|
554
|
+
FilesAccessor instance for chaining
|
|
554
555
|
|
|
555
556
|
Raises:
|
|
556
557
|
RuntimeError: If experiment is not open
|
|
557
558
|
|
|
558
559
|
Examples:
|
|
559
560
|
# Upload file
|
|
560
|
-
experiment.files(
|
|
561
|
+
experiment.files("checkpoints").save(net, to="checkpoint.pt")
|
|
561
562
|
|
|
562
563
|
# List files
|
|
563
|
-
files = experiment.files().list()
|
|
564
|
-
files = experiment.files(
|
|
564
|
+
files = experiment.files("/some/location").list()
|
|
565
|
+
files = experiment.files("/models").list()
|
|
565
566
|
|
|
566
567
|
# Download file
|
|
567
|
-
experiment.files(
|
|
568
|
+
experiment.files("some.text").download()
|
|
569
|
+
experiment.files("some.text").download(to="./model.pt")
|
|
570
|
+
|
|
571
|
+
# Download Files via Glob Pattern
|
|
572
|
+
file_paths = experiment.files("images").list("*.png")
|
|
573
|
+
experiment.files("images").download("*.png")
|
|
574
|
+
|
|
575
|
+
# This is equivalent to downloading to a directory
|
|
576
|
+
experiment.files.download("images/*.png", to="local_images")
|
|
577
|
+
|
|
578
|
+
# Delete files
|
|
579
|
+
experiment.files("some.text").delete()
|
|
580
|
+
experiment.files.delete("some.text")
|
|
581
|
+
|
|
582
|
+
# Specific File Types
|
|
583
|
+
dxp.files.save_text("content", to="view.yaml")
|
|
584
|
+
dxp.files.save_json(dict(hey="yo"), to="config.json")
|
|
585
|
+
dxp.files.save_blob(b"xxx", to="data.bin")
|
|
586
|
+
"""
|
|
587
|
+
if not self._is_open:
|
|
588
|
+
raise RuntimeError(
|
|
589
|
+
"Experiment not started. Use 'with experiment.run:' or call experiment.run.start() first.\n"
|
|
590
|
+
"Example:\n"
|
|
591
|
+
" with dxp.run:\n"
|
|
592
|
+
" dxp.files('path').save()"
|
|
593
|
+
)
|
|
594
|
+
|
|
595
|
+
return FilesAccessor(self)
|
|
596
|
+
|
|
597
|
+
def bindrs(self, bindr_name: str) -> BindrsBuilder:
|
|
598
|
+
"""
|
|
599
|
+
Get a BindrsBuilder for working with file collections (bindrs).
|
|
600
|
+
|
|
601
|
+
Bindrs are collections of files that can span multiple prefixes.
|
|
602
|
+
|
|
603
|
+
Args:
|
|
604
|
+
bindr_name: Name of the bindr (collection)
|
|
605
|
+
|
|
606
|
+
Returns:
|
|
607
|
+
BindrsBuilder instance for chaining
|
|
608
|
+
|
|
609
|
+
Raises:
|
|
610
|
+
RuntimeError: If experiment is not open
|
|
611
|
+
|
|
612
|
+
Examples:
|
|
613
|
+
# List files in a bindr
|
|
614
|
+
file_paths = experiment.bindrs("some-bindr").list()
|
|
568
615
|
|
|
569
|
-
|
|
570
|
-
|
|
616
|
+
Note:
|
|
617
|
+
This is a placeholder for future bindr functionality.
|
|
571
618
|
"""
|
|
572
619
|
if not self._is_open:
|
|
573
620
|
raise RuntimeError(
|
|
574
621
|
"Experiment not started. Use 'with experiment.run:' or call experiment.run.start() first.\n"
|
|
575
622
|
"Example:\n"
|
|
576
623
|
" with dxp.run:\n"
|
|
577
|
-
" dxp.
|
|
624
|
+
" files = dxp.bindrs('my-bindr').list()"
|
|
578
625
|
)
|
|
579
626
|
|
|
580
|
-
return
|
|
627
|
+
return BindrsBuilder(self, bindr_name)
|
|
581
628
|
|
|
582
629
|
def _upload_file(
|
|
583
630
|
self,
|