///|
/// Aggregates token usage and call counts across many requests, so an
/// application can report cumulative consumption (and estimated cost).
pub struct UsageTracker {
mut calls : Int
mut prompt_tokens : Int
mut completion_tokens : Int
prompt_price_per_1k : Double
completion_price_per_1k : Double
}
///|
/// Create a tracker. Prices default to 0 (cost reported as 0 until set).
pub fn UsageTracker::new(
prompt_price_per_1k? : Double = 0.0,
completion_price_per_1k? : Double = 0.0,
) -> UsageTracker {
{
calls: 0,
prompt_tokens: 0,
completion_tokens: 0,
prompt_price_per_1k,
completion_price_per_1k,
}
}
///|
/// Record a usage entry (e.g. from a `ChatResponse.usage`).
pub fn UsageTracker::record(self : UsageTracker, usage : Usage) -> Unit {
self.calls = self.calls + 1
self.prompt_tokens = self.prompt_tokens + usage.prompt_tokens
self.completion_tokens = self.completion_tokens + usage.completion_tokens
}
///|
/// Record the usage from a chat response, if it reported any.
pub fn UsageTracker::record_response(
self : UsageTracker,
response : ChatResponse,
) -> Unit {
match response.usage {
Some(u) => self.record(u)
None => self.calls = self.calls + 1
}
}
///|
/// The number of calls recorded.
pub fn UsageTracker::calls(self : UsageTracker) -> Int {
self.calls
}
///|
/// The total tokens across all recorded calls.
pub fn UsageTracker::total_tokens(self : UsageTracker) -> Int {
self.prompt_tokens + self.completion_tokens
}
///|
/// A `Usage` snapshot of the accumulated totals.
pub fn UsageTracker::snapshot(self : UsageTracker) -> Usage {
{
prompt_tokens: self.prompt_tokens,
completion_tokens: self.completion_tokens,
total_tokens: self.total_tokens(),
}
}
///|
/// The estimated cost so far, in dollars, using the configured prices.
pub fn UsageTracker::cost(self : UsageTracker) -> Double {
estimate_cost(
self.prompt_tokens,
self.completion_tokens,
prompt_price_per_1k=self.prompt_price_per_1k,
completion_price_per_1k=self.completion_price_per_1k,
)
}
///|
/// Reset all counters to zero (prices are preserved).
pub fn UsageTracker::reset(self : UsageTracker) -> Unit {
self.calls = 0
self.prompt_tokens = 0
self.completion_tokens = 0
}
///|
/// A one-line human-readable summary of the accumulated usage.
pub fn UsageTracker::summary(self : UsageTracker) -> String {
"calls=\{self.calls} prompt=\{self.prompt_tokens} " +
"completion=\{self.completion_tokens} total=\{self.total_tokens()}"
}