import os import time from datetime import datetime from pathlib import Path from typing import Dict from dotenv import load_dotenv from together import Together # ------------------------------------------------------------------ # 1. Setup & Config # ------------------------------------------------------------------ # Resolve the project root directory (2 levels up) root_dir = Path(__file__).resolve().parents[2] load_dotenv() # Define the Report File Path in the Root Directory REPORT_FILE = root_dir / "together_status_report.md" API_KEY = os.getenv("TOGETHER_API_KEY") # ------------------------------------------------------------------ # 2. Model Dictionary # ------------------------------------------------------------------ TOGETHER_AI_MODELS = { # --- Qwen --- "Qwen2.5-14B-Instruct": { "id": "together-ai/Qwen/Qwen2.5-14B-Instruct", "provider": "together-ai", }, "Qwen2.5-72B-Instruct": { "id": "together-ai/Qwen/Qwen2.5-72B-Instruct", "provider": "together-ai", }, "Qwen2.5-72B-Instruct-Turbo": { "id": "together-ai/Qwen/Qwen2.5-72B-Instruct-Turbo", "provider": "together-ai", }, "Qwen2.5-7B-Instruct-Turbo": { "id": "together-ai/Qwen/Qwen2.5-7B-Instruct-Turbo", "provider": "together-ai", }, "Qwen2.5-VL-72B-Instruct": { "id": "together-ai/Qwen/Qwen2.5-VL-72B-Instruct", "provider": "together-ai", }, "Qwen3-235B-A22B-Instruct-2507-tput": { "id": "together-ai/Qwen/Qwen3-235B-A22B-Instruct-2507-tput", "provider": "together-ai", }, "Qwen3-235B-A22B-Thinking-2507": { "id": "together-ai/Qwen/Qwen3-235B-A22B-Thinking-2507", "provider": "together-ai", }, "Qwen3-235B-A22B-fp8-tput": { "id": "together-ai/Qwen/Qwen3-235B-A22B-fp8-tput", "provider": "together-ai", }, "Qwen3-Coder-480B-A35B-Instruct-FP8": { "id": "together-ai/Qwen/Qwen3-Coder-480B-A35B-Instruct-FP8", "provider": "together-ai", }, "Qwen3-Next-80B-A3B-Instruct": { "id": "together-ai/Qwen/Qwen3-Next-80B-A3B-Instruct", "provider": "together-ai", }, "Qwen3-Next-80B-A3B-Thinking": { "id": "together-ai/Qwen/Qwen3-Next-80B-A3B-Thinking", "provider": "together-ai", }, "Qwen3-VL-32B-Instruct": { "id": "together-ai/Qwen/Qwen3-VL-32B-Instruct", "provider": "together-ai", }, "Qwen3-VL-8B-Instruct": { "id": "together-ai/Qwen/Qwen3-VL-8B-Instruct", "provider": "together-ai", }, # --- ServiceNow-AI --- "Apriel-1.5-15b-Thinker": { "id": "together-ai/ServiceNow-AI/Apriel-1.5-15b-Thinker", "provider": "together-ai", }, "Apriel-1.6-15b-Thinker": { "id": "together-ai/ServiceNow-AI/Apriel-1.6-15b-Thinker", "provider": "together-ai", }, # --- arcee-ai --- "trinity-mini": { "id": "together-ai/arcee-ai/trinity-mini", "provider": "together-ai", }, # --- arize-ai --- "qwen-2-1.5b-instruct": { "id": "together-ai/arize-ai/qwen-2-1.5b-instruct", "provider": "together-ai", }, # --- deepcogito --- "cogito-v2-1-671b": { "id": "together-ai/deepcogito/cogito-v2-1-671b", "provider": "together-ai", }, "cogito-v2-preview-llama-109B-MoE": { "id": "together-ai/deepcogito/cogito-v2-preview-llama-109B-MoE", "provider": "together-ai", }, "cogito-v2-preview-llama-405B": { "id": "together-ai/deepcogito/cogito-v2-preview-llama-405B", "provider": "together-ai", }, "cogito-v2-preview-llama-70B": { "id": "together-ai/deepcogito/cogito-v2-preview-llama-70B", "provider": "together-ai", }, # --- deepseek-ai --- "DeepSeek-R1": { "id": "together-ai/deepseek-ai/DeepSeek-R1", "provider": "together-ai", }, "DeepSeek-R1-0528-tput": { "id": "together-ai/deepseek-ai/DeepSeek-R1-0528-tput", "provider": "together-ai", }, "DeepSeek-R1-Distill-Llama-70B": { "id": "together-ai/deepseek-ai/DeepSeek-R1-Distill-Llama-70B", "provider": "together-ai", }, "DeepSeek-V3.1": { "id": "together-ai/deepseek-ai/DeepSeek-V3.1", "provider": "together-ai", }, # --- essentialai --- "rnj-1-instruct": { "id": "together-ai/essentialai/rnj-1-instruct", "provider": "together-ai", }, # --- google --- "gemma-2b-it-Ishan": { "id": "together-ai/google/gemma-2b-it-Ishan", "provider": "together-ai", }, "gemma-3n-E4B-it": { "id": "together-ai/google/gemma-3n-E4B-it", "provider": "together-ai", }, # --- marin-community --- "marin-8b-instruct": { "id": "together-ai/marin-community/marin-8b-instruct", "provider": "together-ai", }, # --- meta-llama --- "Llama-3-70b-hf": { "id": "together-ai/meta-llama/Llama-3-70b-hf", "provider": "together-ai", }, "Llama-3.1-405B-Instruct": { "id": "together-ai/meta-llama/Llama-3.1-405B-Instruct", "provider": "together-ai", }, "Llama-3.2-1B-Instruct": { "id": "together-ai/meta-llama/Llama-3.2-1B-Instruct", "provider": "together-ai", }, "Llama-3.2-3B-Instruct-Turbo": { "id": "together-ai/meta-llama/Llama-3.2-3B-Instruct-Turbo", "provider": "together-ai", }, "Llama-3.3-70B-Instruct-Turbo": { "id": "together-ai/meta-llama/Llama-3.3-70B-Instruct-Turbo", "provider": "together-ai", }, "Llama-4-Maverick-17B-128E-Instruct-FP8": { "id": "together-ai/meta-llama/Llama-4-Maverick-17B-128E-Instruct-FP8", "provider": "together-ai", }, "Llama-4-Scout-17B-16E-Instruct": { "id": "together-ai/meta-llama/Llama-4-Scout-17B-16E-Instruct", "provider": "together-ai", }, "Meta-Llama-3-8B-Instruct": { "id": "together-ai/meta-llama/Meta-Llama-3-8B-Instruct", "provider": "together-ai", }, "Meta-Llama-3-8B-Instruct-Lite": { "id": "together-ai/meta-llama/Meta-Llama-3-8B-Instruct-Lite", "provider": "together-ai", }, "Meta-Llama-3.1-405B-Instruct-Turbo": { "id": "together-ai/meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo", "provider": "together-ai", }, "Meta-Llama-3.1-70B-Instruct-Reference": { "id": "together-ai/meta-llama/Meta-Llama-3.1-70B-Instruct-Reference", "provider": "together-ai", }, "Meta-Llama-3.1-70B-Instruct-Turbo": { "id": "together-ai/meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo", "provider": "together-ai", }, "Meta-Llama-3.1-8B-Instruct-Reference": { "id": "together-ai/meta-llama/Meta-Llama-3.1-8B-Instruct-Reference", "provider": "together-ai", }, "Meta-Llama-3.1-8B-Instruct-Turbo": { "id": "together-ai/meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo", "provider": "together-ai", }, # --- mistralai --- "Ministral-3-14B-Instruct-2512": { "id": "together-ai/mistralai/Ministral-3-14B-Instruct-2512", "provider": "together-ai", }, "Mistral-7B-Instruct-v0.2": { "id": "together-ai/mistralai/Mistral-7B-Instruct-v0.2", "provider": "together-ai", }, "Mistral-7B-Instruct-v0.3": { "id": "together-ai/mistralai/Mistral-7B-Instruct-v0.3", "provider": "together-ai", }, "Mistral-Small-24B-Instruct-2501": { "id": "together-ai/mistralai/Mistral-Small-24B-Instruct-2501", "provider": "together-ai", }, "Mixtral-8x7B-Instruct-v0.1": { "id": "together-ai/mistralai/Mixtral-8x7B-Instruct-v0.1", "provider": "together-ai", }, # --- moonshotai --- "Kimi-K2-Instruct-0905": { "id": "together-ai/moonshotai/Kimi-K2-Instruct-0905", "provider": "together-ai", }, "Kimi-K2-Thinking": { "id": "together-ai/moonshotai/Kimi-K2-Thinking", "provider": "together-ai", }, # --- nvidia --- "NVIDIA-Nemotron-Nano-9B-v2": { "id": "together-ai/nvidia/NVIDIA-Nemotron-Nano-9B-v2", "provider": "together-ai", }, # --- openai --- "gpt-oss-120b": { "id": "together-ai/openai/gpt-oss-120b", "provider": "together-ai", }, "gpt-oss-20b": { "id": "together-ai/openai/gpt-oss-20b", "provider": "together-ai", }, # --- scb10x --- "scb10x-typhoon-2-1-gemma3-12b": { "id": "together-ai/scb10x/scb10x-typhoon-2-1-gemma3-12b", "provider": "together-ai", }, # --- togethercomputer --- "MoA-1": { "id": "together-ai/togethercomputer/MoA-1", "provider": "together-ai", }, "MoA-1-Turbo": { "id": "together-ai/togethercomputer/MoA-1-Turbo", "provider": "together-ai", }, "Refuel-Llm-V2": { "id": "together-ai/togethercomputer/Refuel-Llm-V2", "provider": "together-ai", }, "Refuel-Llm-V2-Small": { "id": "together-ai/togethercomputer/Refuel-Llm-V2-Small", "provider": "together-ai", }, # --- zai-org --- "GLM-4.5-Air-FP8": { "id": "together-ai/zai-org/GLM-4.5-Air-FP8", "provider": "together-ai", }, "GLM-4.6": { "id": "together-ai/zai-org/GLM-4.6", "provider": "together-ai", }, "GLM-4.7": { "id": "together-ai/zai-org/GLM-4.7", "provider": "together-ai", }, } # ------------------------------------------------------------------ # 3. Report Management # ------------------------------------------------------------------ def update_markdown(result: Dict): """ Reads the existing MD file at REPORT_FILE, updates entries based on Endpoint ID, and writes back to disk. """ # Define Layout header = "| Provider | Model Name | Endpoint ID | Status | Last Run |" divider = "| :--- | :--- | :--- | :--- | :--- |" # Storage for rows: {endpoint_id: line_string} existing_rows = {} # 1. Read existing if REPORT_FILE.exists(): try: with open(REPORT_FILE, "r", encoding="utf-8") as f: lines = f.readlines() for line in lines: if ( line.strip().startswith("|") and "Endpoint ID" not in line and ":---" not in line ): parts = [p.strip() for p in line.split("|")] if len(parts) >= 6: # parts[0] is empty due to leading | # parts[3] is Endpoint ID row_id = parts[3].strip("`") existing_rows[row_id] = line.strip() except Exception as e: print(f"⚠️ Could not read existing report: {e}") # 2. Format the new result row status_icon = result["status_icon"] status_msg = result["status_msg"] full_status = f"{status_icon} {status_msg}" row_str = ( f"| {result['provider']} | {result['name']} | `{result['full_id']}` | " f"{full_status} | {result['timestamp']} |" ) # Update dictionary (upsert) existing_rows[result["full_id"]] = row_str # 3. Write Back try: with open(REPORT_FILE, "w", encoding="utf-8") as f: f.write("# 📡 Together AI Endpoint Status\n\n") f.write(header + "\n") f.write(divider + "\n") # Sort by Provider, then Model Name sorted_rows = sorted( existing_rows.values(), key=lambda x: x.split("|")[1].strip() ) for row in sorted_rows: f.write(row + "\n") except Exception as e: print(f"❌ Failed to write report to {REPORT_FILE}: {e}") # ------------------------------------------------------------------ # 4. Testing Logic # ------------------------------------------------------------------ def endpoints(): if not API_KEY: print("❌ Error: TOGETHER_API_KEY not found in environment.") return client = Together(api_key=API_KEY) print(f"📂 Report File: {REPORT_FILE}") print(f"🚀 Starting Test for {len(TOGETHER_AI_MODELS)} endpoints...\n") for friendly_name, config in TOGETHER_AI_MODELS.items(): full_id = config["id"] provider = config["provider"] # LOGIC: Strip "together-ai/" prefix to get actual API endpoint string actual_api_model = full_id.replace("together-ai/", "") print(f"Testing: {friendly_name}...", end=" ", flush=True) result_payload = { "name": friendly_name, "provider": provider, "full_id": full_id, "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M"), "status_icon": "❓", "status_msg": "Unknown", } try: # Perform a minimal generation request stream = client.chat.completions.create( model=actual_api_model, messages=[{"role": "user", "content": "Hello"}], max_tokens=5, stream=True, ) # Consume first chunk to verify life received_content = False for chunk in stream: if chunk.choices and chunk.choices[0].delta.content: received_content = True break # One chunk is enough if received_content: print("✅ OK") result_payload["status_icon"] = "✅" result_payload["status_msg"] = "Online" else: print("⚠️ No Content") result_payload["status_icon"] = "⚠️" result_payload["status_msg"] = "Empty Response" except Exception as e: err_str = str(e).lower() if ( "404" in err_str or "not found" in err_str or "model_not_available" in err_str or "does not exist" in err_str ): print("💀 Dead") result_payload["status_icon"] = "💀" result_payload["status_msg"] = "Dead / 404" elif "rate limit" in err_str or "429" in err_str: print("⏳ Rate Limit") result_payload["status_icon"] = "⏳" result_payload["status_msg"] = "Rate Limited" else: print(f"❌ Error: {str(e)[:20]}...") result_payload["status_icon"] = "❌" result_payload["status_msg"] = f"Error: {str(e)[:30]}" # Update the file immediately after each test update_markdown(result_payload) # Sleep briefly time.sleep(1.0) if __name__ == "__main__": endpoints()