mekosotto commited on
Commit
1761dcd
·
1 Parent(s): 26adc32

chore(llm): one-shot OpenRouter free-tier reachability probe

Browse files
Files changed (1) hide show
  1. scripts/diagnose_openrouter.py +79 -0
scripts/diagnose_openrouter.py ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Probe OpenRouter for which free-tier model IDs are reachable today.
2
+
3
+ Reads OPENROUTER_API_KEY from .env (or process env). Issues a single
4
+ 8-token chat completion against a candidate list and prints one line per
5
+ model: status (OK / HTTP-code / exception name) + a 30-char preview of
6
+ the response when OK.
7
+
8
+ Use:
9
+ python scripts/diagnose_openrouter.py
10
+
11
+ Or to probe a custom list:
12
+ python scripts/diagnose_openrouter.py google/gemma-2-9b-it:free meta-llama/llama-3.2-3b-instruct:free
13
+ """
14
+ from __future__ import annotations
15
+
16
+ import os
17
+ import sys
18
+ from pathlib import Path
19
+
20
+ # Manually parse .env without python-dotenv (some envs choke on its
21
+ # frame-introspection in heredocs / non-stack-rooted callers).
22
+ _env_path = Path(__file__).resolve().parent.parent / ".env"
23
+ if _env_path.exists():
24
+ for raw in _env_path.read_text().splitlines():
25
+ s = raw.strip()
26
+ if not s or s.startswith("#") or "=" not in s:
27
+ continue
28
+ k, v = s.split("=", 1)
29
+ os.environ.setdefault(k.strip(), v.strip())
30
+
31
+ if not os.environ.get("OPENROUTER_API_KEY"):
32
+ sys.exit("OPENROUTER_API_KEY not set (looked in env and .env)")
33
+
34
+ # Candidate list: well-known stable free-tier IDs as of 2026-Q2.
35
+ # Update by replacing this list — script is a probe, not a config source.
36
+ DEFAULT_CANDIDATES = [
37
+ "google/gemma-2-9b-it:free",
38
+ "google/gemini-2.0-flash-exp:free",
39
+ "meta-llama/llama-3.2-3b-instruct:free",
40
+ "meta-llama/llama-3.3-70b-instruct:free",
41
+ "mistralai/mistral-7b-instruct:free",
42
+ "qwen/qwen-2.5-72b-instruct:free",
43
+ "deepseek/deepseek-r1:free",
44
+ "deepseek/deepseek-chat:free",
45
+ "nousresearch/hermes-3-llama-3.1-405b:free",
46
+ "microsoft/phi-3-mini-128k-instruct:free",
47
+ ]
48
+
49
+ candidates = sys.argv[1:] or DEFAULT_CANDIDATES
50
+
51
+ from openai import ( # noqa: E402 (after env load)
52
+ OpenAI, APIStatusError, APIConnectionError, RateLimitError, APITimeoutError,
53
+ )
54
+
55
+ client = OpenAI(
56
+ base_url="https://openrouter.ai/api/v1",
57
+ api_key=os.environ["OPENROUTER_API_KEY"],
58
+ timeout=15.0,
59
+ )
60
+
61
+ for m in candidates:
62
+ try:
63
+ c = client.chat.completions.create(
64
+ model=m,
65
+ messages=[{"role": "user", "content": "Reply with the single word OK."}],
66
+ max_tokens=8,
67
+ temperature=0,
68
+ )
69
+ text = (c.choices[0].message.content or "").strip()
70
+ print(f" OK {m} → {text[:30]!r}")
71
+ except APIStatusError as e:
72
+ code = getattr(e, "status_code", "?")
73
+ print(f" {code:<5} {m}")
74
+ except RateLimitError:
75
+ print(f" 429 {m} (rate-limited)")
76
+ except (APIConnectionError, APITimeoutError) as e:
77
+ print(f" CONN {m} ({type(e).__name__})")
78
+ except Exception as e:
79
+ print(f" ERR {m} ({type(e).__name__}: {e})")