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}