| """ |
| Pricing utilities for computing per-run cost from token usage. |
| |
| All prices are specified per 1,000,000 tokens (M tokens) in USD. |
| """ |
|
|
| from __future__ import annotations |
|
|
| from typing import Dict, Optional |
|
|
|
|
| |
| |
| MODEL_PRICES_PER_M: Dict[str, Dict[str, float]] = { |
| |
| |
| "claude-opus-4-1-20250805": {"input": 15.0, "output": 75.0}, |
| "claude-opus-4-5-20251101": {"input": 5.0, "output": 25.0}, |
| "claude-sonnet-4-20250514": {"input": 3.0, "output": 15.0}, |
| "claude-sonnet-4-5-20250929": {"input": 3.0, "output": 15.0}, |
|
|
| |
| "deepseek-v3.1-non-think": {"input": 0.56, "output": 1.68}, |
| "deepseek-v3.2-chat": {"input": 0.27, "output": 0.40}, |
| "deepseek-v3.2-reasoner": {"input": 0.27, "output": 0.40}, |
| "deepseek-v3.1-terminus-thinking": {"input": 0.21, "output": 0.79}, |
| "deepseek-v3.1-terminus": {"input": 0.21, "output": 0.79}, |
|
|
| |
| "gemini-2.5-pro": {"input": 2.5, "output": 15.0}, |
| "gemini-2.5-flash": {"input": 0.3, "output": 2.5}, |
| "gemini-3-pro": {"input": 2.0, "output": 12.0}, |
|
|
| |
| "glm-4.5": {"input": 0.33, "output": 1.32}, |
|
|
| |
| "gpt-5-2025-08-07": {"input": 1.25, "output": 10.0}, |
| "gpt-5.2-2025-12-11": {"input": 1.75, "output": 14.0}, |
| "gpt-5-mini-2025-08-07": {"input": 0.25, "output": 2.0}, |
| "gpt-5-nano-2025-08-07": {"input": 0.05, "output": 0.4}, |
| "gpt-4.1-2025-04-14": {"input": 2.0, "output": 8.0}, |
| "gpt-4.1-mini-2025-04-14": {"input": 0.4, "output": 1.6}, |
| "gpt-4.1-nano-2025-04-14": {"input": 0.1, "output": 0.4}, |
| "o3-2025-04-16": {"input": 2.0, "output": 8.0}, |
| "o4-mini-2025-04-16": {"input": 1.1, "output": 4.4}, |
| "gpt-oss-120b": {"input": 0.072, "output": 0.28}, |
|
|
| |
| "qwen3-coder-480b-a35b-instruct": {"input": 0.2, "output": 0.8}, |
| "qwen3-max-preview": {"input": 1.2, "output": 6}, |
| |
| |
| "grok-4-0709": {"input": 3.0, "output": 15.0}, |
| "grok-code-fast-1": {"input": 0.2, "output": 1.5}, |
| "grok-4-fast": {"input": 0.2, "output": 0.5}, |
|
|
| |
| "kimi-k2-0711-preview": {"input": 0.6, "output": 2.5}, |
| "kimi-k2-0905-preview": {"input": 0.6, "output": 2.5}, |
| } |
|
|
|
|
| def normalize_model_name(model_name: str) -> str: |
| """Normalize model name for pricing lookup. |
| |
| Lowercases only. |
| """ |
| return (model_name or "").strip().lower() |
|
|
|
|
| def get_price_per_m(model_name: str) -> Optional[Dict[str, float]]: |
| """Return per-M token prices for given model, or None if unknown.""" |
| key = normalize_model_name(model_name) |
| return MODEL_PRICES_PER_M.get(key) |
|
|
|
|
| def compute_cost_usd(model_name: str, input_tokens: float, output_tokens: float) -> Optional[float]: |
| """Compute cost in USD given token usage and model pricing. |
| |
| Prices are per 1,000,000 tokens. If pricing unknown, returns None. |
| """ |
| prices = get_price_per_m(model_name) |
| if not prices: |
| return None |
| input_cost = (input_tokens / 1_000_000.0) * prices["input"] |
| output_cost = (output_tokens / 1_000_000.0) * prices["output"] |
| return float(round(input_cost + output_cost, 6)) |
|
|
|
|
|
|