Coverage for little_loops / pricing.py: 38%
8 statements
« prev ^ index » next coverage.py v7.12.0, created at 2026-06-29 00:55 -0500
« prev ^ index » next coverage.py v7.12.0, created at 2026-06-29 00:55 -0500
1"""Model pricing constants for token cost estimation.
3Prices are in USD per million tokens ($/Mtok).
4Source: Anthropic pricing page (as of June 2026).
5"""
7from __future__ import annotations
9# Per-model pricing: {model_id: {token_type: usd_per_million}}
10MODEL_PRICING: dict[str, dict[str, float]] = {
11 # Claude 4.x
12 "claude-opus-4-7": {
13 "input": 15.0,
14 "output": 75.0,
15 "cache_read": 1.50,
16 "cache_creation": 18.75,
17 },
18 "claude-opus-4-6": {
19 "input": 15.0,
20 "output": 75.0,
21 "cache_read": 1.50,
22 "cache_creation": 18.75,
23 },
24 "claude-sonnet-4-6": {
25 "input": 3.0,
26 "output": 15.0,
27 "cache_read": 0.30,
28 "cache_creation": 3.75,
29 },
30 "claude-haiku-4-5-20251001": {
31 "input": 0.80,
32 "output": 4.0,
33 "cache_read": 0.08,
34 "cache_creation": 1.0,
35 },
36 # Claude 3.x (legacy, may still appear in logs)
37 "claude-opus-4-5": {
38 "input": 15.0,
39 "output": 75.0,
40 "cache_read": 1.50,
41 "cache_creation": 18.75,
42 },
43 "claude-sonnet-3-7": {
44 "input": 3.0,
45 "output": 15.0,
46 "cache_read": 0.30,
47 "cache_creation": 3.75,
48 },
49 "claude-haiku-3-5": {
50 "input": 0.80,
51 "output": 4.0,
52 "cache_read": 0.08,
53 "cache_creation": 1.0,
54 },
55}
58def estimate_cost_usd(
59 model: str,
60 input_tokens: int,
61 output_tokens: int,
62 cache_read_tokens: int = 0,
63 cache_creation_tokens: int = 0,
64) -> float | None:
65 """Estimate cost in USD for a token usage event.
67 Returns None if the model is not in MODEL_PRICING.
68 """
69 pricing = MODEL_PRICING.get(model)
70 if pricing is None:
71 return None
72 per_m = 1_000_000.0
73 return (
74 input_tokens * pricing["input"] / per_m
75 + output_tokens * pricing["output"] / per_m
76 + cache_read_tokens * pricing["cache_read"] / per_m
77 + cache_creation_tokens * pricing["cache_creation"] / per_m
78 )