1#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)]
10pub struct Timestamp(pub u64);
11
12impl Timestamp {
13 pub fn now() -> Self {
14 Self(
15 std::time::SystemTime::now()
16 .duration_since(std::time::UNIX_EPOCH)
17 .map(|d| d.as_nanos() as u64)
18 .unwrap_or(0),
19 )
20 }
21 pub fn elapsed(self, since: Self) -> f32 {
23 (self.0.saturating_sub(since.0)) as f32 / 1_000_000_000.0
24 }
25}
26
27#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
29pub struct FrameIndex(pub u64);
30
31#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
36pub struct TokenUsage {
37 pub prompt: u64,
38 pub completion: u64,
39}
40
41impl TokenUsage {
42 pub const ZERO: TokenUsage = TokenUsage {
43 prompt: 0,
44 completion: 0,
45 };
46
47 pub fn total(self) -> u64 {
48 self.prompt + self.completion
49 }
50}
51
52impl std::ops::Add for TokenUsage {
53 type Output = TokenUsage;
54 fn add(self, rhs: TokenUsage) -> TokenUsage {
55 TokenUsage {
56 prompt: self.prompt + rhs.prompt,
57 completion: self.completion + rhs.completion,
58 }
59 }
60}
61
62impl std::ops::AddAssign for TokenUsage {
63 fn add_assign(&mut self, rhs: TokenUsage) {
64 self.prompt += rhs.prompt;
65 self.completion += rhs.completion;
66 }
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72
73 #[test]
74 fn elapsed_is_zero_for_later_since() {
75 let a = Timestamp(1_000);
76 let b = Timestamp(2_000);
77 assert!((b.elapsed(a) - 0.000_001).abs() < 1e-9);
78 assert_eq!(a.elapsed(b), 0.0);
79 }
80
81 #[test]
82 fn token_usage_accumulates() {
83 let a = TokenUsage {
84 prompt: 10,
85 completion: 5,
86 };
87 let mut total = a + TokenUsage::ZERO;
88 total += TokenUsage {
89 prompt: 1,
90 completion: 2,
91 };
92 assert_eq!(total.total(), 18);
93 assert_eq!(
94 total,
95 TokenUsage {
96 prompt: 11,
97 completion: 7
98 }
99 );
100 }
101}