| """Configuration and constants for the Alien Obfuscator application. |
| |
| This module centralizes all static configuration, file paths, and |
| hyper-parameters so that the rest of the codebase can import them without |
| duplicating magic strings. Values are loaded from ``config.yaml`` at the |
| project root, with sensible defaults where applicable. |
| """ |
|
|
| from pathlib import Path |
| from typing import Any, Final |
|
|
| import yaml |
|
|
| |
| |
| |
| PROJECT_ROOT: Final[Path] = Path(__file__).resolve().parent.parent.parent |
| CONFIG_PATH: Final[Path] = PROJECT_ROOT / "config.yaml" |
| ASSETS_DIR: Final[Path] = PROJECT_ROOT / "assets" |
|
|
|
|
| def _load_config() -> dict[str, Any]: |
| """Load config.yaml from the project root, returning an empty dict on failure. |
| |
| Returns |
| ------- |
| dict[str, Any] |
| Parsed YAML configuration. |
| """ |
| if CONFIG_PATH.exists(): |
| with open(CONFIG_PATH, encoding="utf-8") as f: |
| return yaml.safe_load(f) or {} |
| return {} |
|
|
|
|
| _cfg: dict[str, Any] = _load_config() |
|
|
| |
| |
| |
| THEME_LABELS: Final[dict[str, str]] = _cfg.get("themes", {}).get( |
| "labels", |
| { |
| "greek_myth": "Greek / Roman Mythology", |
| "shakespeare": "Shakespeare", |
| "grimm": "Grimms' Fairy Tales / Folklore", |
| "poetry": "Classic Poetry", |
| "chinese_classics": "Chinese Classics", |
| "surprise": "Surprise Me", |
| }, |
| ) |
|
|
| THEME_KEYS: Final[list[str]] = sorted(k for k in THEME_LABELS if k != "surprise") |
|
|
| |
| |
| |
| _riddle_cfg: dict[str, Any] = _cfg.get("riddle", {}) |
| MAX_PLAINTEXT_LENGTH: Final[int] = _riddle_cfg.get("max_plaintext_length", 100) |
| MAX_RIDDLE_LENGTH: Final[int] = _riddle_cfg.get("max_riddle_length", 500) |
| NUM_OPTIONS: Final[int] = _riddle_cfg.get("num_options", 5) |
| MAX_RETRIES: Final[int] = _riddle_cfg.get("max_retries", 2) |
|
|
| |
| |
| |
| DEFAULT_BACKEND: Final[str] = "mock" |
| _llm_cfg: dict[str, Any] = _cfg.get("llm", {}) |
| LLM_TIMEOUT_SECONDS: Final[int] = _llm_cfg.get("timeout_seconds", 15) |
| LLM_MAX_TOKENS: Final[int] = _llm_cfg.get("max_tokens", 4096) |
| LLM_TEMPERATURE: Final[float] = _llm_cfg.get("temperature", 0.8) |
|
|
| |
| _models_cfg: dict[str, Any] = _cfg.get("models", {}) |
| PRIMARY_MODEL: Final[str] = _models_cfg.get("primary", "google/gemma-4-31b-it") |
| FALLBACK_MODEL: Final[str] = _models_cfg.get("fallback", "google/gemma-4-26b-a4b-it") |
| MAX_PARAMETERS: Final[int] = _models_cfg.get("max_parameters", 32_000_000_000) |
|
|
| |
| _backends_cfg: dict[str, Any] = _cfg.get("backends", {}) |
| HF_DEFAULT_MODEL: Final[str] = _backends_cfg.get("hf", {}).get("default_model", "google/gemma-4-31b-it") |
| HF_API_TIMEOUT: Final[int] = _backends_cfg.get("hf", {}).get("timeout", 30) |
| OPENROUTER_DEFAULT_MODEL: Final[str] = _backends_cfg.get("openrouter", {}).get("default_model", "google/gemma-4-31b-it") |
| OPENROUTER_URL: Final[str] = _backends_cfg.get("openrouter", {}).get( |
| "url", "https://openrouter.ai/api/v1/chat/completions" |
| ) |
| OPENROUTER_TIMEOUT: Final[int] = _backends_cfg.get("openrouter", {}).get("timeout", 120) |
| OPENCODE_GO_DEFAULT_MODEL: Final[str] = _backends_cfg.get("opencode-go", {}).get("default_model", "mimo-v2.5") |
| OPENCODE_GO_URL: Final[str] = _backends_cfg.get("opencode-go", {}).get( |
| "url", "https://opencode.ai/zen/go/v1/chat/completions" |
| ) |
| OPENCODE_GO_TIMEOUT: Final[int] = _backends_cfg.get("opencode-go", {}).get("timeout", 120) |
| MODAL_DEFAULT_MODEL: Final[str] = _backends_cfg.get("modal", {}).get("default_model", "google/gemma-4-31b-it") |
| MODAL_TIMEOUT: Final[int] = _backends_cfg.get("modal", {}).get("timeout", 300) |
| LOCAL_DEFAULT_MODEL: Final[str] = _backends_cfg.get("local", {}).get("default_model", "google/gemma-4-31b-it") |
| LOCAL_TIMEOUT: Final[int] = _backends_cfg.get("local", {}).get("timeout", 600) |
| LOCAL_QUANTIZE: Final[str] = _backends_cfg.get("local", {}).get("quantize", "fp16") |
| AUTO_TIMEOUT: Final[int] = _backends_cfg.get("auto", {}).get("timeout", 600) |
| AUTO_FALLBACK_ORDER: Final[str] = _backends_cfg.get("auto", {}).get("fallback_order", "modal,local,mock") |
|
|
| |
| CHALLENGE_PHRASES: Final[list[str]] = _cfg.get( |
| "challenge_phrases", |
| [ |
| "patience is a virtue", |
| "do not count your chickens", |
| "a rolling stone gathers no moss", |
| "the lion's share", |
| "Achilles' heel", |
| "Pandora's box", |
| "star-crossed lovers", |
| "the Midas touch", |
| "Sisyphean task", |
| "Icarus' fall", |
| ], |
| ) |
|
|
| |
| MOCK_DISTRACTORS: Final[list[str]] = _cfg.get("mock_backend", {}).get( |
| "distractors", |
| ["a wrong answer", "another wrong answer", "yet another wrong answer", "the last wrong answer"], |
| ) |
|
|
| |
| |
| |
| _game_cfg: dict[str, Any] = _cfg.get("game", {}) |
| DEFAULT_GAME_DURATION_MINUTES: Final[int] = _game_cfg.get("default_duration_minutes", 10) |
| MIN_GAME_DURATION_MINUTES: Final[int] = _game_cfg.get("min_duration_minutes", 1) |
| MAX_GAME_DURATION_MINUTES: Final[int] = _game_cfg.get("max_duration_minutes", 30) |
| POINTS_PER_CORRECT: Final[int] = _game_cfg.get("points_per_correct", 10) |
| SPEED_BONUS_SECONDS: Final[int] = _game_cfg.get("speed_bonus_seconds", 15) |
| SPEED_BONUS_POINTS: Final[int] = _game_cfg.get("speed_bonus_points", 5) |
| STREAK_BONUS_POINTS: Final[int] = _game_cfg.get("streak_bonus_points", 3) |
|
|
| |
| |
| |
| _app_cfg: dict[str, Any] = _cfg.get("app", {}) |
| APP_TITLE: Final[str] = _app_cfg.get("title", "Alien Obfuscator v1.0") |
| LAUNCH_SERVER_NAME: Final[str] = _app_cfg.get("launch", {}).get("server_name", "0.0.0.0") |
| LAUNCH_SERVER_PORT: Final[int] = _app_cfg.get("launch", {}).get("server_port", 7860) |
| LAUNCH_SHARE: Final[bool] = _app_cfg.get("launch", {}).get("share", False) |
|
|