Spaces:
Paused
Paused
Download api/config.py from chandrakiran06/rosdiff: direct link, hf CLI and curl.
- Browser
- Download file 8.29 kB
-
https://huggingface.co/spaces/chandrakiran06/rosdiff/resolve/main/api/config.py
- Command line
-
hf download hf://spaces/chandrakiran06/rosdiff/api/config.py
-
curl -L -o config.py https://huggingface.co/spaces/chandrakiran06/rosdiff/resolve/main/api/config.py
8.29 kB
| """Settings, read from environment variables (see .env.example).""" | |
| from __future__ import annotations | |
| import os | |
| from dataclasses import dataclass | |
| from functools import lru_cache | |
| from pathlib import Path | |
| REPO_ROOT = Path(__file__).resolve().parent.parent | |
| def _env(name: str, default: str) -> str: | |
| value = os.environ.get(name) | |
| return value if value not in (None, "") else default | |
| class Settings: | |
| # Model: one model for every tester in Stage 1, via any OpenAI-compatible endpoint (OpenRouter by default). | |
| llm_api_key: str | |
| llm_base_url: str | |
| llm_model: str # scene generation (/simulate/generate) | |
| code_llm_model: str # ROS 2 code generation: OpenCode's model, or the direct backend's | |
| llm_timeout: float | |
| # Storage | |
| data_dir: Path | |
| testers_file: Path | |
| log_db: Path | |
| # MuJoCo generation | |
| menagerie_dir: Path | |
| mjcf_max_attempts: int | |
| mjcf_sim_seconds: float | |
| validate_timeout: float | |
| # ROS 2 generation | |
| codegen_backend: str # "opencode" or "direct" | |
| opencode_bin: str | |
| opencode_timeout: float | |
| code_max_attempts: int | |
| # Simulation runs (Modal or RunPod serverless, results in Cloudflare R2) | |
| sim_backend: str # "modal" or "runpod" | |
| modal_app: str | |
| runpod_api_key: str | |
| runpod_endpoint_id: str | |
| run_execution_timeout_s: int | |
| run_max_duration_s: float | |
| run_burst_warn: int # log a warning when a tester starts more runs than this within 10 minutes | |
| report_secret: str # signs report links | |
| public_base_url: str # how testers reach this API (for report links); empty = use the request's host | |
| # Spend: estimated from each job's run time; new jobs are refused once the month's estimate reaches the limit. | |
| monthly_credit_usd: float # 0 = no limit | |
| # ...and each tester gets an equal share of it, enforced before every job against the job's worst case. | |
| compute_testers: int # how many testers share the compute credit | |
| compute_per_tester_usd: float # 0 = monthly_credit_usd / compute_testers | |
| storage_limit_gb: float # new jobs are refused while the R2 bucket holds more than this (0 = no limit) | |
| job_prices: dict # USD per second by hardware: t4, l4, cpu, runpod | |
| job_overhead_s: float # billed seconds per job beyond the worker's own timing (start-up, idle shutdown) | |
| isaac_daily_limit: int # Isaac Sim renders per day, across all testers | |
| auto_review: bool # review every finished simulation video with Cosmos Reason | |
| # AI budget in rupees for the test group: one shared pool, an equal allocation per tester. Only billable | |
| # AI calls count (OpenRouter-exempt ones are recorded but not deducted); GPU/CPU jobs have their own | |
| # dollar limit above (Modal's free credit). | |
| usd_inr: float | |
| budget_total_inr: float | |
| budget_per_user_inr: float | |
| confirm_above_inr: float # ask before running a task estimated to cost more than this | |
| admin_testers: tuple # testers who see the team budget view | |
| hf_namespace: str # Hugging Face user/org that dataset exports are pushed to (with the worker's HF_TOKEN) | |
| foxglove_org: str # optional Foxglove organization slug for the embedded viewer | |
| # Prompt enhancement through OpenCode with a free OpenCode Zen model (never OpenRouter, never billed). | |
| prompt_enhance: bool | |
| enhance_model: str # "<opencode provider>/<model>" | |
| enhance_timeout: float | |
| zen_api_key: str # OpenCode Zen key, if the free model asks for one | |
| # Debugging: the first repair goes to a free OpenCode Zen model first (paid tier only if that call fails). | |
| free_debug: bool | |
| debug_model: str # "opencode/<model>" | |
| owner_api_key: str # persistent key for the owner (bypasses budgets, doesn't count as tester) | |
| def compute_share_usd(self) -> float: | |
| """Each tester's monthly GPU/CPU allowance in dollars (0 = no per-tester limit).""" | |
| if self.compute_per_tester_usd > 0: | |
| return self.compute_per_tester_usd | |
| if self.monthly_credit_usd > 0 and self.compute_testers > 0: | |
| return round(self.monthly_credit_usd / self.compute_testers, 6) | |
| return 0.0 | |
| def interfaces_file(self) -> Path: | |
| return self.data_dir / "ros2_interfaces.json" | |
| def mjcf_schema_file(self) -> Path: | |
| return self.data_dir / "mjcf_schema.json" | |
| # Estimated USD per second of container time, GPU plus the CPU and memory that come with it | |
| # (Modal list prices, Sept 2026; override with JOB_PRICES="t4=...,l4=...,cpu=...,runpod=..."). | |
| DEFAULT_PRICES = {"t4": 0.00019, "l4": 0.00025, "cpu": 0.00004, "runpod": 0.00031} | |
| def _prices(spec: str) -> dict: | |
| prices = dict(DEFAULT_PRICES) | |
| for part in filter(None, (p.strip() for p in spec.split(","))): | |
| key, _, value = part.partition("=") | |
| prices[key.strip()] = float(value) | |
| return prices | |
| def get_settings() -> Settings: | |
| data_dir = Path(_env("ROSDIFF_DATA_DIR", str(REPO_ROOT / "data"))).resolve() | |
| return Settings( | |
| llm_api_key=_env("LLM_API_KEY", ""), | |
| llm_base_url=_env("LLM_BASE_URL", "https://openrouter.ai/api/v1").rstrip("/"), | |
| llm_model=_env("LLM_MODEL", "z-ai/glm-5.2"), | |
| # DeepSeek V4 Flash: 79.0% on SWE-bench Verified (V4 Pro: 80.6%) at about $0.10/$0.20 per M tokens on | |
| # OpenRouter (Sept 2026) - enough for a test phase. For more quality: deepseek/deepseek-v4-pro. | |
| code_llm_model=_env("CODE_LLM_MODEL", "deepseek/deepseek-v4-flash"), | |
| llm_timeout=float(_env("LLM_TIMEOUT", "180")), | |
| data_dir=data_dir, | |
| testers_file=Path(_env("ROSDIFF_TESTERS_FILE", str(REPO_ROOT / "testers.yaml"))), | |
| log_db=Path(_env("ROSDIFF_LOG_DB", str(data_dir / "generations.sqlite3"))), | |
| menagerie_dir=Path(_env("MENAGERIE_DIR", str(data_dir / "sources" / "mujoco_menagerie"))), | |
| mjcf_max_attempts=int(_env("MJCF_MAX_ATTEMPTS", "3")), | |
| mjcf_sim_seconds=float(_env("MJCF_SIM_SECONDS", "2.0")), | |
| validate_timeout=float(_env("VALIDATE_TIMEOUT", "60")), | |
| codegen_backend=_env("CODEGEN_BACKEND", "opencode"), | |
| opencode_bin=_env("OPENCODE_BIN", "opencode"), | |
| opencode_timeout=float(_env("OPENCODE_TIMEOUT", "600")), | |
| code_max_attempts=int(_env("CODE_MAX_ATTEMPTS", "3")), | |
| sim_backend=_env("SIM_BACKEND", "modal").lower(), | |
| modal_app=_env("MODAL_APP", "rosdiff-sim"), | |
| runpod_api_key=_env("RUNPOD_API_KEY", ""), | |
| runpod_endpoint_id=_env("RUNPOD_ENDPOINT_ID", ""), | |
| run_execution_timeout_s=int(_env("RUN_EXECUTION_TIMEOUT_S", "600")), | |
| run_max_duration_s=float(_env("RUN_MAX_DURATION_S", "60")), | |
| run_burst_warn=int(_env("RUN_BURST_WARN", "10")), | |
| report_secret=_env("REPORT_SECRET", ""), | |
| public_base_url=_env("PUBLIC_BASE_URL", "").rstrip("/"), | |
| monthly_credit_usd=float(_env("MONTHLY_CREDIT_LIMIT_USD", "29.98")), | |
| compute_testers=int(_env("COMPUTE_TESTERS", "4")), | |
| compute_per_tester_usd=float(_env("COMPUTE_PER_TESTER_USD", "0")), | |
| storage_limit_gb=float(_env("STORAGE_LIMIT_GB", "9")), | |
| job_prices=_prices(_env("JOB_PRICES", "")), | |
| job_overhead_s=float(_env("JOB_OVERHEAD_S", "45")), | |
| isaac_daily_limit=int(_env("ISAAC_DAILY_LIMIT", "10")), | |
| auto_review=_env("AUTO_REVIEW", "false").lower() in ("1", "true", "yes"), | |
| hf_namespace=_env("HF_NAMESPACE", "rosdiff"), | |
| usd_inr=float(_env("USD_INR", "88")), | |
| budget_total_inr=float(_env("BUDGET_TOTAL_INR", "500")), | |
| budget_per_user_inr=float(_env("BUDGET_PER_USER_INR", "125")), | |
| confirm_above_inr=float(_env("CONFIRM_ABOVE_INR", "10")), | |
| admin_testers=tuple(n.strip() for n in _env("ADMIN_TESTERS", "").split(",") if n.strip()), | |
| foxglove_org=_env("FOXGLOVE_ORG", ""), | |
| prompt_enhance=_env("PROMPT_ENHANCE", "true").lower() in ("1", "true", "yes"), | |
| enhance_model=_env("ENHANCE_MODEL", "opencode/deepseek-v4-flash-free"), | |
| enhance_timeout=float(_env("ENHANCE_TIMEOUT", "90")), | |
| zen_api_key=_env("ZEN_API_KEY", ""), | |
| free_debug=_env("FREE_DEBUG", "true").lower() in ("1", "true", "yes"), | |
| debug_model=_env("DEBUG_MODEL", "opencode/deepseek-v4-flash-free"), | |
| owner_api_key=_env("OWNER_API_KEY", ""), | |
| ) | |