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