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