File size: 4,181 Bytes
c641d5f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
"""Environment-only runtime configuration for the GAIA agent."""

from __future__ import annotations

import os
from dataclasses import dataclass
from pathlib import Path


def _int(name: str, default: int) -> int:
    try:
        return int(os.getenv(name, str(default)))
    except ValueError as exc:
        raise ValueError(f"{name} must be an integer") from exc


def _float(name: str, default: float) -> float:
    try:
        return float(os.getenv(name, str(default)))
    except ValueError as exc:
        raise ValueError(f"{name} must be a number") from exc


def _bool(name: str, default: bool) -> bool:
    value = os.getenv(name)
    if value is None:
        return default
    return value.strip().lower() in {"1", "true", "yes", "on"}


@dataclass(frozen=True)
class Settings:
    api_url: str
    hf_token: str | None
    model_id: str
    vision_model_id: str
    inference_provider: str | None
    asr_model_id: str
    cache_dir: Path
    request_timeout: float
    retries: int
    backoff_seconds: float
    max_steps: int
    use_cache: bool
    stockfish_path: str | None
    fallback_model_id: str | None = None
    fallback_provider: str | None = None
    worker_limit: int = 3
    model_requests_per_minute: float = 20.0
    search_requests_per_minute: float = 30.0
    user_agent: str = "GAIA-Level1-Agent/1.0 (public Hugging Face Space)"
    agent_code_url: str | None = None
    allow_inline_agent_code: bool = False
    local_model_id: str | None = None
    local_model_url: str = "http://127.0.0.1:11434/v1"
    prefer_local_model: bool = False

    @classmethod
    def from_env(cls) -> Settings:
        root = Path(os.getenv("GAIA_CACHE_DIR", "data"))
        provider = (
            os.getenv("HF_PROVIDER") or os.getenv("HF_INFERENCE_PROVIDER") or None
        )
        return cls(
            api_url=os.getenv(
                "GAIA_API_URL", "https://agents-course-unit4-scoring.hf.space"
            ).rstrip("/"),
            hf_token=os.getenv("HF_TOKEN") or None,
            model_id=os.getenv("MODEL_ID")
            or os.getenv("GAIA_MODEL_ID", "openai/gpt-oss-120b"),
            vision_model_id=os.getenv(
                "GAIA_VISION_MODEL_ID", "Qwen/Qwen3-VL-235B-A22B-Instruct"
            ),
            inference_provider=provider,
            asr_model_id=os.getenv("GAIA_ASR_MODEL_ID", "openai/whisper-large-v3"),
            cache_dir=root,
            request_timeout=_float("GAIA_REQUEST_TIMEOUT", 60.0),
            retries=max(1, _int("GAIA_RETRIES", 3)),
            backoff_seconds=max(0.0, _float("GAIA_BACKOFF_SECONDS", 1.0)),
            max_steps=max(1, _int("GAIA_MAX_STEPS", 10)),
            use_cache=_bool("GAIA_USE_CACHE", True),
            stockfish_path=os.getenv("STOCKFISH_PATH") or None,
            fallback_model_id=os.getenv("FALLBACK_MODEL_ID") or "openai/gpt-oss-20b",
            fallback_provider=os.getenv("HF_FALLBACK_PROVIDER") or None,
            worker_limit=max(1, _int("GAIA_WORKERS", 3)),
            model_requests_per_minute=max(
                1.0, _float("GAIA_MODEL_REQUESTS_PER_MINUTE", 20.0)
            ),
            search_requests_per_minute=max(
                1.0, _float("GAIA_SEARCH_REQUESTS_PER_MINUTE", 30.0)
            ),
            user_agent=os.getenv(
                "GAIA_USER_AGENT",
                "GAIA-Level1-Agent/1.0 (public Hugging Face Space)",
            ),
            agent_code_url=os.getenv("GAIA_AGENT_CODE_URL") or None,
            allow_inline_agent_code=_bool("GAIA_ALLOW_INLINE_AGENT_CODE", False),
            local_model_id=os.getenv("GAIA_LOCAL_MODEL_ID") or None,
            local_model_url=os.getenv(
                "GAIA_LOCAL_MODEL_URL", "http://127.0.0.1:11434/v1"
            ).rstrip("/"),
            prefer_local_model=_bool("GAIA_PREFER_LOCAL_MODEL", False),
        )

    def require_hf_token(self) -> str:
        if not self.hf_token:
            raise RuntimeError(
                "HF_TOKEN is required for inference. Add it as a Hugging Face Space secret."
            )
        return self.hf_token