test_final / config /__init__.py
k22056537
feat: ClearML project name, artifacts, repro snapshots, model metadata
479c932
"""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