If you're running AI models in production, costs can spiral out of control fast. A single bug causing an infinite loop, a user sending unexpectedly long prompts, or a model generating verbose outputs can turn a $50/month bill into a $5,000/month nightmare.
The solution? A multi-model cost dashboard that tracks your AI spending in real time, compares costs across providers, and alerts you when something goes wrong. In this tutorial, we'll build one from scratch.
What We're Building
We'll create a cost dashboard that:
- Tracks token usage and costs across multiple AI providers
- Compares spending between models in real time
- Shows cost trends over time with charts
- Sends alerts when daily costs exceed a threshold
- Recommends cheaper model alternatives
Prerequisites
- Python 3.11+ or Node.js 20+
- An API key from Qubax AI (or individual provider keys)
- Basic familiarity with REST APIs
We'll use Python for this tutorial, but the concepts apply to any language.
Step 1: Set Up the Project
mkdir ai-cost-dashboard && cd ai-cost-dashboard
python -m venv venv
source venv/bin/activate
pip install fastapi uvicorn httpx python-dotenvCreate a .env file with your API keys:
# Use Qubax AI as your unified gateway (recommended)
QUBAX_API_KEY=your_api_key_here
QUBAX_BASE_URL=https://api.qubax.ai/v1
# Or individual provider keys
OPENAI_API_KEY=your_openai_key
ANTHROPIC_API_KEY=your_anthropic_key
DEEPSEEK_API_KEY=your_deepseek_keyUsing a unified gateway like Qubax AI is recommended because it gives you a single API endpoint for all models, unified billing, and built-in cost tracking.
Step 2: Create the Cost Tracker
First, let's build the core cost tracking module. This will log every API call with its token usage and calculated cost.
import httpx
import json
import sqlite3
from datetime import datetime, timedelta
from dataclasses import dataclass, asdict
from typing import Optional
@dataclass
class UsageRecord:
timestamp: str
model: str
provider: str
input_tokens: int
output_tokens: int
input_cost: float
output_cost: float
total_cost: float
request_id: str
class CostTracker:
def __init__(self, db_path="costs.db"):
self.conn = sqlite3.connect(db_path)
self._init_db()
# Current pricing per million tokens (update regularly)
self.pricing = {
"gpt-5.6-sol": {"input": 0.90, "output": 5.40},
"claude-opus-5": {"input": 1.50, "output": 7.50},
"deepseek-v4-pro": {"input": 0.11, "output": 0.33},
"glm-5.2": {"input": 0.03, "output": 0.09},
"qwen-3.8-max": {"input": 1.09, "output": 3.26},
}
def _init_db(self):
self.conn.execute("""
CREATE TABLE IF NOT EXISTS usage (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp TEXT,
model TEXT,
provider TEXT,
input_tokens INTEGER,
output_tokens INTEGER,
input_cost REAL,
output_cost REAL,
total_cost REAL,
request_id TEXT
)
""")
self.conn.commit()
def record_usage(self, model: str, provider: str,
input_tokens: int, output_tokens: int,
request_id: str = ""):
prices = self.pricing.get(model, {"input": 0, "output": 0})
input_cost = (input_tokens / 1_000_000) * prices["input"]
output_cost = (output_tokens / 1_000_000) * prices["output"]
total_cost = input_cost + output_cost
record = UsageRecord(
timestamp=datetime.utcnow().isoformat(),
model=model,
provider=provider,
input_tokens=input_tokens,
output_tokens=output_tokens,
input_cost=input_cost,
output_cost=output_cost,
total_cost=total_cost,
request_id=request_id
)
self.conn.execute(
"INSERT INTO usage VALUES (NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
(record.timestamp, record.model, record.provider,
record.input_tokens, record.output_tokens,
record.input_cost, record.output_cost,
record.total_cost, record.request_id)
)
self.conn.commit()
return recordStep 3: Build the API Client Wrapper
Next, let's create a wrapper that intercepts API calls, tracks usage, and logs costs automatically:
import os
from dotenv import load_dotenv
load_dotenv()
class AIClient:
def __init__(self, tracker: CostTracker):
self.tracker = tracker
self.client = httpx.Client(
base_url=os.getenv("QUBAX_BASE_URL", "https://api.qubax.ai/v1"),
headers={"Authorization": f"Bearer {os.getenv('QUBAX_API_KEY')}"}
)
async def chat(self, model: str, messages: list, **kwargs):
"""Send a chat completion request and track costs."""
response = self.client.post("/chat/completions", json={
"model": model,
"messages": messages,
**kwargs
})
data = response.json()
# Track usage
usage = data.get("usage", {})
self.tracker.record_usage(
model=model,
provider=self._get_provider(model),
input_tokens=usage.get("prompt_tokens", 0),
output_tokens=usage.get("completion_tokens", 0),
request_id=data.get("id", "")
)
return data
def _get_provider(self, model: str) -> str:
provider_map = {
"gpt": "OpenAI",
"claude": "Anthropic",
"deepseek": "DeepSeek",
"glm": "Zhipu AI",
"qwen": "Alibaba",
}
for prefix, provider in provider_map.items():
if model.startswith(prefix):
return provider
return "Unknown"Step 4: Create the Dashboard API
Now let's build a FastAPI server that serves cost analytics:
from fastapi import FastAPI, Query
from typing import Optional
import sqlite3
from datetime import datetime, timedelta
app = FastAPI(title="AI Cost Dashboard API")
tracker = CostTracker()
@app.get("/api/costs/summary")
def get_cost_summary(days: int = 7):
"""Get cost summary for the last N days."""
since = (datetime.utcnow() - timedelta(days=days)).isoformat()
conn = sqlite3.connect("costs.db")
rows = conn.execute("""
SELECT
model,
provider,
SUM(input_tokens) as total_input,
SUM(output_tokens) as total_output,
SUM(total_cost) as total_cost,
COUNT(*) as request_count
FROM usage
WHERE timestamp >= ?
GROUP BY model, provider
ORDER BY total_cost DESC
""", (since,)).fetchall()
models = []
grand_total = 0
for row in rows:
model, provider, inp, out, cost, count = row
models.append({
"model": model,
"provider": provider,
"input_tokens": inp,
"output_tokens": out,
"total_cost": round(cost, 4),
"request_count": count,
"avg_cost_per_request": round(cost / count, 6) if count else 0
})
grand_total += cost
return {
"period_days": days,
"total_cost": round(grand_total, 4),
"model_count": len(models),
"models": models
}
@app.get("/api/costs/daily")
def get_daily_costs(days: int = 30):
"""Get daily cost breakdown."""
since = (datetime.utcnow() - timedelta(days=days)).isoformat()
conn = sqlite3.connect("costs.db")
rows = conn.execute("""
SELECT
DATE(timestamp) as date,
model,
SUM(total_cost) as daily_cost,
COUNT(*) as request_count
FROM usage
WHERE timestamp >= ?
GROUP BY DATE(timestamp), model
ORDER BY date DESC
""", (since,)).fetchall()
daily = {}
for row in rows:
date, model, cost, count = row
if date not in daily:
daily[date] = {"date": date, "total": 0, "models": {}}
daily[date]["total"] += cost
daily[date]["models"][model] = round(cost, 4)
return list(daily.values())
@app.get("/api/costs/alerts")
def get_cost_alerts(threshold: float = 10.0):
"""Check if any day exceeded the cost threshold."""
conn = sqlite3.connect("costs.db")
rows = conn.execute("""
SELECT
DATE(timestamp) as date,
SUM(total_cost) as daily_cost
FROM usage
WHERE timestamp >= DATE('now', '-7 days')
GROUP BY DATE(timestamp)
HAVING daily_cost > ?
ORDER BY daily_cost DESC
""", (threshold,)).fetchall()
alerts = []
for row in rows:
date, cost = row
alerts.append({
"date": date,
"cost": round(cost, 2),
"threshold": threshold,
"message": "Daily cost exceeded threshold"
})
return {"alerts": alerts}Step 5: Add Model Recommendation Engine
One of the most powerful features of a cost dashboard is suggesting cheaper alternatives:
@app.get("/api/recommendations")
def get_recommendations():
"""Recommend cheaper model alternatives based on usage."""
conn = sqlite3.connect("costs.db")
rows = conn.execute("""
SELECT model, SUM(total_cost) as total_cost, COUNT(*) as count
FROM usage
WHERE timestamp >= DATE('now', '-7 days')
GROUP BY model
""").fetchall()
# Define cheaper alternatives
alternatives = {
"gpt-5.6-sol": ["deepseek-v4-pro", "glm-5.2"],
"claude-opus-5": ["deepseek-v4-pro", "glm-5.2"],
"qwen-3.8-max": ["deepseek-v4-pro", "glm-5.2"],
}
recommendations = []
for row in rows:
model, cost, count = row
if model in alternatives:
for alt in alternatives[model]:
alt_price = tracker.pricing.get(alt, {})
orig_price = tracker.pricing.get(model, {})
if alt_price and orig_price:
savings = cost * (1 - (alt_price["input"] + alt_price["output"]) /
(orig_price["input"] + orig_price["output"]))
recommendations.append({
"current_model": model,
"suggested_model": alt,
"current_weekly_cost": round(cost, 2),
"estimated_weekly_cost": round(cost - savings, 2),
"estimated_savings": round(savings, 2),
"savings_percent": round((savings / cost) * 100, 1)
})
return {"recommendations": recommendations}Step 6: Run the Dashboard
uvicorn main:app --reload --port 8000Now you can query your dashboard:
# Get 7-day cost summary
curl http://localhost:8000/api/costs/summary?days=7
# Get daily breakdown
curl http://localhost:8000/api/costs/daily?days=30
# Check for cost alerts
curl http://localhost:8000/api/costs/alerts?threshold=10
# Get model recommendations
curl http://localhost:8000/api/recommendationsStep 7: Add Real-Time Monitoring
For production use, add a background task that checks costs every hour and sends alerts:
import asyncio
import smtplib
from email.mime.text import MIMEText
async def monitor_costs():
"""Background task to monitor costs and send alerts."""
while True:
conn = sqlite3.connect("costs.db")
# Check today's cost
today = datetime.utcnow().strftime("%Y-%m-%d")
row = conn.execute("""
SELECT SUM(total_cost) FROM usage
WHERE DATE(timestamp) = ?
""", (today,)).fetchone()
today_cost = row[0] or 0
if today_cost > 50: # $50 daily threshold
send_alert_email(
subject="AI Cost Alert",
body="Daily AI cost has exceeded threshold. Check dashboard."
)
await asyncio.sleep(3600) # Check every hour
def send_alert_email(subject: str, body: str):
msg = MIMEText(body)
msg["Subject"] = subject
msg["From"] = "[email protected]"
msg["To"] = "[email protected]"
with smtplib.SMTP("smtp.yourcompany.com") as server:
server.send_message(msg)Production Tips
- Use a real database: Replace SQLite with PostgreSQL for production. SQLite works fine for prototyping but won't handle concurrent writes at scale.
- Add authentication: Protect your dashboard API with API keys or OAuth.
- Use a unified gateway: Instead of managing separate API keys for each provider, use Qubax AI which provides a single OpenAI-compatible endpoint for all models with built-in cost tracking.
- Set up automated cost routing: Once you have cost data, automatically route simple queries to cheaper models. For example, use GLM 5.2 ($0.03/M input) for basic tasks and reserve GPT-5.6 Sol ($0.90/M input) for complex reasoning.
- Implement prompt caching: Cache responses for identical queries to avoid paying for the same computation twice.
- Track per-user costs: Extend the schema to track which user or feature generated each cost, so you can identify which parts of your application are most expensive.
Full Code Structure
ai-cost-dashboard/
├── .env
├── main.py # FastAPI server
├── tracker.py # CostTracker and AIClient
├── monitor.py # Background monitoring task
├── requirements.txt
└── costs.db # SQLite database (auto-created)FAQ
What is an AI cost dashboard?
An AI cost dashboard is a tool that tracks how much you're spending on AI API calls across different models and providers. It shows token usage, calculates costs, identifies trends, and alerts you when spending exceeds thresholds.
Why do I need to track AI costs?
AI costs can spiral quickly. A single bug, a user sending long prompts, or a model generating verbose responses can multiply your costs. Without monitoring, you might not notice until you get a surprisingly large bill.
How do I calculate AI API costs?
AI API costs = (input tokens × input price / 1,000,000) + (output tokens × output price / 1,000,000). Prices are typically quoted per million tokens. For example, 500,000 input tokens at $1.00/M = $0.50.
Can I use one API for all AI models?
Yes! Using a unified gateway like Qubax AI gives you a single OpenAI-compatible API endpoint for hundreds of models from OpenAI, Anthropic, DeepSeek, Google, and more, with unified billing and cost tracking.
How can I reduce my AI API spending?
Route simple queries to cheaper models (like GLM 5.2 at $0.03/M input), implement prompt caching, optimize your prompts to use fewer tokens, test different effort settings, and set up cost alerts to catch spikes early.
What's the cheapest AI model for API calls?
GLM 5.2 from Zhipu AI is one of the cheapest capable models at $0.03 per million input tokens and $0.09 per million output tokens. DeepSeek V4 Pro is another budget option at $0.11/$0.33. Compare current prices at qubax.ai/models.