1 changed files with 154 additions and 0 deletions
@ -0,0 +1,154 @@ |
|||
#!/usr/bin/env python3 |
|||
|
|||
""" |
|||
secretchat-api-example.py |
|||
|
|||
• Prints model IDs at start |
|||
• Shows which model handles each sentence, 5 sentences |
|||
|
|||
Requires: |
|||
pip install requests python-dotenv |
|||
""" |
|||
|
|||
import os |
|||
import random |
|||
import time |
|||
from typing import List, Union, Tuple, Optional |
|||
|
|||
import requests |
|||
from dotenv import load_dotenv |
|||
|
|||
|
|||
# ── API-key helper ─────────────────────────────────────────────────────────── |
|||
def load_api_key() -> str: |
|||
load_dotenv(os.path.join(os.path.expanduser("~"), ".secretlab.env")) |
|||
key = os.getenv("SECRETLAB_API_KEY") |
|||
if not key: |
|||
raise ValueError("SECRETLAB_API_KEY not found") |
|||
return key |
|||
|
|||
|
|||
# ── /api/models helper ─────────────────────────────────────────────────────── |
|||
def fetch_model_ids(api_key: str, base_url: str) -> List[str]: |
|||
resp = requests.get( |
|||
f"{base_url}/api/models", |
|||
headers={"Authorization": f"Bearer {api_key}"}, |
|||
timeout=300, |
|||
) |
|||
resp.raise_for_status() |
|||
raw: Union[list, dict] = resp.json() |
|||
|
|||
if isinstance(raw, dict): # unwrap {"models":[...]} or similar |
|||
for key in ("models", "data", "items", "result"): |
|||
if key in raw and isinstance(raw[key], list): |
|||
raw = raw[key] |
|||
break |
|||
|
|||
if not isinstance(raw, list): |
|||
raise RuntimeError("Unexpected /api/models response") |
|||
|
|||
ids: List[str] = [] |
|||
for item in raw: |
|||
if isinstance(item, str): |
|||
ids.append(item) |
|||
elif isinstance(item, dict): |
|||
if isinstance(item.get("model"), str): |
|||
ids.append(item["model"]) |
|||
elif isinstance(item.get("ollama"), dict) and isinstance( |
|||
item["ollama"].get("model"), str |
|||
): |
|||
ids.append(item["ollama"]["model"]) |
|||
if not ids: |
|||
raise RuntimeError("No model IDs found") |
|||
return ids |
|||
|
|||
|
|||
# ── classify helper ────────────────────────────────────────────────────────── |
|||
def classify( |
|||
sentence: str, |
|||
api_key: str, |
|||
base_url: str, |
|||
models: List[str], |
|||
retries: int = 6, |
|||
backoff: int = 2, |
|||
) -> Tuple[str, Optional[str]]: |
|||
"""Return (model_used, classification or None).""" |
|||
url = f"{base_url}/api/chat/completions" |
|||
|
|||
for attempt in range(1, retries + 1): |
|||
model = random.choice(models) |
|||
payload = { |
|||
"model": model, |
|||
"messages": [ |
|||
{ |
|||
"role": "system", |
|||
"content": ( |
|||
"Respond ONLY with 'Positive' or 'Negative'. " |
|||
"No other words or punctuation." |
|||
), |
|||
}, |
|||
{"role": "user", "content": f"Classify this:\n{sentence}"}, |
|||
], |
|||
"temperature": 0.0, |
|||
} |
|||
|
|||
try: |
|||
r = requests.post( |
|||
url, |
|||
headers={ |
|||
"Authorization": f"Bearer {api_key}", |
|||
"Content-Type": "application/json", |
|||
}, |
|||
json=payload, |
|||
timeout=300, |
|||
) |
|||
if r.status_code == 200: |
|||
result = r.json()["choices"][0]["message"]["content"].strip() |
|||
return model, result |
|||
print(f"API error {r.status_code}: {r.text}") |
|||
return model, None |
|||
except requests.exceptions.RequestException as e: |
|||
print(f"Network error ({attempt}/{retries}): {e}") |
|||
if attempt < retries: |
|||
time.sleep(backoff) |
|||
backoff *= 2 |
|||
else: |
|||
return model, None |
|||
|
|||
|
|||
# ── main loop ──────────────────────────────────────────────────────────────── |
|||
def main() -> None: |
|||
api_key = load_api_key() |
|||
BASE = "https://chat.secretlab.page" |
|||
models = fetch_model_ids(api_key, BASE) |
|||
|
|||
print("Models:") |
|||
for m in models: |
|||
print(m) |
|||
print("-" * 40, "\n") |
|||
|
|||
sentences = [ |
|||
"I love sunny days!", |
|||
"This is a bland sandwich.", |
|||
"I really hate waiting in long lines.", |
|||
"The meeting was okay, nothing special.", |
|||
"I am so excited about the upcoming holidays!", |
|||
] |
|||
|
|||
for run in range(1): # repeat 1 times |
|||
print(f"\n--- Run {run+1} ---\n") |
|||
|
|||
for idx, s in enumerate(sentences, 1): |
|||
model_used, res = classify(s, api_key, BASE, models) |
|||
|
|||
print(f"Sentence {idx}: {s}") |
|||
print(f"Model : {model_used}") |
|||
print(f"Result : {res or 'Failed'}\n") |
|||
|
|||
time.sleep(1) # optional pause between runs |
|||
|
|||
print("\nAll runs complete!\n") |
|||
|
|||
|
|||
if __name__ == "__main__": |
|||
main() |
Loading…
Reference in new issue