1use async_trait::async_trait;
2
3use crate::model::{Model, ModelError, ModelRequest, ModelResponse, ModelStream, Usage};
4
5#[derive(Debug, Clone, Copy, Default, PartialEq)]
9pub struct Pricing {
10 pub input: f64,
11 pub output: f64,
12 pub cache_read: f64,
13 pub cache_write: f64,
14}
15
16impl Pricing {
17 pub fn new(input: f64, output: f64) -> Self {
18 Self { input, output, cache_read: input * 0.1, cache_write: input * 1.25 }
19 }
20
21 pub fn cost(&self, u: &Usage) -> f64 {
22 (u.input_tokens as f64 * self.input
23 + u.output_tokens as f64 * self.output
24 + u.cache_read_tokens as f64 * self.cache_read
25 + u.cache_write_tokens as f64 * self.cache_write)
26 / 1_000_000.0
27 }
28
29 pub fn max(self, other: Pricing) -> Pricing {
32 Pricing {
33 input: self.input.max(other.input),
34 output: self.output.max(other.output),
35 cache_read: self.cache_read.max(other.cache_read),
36 cache_write: self.cache_write.max(other.cache_write),
37 }
38 }
39}
40
41pub struct Priced<M> {
43 inner: M,
44 pricing: Pricing,
45}
46
47impl<M: Model> Priced<M> {
48 pub fn new(inner: M, pricing: Pricing) -> Self {
49 Self { inner, pricing }
50 }
51}
52
53#[async_trait]
54impl<M: Model> Model for Priced<M> {
55 fn id(&self) -> String {
56 self.inner.id()
57 }
58
59 async fn complete(&self, request: &ModelRequest) -> Result<ModelResponse, ModelError> {
60 self.inner.complete(request).await
61 }
62
63 async fn stream(&self, request: &ModelRequest) -> Result<ModelStream, ModelError> {
64 self.inner.stream(request).await
65 }
66
67 fn pricing(&self) -> Option<Pricing> {
68 Some(self.pricing)
69 }
70
71 fn unpriced_models(&self) -> Vec<String> {
72 Vec::new()
73 }
74}