Spaces:
Sleeping
Sleeping
Download src/tasks.py from vivekharry/scaler: direct link, hf CLI and curl.
- Browser
- Download file 4.55 kB
-
https://huggingface.co/spaces/vivekharry/scaler/resolve/main/src/tasks.py
- Command line
-
hf download hf://spaces/vivekharry/scaler/src/tasks.py
-
curl -L -o tasks.py https://huggingface.co/spaces/vivekharry/scaler/resolve/main/src/tasks.py
4.55 kB
| """ | |
| Task definitions and grading logic. | |
| This module provides two APIs: | |
| 1. Legacy tasks (REGISTRY) — the original 3 hardcoded tasks, backward-compatible. | |
| 2. Scenario tasks (ScenarioTask) — wraps the new composable scenario engine so the | |
| environment can treat both identically via the Objective interface. | |
| """ | |
| from typing import Dict, Tuple, List, Optional | |
| from .virtual_filesystem import SystemStore | |
| from .terminal_emulator import Shell | |
| from .scenarios import ( | |
| Scenario, FaultInjector, CascadeEngine, ScenarioGrader, | |
| load_scenario, SCENARIO_CATALOG, list_scenarios, | |
| ) | |
| # ====================================================================== | |
| # BASE CLASS | |
| # ====================================================================== | |
| class Objective: | |
| def __init__(self, nm: str, diff: str, desc: str): | |
| self.nm = nm | |
| self.diff = diff | |
| self.desc = desc | |
| self.lvls: Dict[int, str] = {} | |
| self.max_sc = 1.0 | |
| def eval(self, fs: SystemStore, sh: Shell) -> Tuple[float, Dict]: | |
| raise NotImplementedError | |
| def guide(self) -> str: | |
| raise NotImplementedError | |
| # ====================================================================== | |
| # SCENARIO TASK — wraps the composable scenario engine | |
| # ====================================================================== | |
| class ScenarioTask(Objective): | |
| """Wraps a Scenario through the Objective interface for TrainingEnv.""" | |
| def __init__(self, scenario: Scenario): | |
| super().__init__(nm=scenario.name, diff=scenario.difficulty, desc=scenario.description) | |
| self.scenario = scenario | |
| self._injector: Optional[FaultInjector] = None | |
| self._cascade: Optional[CascadeEngine] = None | |
| self._grader: Optional[ScenarioGrader] = None | |
| self._faults_applied = False | |
| def setup(self, fs: SystemStore, sh: Shell) -> None: | |
| """Inject faults and prepare the scenario. Call once after env reset.""" | |
| self._injector = FaultInjector(fs) | |
| self._cascade = CascadeEngine(fs, self._injector) | |
| self._grader = ScenarioGrader(fs, sh) | |
| # apply initial faults | |
| for fault in self.scenario.faults: | |
| self._injector.inject(fault) | |
| # run one cascade tick (some faults trigger immediately) | |
| self._cascade.tick(self.scenario.cascades) | |
| self._faults_applied = True | |
| def guide(self) -> str: | |
| return self.scenario.guide() | |
| def eval(self, fs: SystemStore, sh: Shell) -> Tuple[float, Dict]: | |
| # ensure grader exists (lazy init if setup wasn't called) | |
| if self._grader is None: | |
| self.setup(fs, sh) | |
| # tick cascades every eval | |
| triggered = [] | |
| if self._cascade: | |
| triggered = self._cascade.tick(self.scenario.cascades) | |
| score, meta = self._grader.evaluate(self.scenario.objectives) | |
| meta["task"] = self.scenario.name | |
| meta["difficulty"] = self.scenario.difficulty | |
| meta["cascades_triggered"] = triggered | |
| return score, meta | |
| def get_task(key: str) -> Objective: | |
| """ | |
| Get a task by its scenario key. | |
| """ | |
| if key in SCENARIO_CATALOG: | |
| return ScenarioTask(load_scenario(key)) | |
| raise ValueError( | |
| f"Unknown scenario key: '{key}'. " | |
| f"Available: {list(SCENARIO_CATALOG.keys())}" | |
| ) | |
| def all_task_keys() -> List[str]: | |
| """Return all available scenario keys.""" | |
| return list(SCENARIO_CATALOG.keys()) | |
| def task_metadata(key: str) -> Dict: | |
| """Return metadata for a task/scenario.""" | |
| task = get_task(key) | |
| meta = { | |
| "key": key, | |
| "name": task.nm, | |
| "difficulty": task.diff, | |
| "description": task.desc, | |
| "instructions": task.guide(), | |
| } | |
| if isinstance(task, ScenarioTask): | |
| objectives = [ | |
| {"description": o.description, "points": o.points, "completed": o.completed} | |
| for o in task.scenario.objectives | |
| ] | |
| total_points = round(sum(o.points for o in task.scenario.objectives), 4) | |
| meta["objectives"] = objectives | |
| # Alias for validators that expect explicit "graders" with a score field. | |
| meta["graders"] = [ | |
| { | |
| "name": f"grader_{idx}", | |
| "description": obj["description"], | |
| "score": obj["points"], | |
| } | |
| for idx, obj in enumerate(objectives, start=1) | |
| ] | |
| meta["objective_count"] = len(objectives) | |
| meta["total_points"] = total_points | |
| meta["score"] = total_points | |
| return meta | |