ai_lib_rust/tokens/
pricing.rs1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct ModelPricing { pub model: String, pub input_cost_per_1k: f64, pub output_cost_per_1k: f64, pub currency: String }
7
8impl ModelPricing {
9 pub fn new(model: &str, input: f64, output: f64) -> Self { Self { model: model.into(), input_cost_per_1k: input, output_cost_per_1k: output, currency: "USD".into() } }
10 pub fn calculate_cost(&self, input_tokens: u32, output_tokens: u32) -> CostEstimate {
11 let ic = (input_tokens as f64 / 1000.0) * self.input_cost_per_1k;
12 let oc = (output_tokens as f64 / 1000.0) * self.output_cost_per_1k;
13 CostEstimate { model: self.model.clone(), input_tokens, output_tokens, input_cost: ic, output_cost: oc, total_cost: ic + oc, currency: self.currency.clone() }
14 }
15 pub fn gpt_4o() -> Self { Self::new("gpt-4o", 0.005, 0.015) }
16 pub fn gpt_4o_mini() -> Self { Self::new("gpt-4o-mini", 0.00015, 0.0006) }
17 pub fn claude_35_sonnet() -> Self { Self::new("claude-3-5-sonnet", 0.003, 0.015) }
18 pub fn claude_3_haiku() -> Self { Self::new("claude-3-haiku", 0.00025, 0.00125) }
19 pub fn for_model(model: &str) -> Option<Self> {
20 let m = model.to_lowercase();
21 if m.contains("gpt-4o-mini") { Some(Self::gpt_4o_mini()) }
22 else if m.contains("gpt-4o") { Some(Self::gpt_4o()) }
23 else if m.contains("claude-3-5-sonnet") { Some(Self::claude_35_sonnet()) }
24 else if m.contains("claude-3-haiku") { Some(Self::claude_3_haiku()) }
25 else { None }
26 }
27}
28
29#[derive(Debug, Clone, Serialize, Deserialize)]
30pub struct CostEstimate { pub model: String, pub input_tokens: u32, pub output_tokens: u32, pub input_cost: f64, pub output_cost: f64, pub total_cost: f64, pub currency: String }
31
32impl CostEstimate {
33 pub fn format(&self) -> String { format!("{} {:.6}", self.currency, self.total_cost) }
34 pub fn format_detailed(&self) -> String { if self.total_cost < 0.01 { format!("{:.4}ยข", self.total_cost * 100.0) } else { format!("${:.4}", self.total_cost) } }
35}