hydraflow 0.2.18__py3-none-any.whl → 0.3.0__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
hydraflow/__init__.py CHANGED
@@ -1,5 +1,6 @@
1
+ """Provide a collection of MLflow runs."""
2
+
1
3
  from .context import chdir_artifact, log_run, start_run, watch
2
- from .info import get_artifact_dir, get_hydra_output_dir, load_config
3
4
  from .mlflow import (
4
5
  list_runs,
5
6
  search_runs,
@@ -7,6 +8,8 @@ from .mlflow import (
7
8
  )
8
9
  from .progress import multi_tasks_progress, parallel_progress
9
10
  from .run_collection import RunCollection
11
+ from .run_data import load_config
12
+ from .run_info import get_artifact_dir, get_hydra_output_dir
10
13
 
11
14
  __all__ = [
12
15
  "RunCollection",
hydraflow/config.py CHANGED
@@ -11,6 +11,20 @@ if TYPE_CHECKING:
11
11
  from typing import Any
12
12
 
13
13
 
14
+ def collect_params(config: object) -> dict[str, Any]:
15
+ """Iterate over parameters and collect them into a dictionary.
16
+
17
+ Args:
18
+ config (object): The configuration object to iterate over.
19
+ prefix (str): The prefix to prepend to the parameter keys.
20
+
21
+ Returns:
22
+ dict[str, Any]: A dictionary of collected parameters.
23
+
24
+ """
25
+ return dict(iter_params(config))
26
+
27
+
14
28
  def iter_params(config: object, prefix: str = "") -> Iterator[tuple[str, Any]]:
15
29
  """Recursively iterate over the parameters in the given configuration object.
16
30
 
hydraflow/context.py CHANGED
@@ -14,8 +14,8 @@ from hydra.core.hydra_config import HydraConfig
14
14
  from watchdog.events import FileModifiedEvent, PatternMatchingEventHandler
15
15
  from watchdog.observers import Observer
16
16
 
17
- from hydraflow.info import get_artifact_dir
18
17
  from hydraflow.mlflow import log_params
18
+ from hydraflow.run_info import get_artifact_dir
19
19
 
20
20
  if TYPE_CHECKING:
21
21
  from collections.abc import Callable, Iterator
@@ -24,10 +24,12 @@ from itertools import chain
24
24
  from typing import TYPE_CHECKING, Any, Concatenate, ParamSpec, TypeVar, overload
25
25
 
26
26
  from mlflow.entities import RunStatus
27
+ from polars.dataframe import DataFrame
27
28
 
28
29
  import hydraflow.param
29
- from hydraflow.config import iter_params
30
- from hydraflow.info import RunCollectionInfo
30
+ from hydraflow.config import collect_params, iter_params
31
+ from hydraflow.run_data import RunCollectionData
32
+ from hydraflow.run_info import RunCollectionInfo
31
33
 
32
34
  if TYPE_CHECKING:
33
35
  from collections.abc import Callable, Iterator
@@ -61,8 +63,12 @@ class RunCollection:
61
63
  _info: RunCollectionInfo = field(init=False)
62
64
  """An instance of `RunCollectionInfo`."""
63
65
 
66
+ _data: RunCollectionData = field(init=False)
67
+ """An instance of `RunCollectionData`."""
68
+
64
69
  def __post_init__(self) -> None:
65
70
  self._info = RunCollectionInfo(self)
71
+ self._data = RunCollectionData(self)
66
72
 
67
73
  def __repr__(self) -> str:
68
74
  return f"{self.__class__.__name__}({len(self)})"
@@ -101,6 +107,11 @@ class RunCollection:
101
107
  """An instance of `RunCollectionInfo`."""
102
108
  return self._info
103
109
 
110
+ @property
111
+ def data(self) -> RunCollectionData:
112
+ """An instance of `RunCollectionData`."""
113
+ return self._data
114
+
104
115
  def take(self, n: int) -> RunCollection:
105
116
  """Take the first n runs from the collection.
106
117
 
@@ -371,7 +382,7 @@ class RunCollection:
371
382
  raise ValueError(msg)
372
383
 
373
384
  def try_get(self, config: object | None = None, **kwargs) -> Run | None:
374
- """Try to retrieve a specific `Run` instance based on the provided config.
385
+ """Try to get a specific `Run` instance based on the provided configuration.
375
386
 
376
387
  This method filters the runs in the collection according to the
377
388
  specified configuration object and returns the run that matches the
@@ -505,7 +516,7 @@ class RunCollection:
505
516
  in the collection.
506
517
 
507
518
  """
508
- return (func(config, *args, **kwargs) for config in self.info.config)
519
+ return (func(config, *args, **kwargs) for config in self.data.config)
509
520
 
510
521
  def map_uri(
511
522
  self,
@@ -584,6 +595,16 @@ class RunCollection:
584
595
 
585
596
  return {key: RunCollection(runs) for key, runs in grouped_runs.items()}
586
597
 
598
+ @property
599
+ def config(self) -> DataFrame:
600
+ """Get the runs' configurations as a polars DataFrame.
601
+
602
+ Returns:
603
+ A polars DataFrame containing the runs' configurations.
604
+
605
+ """
606
+ return DataFrame(self.map_config(collect_params))
607
+
587
608
 
588
609
  def _param_matches(run: Run, key: str, value: Any) -> bool:
589
610
  params = run.data.params
@@ -634,8 +655,10 @@ def filter_runs(
634
655
  """
635
656
  for key, value in chain(iter_params(config), kwargs.items()):
636
657
  runs = [run for run in runs if _param_matches(run, key, value)]
658
+ if not runs:
659
+ return []
637
660
 
638
- if len(runs) == 0 or status is None:
661
+ if status is None:
639
662
  return runs
640
663
 
641
664
  return filter_runs_by_status(runs, status)
hydraflow/run_data.py ADDED
@@ -0,0 +1,56 @@
1
+ """Provide information about MLflow runs."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING
6
+
7
+ from omegaconf import DictConfig, OmegaConf
8
+
9
+ from hydraflow.run_info import get_artifact_dir
10
+
11
+ if TYPE_CHECKING:
12
+ from mlflow.entities import Run
13
+
14
+ from hydraflow.run_collection import RunCollection
15
+
16
+
17
+ class RunCollectionData:
18
+ """Provide information about MLflow runs."""
19
+
20
+ def __init__(self, runs: RunCollection) -> None:
21
+ self._runs = runs
22
+
23
+ @property
24
+ def params(self) -> list[dict[str, str]]:
25
+ """Get the parameters for each run in the collection."""
26
+ return [run.data.params for run in self._runs]
27
+
28
+ @property
29
+ def metrics(self) -> list[dict[str, float]]:
30
+ """Get the metrics for each run in the collection."""
31
+ return [run.data.metrics for run in self._runs]
32
+
33
+ @property
34
+ def config(self) -> list[DictConfig]:
35
+ """Get the configuration for each run in the collection."""
36
+ 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
@@ -8,7 +8,7 @@ from typing import TYPE_CHECKING
8
8
  import mlflow
9
9
  from hydra.core.hydra_config import HydraConfig
10
10
  from mlflow.tracking import artifact_utils
11
- from omegaconf import DictConfig, OmegaConf
11
+ from omegaconf import OmegaConf
12
12
 
13
13
  if TYPE_CHECKING:
14
14
  from mlflow.entities import Run
@@ -27,16 +27,6 @@ class RunCollectionInfo:
27
27
  """Get the run ID for each run in the collection."""
28
28
  return [run.info.run_id for run in self._runs]
29
29
 
30
- @property
31
- def params(self) -> list[dict[str, str]]:
32
- """Get the parameters for each run in the collection."""
33
- return [run.data.params for run in self._runs]
34
-
35
- @property
36
- def metrics(self) -> list[dict[str, float]]:
37
- """Get the metrics for each run in the collection."""
38
- return [run.data.metrics for run in self._runs]
39
-
40
30
  @property
41
31
  def artifact_uri(self) -> list[str | None]:
42
32
  """Get the artifact URI for each run in the collection."""
@@ -47,11 +37,6 @@ class RunCollectionInfo:
47
37
  """Get the artifact directory for each run in the collection."""
48
38
  return [get_artifact_dir(run) for run in self._runs]
49
39
 
50
- @property
51
- def config(self) -> list[DictConfig]:
52
- """Get the configuration for each run in the collection."""
53
- return [load_config(run) for run in self._runs]
54
-
55
40
 
56
41
  def get_artifact_dir(run: Run | None = None) -> Path:
57
42
  """Retrieve the artifact directory for the given run.
@@ -104,23 +89,3 @@ def get_hydra_output_dir(run: Run | None = None) -> Path:
104
89
  return Path(hc.hydra.runtime.output_dir)
105
90
 
106
91
  raise FileNotFoundError
107
-
108
-
109
- def load_config(run: Run) -> DictConfig:
110
- """Load the configuration for a given run.
111
-
112
- This function loads the configuration for the provided Run instance
113
- by downloading the configuration file from the MLflow artifacts and
114
- loading it using OmegaConf. It returns an empty config if
115
- `.hydra/config.yaml` is not found in the run's artifact directory.
116
-
117
- Args:
118
- run (Run): The Run instance for which to load the configuration.
119
-
120
- Returns:
121
- The loaded configuration as a DictConfig object. Returns an empty
122
- DictConfig if the configuration file is not found.
123
-
124
- """
125
- path = get_artifact_dir(run) / ".hydra/config.yaml"
126
- return OmegaConf.load(path) # type: ignore
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: hydraflow
3
- Version: 0.2.18
3
+ Version: 0.3.0
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
@@ -17,6 +17,7 @@ Requires-Python: >=3.10
17
17
  Requires-Dist: hydra-core>=1.3
18
18
  Requires-Dist: joblib
19
19
  Requires-Dist: mlflow>=2.15
20
+ Requires-Dist: polars
20
21
  Requires-Dist: rich
21
22
  Requires-Dist: watchdog
22
23
  Requires-Dist: watchfiles
@@ -0,0 +1,15 @@
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,,
@@ -1,14 +0,0 @@
1
- hydraflow/__init__.py,sha256=B7rWSiGP5WwWjijcb41Bv9uuo5MQ6gbBbVWGAWYtK-k,598
2
- hydraflow/asyncio.py,sha256=-i1C8KAmNDImrjHnk92Csaa1mpjdK8Vp4ZVaQV-l94s,6634
3
- hydraflow/config.py,sha256=sBaEYPMAGSIOc_wdDsWm0k4y3AZyWIET8gqa_o95SDA,2089
4
- hydraflow/context.py,sha256=ih_jnexaHoToNq1dZ6sBzhJWFluPiQluOlYTYOzNEgk,8222
5
- hydraflow/info.py,sha256=Vzyz9dEWcU9ovRG3JWshxIazzod1cZoHF74bHhHL3AI,3946
6
- hydraflow/mlflow.py,sha256=GkOr_pXfpfY5USYBLrCigHcP13VgrAK_e9kheR1Wke4,8579
7
- hydraflow/param.py,sha256=dvIXcKgc_MPiju3WEk9qz5FOUeK5qSj-YWN2ophCpUM,1938
8
- hydraflow/progress.py,sha256=zvKX1HCN8_xDOsgYOEcLLhkhdPdep-U8vHrc0XZ-6SQ,6163
9
- hydraflow/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- hydraflow/run_collection.py,sha256=gsseBQ6a2YolNanISgEgkjei7o9U6ZGV-Tk50UYH850,24295
11
- hydraflow-0.2.18.dist-info/METADATA,sha256=roL3lGtlIibF6rHbCp4aXrCphhq-OkNe0JwLxM1xtBY,3819
12
- hydraflow-0.2.18.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
13
- hydraflow-0.2.18.dist-info/licenses/LICENSE,sha256=IGdDrBPqz1O0v_UwCW-NJlbX9Hy9b3uJ11t28y2srmY,1062
14
- hydraflow-0.2.18.dist-info/RECORD,,