Skip to main content

systemprompt_api/services/gateway/
pricing.rs

1#[derive(Debug, Clone, Copy)]
2pub struct ModelPricing {
3    pub input_cost_per_1k: f32,
4    pub output_cost_per_1k: f32,
5}
6
7impl ModelPricing {
8    pub const fn zero() -> Self {
9        Self {
10            input_cost_per_1k: 0.0,
11            output_cost_per_1k: 0.0,
12        }
13    }
14}
15
16pub fn lookup(provider: &str, model: &str) -> ModelPricing {
17    let model_lc = model.to_ascii_lowercase();
18    let m = model_lc.as_str();
19
20    if provider.eq_ignore_ascii_case("anthropic") {
21        return match m {
22            x if x.starts_with("claude-opus-4-7") => ModelPricing {
23                input_cost_per_1k: 15.0,
24                output_cost_per_1k: 75.0,
25            },
26            x if x.starts_with("claude-opus-4") => ModelPricing {
27                input_cost_per_1k: 15.0,
28                output_cost_per_1k: 75.0,
29            },
30            x if x.starts_with("claude-sonnet-4") => ModelPricing {
31                input_cost_per_1k: 3.0,
32                output_cost_per_1k: 15.0,
33            },
34            x if x.starts_with("claude-haiku-4") => ModelPricing {
35                input_cost_per_1k: 1.0,
36                output_cost_per_1k: 5.0,
37            },
38            _ => unknown(provider, model),
39        };
40    }
41
42    if provider.eq_ignore_ascii_case("minimax") {
43        return match m {
44            x if x.starts_with("minimax-m1") || x == "abab7-chat-preview" => ModelPricing {
45                input_cost_per_1k: 0.0004,
46                output_cost_per_1k: 0.0022,
47            },
48            x if x.starts_with("minimax-text-01") || x.starts_with("abab6.5") => ModelPricing {
49                input_cost_per_1k: 0.0002,
50                output_cost_per_1k: 0.0011,
51            },
52            _ => unknown(provider, model),
53        };
54    }
55
56    if provider.eq_ignore_ascii_case("openai") {
57        return match m {
58            x if x.starts_with("gpt-4o-mini") => ModelPricing {
59                input_cost_per_1k: 0.15,
60                output_cost_per_1k: 0.6,
61            },
62            x if x.starts_with("gpt-4o") => ModelPricing {
63                input_cost_per_1k: 2.5,
64                output_cost_per_1k: 10.0,
65            },
66            _ => unknown(provider, model),
67        };
68    }
69
70    unknown(provider, model)
71}
72
73fn unknown(provider: &str, model: &str) -> ModelPricing {
74    tracing::warn!(
75        provider = provider,
76        model = model,
77        "Gateway pricing lookup: no entry for (provider, model) — cost_microdollars will be 0"
78    );
79    ModelPricing::zero()
80}
81
82pub fn cost_microdollars(pricing: ModelPricing, input_tokens: u32, output_tokens: u32) -> i64 {
83    let input = f64::from(input_tokens);
84    let output = f64::from(output_tokens);
85    let input_cost = (input / 1000.0) * f64::from(pricing.input_cost_per_1k);
86    let output_cost = (output / 1000.0) * f64::from(pricing.output_cost_per_1k);
87    ((input_cost + output_cost) * 1_000_000.0).round() as i64
88}