use crate::normalize::normalize_model_id;
use crate::usage::Usage;
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Pricing {
pub input_per_mtok: f64,
pub output_per_mtok: f64,
pub cached_input_per_mtok: f64,
}
impl Pricing {
pub fn cost_for(&self, usage: &Usage) -> f64 {
(usage.input_tokens as f64 * self.input_per_mtok
+ usage.output_tokens as f64 * self.output_per_mtok
+ usage.cached_input_tokens as f64 * self.cached_input_per_mtok)
/ 1_000_000.0
}
}
pub const DEFAULT_PRICING_TABLE: &[(&str, Pricing)] = &[
(
"gpt-5",
Pricing {
input_per_mtok: 1.25,
output_per_mtok: 10.0,
cached_input_per_mtok: 0.125,
},
),
(
"gpt-5-mini",
Pricing {
input_per_mtok: 0.25,
output_per_mtok: 2.0,
cached_input_per_mtok: 0.025,
},
),
(
"gpt-5-nano",
Pricing {
input_per_mtok: 0.05,
output_per_mtok: 0.4,
cached_input_per_mtok: 0.005,
},
),
(
"gpt-4.1",
Pricing {
input_per_mtok: 2.0,
output_per_mtok: 8.0,
cached_input_per_mtok: 0.5,
},
),
(
"gpt-4.1-mini",
Pricing {
input_per_mtok: 0.4,
output_per_mtok: 1.6,
cached_input_per_mtok: 0.1,
},
),
(
"gpt-4.1-nano",
Pricing {
input_per_mtok: 0.1,
output_per_mtok: 0.4,
cached_input_per_mtok: 0.025,
},
),
(
"gpt-4o",
Pricing {
input_per_mtok: 2.5,
output_per_mtok: 10.0,
cached_input_per_mtok: 1.25,
},
),
(
"gpt-4o-mini",
Pricing {
input_per_mtok: 0.15,
output_per_mtok: 0.6,
cached_input_per_mtok: 0.075,
},
),
(
"o3",
Pricing {
input_per_mtok: 2.0,
output_per_mtok: 8.0,
cached_input_per_mtok: 0.5,
},
),
(
"o3-mini",
Pricing {
input_per_mtok: 1.1,
output_per_mtok: 4.4,
cached_input_per_mtok: 0.55,
},
),
(
"o4-mini",
Pricing {
input_per_mtok: 1.1,
output_per_mtok: 4.4,
cached_input_per_mtok: 0.275,
},
),
];
pub fn default_pricing(model_id: &str) -> Option<Pricing> {
let key = normalize_model_id(model_id);
DEFAULT_PRICING_TABLE
.iter()
.find(|(k, _)| *k == key)
.map(|(_, p)| *p)
}