Skip to main content

openai_cost/
usage.rs

1//! Token usage block.
2
3#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5
6/// Three-field token usage as returned by OpenAI's chat-completion and
7/// responses APIs.
8///
9/// Chat Completions exposes the cached count under
10/// `prompt_tokens_details.cached_tokens`; the Responses API uses
11/// `cached_input_tokens` directly. The `From` impls in this crate flatten
12/// both shapes onto these fields.
13#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
14#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
15#[cfg_attr(feature = "serde", serde(default))]
16pub struct Usage {
17    /// Fresh input/prompt tokens (not served from the prompt cache).
18    pub input_tokens: u64,
19    /// Output/completion tokens.
20    pub output_tokens: u64,
21    /// Input tokens that were served from the prompt cache (cache hit).
22    pub cached_input_tokens: u64,
23}
24
25impl Usage {
26    /// True when the request hit the prompt cache.
27    pub fn cache_hit(&self) -> bool {
28        self.cached_input_tokens > 0
29    }
30
31    /// Total tokens billed (input + output + cached_input).
32    pub fn total_tokens(&self) -> u64 {
33        self.input_tokens + self.output_tokens + self.cached_input_tokens
34    }
35
36    /// Build a Usage from a Chat Completions response.
37    ///
38    /// OpenAI reports `prompt_tokens` as **including** cached tokens, so we
39    /// subtract `cached_tokens` from `prompt_tokens` to get the fresh
40    /// input count this struct expects.
41    pub fn from_chat_completions(
42        prompt_tokens: u64,
43        completion_tokens: u64,
44        cached_tokens: u64,
45    ) -> Self {
46        Self {
47            input_tokens: prompt_tokens.saturating_sub(cached_tokens),
48            output_tokens: completion_tokens,
49            cached_input_tokens: cached_tokens,
50        }
51    }
52
53    /// Build a Usage from a Responses-API response.
54    ///
55    /// On the Responses API, `input_tokens` already excludes cached tokens
56    /// (cached_input_tokens is reported separately).
57    pub fn from_responses_api(
58        input_tokens: u64,
59        output_tokens: u64,
60        cached_input_tokens: u64,
61    ) -> Self {
62        Self {
63            input_tokens,
64            output_tokens,
65            cached_input_tokens,
66        }
67    }
68}