Ctrl K
ComunidadGuías…

tests/integration/get_together_endpoints.py

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
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()