File size: 1,997 Bytes
eb4abb8
 
 
 
 
479c932
 
 
eb4abb8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
"""Load app and model config from YAML. Single source for hyperparameters and tunables."""

from __future__ import annotations

import os

# ClearML UI project name (must match the project in your ClearML workspace).
CLEARML_PROJECT_NAME = "FocusGuards Large Group Project"
from pathlib import Path
from typing import Any

_CONFIG: dict[str, Any] | None = None


def _default_path() -> Path:
    return Path(__file__).resolve().parent / "default.yaml"


def load_config(path: str | Path | None = None) -> dict[str, Any]:
    """Load YAML config. Uses FOCUSGUARD_CONFIG env or config/default.yaml."""
    global _CONFIG
    if _CONFIG is not None:
        return _CONFIG
    import yaml
    p = path or os.environ.get("FOCUSGUARD_CONFIG") or _default_path()
    p = Path(p)
    if not p.is_file():
        _CONFIG = {}
        return _CONFIG
    with open(p, "r", encoding="utf-8") as f:
        _CONFIG = yaml.safe_load(f) or {}
    return _CONFIG


def get(key_path: str, default: Any = None) -> Any:
    """Return a nested config value. E.g. get('app.db_path'), get('mlp.epochs')."""
    cfg = load_config()
    for part in key_path.split("."):
        if not isinstance(cfg, dict) or part not in cfg:
            return default
        cfg = cfg[part]
    return cfg


def flatten_for_clearml(cfg: dict[str, Any] | None = None, prefix: str = "") -> dict[str, Any]:
    """Flatten nested config so every value appears as a ClearML task parameter (no nested dicts)."""
    cfg = cfg if cfg is not None else load_config()
    out = {}
    for k, v in cfg.items():
        key = f"{prefix}/{k}" if prefix else k
        if isinstance(v, dict) and v and not any(isinstance(x, (dict, list)) for x in v.values()):
            for k2, v2 in v.items():
                out[f"{key}/{k2}"] = v2
        elif isinstance(v, dict) and v:
            out.update(flatten_for_clearml(v, key))
        elif isinstance(v, list):
            out[key] = str(v)
        else:
            out[key] = v
    return out