Spaces:
Running on Zero
Running on Zero
| """ | |
| utils.py | |
| ======== | |
| Shared helpers used across every model module: reproducibility seeding, | |
| device detection, checkpoint save/load, and a simple logger. | |
| """ | |
| import logging | |
| import os | |
| import random | |
| import pickle | |
| from pathlib import Path | |
| from typing import Any | |
| import numpy as np | |
| try: | |
| import torch | |
| except ImportError: | |
| torch = None | |
| def seed_everything(seed: int = 42) -> None: | |
| """Set every RNG (python, numpy, torch) for reproducibility. | |
| Matches the set_seed()/torch.manual_seed() calls in all training notebooks. | |
| """ | |
| random.seed(seed) | |
| np.random.seed(seed) | |
| os.environ["PYTHONHASHSEED"] = str(seed) | |
| if torch is not None: | |
| torch.manual_seed(seed) | |
| if torch.cuda.is_available(): | |
| torch.cuda.manual_seed_all(seed) | |
| torch.backends.cudnn.deterministic = True | |
| torch.backends.cudnn.benchmark = False | |
| def get_device(): | |
| """Return 'cuda' if available else 'cpu' (same logic as every notebook).""" | |
| if torch is None: | |
| return "cpu" | |
| return torch.device("cuda" if torch.cuda.is_available() else "cpu") | |
| def save_model(model, path: Path) -> None: | |
| """Save a torch model's state_dict to disk (creates parent dirs).""" | |
| path = Path(path) | |
| path.parent.mkdir(parents=True, exist_ok=True) | |
| torch.save(model.state_dict(), path) | |
| def load_model(model, path: Path, device=None): | |
| """Load a torch model's state_dict from disk in-place and return it in eval mode.""" | |
| device = device or get_device() | |
| model.load_state_dict(torch.load(path, map_location=device)) | |
| model.to(device) | |
| model.eval() | |
| return model | |
| def save_pickle(obj: Any, path: Path) -> None: | |
| path = Path(path) | |
| path.parent.mkdir(parents=True, exist_ok=True) | |
| with open(path, "wb") as f: | |
| pickle.dump(obj, f) | |
| def load_pickle(path: Path) -> Any: | |
| with open(path, "rb") as f: | |
| return pickle.load(f) | |
| def get_logger(name: str = "smart_mcq_solver") -> logging.Logger: | |
| """Simple stdout logger, reused everywhere instead of print().""" | |
| logger = logging.getLogger(name) | |
| if not logger.handlers: | |
| handler = logging.StreamHandler() | |
| formatter = logging.Formatter("[%(asctime)s] %(levelname)s - %(message)s", "%H:%M:%S") | |
| handler.setFormatter(formatter) | |
| logger.addHandler(handler) | |
| logger.setLevel(logging.INFO) | |
| return logger |