SulmanK's picture
Restore full project documentation and add Hugging Face Space integration
09f204f
Raw
History Blame Contribute Delete
2.85 kB
from __future__ import annotations
from enum import Enum
from typing import Literal
from pydantic import BaseModel, ConfigDict, Field, field_validator
class PriorityTier(str, Enum):
low = "low"
medium = "medium"
high = "high"
class ActionKind(str, Enum):
place = "place"
defer = "defer"
class GPUState(BaseModel):
model_config = ConfigDict(extra="forbid")
gpu_id: str
vram_capacity: int = Field(ge=1)
speed_multiplier: float = Field(gt=0)
cost_per_step: float = Field(ge=0)
current_job_id: str | None = None
busy: bool = False
class JobState(BaseModel):
model_config = ConfigDict(extra="forbid")
job_id: str
vram_requirement: int = Field(ge=1)
estimated_runtime: float = Field(gt=0)
remaining_runtime: float = Field(ge=0)
priority: PriorityTier
deadline: int = Field(ge=0)
pending_ticks: int = Field(ge=0, default=0)
assigned_gpu_id: str | None = None
status: Literal["pending", "running", "completed", "missed"] = "pending"
class SchedulingMetrics(BaseModel):
model_config = ConfigDict(extra="forbid")
total_reward: float = 0.0
completed_jobs: int = 0
missed_deadlines: int = 0
invalid_actions: int = 0
allocation: float = 0.0
total_cost: float = 0.0
average_pending_ticks: float = 0.0
class ActionLogEntry(BaseModel):
model_config = ConfigDict(extra="forbid")
tick_index: int
action: str
rationale: str
score_delta: float
valid: bool
details: str
class SchedulingObservation(BaseModel):
model_config = ConfigDict(extra="forbid")
scenario_id: str
current_tick: int = Field(ge=0)
tick_limit: int = Field(ge=1)
pending_jobs: list[JobState]
running_jobs: list[JobState]
completed_jobs: list[JobState]
missed_jobs: list[JobState]
gpus: list[GPUState]
metrics: SchedulingMetrics
last_event: str | None = None
action_log: list[ActionLogEntry] = Field(default_factory=list)
class SchedulingAction(BaseModel):
model_config = ConfigDict(extra="forbid")
action: ActionKind
job_id: str | None = None
gpu_id: str | None = None
rationale: str = Field(min_length=1, max_length=240)
@field_validator("rationale")
@classmethod
def normalize_rationale(cls, value: str) -> str:
stripped = value.strip()
if not stripped:
raise ValueError("rationale must not be empty")
return stripped
class SchedulingStepResult(BaseModel):
model_config = ConfigDict(extra="forbid")
observation: SchedulingObservation
score: float
done: bool
info: dict[str, str | float | int | bool]
class ScenarioConfig(BaseModel):
model_config = ConfigDict(extra="forbid")
scenario_id: str
tick_limit: int = Field(ge=1)
gpus: list[GPUState]
jobs: list[JobState]