hydraflow 0.3.0__py3-none-any.whl → 0.3.1__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.
- hydraflow/__init__.py +5 -9
- hydraflow/config.py +10 -2
- hydraflow/context.py +19 -0
- hydraflow/mlflow.py +8 -2
- hydraflow/run_data.py +4 -26
- hydraflow/run_info.py +4 -61
- hydraflow/utils.py +88 -0
- {hydraflow-0.3.0.dist-info → hydraflow-0.3.1.dist-info}/METADATA +1 -1
- hydraflow-0.3.1.dist-info/RECORD +16 -0
- hydraflow-0.3.0.dist-info/RECORD +0 -15
- {hydraflow-0.3.0.dist-info → hydraflow-0.3.1.dist-info}/WHEEL +0 -0
- {hydraflow-0.3.0.dist-info → hydraflow-0.3.1.dist-info}/licenses/LICENSE +0 -0
hydraflow/__init__.py
CHANGED
@@ -1,19 +1,15 @@
|
|
1
|
-
"""
|
1
|
+
"""Integrate Hydra and MLflow to manage and track machine learning experiments."""
|
2
2
|
|
3
|
-
from .context import chdir_artifact, log_run, start_run, watch
|
4
|
-
from .mlflow import
|
5
|
-
list_runs,
|
6
|
-
search_runs,
|
7
|
-
set_experiment,
|
8
|
-
)
|
3
|
+
from .context import chdir_artifact, chdir_hydra, log_run, start_run, watch
|
4
|
+
from .mlflow import list_runs, search_runs, set_experiment
|
9
5
|
from .progress import multi_tasks_progress, parallel_progress
|
10
6
|
from .run_collection import RunCollection
|
11
|
-
from .
|
12
|
-
from .run_info import get_artifact_dir, get_hydra_output_dir
|
7
|
+
from .utils import get_artifact_dir, get_hydra_output_dir, load_config
|
13
8
|
|
14
9
|
__all__ = [
|
15
10
|
"RunCollection",
|
16
11
|
"chdir_artifact",
|
12
|
+
"chdir_hydra",
|
17
13
|
"get_artifact_dir",
|
18
14
|
"get_hydra_output_dir",
|
19
15
|
"list_runs",
|
hydraflow/config.py
CHANGED
@@ -54,7 +54,7 @@ def _iter_params(config: object, prefix: str = "") -> Iterator[tuple[str, Any]]:
|
|
54
54
|
if isinstance(config, DictConfig):
|
55
55
|
for key, value in config.items():
|
56
56
|
if _is_param(value):
|
57
|
-
yield f"{prefix}{key}", value
|
57
|
+
yield f"{prefix}{key}", _convert(value)
|
58
58
|
|
59
59
|
else:
|
60
60
|
yield from _iter_params(value, f"{prefix}{key}.")
|
@@ -62,7 +62,7 @@ def _iter_params(config: object, prefix: str = "") -> Iterator[tuple[str, Any]]:
|
|
62
62
|
elif isinstance(config, ListConfig):
|
63
63
|
for index, value in enumerate(config):
|
64
64
|
if _is_param(value):
|
65
|
-
yield f"{prefix}{index}", value
|
65
|
+
yield f"{prefix}{index}", _convert(value)
|
66
66
|
|
67
67
|
else:
|
68
68
|
yield from _iter_params(value, f"{prefix}{index}.")
|
@@ -78,3 +78,11 @@ def _is_param(value: object) -> bool:
|
|
78
78
|
return False
|
79
79
|
|
80
80
|
return True
|
81
|
+
|
82
|
+
|
83
|
+
def _convert(value: Any) -> Any:
|
84
|
+
"""Convert the given value to a Python object."""
|
85
|
+
if isinstance(value, ListConfig):
|
86
|
+
return list(value)
|
87
|
+
|
88
|
+
return value
|
hydraflow/context.py
CHANGED
@@ -238,6 +238,25 @@ class Handler(PatternMatchingEventHandler):
|
|
238
238
|
self.func(file)
|
239
239
|
|
240
240
|
|
241
|
+
@contextmanager
|
242
|
+
def chdir_hydra() -> Iterator[Path]:
|
243
|
+
"""Change the current working directory to the hydra output directory.
|
244
|
+
|
245
|
+
This context manager changes the current working directory to the hydra output
|
246
|
+
directory. It ensures that the directory is changed back to the original
|
247
|
+
directory after the context is exited.
|
248
|
+
"""
|
249
|
+
curdir = Path.cwd()
|
250
|
+
path = HydraConfig.get().runtime.output_dir
|
251
|
+
|
252
|
+
os.chdir(path)
|
253
|
+
try:
|
254
|
+
yield Path(path)
|
255
|
+
|
256
|
+
finally:
|
257
|
+
os.chdir(curdir)
|
258
|
+
|
259
|
+
|
241
260
|
@contextmanager
|
242
261
|
def chdir_artifact(
|
243
262
|
run: Run,
|
hydraflow/mlflow.py
CHANGED
@@ -207,8 +207,14 @@ def _list_runs(
|
|
207
207
|
if experiment := mlflow.get_experiment_by_name(name):
|
208
208
|
loc = experiment.artifact_location
|
209
209
|
|
210
|
-
if isinstance(loc, str)
|
211
|
-
|
210
|
+
if isinstance(loc, str):
|
211
|
+
if loc.startswith("file://"):
|
212
|
+
path = Path(mlflow.artifacts.download_artifacts(loc))
|
213
|
+
elif Path(loc).is_dir():
|
214
|
+
path = Path(loc)
|
215
|
+
else:
|
216
|
+
continue
|
217
|
+
|
212
218
|
run_ids.extend(file.stem for file in path.iterdir() if file.is_dir())
|
213
219
|
|
214
220
|
it = (joblib.delayed(mlflow.get_run)(run_id) for run_id in run_ids)
|
hydraflow/run_data.py
CHANGED
@@ -1,21 +1,19 @@
|
|
1
|
-
"""Provide
|
1
|
+
"""Provide data about `RunCollection` instances."""
|
2
2
|
|
3
3
|
from __future__ import annotations
|
4
4
|
|
5
5
|
from typing import TYPE_CHECKING
|
6
6
|
|
7
|
-
from
|
8
|
-
|
9
|
-
from hydraflow.run_info import get_artifact_dir
|
7
|
+
from hydraflow.utils import load_config
|
10
8
|
|
11
9
|
if TYPE_CHECKING:
|
12
|
-
from
|
10
|
+
from omegaconf import DictConfig
|
13
11
|
|
14
12
|
from hydraflow.run_collection import RunCollection
|
15
13
|
|
16
14
|
|
17
15
|
class RunCollectionData:
|
18
|
-
"""Provide
|
16
|
+
"""Provide data about a `RunCollection` instance."""
|
19
17
|
|
20
18
|
def __init__(self, runs: RunCollection) -> None:
|
21
19
|
self._runs = runs
|
@@ -34,23 +32,3 @@ class RunCollectionData:
|
|
34
32
|
def config(self) -> list[DictConfig]:
|
35
33
|
"""Get the configuration for each run in the collection."""
|
36
34
|
return [load_config(run) for run in self._runs]
|
37
|
-
|
38
|
-
|
39
|
-
def load_config(run: Run) -> DictConfig:
|
40
|
-
"""Load the configuration for a given run.
|
41
|
-
|
42
|
-
This function loads the configuration for the provided Run instance
|
43
|
-
by downloading the configuration file from the MLflow artifacts and
|
44
|
-
loading it using OmegaConf. It returns an empty config if
|
45
|
-
`.hydra/config.yaml` is not found in the run's artifact directory.
|
46
|
-
|
47
|
-
Args:
|
48
|
-
run (Run): The Run instance for which to load the configuration.
|
49
|
-
|
50
|
-
Returns:
|
51
|
-
The loaded configuration as a DictConfig object. Returns an empty
|
52
|
-
DictConfig if the configuration file is not found.
|
53
|
-
|
54
|
-
"""
|
55
|
-
path = get_artifact_dir(run) / ".hydra/config.yaml"
|
56
|
-
return OmegaConf.load(path) # type: ignore
|
hydraflow/run_info.py
CHANGED
@@ -1,23 +1,19 @@
|
|
1
|
-
"""Provide information about
|
1
|
+
"""Provide information about `RunCollection` instances."""
|
2
2
|
|
3
3
|
from __future__ import annotations
|
4
4
|
|
5
|
-
from pathlib import Path
|
6
5
|
from typing import TYPE_CHECKING
|
7
6
|
|
8
|
-
import
|
9
|
-
from hydra.core.hydra_config import HydraConfig
|
10
|
-
from mlflow.tracking import artifact_utils
|
11
|
-
from omegaconf import OmegaConf
|
7
|
+
from hydraflow.utils import get_artifact_dir
|
12
8
|
|
13
9
|
if TYPE_CHECKING:
|
14
|
-
from
|
10
|
+
from pathlib import Path
|
15
11
|
|
16
12
|
from hydraflow.run_collection import RunCollection
|
17
13
|
|
18
14
|
|
19
15
|
class RunCollectionInfo:
|
20
|
-
"""Provide information about
|
16
|
+
"""Provide information about a `RunCollection` instance."""
|
21
17
|
|
22
18
|
def __init__(self, runs: RunCollection) -> None:
|
23
19
|
self._runs = runs
|
@@ -36,56 +32,3 @@ class RunCollectionInfo:
|
|
36
32
|
def artifact_dir(self) -> list[Path]:
|
37
33
|
"""Get the artifact directory for each run in the collection."""
|
38
34
|
return [get_artifact_dir(run) for run in self._runs]
|
39
|
-
|
40
|
-
|
41
|
-
def get_artifact_dir(run: Run | None = None) -> Path:
|
42
|
-
"""Retrieve the artifact directory for the given run.
|
43
|
-
|
44
|
-
This function uses MLflow to get the artifact directory for the given run.
|
45
|
-
|
46
|
-
Args:
|
47
|
-
run (Run | None): The run object. Defaults to None.
|
48
|
-
|
49
|
-
Returns:
|
50
|
-
The local path to the directory where the artifacts are downloaded.
|
51
|
-
|
52
|
-
"""
|
53
|
-
if run is None:
|
54
|
-
uri = mlflow.get_artifact_uri()
|
55
|
-
else:
|
56
|
-
uri = artifact_utils.get_artifact_uri(run.info.run_id)
|
57
|
-
|
58
|
-
return Path(mlflow.artifacts.download_artifacts(uri))
|
59
|
-
|
60
|
-
|
61
|
-
def get_hydra_output_dir(run: Run | None = None) -> Path:
|
62
|
-
"""Retrieve the Hydra output directory for the given run.
|
63
|
-
|
64
|
-
This function returns the Hydra output directory. If no run is provided,
|
65
|
-
it retrieves the output directory from the current Hydra configuration.
|
66
|
-
If a run is provided, it retrieves the artifact path for the run, loads
|
67
|
-
the Hydra configuration from the downloaded artifacts, and returns the
|
68
|
-
output directory specified in that configuration.
|
69
|
-
|
70
|
-
Args:
|
71
|
-
run (Run | None): The run object. Defaults to None.
|
72
|
-
|
73
|
-
Returns:
|
74
|
-
Path: The path to the Hydra output directory.
|
75
|
-
|
76
|
-
Raises:
|
77
|
-
FileNotFoundError: If the Hydra configuration file is not found
|
78
|
-
in the artifacts.
|
79
|
-
|
80
|
-
"""
|
81
|
-
if run is None:
|
82
|
-
hc = HydraConfig.get()
|
83
|
-
return Path(hc.runtime.output_dir)
|
84
|
-
|
85
|
-
path = get_artifact_dir(run) / ".hydra/hydra.yaml"
|
86
|
-
|
87
|
-
if path.exists():
|
88
|
-
hc = OmegaConf.load(path)
|
89
|
-
return Path(hc.hydra.runtime.output_dir)
|
90
|
-
|
91
|
-
raise FileNotFoundError
|
hydraflow/utils.py
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
"""Provide utility functions for HydraFlow."""
|
2
|
+
|
3
|
+
from __future__ import annotations
|
4
|
+
|
5
|
+
from pathlib import Path
|
6
|
+
from typing import TYPE_CHECKING
|
7
|
+
|
8
|
+
import mlflow
|
9
|
+
from hydra.core.hydra_config import HydraConfig
|
10
|
+
from mlflow.entities import Run
|
11
|
+
from mlflow.tracking import artifact_utils
|
12
|
+
from omegaconf import DictConfig, OmegaConf
|
13
|
+
|
14
|
+
if TYPE_CHECKING:
|
15
|
+
from mlflow.entities import Run
|
16
|
+
|
17
|
+
|
18
|
+
def get_artifact_dir(run: Run | None = None) -> Path:
|
19
|
+
"""Retrieve the artifact directory for the given run.
|
20
|
+
|
21
|
+
This function uses MLflow to get the artifact directory for the given run.
|
22
|
+
|
23
|
+
Args:
|
24
|
+
run (Run | None): The run object. Defaults to None.
|
25
|
+
|
26
|
+
Returns:
|
27
|
+
The local path to the directory where the artifacts are downloaded.
|
28
|
+
|
29
|
+
"""
|
30
|
+
if run is None:
|
31
|
+
uri = mlflow.get_artifact_uri()
|
32
|
+
else:
|
33
|
+
uri = artifact_utils.get_artifact_uri(run.info.run_id)
|
34
|
+
|
35
|
+
return Path(mlflow.artifacts.download_artifacts(uri))
|
36
|
+
|
37
|
+
|
38
|
+
def get_hydra_output_dir(run: Run | None = None) -> Path:
|
39
|
+
"""Retrieve the Hydra output directory for the given run.
|
40
|
+
|
41
|
+
This function returns the Hydra output directory. If no run is provided,
|
42
|
+
it retrieves the output directory from the current Hydra configuration.
|
43
|
+
If a run is provided, it retrieves the artifact path for the run, loads
|
44
|
+
the Hydra configuration from the downloaded artifacts, and returns the
|
45
|
+
output directory specified in that configuration.
|
46
|
+
|
47
|
+
Args:
|
48
|
+
run (Run | None): The run object. Defaults to None.
|
49
|
+
|
50
|
+
Returns:
|
51
|
+
Path: The path to the Hydra output directory.
|
52
|
+
|
53
|
+
Raises:
|
54
|
+
FileNotFoundError: If the Hydra configuration file is not found
|
55
|
+
in the artifacts.
|
56
|
+
|
57
|
+
"""
|
58
|
+
if run is None:
|
59
|
+
hc = HydraConfig.get()
|
60
|
+
return Path(hc.runtime.output_dir)
|
61
|
+
|
62
|
+
path = get_artifact_dir(run) / ".hydra/hydra.yaml"
|
63
|
+
|
64
|
+
if path.exists():
|
65
|
+
hc = OmegaConf.load(path)
|
66
|
+
return Path(hc.hydra.runtime.output_dir)
|
67
|
+
|
68
|
+
raise FileNotFoundError
|
69
|
+
|
70
|
+
|
71
|
+
def load_config(run: Run) -> DictConfig:
|
72
|
+
"""Load the configuration for a given run.
|
73
|
+
|
74
|
+
This function loads the configuration for the provided Run instance
|
75
|
+
by downloading the configuration file from the MLflow artifacts and
|
76
|
+
loading it using OmegaConf. It returns an empty config if
|
77
|
+
`.hydra/config.yaml` is not found in the run's artifact directory.
|
78
|
+
|
79
|
+
Args:
|
80
|
+
run (Run): The Run instance for which to load the configuration.
|
81
|
+
|
82
|
+
Returns:
|
83
|
+
The loaded configuration as a DictConfig object. Returns an empty
|
84
|
+
DictConfig if the configuration file is not found.
|
85
|
+
|
86
|
+
"""
|
87
|
+
path = get_artifact_dir(run) / ".hydra/config.yaml"
|
88
|
+
return OmegaConf.load(path) # type: ignore
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: hydraflow
|
3
|
-
Version: 0.3.
|
3
|
+
Version: 0.3.1
|
4
4
|
Summary: Hydraflow integrates Hydra and MLflow to manage and track machine learning experiments.
|
5
5
|
Project-URL: Documentation, https://github.com/daizutabi/hydraflow
|
6
6
|
Project-URL: Source, https://github.com/daizutabi/hydraflow
|
@@ -0,0 +1,16 @@
|
|
1
|
+
hydraflow/__init__.py,sha256=6sfM1ashUkfrNf7lOR7raFYhG8YdOAJR-JgRNL_IVo8,698
|
2
|
+
hydraflow/asyncio.py,sha256=-i1C8KAmNDImrjHnk92Csaa1mpjdK8Vp4ZVaQV-l94s,6634
|
3
|
+
hydraflow/config.py,sha256=6V5omJ3-h9-ZwVpM5rTA4FqE_mu8urTy9OqV4zG79gw,2671
|
4
|
+
hydraflow/context.py,sha256=412884e84qIEYtbxJT4roYsKfldGaTKzgo6Q1FAsT5U,8733
|
5
|
+
hydraflow/mlflow.py,sha256=JELqXFCJ9MsEJaQWT5dyleTFk8BHL7cQwW_gzhkPoIg,8729
|
6
|
+
hydraflow/param.py,sha256=dvIXcKgc_MPiju3WEk9qz5FOUeK5qSj-YWN2ophCpUM,1938
|
7
|
+
hydraflow/progress.py,sha256=zvKX1HCN8_xDOsgYOEcLLhkhdPdep-U8vHrc0XZ-6SQ,6163
|
8
|
+
hydraflow/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
+
hydraflow/run_collection.py,sha256=Xv6-KD5ac-vv-4Q3PZrzJy1x84H_g7UoP7ZqZ8_DQeQ,24973
|
10
|
+
hydraflow/run_data.py,sha256=ZXVr0PHyufH9wwyQYWtpE4_MheAC2ArTW_J1TTMQ4iI,983
|
11
|
+
hydraflow/run_info.py,sha256=sMXOo20ClaRIommMEzuAbO_OrcXx7M1Yt4FMV7spxz0,998
|
12
|
+
hydraflow/utils.py,sha256=aRdBdToKfvHhN2qFiRzPHIdQxS7cTpZREQeP8HreAfI,2676
|
13
|
+
hydraflow-0.3.1.dist-info/METADATA,sha256=W38pNcCNy7Kmx1t9dwFoANsRjCk40-KBJUWux_BvHqA,3840
|
14
|
+
hydraflow-0.3.1.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
|
15
|
+
hydraflow-0.3.1.dist-info/licenses/LICENSE,sha256=IGdDrBPqz1O0v_UwCW-NJlbX9Hy9b3uJ11t28y2srmY,1062
|
16
|
+
hydraflow-0.3.1.dist-info/RECORD,,
|
hydraflow-0.3.0.dist-info/RECORD
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
hydraflow/__init__.py,sha256=zlLTztJPXyBFJC5Z8G7_OnlfzAHJPRrfE1c2OoDvlTg,667
|
2
|
-
hydraflow/asyncio.py,sha256=-i1C8KAmNDImrjHnk92Csaa1mpjdK8Vp4ZVaQV-l94s,6634
|
3
|
-
hydraflow/config.py,sha256=Wx7jymwLVr5EfpzXBpvv3Ax3VhGhvWyA7Yy6EzsPYWk,2479
|
4
|
-
hydraflow/context.py,sha256=IaDy-ZCdCfWwv95S-gyQNp062oBdtSVaz6dxGmO6Y8w,8226
|
5
|
-
hydraflow/mlflow.py,sha256=GkOr_pXfpfY5USYBLrCigHcP13VgrAK_e9kheR1Wke4,8579
|
6
|
-
hydraflow/param.py,sha256=dvIXcKgc_MPiju3WEk9qz5FOUeK5qSj-YWN2ophCpUM,1938
|
7
|
-
hydraflow/progress.py,sha256=zvKX1HCN8_xDOsgYOEcLLhkhdPdep-U8vHrc0XZ-6SQ,6163
|
8
|
-
hydraflow/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
-
hydraflow/run_collection.py,sha256=Xv6-KD5ac-vv-4Q3PZrzJy1x84H_g7UoP7ZqZ8_DQeQ,24973
|
10
|
-
hydraflow/run_data.py,sha256=HgXGjV5oN6VxOAhrFRjubWz5ZiRqT1a2VdS5OcH2UQQ,1732
|
11
|
-
hydraflow/run_info.py,sha256=4QrTmyPEQ_PVn7JKXJIa9NkXGAdqh8k5Sue1ggQS5aQ,2678
|
12
|
-
hydraflow-0.3.0.dist-info/METADATA,sha256=DmC1Yjwuc3snUQiePCr5xvdtbfIevOapiA2sg8w6Aho,3840
|
13
|
-
hydraflow-0.3.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
|
14
|
-
hydraflow-0.3.0.dist-info/licenses/LICENSE,sha256=IGdDrBPqz1O0v_UwCW-NJlbX9Hy9b3uJ11t28y2srmY,1062
|
15
|
-
hydraflow-0.3.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|