File size: 15,285 Bytes
5355966
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
"""Model registry, client construction, and the key policy for public hosting.

Every provider here speaks the OpenAI wire format, so one client class covers
all of them and only the base URL changes.

Key policy, in priority order per request:

  1. A key the visitor typed into the UI ("bring your own key"). Used for that
     single request and then dropped - never logged, never persisted, never
     written to disk.
  2. Otherwise the host's own key for that provider, if one is configured.
     On the public deployment that is deliberately a free-tier provider, and
     it is rate limited per session.

The demo defaults to Groq's free tier serving gpt-oss-120b - which is the model
that actually won this project's benchmark, so the zero-cost path is also the
one that shows the best result.
"""

from __future__ import annotations

import os
import time
from dataclasses import dataclass, field

from openai import OpenAI

# --------------------------------------------------------------------------
# registry
# --------------------------------------------------------------------------


@dataclass(frozen=True)
class Provider:
    key_env: str          # environment variable holding the key
    base_url: str | None  # None means the OpenAI default endpoint
    label: str
    signup: str = ""
    needs_key: bool = True


PROVIDERS: dict[str, Provider] = {
    "openai": Provider("OPENAI_API_KEY", None, "OpenAI",
                       "https://platform.openai.com/api-keys"),
    "anthropic": Provider("ANTHROPIC_API_KEY", "https://api.anthropic.com/v1/", "Anthropic",
                          "https://console.anthropic.com/settings/keys"),
    "google": Provider("GOOGLE_API_KEY", "https://generativelanguage.googleapis.com/v1beta/openai/", "Google",
                       "https://aistudio.google.com/apikey"),
    "grok": Provider("GROK_API_KEY", "https://api.x.ai/v1", "xAI",
                     "https://console.x.ai"),
    "groq": Provider("GROQ_API_KEY", "https://api.groq.com/openai/v1", "Groq (free tier)",
                     "https://console.groq.com/keys"),
    "openrouter": Provider("OPENROUTER_API_KEY", "https://openrouter.ai/api/v1", "OpenRouter",
                           "https://openrouter.ai/keys"),
    "ollama": Provider("", os.getenv("OLLAMA_BASE_URL", "http://localhost:11434/v1"),
                       "Ollama (local)", "https://ollama.com", needs_key=False),
}


DEMO = "demo"      # cheap or free - the host's key may serve these
BYOK = "byok"      # expensive - the visitor must supply their own key
LOCAL = "local"    # runs on the machine hosting the app, costs nothing


@dataclass(frozen=True)
class Model:
    id: str
    provider: str
    display: str
    note: str = ""
    reasoning: bool = False  # accepts the reasoning_effort parameter
    tier: str = BYOK         # default to the safe side: never spend the host's money


# Tiering is based on measured results, not list price alone. On the max-subarray
# benchmark, gpt-5-nano produced a correct translation running 62x faster than
# Python; GPT-5 with high reasoning effort scored 63x. The difference is noise,
# and the cost difference is not - so the small model is the demo default and
# the frontier models are opt-in with the visitor's own key.
MODELS: list[Model] = [
    # -- demo tier: safe to serve with the host's key --------------------
    Model("openai/gpt-oss-120b", "groq", "GPT-OSS 120B",
          "free tier - fastest result in this benchmark", tier=DEMO),
    Model("gpt-5-nano", "openai", "GPT-5 Nano",
          "very low cost - scored 62x on the benchmark", reasoning=True, tier=DEMO),
    Model("gpt-5-mini", "openai", "GPT-5 Mini",
          "low cost - scored 63x", reasoning=True, tier=DEMO),

    # -- frontier: visitor's own key only --------------------------------
    Model("gpt-5", "openai", "GPT-5", "frontier", reasoning=True, tier=BYOK),
    Model("claude-sonnet-5", "anthropic", "Claude Sonnet 5", "frontier", tier=BYOK),
    Model("grok-4", "grok", "Grok 4", "frontier", tier=BYOK),
    Model("qwen/qwen3-coder-30b-a3b-instruct", "openrouter", "Qwen3 Coder 30B",
          "open weights", tier=BYOK),
    # Flash models failed to compile on both benchmarks tried - they emit Python
    # format strings such as {:.6f}, which is not valid Rust. Kept for comparison
    # because that failure is itself an interesting result, but not defaulted to.
    Model("gemini-3.5-flash", "google", "Gemini 3.5 Flash",
          "fast, but failed to compile in testing", tier=BYOK),

    # -- local via Ollama -------------------------------------------------
    Model("gpt-oss:20b", "ollama", "GPT-OSS 20B", "runs locally", tier=LOCAL),
    Model("qwen2.5-coder", "ollama", "Qwen2.5 Coder", "runs locally", tier=LOCAL),
    Model("deepseek-coder-v2", "ollama", "DeepSeek Coder V2", "runs locally", tier=LOCAL),
]

BY_ID = {m.id: m for m in MODELS}

DEMO_MODEL = os.getenv("DEMO_MODEL", "openai/gpt-oss-120b")


# --------------------------------------------------------------------------
# availability
# --------------------------------------------------------------------------


_ollama_cache: tuple[float, bool] | None = None


def ollama_reachable() -> bool:
    """Whether a local Ollama server is actually answering.

    Ollama needs no key, so a key check would report its models as ready even
    with nothing running - and the visitor would get a connection error after
    waiting. Probing the socket keeps the availability badges honest. Cached
    briefly so it does not run on every dropdown render.
    """
    global _ollama_cache
    now = time.time()
    if _ollama_cache and now - _ollama_cache[0] < 30:
        return _ollama_cache[1]

    import urllib.error
    import urllib.request

    base = PROVIDERS["ollama"].base_url or ""
    url = base.rstrip("/").removesuffix("/v1") + "/api/tags"
    try:
        with urllib.request.urlopen(url, timeout=1.5) as response:
            alive = response.status == 200
    except Exception:
        alive = False

    _ollama_cache = (now, alive)
    return alive


def host_key_for(provider: str) -> str | None:
    """The host's configured key for a provider, if any."""
    spec = PROVIDERS[provider]
    if not spec.needs_key:
        return "not-needed" if ollama_reachable() else None
    value = os.getenv(spec.key_env, "").strip()
    return value or None


def may_use_host_key(model: Model) -> bool:
    """Whether this model is allowed to spend the owner's credits.

    Frontier models never are - not on the public demo and not locally. The
    measured benefit over gpt-5-nano on this task is nil (62x vs 63x), so
    charging frontier prices for it is pure waste, and an accidental click
    while developing costs just as much as a visitor's.
    """
    if model.tier == LOCAL:
        return True          # costs nothing, runs on this machine
    return model.tier == DEMO


def visible_models() -> list[Model]:
    """Models worth showing on this instance.

    Local models are hidden unless Ollama is actually answering. The probe runs
    on the *server*, so a hosted container will never find one - and listing a
    permanently broken option is worse than not listing it.
    """
    models = [m for m in MODELS if m.tier != LOCAL]
    if not PUBLIC and ollama_reachable():
        models += [m for m in MODELS if m.tier == LOCAL]
    return models


def is_available(model_id: str) -> bool:
    """True when the host can serve this model with no key from the visitor."""
    model = BY_ID.get(model_id)
    if not model or not may_use_host_key(model):
        return False
    return host_key_for(model.provider) is not None


def needs_own_key(model_id: str) -> bool:
    """True when this model requires the visitor to supply a key."""
    model = BY_ID.get(model_id)
    if not model or model.tier == LOCAL:
        return False
    return not is_available(model_id)


def choice_label(model: Model) -> str:
    """Dropdown label. The cost warning goes first, where it cannot be missed.

    Trailing markers get truncated in a narrow select element - exactly the
    situation where someone is about to spend money without meaning to.
    """
    note = f" - {model.note}" if model.note else ""

    if is_available(model.id) or model.tier == LOCAL:
        return f"{model.display}{note}"
    if model.tier == DEMO and not PUBLIC:
        # Local dev: the owner can fix this, and naming the variable is the
        # fastest route. Suppressed in public mode - a visitor cannot set an
        # environment variable on someone else's server, so it would only
        # confuse them. There, the honest instruction is the same as frontier.
        return f"(set {PROVIDERS[model.provider].key_env})  {model.display}{note}"
    return f"(need your own key)  {model.display}{note}"


def dropdown_choices() -> list[tuple[str, str]]:
    """(label, value) pairs, ready models first."""
    models = visible_models()
    ordered = sorted(models, key=lambda m: (not is_available(m.id), models.index(m)))
    return [(choice_label(m), m.id) for m in ordered]


def default_model() -> str:
    """Prefer the configured demo model, then any ready model, then anything."""
    models = visible_models()
    if is_available(DEMO_MODEL):
        return DEMO_MODEL
    for m in models:
        if m.tier == DEMO and is_available(m.id):
            return m.id
    for m in models:
        if is_available(m.id):
            return m.id
    return models[0].id


def availability_summary() -> str:
    """Short markdown line describing what the running instance can serve."""
    models = visible_models()
    ready = [m for m in models if is_available(m.id)]
    if not ready:
        return (
            "**No models ready.** Add a provider key to `.env` "
            "(see `.env.example`), or paste your own key below to try it now."
        )
    names = ", ".join(m.display for m in ready[:3])
    extra = f" +{len(ready) - 3} more" if len(ready) > 3 else ""
    tail = ""
    if PUBLIC:
        tail = "  Frontier models need your own key - they are too costly to give away."
    return f"**Ready now:** {names}{extra}.{tail}"


# --------------------------------------------------------------------------
# rate limiting
# --------------------------------------------------------------------------


@dataclass
class RateLimiter:
    """Per-session cap on requests that spend the *host's* key.

    Requests carrying a visitor's own key are never counted - they cost the
    host nothing, so throttling them would only punish the considerate.

    In-memory and per-process, which is the right size for a single-container
    demo. A multi-replica deployment would need shared state.
    """

    limit: int = field(default_factory=lambda: int(os.getenv("DEMO_RATE_LIMIT", "5")))
    window_seconds: int = 3600
    _hits: dict[str, list[float]] = field(default_factory=dict)

    def check(self, session_id: str) -> tuple[bool, str]:
        if self.limit <= 0:
            return True, ""
        now = time.time()
        recent = [t for t in self._hits.get(session_id, []) if now - t < self.window_seconds]
        self._hits[session_id] = recent
        if len(recent) >= self.limit:
            wait = int((self.window_seconds - (now - recent[0])) / 60) + 1
            return False, (
                f"Demo limit reached ({self.limit} free conversions per hour).\n\n"
                f"Try again in ~{wait} minutes, or open **Use your own API key** "
                f"below for unlimited use with your own account."
            )
        return True, ""

    def record(self, session_id: str) -> None:
        self._hits.setdefault(session_id, []).append(time.time())

    def remaining(self, session_id: str) -> int:
        if self.limit <= 0:
            return -1
        now = time.time()
        recent = [t for t in self._hits.get(session_id, []) if now - t < self.window_seconds]
        return max(0, self.limit - len(recent))


limiter = RateLimiter()
PUBLIC = os.getenv("PUBLIC_DEPLOYMENT", "0") == "1"


# --------------------------------------------------------------------------
# client construction
# --------------------------------------------------------------------------


class NoKeyError(RuntimeError):
    """Raised when neither the visitor nor the host can supply a usable key."""


def build_client(model_id: str, user_key: str | None) -> tuple[OpenAI, bool]:
    """Return (client, used_host_key).

    `user_key` is used for this call only. It is never stored, logged, or
    written anywhere - it lives in this frame and is released with it.
    """
    model = BY_ID.get(model_id)
    if model is None:
        raise NoKeyError(f"Unknown model: {model_id}")

    spec = PROVIDERS[model.provider]
    user_key = (user_key or "").strip()

    if user_key:
        key, used_host = user_key, False
    elif not may_use_host_key(model):
        # Frontier tier. Refuse before the host key is even read, rather than
        # reading it and checking a limit afterwards.
        raise NoKeyError(
            f"**{model.display}** is a frontier model and never runs on this "
            f"instance's key - a few clicks is real money.\n\n"
            f"Open **Use your own API key** below and paste a {spec.label} key "
            f"({spec.signup}) to use it.\n\n"
            f"Or pick a model without the warning: on this benchmark GPT-5 Nano "
            f"scored 62x against GPT-5's 63x, so you give up essentially nothing."
        )
    else:
        host = host_key_for(model.provider)
        if host is None:
            if not spec.needs_key:
                raise NoKeyError(
                    f"**{model.display}** runs through a local Ollama server, and "
                    f"none is responding at {spec.base_url}.\n\n"
                    f"Start it with `ollama serve` and `ollama pull {model.id}`, "
                    f"or choose a hosted model instead. Pasting an API key will "
                    f"not help with a local model."
                )
            raise NoKeyError(
                f"**{model.display}** needs a {spec.label} key, and this instance "
                f"has none configured.\n\n"
                f"Open **Use your own API key** below and paste a {spec.label} key "
                f"({spec.signup}), or pick a model marked as ready."
            )
        key, used_host = host, True

    if not spec.needs_key:
        return OpenAI(api_key="ollama", base_url=spec.base_url), used_host
    if spec.base_url:
        return OpenAI(api_key=key, base_url=spec.base_url), used_host
    return OpenAI(api_key=key), used_host


def scrub(text: str) -> str:
    """Strip anything key-shaped out of text before it reaches the UI.

    Provider SDKs sometimes echo the offending credential back inside an error
    message. Since those messages get rendered into the page, they pass
    through here first.
    """
    import re

    patterns = [
        r"sk-[A-Za-z0-9_\-]{12,}",
        r"gsk_[A-Za-z0-9_\-]{12,}",
        r"xai-[A-Za-z0-9_\-]{12,}",
        r"AIza[A-Za-z0-9_\-]{20,}",
        r"sk-or-v1-[A-Za-z0-9_\-]{12,}",
        r"pplx-[A-Za-z0-9_\-]{12,}",
    ]
    for pattern in patterns:
        text = re.sub(pattern, "[redacted]", text)
    return text