68 lines
3.4 KiB
Python
68 lines
3.4 KiB
Python
#!/usr/bin/env python3
|
||
"""Ф1 шаг 0 — ЖИВОЙ листинг моделей по каждому ключу. $0 (GET /models не биллится).
|
||
|
||
Зачем отдельным скриптом и почему первым. Гардрейл CLAUDE.md: «слаги моделей не менять без live-
|
||
фактчека `/models`», и quirks 00 несёт отдельный урок календаря — «слаг живой ≠ модель та же»
|
||
(DeepSeek 31.07 сменил веса под неизменным слагом, D39.61). Пре-рег обязан назвать кандидатов
|
||
слагами, снятыми В ДЕНЬ ЗАПУСКА, иначе смета и вердикты Ф1 повисают на памяти сессии.
|
||
|
||
Ключи не печатаются никогда — скрипт выводит только имена моделей и HTTP-код.
|
||
`.env` читается через python-dotenv; для Claude файл закрыт deny-правилом, и это правильно.
|
||
"""
|
||
from __future__ import annotations
|
||
import json
|
||
import os
|
||
from pathlib import Path
|
||
|
||
import requests
|
||
from dotenv import load_dotenv
|
||
|
||
REPO = Path("/home/ubuntu/projects/textmachine")
|
||
load_dotenv(REPO / "eval" / ".env")
|
||
OUT = Path.home() / "books" / "role-topology"
|
||
OUT.mkdir(parents=True, exist_ok=True)
|
||
|
||
# (провайдер, base_url, env-ключ) — источник: quirks 00 «Эндпоинты и модели»; семь ключей,
|
||
# перечисленных промтом эксп-21 Ф1.
|
||
PROVIDERS = [
|
||
("deepseek", "https://api.deepseek.com/v1", "DEEPSEEK_API_KEY"),
|
||
("zai", "https://api.z.ai/api/paas/v4", "ZAI_API_KEY"),
|
||
("kimi", "https://api.moonshot.ai/v1", "KIMI_API_KEY"),
|
||
("openai", "https://api.openai.com/v1", "OPENAI_API_KEY"),
|
||
("gemini", "https://generativelanguage.googleapis.com/v1beta/openai", "GEMINI_API_KEY"),
|
||
("xai", "https://api.x.ai/v1", "XAI_API_KEY"),
|
||
("mistral", "https://api.mistral.ai/v1", "MISTRAL_API_KEY"),
|
||
]
|
||
|
||
|
||
def main() -> None:
|
||
snap = {}
|
||
for name, base, env in PROVIDERS:
|
||
key = os.getenv(env)
|
||
if not key:
|
||
print(f"{name:10s} КЛЮЧА НЕТ ({env}) — провайдер вне скрина, объявить в пре-реге")
|
||
snap[name] = {"error": "no key"}
|
||
continue
|
||
try:
|
||
r = requests.get(f"{base}/models", headers={"Authorization": f"Bearer {key}"},
|
||
timeout=30)
|
||
except Exception as e: # noqa: BLE001
|
||
print(f"{name:10s} СЕТЬ: {type(e).__name__}")
|
||
snap[name] = {"error": type(e).__name__}
|
||
continue
|
||
if r.status_code != 200:
|
||
print(f"{name:10s} HTTP {r.status_code}")
|
||
snap[name] = {"error": f"http {r.status_code}", "body": r.text[:200]}
|
||
continue
|
||
ids = sorted(m["id"] for m in r.json().get("data", []))
|
||
snap[name] = {"models": ids}
|
||
print(f"{name:10s} {len(ids):3d}: {', '.join(ids[:40])}")
|
||
if len(ids) > 40:
|
||
print(f"{'':10s} …ещё {len(ids) - 40}")
|
||
(OUT / "models-live.json").write_text(json.dumps(snap, ensure_ascii=False, indent=1),
|
||
encoding="utf-8")
|
||
print(f"\nснимок → {OUT / 'models-live.json'}")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|