| """Per-challenge configuration. |
| |
| Everything that distinguishes one challenge from another arrives through |
| environment variables β on a deployed Space they are written by |
| ``bootstrap/init_challenge.py`` from the repo's ``challenge.yaml``. The app |
| itself never reads challenge.yaml, so a running Space can be reconfigured by |
| editing its variables alone. |
| """ |
| import json |
| from functools import lru_cache |
| from typing import Literal |
|
|
| from huggingface_hub import get_token |
| from pydantic import Field, model_validator |
| from pydantic_settings import BaseSettings, SettingsConfigDict |
|
|
|
|
| class Settings(BaseSettings): |
| model_config = SettingsConfigDict(env_file=".env", extra="ignore") |
|
|
| |
| org: str = Field(alias="ORG") |
| collab_slug: str = Field(alias="COLLAB_SLUG") |
| |
| central_bucket: str = Field("", alias="CENTRAL_BUCKET") |
| |
| |
| |
| |
| |
| audit_bucket: str = Field(alias="AUDIT_BUCKET") |
| |
| |
| |
| job_quota_ledger_path: str = Field( |
| "quota/job_ledger.jsonl", alias="JOB_QUOTA_LEDGER_PATH" |
| ) |
|
|
| |
| |
| |
| hf_token: str | None = Field(None, alias="HF_TOKEN") |
|
|
| |
| |
| score_field: str = Field("score", alias="SCORE_FIELD") |
| |
| score_unit: str = Field("points", alias="SCORE_UNIT") |
| |
| score_order: Literal["desc", "asc"] = Field("desc", alias="SCORE_ORDER") |
| |
| |
| |
| required_result_fields: str = Field( |
| "score,method,status,description", alias="REQUIRED_RESULT_FIELDS" |
| ) |
|
|
| sync_max_bytes: int = Field(5 * 1024**3, alias="SYNC_MAX_BYTES") |
| sync_max_files: int = Field(10_000, alias="SYNC_MAX_FILES") |
|
|
| bucket_write_per_minute: int = Field(60, alias="BUCKET_WRITE_PER_MINUTE") |
| bucket_write_burst: int = Field(20, alias="BUCKET_WRITE_BURST") |
| raw_message_per_minute: int = Field(5, alias="RAW_MESSAGE_PER_MINUTE") |
| raw_message_per_hour: int = Field(30, alias="RAW_MESSAGE_PER_HOUR") |
| registration_per_minute: int = Field(3, alias="REGISTRATION_PER_MINUTE") |
|
|
| dedup_lru_size: int = Field(10_000, alias="DEDUP_LRU_SIZE") |
|
|
| |
| |
| listing_ttl_s: float = Field(30.0, alias="LISTING_TTL_S") |
| content_cache_max_bytes: int = Field(64 * 1024**2, alias="CONTENT_CACHE_MAX_BYTES") |
| expand_max_limit: int = Field(200, alias="EXPAND_MAX_LIMIT") |
| mention_fanout_cap: int = Field(10, alias="MENTION_FANOUT_CAP") |
|
|
| |
| |
| org_roles_ttl_s: float = Field(300.0, alias="ORG_ROLES_TTL_S") |
|
|
| |
| |
| |
| |
| digest_channel_recent: int = Field(3, alias="DIGEST_CHANNEL_RECENT") |
|
|
| |
| |
| |
| |
| |
| longpoll_max_wait_s: float = Field(55.0, alias="LONGPOLL_MAX_WAIT_S") |
| |
| |
| |
| |
| |
| |
| longpoll_max_waiters_per_owner: int = Field(4, alias="LONGPOLL_MAX_WAITERS_PER_OWNER") |
| longpoll_max_waiters_total: int = Field(256, alias="LONGPOLL_MAX_WAITERS_TOTAL") |
| |
| |
| |
| |
| |
| |
| |
| longpoll_wake_spread_s: float = Field(8.0, alias="LONGPOLL_WAKE_SPREAD_S") |
| longpoll_wake_spread_threshold: int = Field(20, alias="LONGPOLL_WAKE_SPREAD_THRESHOLD") |
|
|
| |
| jobs_enabled: bool = Field(False, alias="JOBS_ENABLED") |
| |
| |
| |
| |
| |
| harness_prefix: str = Field("shared_resources/harness", alias="HARNESS_PREFIX") |
| harness_entrypoint: str = Field("run.py", alias="JOB_HARNESS_ENTRYPOINT") |
| |
| job_extra_args: str = Field("[]", alias="JOB_EXTRA_ARGS") |
| job_image: str = Field("python:3.12", alias="JOB_IMAGE") |
| job_flavor: str = Field("a10g-small", alias="JOB_FLAVOR") |
| job_timeout_minutes: int = Field(40, alias="JOB_TIMEOUT_MINUTES") |
| |
| job_watch_poll_s: int = Field(20, alias="JOB_WATCH_POLL_S") |
| job_watch_grace_s: int = Field(180, alias="JOB_WATCH_GRACE_S") |
| job_log_tail_lines: int = Field(2000, alias="JOB_LOG_TAIL_LINES") |
|
|
| |
| job_per_agent_per_day: int = Field(10, alias="JOB_PER_AGENT_PER_DAY") |
| job_per_user_per_day: int = Field(30, alias="JOB_PER_USER_PER_DAY") |
|
|
| |
| |
| |
| |
| |
| verifier_enabled: bool = Field(False, alias="VERIFIER_ENABLED") |
| verifier_agent: str = Field("", alias="VERIFIER_AGENT") |
| private_dataset_prefix: str = Field("eval_dataset", alias="PRIVATE_DATASET_PREFIX") |
| verification_runs_prefix: str = Field( |
| "verification_runs", alias="VERIFICATION_RUNS_PREFIX" |
| ) |
| |
| score_tol: float = Field(0.05, alias="VERIFIER_SCORE_TOL") |
| |
| |
| guard_field: str = Field("", alias="VERIFIER_GUARD_FIELD") |
| guard_cap: float = Field(0.0, alias="VERIFIER_GUARD_CAP") |
|
|
| @model_validator(mode="after") |
| def _derive_defaults(self) -> "Settings": |
| if not self.central_bucket: |
| self.central_bucket = f"{self.org}/{self.collab_slug}-main-bucket" |
| return self |
|
|
| @property |
| def agent_bucket_prefix(self) -> str: |
| return f"{self.collab_slug}-" |
|
|
| @property |
| def required_result_field_list(self) -> list[str]: |
| fields = [f.strip() for f in self.required_result_fields.split(",") if f.strip()] |
| if self.score_field not in fields: |
| fields.insert(0, self.score_field) |
| return fields |
|
|
| @property |
| def job_extra_arg_list(self) -> list[str]: |
| try: |
| args = json.loads(self.job_extra_args) |
| except json.JSONDecodeError: |
| raise ValueError(f"JOB_EXTRA_ARGS is not valid JSON: {self.job_extra_args!r}") |
| if not isinstance(args, list): |
| raise ValueError("JOB_EXTRA_ARGS must be a JSON list of strings") |
| return [str(a) for a in args] |
|
|
| def agent_bucket(self, agent_id: str) -> str: |
| return f"{self.org}/{self.collab_slug}-{agent_id}" |
|
|
| def better(self, a: float, b: float) -> bool: |
| """True iff score ``a`` beats score ``b`` under the configured order.""" |
| return a > b if self.score_order == "desc" else a < b |
|
|
| def resolved_token(self) -> str: |
| if self.hf_token: |
| return self.hf_token |
| cached = get_token() |
| if not cached: |
| raise RuntimeError( |
| "no HF token available; set HF_TOKEN or run `hf auth login`" |
| ) |
| return cached |
|
|
|
|
| @lru_cache |
| def get_settings() -> Settings: |
| return Settings() |
|
|