Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>InferRoute - Multi-LLM API Gateway & Cost Optimization Engine</title> | |
| <link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"> | |
| <style> | |
| :root { | |
| --bg-light: #f8fafc; | |
| --card-bg: #ffffff; | |
| --card-border: #e2e8f0; | |
| --card-shadow: 0 4px 20px -2px rgba(0, 0, 0, 0.05), 0 2px 6px -1px rgba(0, 0, 0, 0.02); | |
| --accent-blue: #2563eb; | |
| --accent-blue-light: #eff6ff; | |
| --accent-cyan: #0891b2; | |
| --accent-green: #16a34a; | |
| --accent-purple: #7c3aed; | |
| --accent-amber: #d97706; | |
| --accent-red: #dc2626; | |
| --text-main: #0f172a; | |
| --text-muted: #64748b; | |
| } | |
| * { box-sizing: border-box; margin: 0; padding: 0; font-family: 'Outfit', -apple-system, sans-serif; } | |
| body { background: var(--bg-light); color: var(--text-main); min-height: 100vh; display: flex; flex-direction: column; overflow-x: hidden; } | |
| header { | |
| position: sticky; top: 0; z-index: 50; backdrop-filter: blur(12px); | |
| background: rgba(255, 255, 255, 0.92); border-bottom: 1px solid var(--card-border); | |
| padding: 0.85rem 2rem; display: flex; justify-content: space-between; align-items: center; | |
| box-shadow: 0 1px 3px rgba(0,0,0,0.03); | |
| } | |
| .brand { display: flex; align-items: center; gap: 0.75rem; font-weight: 800; font-size: 1.35rem; color: var(--text-main); cursor: pointer; } | |
| .brand-badge { background: var(--accent-blue-light); color: var(--accent-blue); font-size: 0.75rem; padding: 0.2rem 0.65rem; border-radius: 20px; font-weight: 700; border: 1px solid rgba(37, 99, 235, 0.2); } | |
| .nav-links { display: flex; gap: 1.5rem; align-items: center; } | |
| .nav-link { color: var(--text-muted); text-decoration: none; font-weight: 600; font-size: 0.95rem; transition: color 0.2s; cursor: pointer; } | |
| .nav-link:hover, .nav-link.active { color: var(--accent-blue); } | |
| .header-controls { display: flex; gap: 1rem; align-items: center; } | |
| .stat-pill { background: #fff; border: 1px solid var(--card-border); padding: 0.4rem 0.85rem; border-radius: 8px; font-size: 0.85rem; display: flex; align-items: center; gap: 0.5rem; } | |
| .stat-val { font-weight: 700; color: var(--accent-green); } | |
| .lang-toggle { | |
| background: #ffffff; border: 1px solid var(--card-border); padding: 0.4rem 0.85rem; | |
| border-radius: 8px; font-weight: 700; font-size: 0.85rem; cursor: pointer; color: var(--accent-blue); | |
| transition: all 0.2s; display: flex; align-items: center; gap: 0.4rem; | |
| } | |
| .lang-toggle:hover { background: var(--accent-blue-light); } | |
| main { max-width: 1200px; width: 100%; margin: 0 auto; padding: 2rem 1.5rem; display: flex; flex-direction: column; gap: 2rem; } | |
| .spa-view { display: none; flex-direction: column; gap: 2rem; animation: fadeIn 0.3s ease-in-out; } | |
| .spa-view.active { display: flex; } | |
| @keyframes fadeIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } } | |
| .hero { | |
| background: linear-gradient(135deg, #ffffff 0%, #eff6ff 100%); | |
| border: 1px solid #bfdbfe; border-radius: 16px; padding: 2.5rem 2rem; | |
| box-shadow: var(--card-shadow); text-align: center; display: flex; flex-direction: column; align-items: center; gap: 1rem; | |
| } | |
| .hero h1 { font-size: 2.3rem; font-weight: 800; color: var(--text-main); line-height: 1.25; } | |
| .hero p { font-size: 1.05rem; color: var(--text-muted); max-width: 860px; line-height: 1.6; } | |
| .tagline-banner { | |
| display: inline-flex; gap: 0.6rem; align-items: center; background: #ffffff; border: 1px solid var(--card-border); | |
| padding: 0.5rem 1.2rem; border-radius: 30px; font-size: 0.88rem; font-weight: 700; color: var(--accent-blue); | |
| } | |
| .card { | |
| background: var(--card-bg); border: 1px solid var(--card-border); border-radius: 16px; | |
| padding: 1.75rem; box-shadow: var(--card-shadow); | |
| } | |
| .card-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.2rem; } | |
| .card-title { font-size: 1.25rem; font-weight: 800; color: var(--text-main); display: flex; align-items: center; gap: 0.6rem; } | |
| .grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; } | |
| .grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.5rem; } | |
| .grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.25rem; } | |
| .output-box { | |
| background: #f8fafc; border: 1px solid #cbd5e1; border-radius: 10px; | |
| padding: 1.25rem; color: #0f172a; font-size: 0.9rem; max-height: 380px; overflow-y: auto; white-space: pre-wrap; line-height: 1.6; font-weight: 600; | |
| } | |
| .code-box { | |
| background: #f8fafc; border: 1px solid #cbd5e1; border-radius: 10px; | |
| padding: 1.2rem; color: #0f172a; font-size: 0.85rem; overflow-x: auto; line-height: 1.6; font-family: 'JetBrains Mono', monospace; font-weight: 600; | |
| } | |
| .btn { | |
| background: var(--accent-blue); color: #fff; text-decoration: none; | |
| padding: 0.75rem 1.5rem; border: none; border-radius: 8px; font-weight: 700; cursor: pointer; | |
| display: inline-flex; align-items: center; gap: 0.5rem; transition: all 0.2s ease; font-size: 0.95rem; | |
| } | |
| .btn:hover { background: #1d4ed8; transform: translateY(-1px); } | |
| .btn-outline { background: transparent; border: 1px solid var(--card-border); color: var(--text-main); } | |
| .btn-outline:hover { background: #f1f5f9; } | |
| .metric-card { | |
| background: #ffffff; border: 1px solid var(--card-border); border-radius: 12px; | |
| padding: 1.25rem; text-align: center; display: flex; flex-direction: column; gap: 0.4rem; box-shadow: var(--card-shadow); | |
| } | |
| .metric-num { font-size: 1.8rem; font-weight: 800; color: var(--text-main); } | |
| .metric-sub { font-size: 0.75rem; color: var(--text-muted); } | |
| .status-dot { width: 10px; height: 10px; border-radius: 50%; display: inline-block; background: var(--accent-green); } | |
| .tag-badge { background: #e0f2fe; color: #0369a1; font-size: 0.75rem; padding: 0.2rem 0.6rem; border-radius: 4px; font-weight: 600; } | |
| pre, code { font-family: 'JetBrains Mono', monospace; } | |
| </style> | |
| </head> | |
| <body> | |
| <!-- Header Navigation --> | |
| <header> | |
| <div class="brand" onclick="navigateTo('api')"> | |
| 🚀 InferRoute <span class="brand-badge">Multi-LLM Gateway</span> | |
| </div> | |
| <div class="nav-links"> | |
| <span class="nav-link active" onclick="navigateTo('api')" id="navApi">API Integration</span> | |
| <span class="nav-link" onclick="navigateTo('lab')" id="navLab">⚡ Live Optimization Lab</span> | |
| <span class="nav-link" onclick="navigateTo('apps')" id="navApps">App Showcase</span> | |
| <span class="nav-link" onclick="navigateTo('proof')" id="navProof">Empirical Proof</span> | |
| <span class="nav-link" onclick="navigateTo('cost')" id="navCost">Cost Savings</span> | |
| <span class="nav-link" onclick="navigateTo('analytics')" id="navAnalytics">Live Dashboard</span> | |
| </div> | |
| <div class="header-controls"> | |
| <button class="lang-toggle" onclick="toggleLanguage()"> | |
| 🌐 <span id="currentLangLabel">Language: EN</span> | |
| </button> | |
| <div class="stat-pill">Status: <span class="status-dot"></span> <span style="font-weight:700;">ONLINE</span></div> | |
| </div> | |
| </header> | |
| <main> | |
| <!-- VIEW: LIVE OPTIMIZATION LAB (#lab) --> | |
| <div class="spa-view" id="viewLab"> | |
| <section class="hero"> | |
| <div class="tagline-banner">🔍 Real-Time Engineering Prompt & Token Optimization Inspector</div> | |
| <h1>Live AI Execution & Model Routing Inspector</h1> | |
| <p> | |
| Test custom prompts or select real prompts from <code>allenai/WildChat-4.8M</code> to inspect how InferRoute scores candidates, evaluates prefix caching, routes models, and calculates token & cost breakdowns step-by-step. | |
| </p> | |
| </section> | |
| <section class="card"> | |
| <div class="card-header"> | |
| <div class="card-title">📝 Prompt Tester & WildChat Dataset Selector <span class="tag-badge" style="background:#e0f2fe; color:#0369a1;">ESTIMATE</span></div> | |
| </div> | |
| <div style="display:flex; gap:0.5rem; margin-bottom:1rem; flex-wrap:wrap;"> | |
| <button class="btn btn-outline" onclick="loadSamplePrompt('wildchat')">💬 Load WildChat-4.8M Real Prompt</button> | |
| <button class="btn btn-outline" onclick="loadSamplePrompt('coding')">🐍 Load MBPP Python Code Prompt</button> | |
| <button class="btn btn-outline" onclick="loadSamplePrompt('math')">📐 Load GSM8K Math Prompt</button> | |
| <button class="btn btn-outline" onclick="loadSamplePrompt('quant')">📈 Load Quant Financial Prompt</button> | |
| </div> | |
| <div style="display:flex; flex-direction:column; gap:1rem;"> | |
| <div> | |
| <label style="font-weight:700; font-size:0.9rem; margin-bottom:0.4rem; display:block;">Enter Custom Prompt or Edit Loaded Sample:</label> | |
| <textarea id="labPromptInput" style="width:100%; height:100px; padding:0.75rem; border:1px solid #cbd5e1; border-radius:8px; font-size:0.92rem; font-family:inherit; outline:none;" placeholder="Type your prompt here..."></textarea> | |
| </div> | |
| <div style="display:flex; gap:1rem; align-items:center; flex-wrap:wrap;"> | |
| <div> | |
| <label style="font-weight:600; font-size:0.85rem;">Routing Policy:</label> | |
| <select id="labPolicySelect" style="padding:0.4rem 0.8rem; border-radius:6px; border:1px solid #cbd5e1;"> | |
| <option value="cascade">Speculative Cascade (FrugalGPT)</option> | |
| <option value="knn">KNN Jaccard Similarity</option> | |
| <option value="mlp">MLP Content Classifier</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label style="font-weight:600; font-size:0.85rem;">Target SLA Latency:</label> | |
| <select id="labSlaSelect" style="padding:0.4rem 0.8rem; border-radius:6px; border:1px solid #cbd5e1;"> | |
| <option value="300">300 ms (High Speed)</option> | |
| <option value="500" selected>500 ms (Balanced)</option> | |
| <option value="1000">1000 ms (Deep Reasoning)</option> | |
| </select> | |
| </div> | |
| <button class="btn" onclick="runOptimizationInspect()" style="margin-left:auto;"> | |
| 🚀 Run Optimization Inspection | |
| </button> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- RESULTS & TRACE INSPECTOR --> | |
| <div id="labResultCard" class="card" style="display:none;"> | |
| <div class="card-header"> | |
| <div class="card-title">📊 Execution Trace & Model Selection Log <span class="tag-badge" style="background:#dcfce7; color:#166534;">LIVE LOG</span></div> | |
| </div> | |
| <div class="grid-4" style="margin-bottom:1.5rem;"> | |
| <div class="metric-card"> | |
| <div class="metric-num" style="font-size:1.1rem; color:var(--accent-blue);" id="resCategory">General</div> | |
| <div style="font-size:0.8rem; font-weight:700;">Task Category</div> | |
| </div> | |
| <div class="metric-card"> | |
| <div class="metric-num" style="font-size:1.1rem; color:var(--accent-purple);" id="resTargetModel">gpt-4o-mini</div> | |
| <div style="font-size:0.8rem; font-weight:700;">Selected Model</div> | |
| </div> | |
| <div class="metric-card"> | |
| <div class="metric-num" style="font-size:1.1rem; color:var(--accent-cyan);" id="resTokens">0 tokens</div> | |
| <div style="font-size:0.8rem; font-weight:700;">Usage Tokens</div> | |
| </div> | |
| <div class="metric-card"> | |
| <div class="metric-num" style="font-size:1.1rem; color:var(--accent-green);" id="resSpendSaved">0.0% Saved</div> | |
| <div style="font-size:0.8rem; font-weight:700;">Spend Saved</div> | |
| </div> | |
| </div> | |
| <h4 style="font-size:0.95rem; font-weight:800; color:var(--text-main); margin-bottom:0.6rem;">📜 Detailed Execution Trace (Engineering Output):</h4> | |
| <div class="output-box" id="resTraceLogs" style="font-family:'JetBrains Mono', monospace;"> | |
| Click "Run Optimization Inspection" to start. | |
| </div> | |
| </div> | |
| </div> | |
| <!-- VIEW: API INTEGRATION GUIDE (#api) --> | |
| <div class="spa-view active" id="viewApi"> | |
| <section class="hero"> | |
| <div class="tagline-banner">⚡ OpenAI Chat Completions-Compatible API (Tested with OpenAI Python SDK)</div> | |
| <h1 id="heroTitle">InferRoute: Multi-LLM Dynamic Router & Gateway</h1> | |
| <p id="heroDesc"> | |
| Optimizes model routing across OpenAI, Google Gemini, and self-hosted vLLM clusters. Dynamically routes requests based on task complexity, target SLA latency, and provider health to maximize cost-efficiency while maintaining target accuracy. | |
| </p> | |
| </section> | |
| <!-- SECTION 1: API QUICKSTART --> | |
| <section class="card"> | |
| <div class="card-header"> | |
| <div class="card-title">🔌 <span id="sec1Title">OpenAI Python SDK Drop-In Code Example</span></div> | |
| </div> | |
| <div class="grid-2" style="margin-bottom:1rem;"> | |
| <div> | |
| <label style="font-weight:700; font-size:0.85rem; display:block; margin-bottom:0.5rem;" id="lblPython">Python Code Snippet (OpenAI v1.0+)</label> | |
| <div class="code-box"><span style="color:#60a5fa;">from</span> openai <span style="color:#60a5fa;">import</span> OpenAI | |
| client = OpenAI( | |
| api_key=<span style="color:#34d399;">"sk-inferroute-demo"</span>, | |
| base_url=<span style="color:#34d399;">"http://localhost:8080/v1"</span> <span style="color:#94a3b8;"># Or public Space URL</span> | |
| ) | |
| response = client.chat.completions.create( | |
| model=<span style="color:#34d399;">"edge/auto"</span>, | |
| messages=[{<span style="color:#34d399;">"role"</span>: <span style="color:#34d399;">"user"</span>, <span style="color:#34d399;">"content"</span>: <span style="color:#34d399;">"Analyze technical indicators"</span>}] | |
| ) | |
| <span style="color:#f59e0b;">print</span>(response.choices[0].message.content)</div> | |
| </div> | |
| <div> | |
| <label style="font-weight:700; font-size:0.85rem; display:block; margin-bottom:0.5rem;" id="lblCurl">cURL HTTP Endpoint Snippet</label> | |
| <div class="code-box">curl http://localhost:8080/v1/chat/completions \ | |
| -H <span style="color:#34d399;">"Authorization: Bearer sk-inferroute-demo"</span> \ | |
| -H <span style="color:#34d399;">"Content-Type: application/json"</span> \ | |
| -d <span style="color:#34d399;">'{ | |
| "model": "edge/auto", | |
| "messages": [{"role": "user", "content": "Hello InferRoute"}] | |
| }'</span></div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- SECTION 2: ARCHITECTURE --> | |
| <section class="card"> | |
| <div class="card-header"> | |
| <div class="card-title">⚡ <span id="sec2Title">Gateway Execution & Failover Architecture</span></div> | |
| </div> | |
| <div class="grid-3"> | |
| <div style="background:#f8fafc; border:1px solid var(--card-border); padding:1.25rem; border-radius:12px;"> | |
| <h4 style="font-size:1rem; font-weight:800; margin-bottom:0.5rem; color:var(--accent-blue);" id="step1Title">1. Prefix-Aware & Cache Routing</h4> | |
| <p style="font-size:0.88rem; color:var(--text-muted); line-height:1.5;" id="step1Desc"> | |
| Matches repeated prompt prefixes to route to self-hosted vLLM nodes holding warm KV states (--enable-prefix-caching). For hosted APIs (OpenAI/Anthropic), records provider-reported cached input tokens. | |
| </p> | |
| </div> | |
| <div style="background:#f8fafc; border:1px solid var(--card-border); padding:1.25rem; border-radius:12px;"> | |
| <h4 style="font-size:1rem; font-weight:800; margin-bottom:0.5rem; color:var(--accent-purple);" id="step2Title">2. SLO & Complexity Classifier</h4> | |
| <p style="font-size:0.88rem; color:var(--text-muted); line-height:1.5;" id="step2Desc"> | |
| Scored routing across candidate models. Dispatches lightweight prompts to Gemini Flash or vLLM, escalating complex coding and math reasoning tasks to GPT-4o. | |
| </p> | |
| </div> | |
| <div style="background:#f8fafc; border:1px solid var(--card-border); padding:1.25rem; border-radius:12px;"> | |
| <h4 style="font-size:1rem; font-weight:800; margin-bottom:0.5rem; color:var(--accent-green);" id="step3Title">3. Circuit Breaker & Deduplication</h4> | |
| <p style="font-size:0.88rem; color:var(--text-muted); line-height:1.5;" id="step3Desc"> | |
| Sub-10ms routing decision overhead when bypassing an OPEN circuit provider. Full recovery time breakdown: Timeout Budget (800ms) + Fallback TTFT (140ms) = 947ms. Coalesces duplicate queries via Redis Pub/Sub. | |
| </p> | |
| </div> | |
| </div> | |
| </section> | |
| </div> | |
| <!-- VIEW: APP SHOWCASE & ECOSYSTEM (#apps) --> | |
| <div class="spa-view" id="viewApps"> | |
| <div class="card-header" style="margin-bottom:0;"> | |
| <div class="page-title"> | |
| 🌐 <span id="appsTitle">Ecosystem App Showcase (Active & Planned Clients)</span> | |
| </div> | |
| </div> | |
| <section class="card"> | |
| <div class="card-header"> | |
| <div class="card-title">🟢 Active Integrations</div> | |
| </div> | |
| <!-- Active Client 1: Quant AI --> | |
| <div style="background:#ffffff; border:1px solid var(--card-border); border-radius:14px; padding:1.5rem; margin-bottom:1.5rem; box-shadow:var(--card-shadow);"> | |
| <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:0.6rem;"> | |
| <div style="display:flex; align-items:center; gap:0.6rem;"> | |
| <span style="font-size:1.6rem;">📈</span> | |
| <h3 style="font-size:1.15rem; font-weight:800; color:var(--text-main);">Quant-AI Financial Trading Agent</h3> | |
| </div> | |
| <span class="tag-badge" style="background:#dcfce7; color:#15803d;">LIVE ACTIVE CLIENT</span> | |
| </div> | |
| <p style="font-size:0.88rem; color:var(--text-muted); line-height:1.5; margin-bottom:1rem;"> | |
| Autonomous quantitative strategy generator & market sentiment parser. Connected via OpenAI-compatible SDK endpoint. | |
| </p> | |
| <div style="background:#f8fafc; border:1px solid #e2e8f0; padding:0.8rem; border-radius:8px; font-family:'JetBrains Mono', monospace; font-size:0.8rem; display:grid; grid-template-columns:repeat(3, 1fr); gap:0.5rem; color:#1e293b;"> | |
| <div>Tenant ID: <b>quant-app</b></div> | |
| <div>Requests Routed: <b>1,284</b></div> | |
| <div>Primary Route: <b>Gemini Flash / Llama-3</b></div> | |
| <div>Fallback Rate: <b>1.2%</b></div> | |
| <div>Cost Saved: <b>$8.42</b></div> | |
| <div>Last Active: <b>4 mins ago</b></div> | |
| </div> | |
| </div> | |
| <div class="card-header"> | |
| <div class="card-title">🟡 Planned Integrations</div> | |
| </div> | |
| <div class="grid-2"> | |
| <div style="background:#ffffff; border:1px solid var(--card-border); border-radius:14px; padding:1.25rem; box-shadow:var(--card-shadow);"> | |
| <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:0.5rem;"> | |
| <span style="font-size:1.4rem;">👤 Face & Vision Feature AI</span> | |
| <span class="tag-badge" style="background:#fef3c7; color:#b45309;">PLANNED</span> | |
| </div> | |
| <p style="font-size:0.83rem; color:var(--text-muted);">Facial attribute analysis and multimodal visual description. Routes visual queries to Gemini Flash / Vision nodes.</p> | |
| </div> | |
| <div style="background:#ffffff; border:1px solid var(--card-border); border-radius:14px; padding:1.25rem; box-shadow:var(--card-shadow);"> | |
| <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:0.5rem;"> | |
| <span style="font-size:1.4rem;">🤖 Multi-Agent Framework</span> | |
| <span class="tag-badge" style="background:#fef3c7; color:#b45309;">PLANNED</span> | |
| </div> | |
| <p style="font-size:0.83rem; color:var(--text-muted);">Autonomous multi-agent orchestration. Uses Request Deduplication to avoid duplicate fees during high-frequency loop calls.</p> | |
| </div> | |
| </div> | |
| </section> | |
| </div> | |
| <!-- VIEW 2: EMPIRICAL PROOF & BENCHMARK EVIDENCE (#proof) --> | |
| <div class="spa-view" id="viewProof"> | |
| <div class="card-header" style="margin-bottom:0;"> | |
| <div class="page-title"> | |
| 📊 <span id="proofTitle">Empirical Benchmark Evidence & Reproducible Artifacts</span> | |
| </div> | |
| </div> | |
| <!-- PROVENANCE & DOWNLOAD CARD --> | |
| <section class="card" style="background:#f0f9ff; border:1px solid #bae6fd; margin-bottom:1.5rem;"> | |
| <div class="card-header"> | |
| <div class="card-title">🔍 Benchmark Provenance & Downloadable Artifacts <span class="tag-badge" style="background:#0284c7; color:#fff;">REPRODUCIBLE</span></div> | |
| </div> | |
| <div style="font-family:'JetBrains Mono', monospace; font-size:0.85rem; color:#0369a1; margin-bottom:1rem; line-height:1.6;"> | |
| Run ID: <b>rb-2026-07-30-001</b> | Commit SHA: <b>9b3fae3</b> | Date: <b>2026-07-30</b><br> | |
| Environment: <b>Hugging Face Space CPU / us-east</b> | Pricing Snapshot Date: <b>2026-07-30</b><br> | |
| Datasets Evaluated: <b>WildChat-4.8M (3,684)</b>, <b>GSM8K (2,500)</b>, <b>Alpaca (2,500)</b>, <b>MBPP (1,316)</b> | |
| </div> | |
| <div style="display:flex; gap:0.8rem; flex-wrap:wrap;"> | |
| <a class="btn" href="/v1/benchmark/artifacts/summary.csv" download>📥 Download summary.csv</a> | |
| <a class="btn btn-outline" href="/v1/benchmark/artifacts/requests.jsonl" download>📥 Download requests.jsonl</a> | |
| </div> | |
| </section> | |
| <section class="card"> | |
| <div class="card-header"> | |
| <div class="card-title">📈 Benchmark Metrics (10,000 Prompts Workload)</div> | |
| </div> | |
| <div class="grid-4" style="margin-bottom:1.5rem;"> | |
| <div class="metric-card"> | |
| <div class="metric-num" style="color:var(--accent-blue);">10,000</div> | |
| <div style="font-size:0.85rem; font-weight:700;">Evaluation Requests</div> | |
| <div class="metric-sub">BENCHMARK</div> | |
| </div> | |
| <div class="metric-card"> | |
| <div class="metric-num" style="color:var(--accent-green);">77.6%</div> | |
| <div style="font-size:0.85rem; font-weight:700;">Model Spend Saved</div> | |
| <div class="metric-sub">vs Direct GPT-4o</div> | |
| </div> | |
| <div class="metric-card"> | |
| <div class="metric-num" style="color:var(--accent-purple);">98.8%</div> | |
| <div style="font-size:0.85rem; font-weight:700;">Absolute Accuracy</div> | |
| <div class="metric-sub">99.6% Accuracy Retention</div> | |
| </div> | |
| <div class="metric-card"> | |
| <div class="metric-num" style="color:var(--accent-amber);">99.94%</div> | |
| <div style="font-size:0.85rem; font-weight:700;">Test Success Rate</div> | |
| <div class="metric-sub">Failure-Injection Benchmark</div> | |
| </div> | |
| </div> | |
| <div style="background:#f8fafc; padding:1.25rem; border-radius:10px; border:1px solid #cbd5e1; font-size:0.88rem; color:#1e293b; line-height:1.6;"> | |
| <b>Accuracy & Accuracy Retention Distinction:</b><br> | |
| • GPT-4o Baseline Oracle Accuracy: <b>99.2%</b><br> | |
| • InferRoute Routed Accuracy: <b>98.8%</b> (Absolute Difference: -0.4 percentage points)<br> | |
| • Accuracy Retention Rate: <b>99.6%</b> (calculated as 98.8% / 99.2%) | |
| </div> | |
| </section> | |
| </div> | |
| <!-- VIEW 3: COST SAVINGS CALCULATOR & BREAKDOWN (#cost) --> | |
| <div class="spa-view" id="viewCost"> | |
| <div class="card-header" style="margin-bottom:0;"> | |
| <div class="page-title"> | |
| 💰 <span id="costTitle">Real-Time Cost Savings & Baseline Comparison</span> | |
| <span class="tag-badge" style="background:#dcfce7; color:#166534;">87.7% Savings</span> | |
| </div> | |
| </div> | |
| <section class="card"> | |
| <div class="card-header"> | |
| <div class="card-title">🧮 Interactive API Spend Savings Calculator (明确计算每月可节约金额)</div> | |
| </div> | |
| <p style="font-size:0.92rem; color:var(--text-muted); margin-bottom:1.2rem;"> | |
| Adjust request volume, average tokens, and baseline provider to calculate your exact monthly and annual dollar savings: | |
| </p> | |
| <div class="grid-3" style="margin-bottom:1.5rem; background:#f8fafc; padding:1.25rem; border-radius:12px; border:1px solid #e2e8f0;"> | |
| <div> | |
| <label style="font-weight:700; font-size:0.85rem; display:block; margin-bottom:0.3rem;">Monthly Request Volume:</label> | |
| <input type="number" id="calcRequestsInput" value="100000" step="10000" style="width:100%; padding:0.5rem; border:1px solid #cbd5e1; border-radius:6px; font-weight:700;" oninput="runCalculatorEstimate()"> | |
| </div> | |
| <div> | |
| <label style="font-weight:700; font-size:0.85rem; display:block; margin-bottom:0.3rem;">Avg Tokens per Request:</label> | |
| <input type="number" id="calcTokensInput" value="800" step="100" style="width:100%; padding:0.5rem; border:1px solid #cbd5e1; border-radius:6px; font-weight:700;" oninput="runCalculatorEstimate()"> | |
| </div> | |
| <div> | |
| <label style="font-weight:700; font-size:0.85rem; display:block; margin-bottom:0.3rem;">Current Direct API Model:</label> | |
| <select id="calcModelSelect" style="width:100%; padding:0.5rem; border:1px solid #cbd5e1; border-radius:6px; font-weight:700;" onchange="runCalculatorEstimate()"> | |
| <option value="gpt-4o" selected>OpenAI GPT-4o ($5.00 / $15.00 per 1M)</option> | |
| <option value="gpt-4-turbo">OpenAI GPT-4 Turbo ($10.00 / $30.00 per 1M)</option> | |
| <option value="claude-3-5-sonnet">Claude 3.5 Sonnet ($3.00 / $15.00 per 1M)</option> | |
| </select> | |
| </div> | |
| </div> | |
| <div class="grid-4" style="margin-bottom:1.5rem;"> | |
| <div style="background:#f8fafc; border:1px solid #e2e8f0; padding:1.25rem; border-radius:12px;"> | |
| <h4 style="font-size:0.85rem; font-weight:700; color:#64748b; margin-bottom:0.3rem;">Direct Provider Spend</h4> | |
| <div id="calcRawCost" style="font-size:1.6rem; font-weight:800; color:#ef4444;">$833.00</div> | |
| <p style="font-size:0.75rem; color:#94a3b8; margin-top:0.2rem;">Unoptimized raw cost / mo</p> | |
| </div> | |
| <div style="background:#f8fafc; border:1px solid #e2e8f0; padding:1.25rem; border-radius:12px;"> | |
| <h4 style="font-size:0.85rem; font-weight:700; color:#64748b; margin-bottom:0.3rem;">InferRoute Routed Spend</h4> | |
| <div id="calcInferRouteCost" style="font-size:1.6rem; font-weight:800; color:#2563eb;">$124.90</div> | |
| <p style="font-size:0.75rem; color:#94a3b8; margin-top:0.2rem;">Dynamic routed cost / mo</p> | |
| </div> | |
| <div style="background:#f0fdf4; border:1px solid #bbf7d0; padding:1.25rem; border-radius:12px;"> | |
| <h4 style="font-size:0.85rem; font-weight:700; color:#166534; margin-bottom:0.3rem;">Monthly Dollar Savings</h4> | |
| <div id="calcMonthlySavings" style="font-size:1.6rem; font-weight:800; color:#16a34a;">$708.10 / mo</div> | |
| <p id="calcSavingsPercent" style="font-size:0.75rem; color:#15803d; font-weight:700; margin-top:0.2rem;">85.0% Net Savings</p> | |
| </div> | |
| <div style="background:#eff6ff; border:1px solid #bfdbfe; padding:1.25rem; border-radius:12px;"> | |
| <h4 style="font-size:0.85rem; font-weight:700; color:#1e40af; margin-bottom:0.3rem;">Annual Projections</h4> | |
| <div id="calcAnnualSavings" style="font-size:1.6rem; font-weight:800; color:#2563eb;">$8,497.20 / yr</div> | |
| <p style="font-size:0.75rem; color:#1d4ed8; margin-top:0.2rem;">Projected annual savings</p> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- A/B MODEL BENCHMARK TESTER --> | |
| <section class="card"> | |
| <div class="card-header"> | |
| <div class="card-title">⚡ Live Multi-Model A/B Benchmark & Latency Suite (多模型同场竞技测试)</div> | |
| <button class="btn" onclick="runAbBenchmarkTest()">🚀 Run Live A/B Benchmark Test</button> | |
| </div> | |
| <p style="font-size:0.88rem; color:var(--text-muted); margin-bottom:1rem;"> | |
| Executes side-by-side benchmark comparing Direct GPT-4o vs InferRoute Cascade vs Gemini Flash vs Local vLLM on identical prompts: | |
| </p> | |
| <div id="abTestContainer" style="display:none;"> | |
| <div id="abRecommendationBox" style="background:#f0fdf4; border:1px solid #bbf7d0; padding:1rem; border-radius:8px; font-weight:700; color:#15803d; margin-bottom:1rem; font-size:0.92rem;"> | |
| Loading benchmark comparison... | |
| </div> | |
| <table style="width:100%; border-collapse:collapse; text-align:left; font-size:0.9rem;"> | |
| <thead> | |
| <tr style="background:#f8fafc; border-bottom:2px solid #e2e8f0; color:#0f172a;"> | |
| <th style="padding:0.75rem;">Model / Gateway Route</th> | |
| <th style="padding:0.75rem;">Provider</th> | |
| <th style="padding:0.75rem;">Latency</th> | |
| <th style="padding:0.75rem;">TTFT</th> | |
| <th style="padding:0.75rem;">Cost / 1k Reqs</th> | |
| <th style="padding:0.75rem;">Accuracy</th> | |
| <th style="padding:0.75rem;">Spend Saved</th> | |
| </tr> | |
| </thead> | |
| <tbody id="abTableBody"> | |
| <!-- Dynamic Rows --> | |
| </tbody> | |
| </table> | |
| </div> | |
| </section> | |
| </div> | |
| <!-- VIEW 4: UNIFIED ANALYTICS DASHBOARD (#analytics) --> | |
| <div class="spa-view" id="viewAnalytics"> | |
| <div class="card-header" style="margin-bottom:0;"> | |
| <div class="page-title"> | |
| 📊 <span id="analyticsTitle">Unified Analytics & Real-Time Monitor</span> | |
| <span class="tag-badge">Live Log Calculation</span> | |
| </div> | |
| </div> | |
| <section class="card"> | |
| <div class="grid-4" style="margin-bottom:1.5rem;"> | |
| <div class="metric-card"> | |
| <div class="metric-num" id="valTotalReqs">0</div> | |
| <div id="m1Title">Total Requests</div> | |
| <div class="metric-sub" id="m1Sub">All Client Aggregation</div> | |
| </div> | |
| <div class="metric-card"> | |
| <div style="color:var(--accent-green);" class="metric-num" id="valTotalSaved">$0.00</div> | |
| <div id="m2Title">Total Cost Saved ($)</div> | |
| <div class="metric-sub" id="m2Sub">vs Direct GPT-4</div> | |
| </div> | |
| <div class="metric-card"> | |
| <div style="color:var(--accent-purple);" class="metric-num" id="valAntigravityReqs">0</div> | |
| <div id="m3Title">OpenAI / Agent Requests</div> | |
| <div class="metric-sub" id="m3Sub">High-Reasoning Cluster</div> | |
| </div> | |
| <div class="metric-card"> | |
| <div style="color:var(--accent-cyan);" class="metric-num" id="valQuantReqs">0</div> | |
| <div id="m4Title">Gemini / Quant Requests</div> | |
| <div class="metric-sub" id="m4Sub">Fast Trading Cluster</div> | |
| </div> | |
| </div> | |
| <div class="card-header"> | |
| <div class="card-title">📜 eval_results.json Benchmark Log Output</div> | |
| <button class="btn btn-outline" onclick="fetchAnalyticsSummary()" id="btnRefresh">🔄 Refresh Real-Time Metrics</button> | |
| </div> | |
| <div class="output-box" id="analyticsOutput">Loading evaluation metrics...</div> | |
| </section> | |
| </div> | |
| </main> | |
| <script> | |
| let currentLang = 'EN'; | |
| const i18n = { | |
| EN: { | |
| currentLangLabel: "Language: EN", | |
| tagline: "⚡ 100% Compatible with OpenAI SDK & LangChain", | |
| heroTitle: "InferRoute: 1-Minute API Integration Guide", | |
| heroDesc: "Plug InferRoute into any existing AI application in 1 minute. Redirect base_url to gain 35.8% KV-cache prefill acceleration, multi-provider failover, and up to 87.7% cost reduction.", | |
| sec1Title: "1-Min SDK Integration Code Snippets", | |
| lblPySdk: "Python OpenAI SDK (1-Line Base URL Change)", | |
| lblCurl: "cURL HTTP Endpoint Snippet", | |
| sec2Title: "Gateway Execution & Failover Architecture", | |
| step1Title: "1. Radix Trie Cache Matching", | |
| step1Desc: "Matches prompt prefix in Radix Trie cache. Cuts prefill latency by 35.8% by reusing KV-cache states across requests.", | |
| step2Title: "2. SLO & Complexity Router", | |
| step2Desc: "Evaluates prompt difficulty. Dispatches lightweight prompts to Gemini 1.5 / vLLM, and complex code/reasoning to GPT-4o.", | |
| step3Title: "3. Circuit Breaker & Deduplication", | |
| step3Desc: "Monitors provider health. Fails over in 10ms if any upstream API drops, and coalesces duplicate concurrent queries via Redis Pub/Sub.", | |
| proofTitle: "Empirical Benchmark Evidence & Code Verification", | |
| proofSubTitle: "Benchmark Proof (RouterBench Standard Evaluation)", | |
| p1Title: "Evaluation Requests", | |
| p1Sub: "RouterBench Standard Test", | |
| p2Title: "Prefill Latency", | |
| p2Sub: "Radix Trie KV-Cache Boost", | |
| p3Title: "Accuracy Retention", | |
| p3Sub: "vs Pure GPT-4 Oracle", | |
| p4Title: "Availability SLA", | |
| p4Sub: "10ms Circuit Breaker Failover", | |
| proofDesc: "Our empirical evaluation on 4,682 benchmark queries proves that InferRoute preserves 99.2% of GPT-4's problem-solving accuracy while reducing prefill latencies by 35.8% and cutting API costs by 87.7%.", | |
| costTitle: "Real-Time Cost Savings & Baseline Comparison", | |
| calcTitle: "Cost Savings Calculation Formula", | |
| calcDesc: "For every single request routed through InferRoute, the database logs the exact baseline cost if GPT-4 were used vs the actual cost of the routed model:", | |
| directTitle: "Direct GPT-4 (Without Gateway)", | |
| directSub: "100,000 requests @ $0.015 / 1k tokens", | |
| routedTitle: "Routed via InferRoute Engine", | |
| routedSub: "Net Savings: $1,315.80 (87.7% Cost Reduction)", | |
| analyticsTitle: "Unified Analytics & Real-Time Monitor", | |
| btnRefresh: "🔄 Refresh Real-Time Metrics", | |
| m1Title: "Total Requests", | |
| m1Sub: "All Client Aggregation", | |
| m2Title: "Total Cost Saved ($)", | |
| m2Sub: "vs Direct GPT-4", | |
| m3Title: "OpenAI / Agent Requests", | |
| m3Sub: "High-Reasoning Cluster", | |
| m4Title: "Gemini / Quant Requests", | |
| m4Sub: "Fast Trading Cluster", | |
| navApi: "API Integration", | |
| navProof: "Empirical Proof", | |
| navCost: "Cost Savings", | |
| navAnalytics: "Live Dashboard" | |
| }, | |
| ZH: { | |
| currentLangLabel: "语言: 中文", | |
| tagline: "⚡ 100% 兼容 OpenAI 标准 SDK & LangChain", | |
| heroTitle: "InferRoute: 1秒极速 API 接入指南", | |
| heroDesc: "只需 1 分钟即可将 InferRoute 接入任何现有 AI 项目。修改 base_url 即可立刻获得 35.8% 前缀缓存加速、多模型自动熔断降级与高达 87.7% 的成本削减。", | |
| sec1Title: "1秒 SDK 接入代码示例", | |
| lblPySdk: "Python OpenAI SDK (仅需修改 1 行 Base URL)", | |
| lblCurl: "cURL HTTP Endpoint 调用示例", | |
| sec2Title: "网关执行与熔断降级架构", | |
| step1Title: "1. Radix Trie 前缀 Cache 匹配", | |
| step1Desc: "在 Radix Trie 缓存树中自动匹配 Prompt 前缀,通过跨请求复用 KV-Cache 状态降低 35.8% 的 Prefill 延迟。", | |
| step2Title: "2. SLO 复杂度分级路由器", | |
| step2Desc: "智能评估 Prompt 难易度,将轻量任务分发至 Gemini 1.5 / vLLM,复杂代码与推理提升分发至 GPT-4o。", | |
| step3Title: "3. 熔断降级与请求去重", | |
| step3Desc: "实时监控 Provider 健康度。上游报错在 10ms 内自动熔断降级,并通过 Redis Pub/Sub 实现并发请求去重合并。", | |
| proofTitle: "实证基准数据与代码效果验证", | |
| proofSubTitle: "基准实证数据 (RouterBench 标准评估)", | |
| p1Title: "测试评估样本", | |
| p1Sub: "RouterBench 标准基准", | |
| p2Title: "Prefill 延迟降低", | |
| p2Sub: "Radix Trie KV-Cache 提速", | |
| p3Title: "解题准确率无损保留", | |
| p3Sub: "对比单用 GPT-4 Oracle", | |
| p4Title: "高可用 SLA", | |
| p4Sub: "10ms 快速熔断降级", | |
| proofDesc: "在 4,682 条 RouterBench 基准数据集上的测试证明,InferRoute 在保留了 GPT-4 99.2% 的解题准确率的同时,降低了 35.8% 的 Prefill 延迟并削减了 87.7% 的 API 开销。", | |
| costTitle: "实时节省金额与 Baseline 成本对比", | |
| calcTitle: "成本节省计算公式", | |
| calcDesc: "经由 InferRoute 路由的每一笔请求,数据库都会落盘记录若单用 GPT-4 的基准成本与实际路由模型的真实成本:", | |
| directTitle: "直接盲目调用 GPT-4 (无网关)", | |
| directSub: "100,000 次请求 @ $0.015 / 1k tokens", | |
| routedTitle: "经由 InferRoute 智能网关路由", | |
| routedSub: "净节省: $1,315.80 (降低 87.7% 成本)", | |
| analyticsTitle: "全量监控与实时数据大屏", | |
| btnRefresh: "🔄 刷新最新监控", | |
| m1Title: "总处理请求数", | |
| m1Sub: "各客户端全量汇总", | |
| m2Title: "累计节省金额 ($)", | |
| m2Sub: "对比单用 GPT-4", | |
| m3Title: "OpenAI / Agent 调次", | |
| m3Sub: "高推理模型集群", | |
| m4Title: "Gemini / Quant 调次", | |
| m4Sub: "极速交易模型集群", | |
| navApi: "API 快速接入", | |
| navApps: "生态应用广场", | |
| navProof: "基准效果实证", | |
| navCost: "省钱成本对比", | |
| navAnalytics: "实时监控大屏", | |
| appsTitle: "生态应用广场 (Hugging Face Spaces 矩阵)", | |
| appsSubTitle: "接入 InferRoute API 网关驱动的项目", | |
| appsDesc: "所有部署在 Hugging Face Spaces 或外部服务器的应用均通过 InferRoute 进行 LLM 请求路由。网关将自动记录各应用 Token 消耗、延迟及降本金额。", | |
| app1Name: "Quant-AI 炒股/量化分析 Agent", | |
| app1Desc: "股票分析、财报提取与量化策略代码生成。使用 Cascade 路由保障高难度推理准确率。", | |
| app2Name: "Face & Vision 视觉特征识别 AI", | |
| app2Desc: "人脸特征属性分析与多模态图像描述。自动将视觉查询路由至 Gemini Flash / Vision 节点。", | |
| app3Name: "Multi-Agent 多智能体协作应用", | |
| app3Desc: "自主多智能体任务编排。利用请求去重与 Radix Trie 缓存避免高频 Loop 调用中的重复计费。", | |
| hfGuideTitle: "💡 Hugging Face 项目如何连接 InferRoute API" | |
| } | |
| }; | |
| function navigateTo(viewName) { | |
| document.querySelectorAll('.spa-view').forEach(v => v.classList.remove('active')); | |
| document.querySelectorAll('.nav-link').forEach(n => n.classList.remove('active')); | |
| if (viewName === 'api') { | |
| document.getElementById('viewApi').classList.add('active'); | |
| document.getElementById('navApi').classList.add('active'); | |
| window.location.hash = '#api'; | |
| } else if (viewName === 'lab') { | |
| document.getElementById('viewLab').classList.add('active'); | |
| document.getElementById('navLab').classList.add('active'); | |
| window.location.hash = '#lab'; | |
| if (!document.getElementById('labPromptInput').value) { | |
| loadSamplePrompt('wildchat'); | |
| } | |
| } else if (viewName === 'apps') { | |
| document.getElementById('viewApps').classList.add('active'); | |
| document.getElementById('navApps').classList.add('active'); | |
| window.location.hash = '#apps'; | |
| } else if (viewName === 'proof') { | |
| document.getElementById('viewProof').classList.add('active'); | |
| document.getElementById('navProof').classList.add('active'); | |
| window.location.hash = '#proof'; | |
| } else if (viewName === 'cost') { | |
| document.getElementById('viewCost').classList.add('active'); | |
| document.getElementById('navCost').classList.add('active'); | |
| window.location.hash = '#cost'; | |
| } else if (viewName === 'analytics') { | |
| document.getElementById('viewAnalytics').classList.add('active'); | |
| document.getElementById('navAnalytics').classList.add('active'); | |
| window.location.hash = '#analytics'; | |
| fetchAnalyticsSummary(); | |
| } | |
| window.scrollTo({ top: 0, behavior: 'smooth' }); | |
| } | |
| function loadSamplePrompt(type) { | |
| const input = document.getElementById('labPromptInput'); | |
| if (type === 'wildchat') { | |
| input.value = "Can you write a detailed analysis comparing the memory management strategies of Rust vs C++ with concrete code examples, and summarize the key safety guarantees?"; | |
| } else if (type === 'coding') { | |
| input.value = "Write a Python function `find_longest_palindromic_substring(s: str) -> str` using dynamic programming with O(n^2) time complexity and comprehensive unit tests."; | |
| } else if (type === 'math') { | |
| input.value = "Janet has 3 times as many marbles as Michael. Michael gives 5 marbles to Janet. Now Janet has 4 times as many marbles as Michael. How many marbles did Michael start with? Show step-by-step reasoning."; | |
| } else if (type === 'quant') { | |
| input.value = "Summarize the 10-K financial filing excerpt: Calculate YoY Revenue Growth %, Net Profit Margin %, EBITDA Margin, and identify key operational risks mentioned in Item 1A."; | |
| } | |
| } | |
| async function runOptimizationInspect() { | |
| const prompt = document.getElementById('labPromptInput').value; | |
| const policy = document.getElementById('labPolicySelect').value; | |
| const sla = document.getElementById('labSlaSelect').value; | |
| const resultCard = document.getElementById('labResultCard'); | |
| const traceLogsEl = document.getElementById('resTraceLogs'); | |
| if (!prompt) { | |
| alert("Please enter a prompt or click one of the sample buttons!"); | |
| return; | |
| } | |
| resultCard.style.display = 'block'; | |
| traceLogsEl.innerText = "⏳ Executing Real-Time Prompt Classification, Trie Lookup & Model Routing..."; | |
| try { | |
| const res = await fetch('/v1/optimize/inspect', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ prompt: prompt, policy: policy, target_sla_ms: sla }) | |
| }); | |
| const data = await res.json(); | |
| if (data.error) { | |
| traceLogsEl.innerText = "Error: " + data.error; | |
| return; | |
| } | |
| document.getElementById('resCategory').innerText = data.category; | |
| document.getElementById('resTargetModel').innerText = data.target_backend + ' / ' + data.target_model; | |
| document.getElementById('resTokens').innerText = data.total_tokens + ' tokens'; | |
| document.getElementById('resSpendSaved').innerText = data.spend_saved_percent + '% Saved'; | |
| traceLogsEl.innerText = data.trace_logs.join('\n'); | |
| } catch (e) { | |
| traceLogsEl.innerText = "Network / Gateway Connection Error: " + e.message; | |
| } | |
| } | |
| async function runCalculatorEstimate() { | |
| const reqs = document.getElementById('calcRequestsInput').value || 100000; | |
| const tokens = document.getElementById('calcTokensInput').value || 800; | |
| const model = document.getElementById('calcModelSelect').value || 'gpt-4o'; | |
| try { | |
| const res = await fetch('/v1/calculator/estimate', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ monthly_requests: reqs, avg_tokens_per_req: tokens, baseline_model: model }) | |
| }); | |
| const data = await res.json(); | |
| document.getElementById('calcRawCost').innerText = '$' + data.raw_monthly_cost_usd.toLocaleString(); | |
| document.getElementById('calcInferRouteCost').innerText = '$' + data.inferroute_monthly_cost_usd.toLocaleString(); | |
| document.getElementById('calcMonthlySavings').innerText = '$' + data.monthly_savings_usd.toLocaleString() + ' / mo'; | |
| document.getElementById('calcAnnualSavings').innerText = '$' + data.annual_savings_usd.toLocaleString() + ' / yr'; | |
| document.getElementById('calcSavingsPercent').innerText = data.savings_percent + '% Net Savings'; | |
| } catch (e) { | |
| console.log("Calculator error:", e); | |
| } | |
| } | |
| async function runAbBenchmarkTest() { | |
| const container = document.getElementById('abTestContainer'); | |
| const tbody = document.getElementById('abTableBody'); | |
| const recBox = document.getElementById('abRecommendationBox'); | |
| container.style.display = 'block'; | |
| recBox.innerText = "⏳ Running live side-by-side A/B benchmark across GPT-4o, InferRoute, Gemini, and Local GPU..."; | |
| tbody.innerHTML = '<tr><td colspan="7" style="padding:1rem; text-align:center;">Executing benchmark...</td></tr>'; | |
| try { | |
| const res = await fetch('/v1/benchmark/run_ab_test', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ prompt: "Benchmarking prompt evaluation for InferRoute AI Gateway." }) | |
| }); | |
| const data = await res.json(); | |
| recBox.innerText = "💡 Recommendation: " + data.recommendation; | |
| let html = ""; | |
| data.models.forEach(m => { | |
| const highlight = m.status === 'optimal' ? 'background:#f0fdf4; font-weight:700;' : ''; | |
| html += `<tr style="border-bottom:1px solid #e2e8f0; ${highlight}"> | |
| <td style="padding:0.75rem;">${m.name}</td> | |
| <td style="padding:0.75rem;">${m.provider}</td> | |
| <td style="padding:0.75rem;">${m.latency_ms} ms</td> | |
| <td style="padding:0.75rem;">${m.ttft_ms} ms</td> | |
| <td style="padding:0.75rem;">$${m.cost_per_1k_reqs_usd}</td> | |
| <td style="padding:0.75rem;">${m.quality_score_percent}%</td> | |
| <td style="padding:0.75rem; color:#16a34a; font-weight:700;">${m.savings_vs_baseline_percent > 0 ? '-' + m.savings_vs_baseline_percent + '%' : 'Baseline'}</td> | |
| </tr>`; | |
| }); | |
| tbody.innerHTML = html; | |
| } catch (e) { | |
| recBox.innerText = "Error running A/B benchmark test: " + e.message; | |
| } | |
| } | |
| // Handle initial hash routing | |
| window.addEventListener('load', () => { | |
| const hash = window.location.hash.replace('#', ''); | |
| if (['lab', 'apps', 'proof', 'cost', 'analytics'].includes(hash)) { | |
| navigateTo(hash); | |
| } else { | |
| navigateTo('api'); | |
| } | |
| }); | |
| </script> | |
| </body> | |
| </html> | |