Spaces:
Sleeping
Sleeping
Download tasks/registry.py from infoclassifier/InfoClassifier: direct link, hf CLI and curl.
- Browser
- Download file 5.21 kB
-
https://huggingface.co/spaces/infoclassifier/InfoClassifier/resolve/main/tasks/registry.py
- Command line
-
hf download hf://spaces/infoclassifier/InfoClassifier/tasks/registry.py
-
curl -L -o registry.py https://huggingface.co/spaces/infoclassifier/InfoClassifier/resolve/main/tasks/registry.py
5.21 kB
| """ | |
| tasks/registry.py | |
| ================= | |
| Deterministic task registry for InformationIntegrityEnv. | |
| Loads pre-built scenario datasets from tasks/{difficulty}/scenarios.json. | |
| NO external API calls — all scenarios are static and reproducible. | |
| Usage | |
| ----- | |
| from tasks.registry import TASKS | |
| task = TASKS["easy"] | |
| scenario = task.get_scenario(0) # by index | |
| scenario = task.get_scenario("easy_001") # by id | |
| all_sc = task.get_all_scenarios() | |
| # Random selection (seeded for reproducibility) | |
| import random | |
| rng = random.Random(42) | |
| scenario = task.sample(rng) | |
| """ | |
| from __future__ import annotations | |
| import json | |
| import os | |
| import random | |
| from typing import Dict, List, Optional | |
| # --------------------------------------------------------------------------- | |
| # Path resolution | |
| # --------------------------------------------------------------------------- | |
| _TASKS_DIR = os.path.dirname(os.path.abspath(__file__)) | |
| def _load_scenarios(difficulty: str) -> List[dict]: | |
| path = os.path.join(_TASKS_DIR, difficulty, "scenarios.json") | |
| if not os.path.exists(path): | |
| raise FileNotFoundError( | |
| f"Scenario dataset not found: {path}\n" | |
| f"Run data_collector.py to build datasets, or check tasks/{difficulty}/scenarios.json" | |
| ) | |
| with open(path, "r", encoding="utf-8") as fh: | |
| data = json.load(fh) | |
| if not isinstance(data, list) or not data: | |
| raise ValueError(f"scenarios.json for '{difficulty}' must be a non-empty JSON array") | |
| return data | |
| # --------------------------------------------------------------------------- | |
| # Task class | |
| # --------------------------------------------------------------------------- | |
| class Task: | |
| """ | |
| Wraps one difficulty-level dataset. | |
| Parameters | |
| ---------- | |
| difficulty : str | |
| One of 'easy', 'medium', 'hard'. | |
| """ | |
| def __init__(self, difficulty: str) -> None: | |
| self.difficulty = difficulty | |
| self._scenarios: List[dict] = _load_scenarios(difficulty) | |
| self._index_by_id: Dict[str, dict] = {s["id"]: s for s in self._scenarios} | |
| # ------------------------------------------------------------------ | |
| # Public API | |
| # ------------------------------------------------------------------ | |
| def get_scenario(self, scenario_id: str | int) -> dict: | |
| """ | |
| Return a scenario by index (int) or scenario id (str). | |
| Returns a fresh copy so the env cannot mutate the dataset. | |
| """ | |
| if isinstance(scenario_id, int): | |
| if scenario_id < 0 or scenario_id >= len(self._scenarios): | |
| raise IndexError( | |
| f"Scenario index {scenario_id} out of range " | |
| f"(dataset has {len(self._scenarios)} scenarios)" | |
| ) | |
| return dict(self._scenarios[scenario_id]) | |
| # String id lookup | |
| if scenario_id not in self._index_by_id: | |
| raise KeyError( | |
| f"Scenario id '{scenario_id}' not found in {self.difficulty} dataset. " | |
| f"Available ids: {list(self._index_by_id.keys())}" | |
| ) | |
| return dict(self._index_by_id[scenario_id]) | |
| def get_all_scenarios(self) -> List[dict]: | |
| """Return all scenarios as a list of dicts (copies).""" | |
| return [dict(s) for s in self._scenarios] | |
| def sample(self, rng: Optional[random.Random] = None) -> dict: | |
| """Return a uniformly random scenario (optionally seeded).""" | |
| rng = rng or random.Random() | |
| return dict(rng.choice(self._scenarios)) | |
| def __len__(self) -> int: | |
| return len(self._scenarios) | |
| def __repr__(self) -> str: | |
| return f"Task(difficulty={self.difficulty!r}, n_scenarios={len(self)})" | |
| # --------------------------------------------------------------------------- | |
| # Lazy-loaded registry singleton | |
| # --------------------------------------------------------------------------- | |
| class _TaskRegistry: | |
| """ | |
| Lazy-loading registry. Datasets are only read from disk on first access, | |
| so importing this module does not cause IO at import time. | |
| """ | |
| _cache: Dict[str, Task] = {} | |
| _SUPPORTED = ("easy", "medium", "hard") | |
| def __getitem__(self, difficulty: str) -> Task: | |
| key = difficulty.lower().strip() | |
| if key not in self._SUPPORTED: | |
| raise KeyError( | |
| f"Unknown difficulty '{difficulty}'. " | |
| f"Supported values: {list(self._SUPPORTED)}" | |
| ) | |
| if key not in self._cache: | |
| self._cache[key] = Task(key) | |
| return self._cache[key] | |
| def __contains__(self, difficulty: str) -> bool: | |
| return difficulty.lower().strip() in self._SUPPORTED | |
| def keys(self): | |
| return self._SUPPORTED | |
| def items(self): | |
| return [(d, self[d]) for d in self._SUPPORTED] | |
| def reload(self) -> None: | |
| """Force reload all datasets from disk (useful for tests).""" | |
| self._cache.clear() | |
| def __repr__(self) -> str: | |
| loaded = list(self._cache.keys()) | |
| return f"TaskRegistry(supported={list(self._SUPPORTED)}, loaded={loaded})" | |
| # Singleton — import and use directly: from tasks.registry import TASKS | |
| TASKS = _TaskRegistry() | |