pub struct Usage {
pub prompt_tokens: u64,
pub completion_tokens: u64,
pub total_tokens: u64,
pub cache_read_tokens: u64,
pub cache_write_tokens: u64,
pub reasoning_tokens: u64,
pub server_tool_requests: u64,
}Expand description
Token usage for one completion, in a vendor-neutral shape. Used to enforce the cost budget and to record spend in the trace.
Construct with ..Default::default(): fields are added in minor releases —
0.18.0 added the cache, reasoning and server-tool counters below — and a
literal naming every field is what a widening breaks.
use io_harness::{Containment, Draw, Ledger, Usage};
let ledger = Ledger::new(&Containment::new(4, 2, 1, 10_000));
let usage = Usage {
prompt_tokens: 4_000,
completion_tokens: 500,
total_tokens: 4_500,
// Of those 4,000 prompt tokens, 3,000 were served from the provider's
// cache — which is billed at a fraction of a fresh read, and is why a
// token-only figure understates nothing but overstates the bill.
cache_read_tokens: 3_000,
..Default::default()
};
// `total_tokens` is the figure the budget is enforced in: the provider's own
// total, taken as reported rather than re-derived from the other two.
assert_eq!(ledger.draw_tokens(usage.total_tokens), Draw::Ok);
assert_eq!(ledger.remaining_tokens(), 5_500);
// The cache counters are a *breakdown* of the prompt, not an addition to it:
// adding them to `total_tokens` would double-count what the provider already
// counted once.
assert!(usage.cache_read_tokens <= usage.prompt_tokens);
// A provider that reports nothing gives `None`, not a zero: an unknown cost
// and a free step are different facts, and the loop treats them differently.
let unknown: Option<Usage> = None;
assert_eq!(unknown.map(|u| u.total_tokens), None);Fields§
§prompt_tokens: u64Tokens in the prompt.
completion_tokens: u64Tokens the model generated.
total_tokens: u64Total tokens billed for this completion.
cache_read_tokens: u64(0.18.0) Prompt tokens served from the provider’s cache rather than read
fresh. A breakdown of Usage::prompt_tokens, not an addition to it, and
priced far lower — which is the whole reason to record it separately.
cache_write_tokens: u64(0.18.0) Prompt tokens the provider wrote into its cache on this call.
Also a breakdown of Usage::prompt_tokens, and usually priced above a
fresh read rather than below it.
reasoning_tokens: u64(0.18.0) Tokens the model spent reasoning before answering, where the
provider reports them separately. A breakdown of
Usage::completion_tokens.
server_tool_requests: u64(0.18.0) Provider-executed tool requests — a server-side web search, say — made while serving this completion. Billed per request rather than per token, so a token-only schema under-reports the money silently.
Zero everywhere until the crate declares such tools (0.22.0). The counter exists first so that adding them is not a second widening of this type.
Trait Implementations§
impl Copy for Usage
Source§impl<'de> Deserialize<'de> for Usage
impl<'de> Deserialize<'de> for Usage
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl Eq for Usage
impl StructuralPartialEq for Usage
Auto Trait Implementations§
impl Freeze for Usage
impl RefUnwindSafe for Usage
impl Send for Usage
impl Sync for Usage
impl Unpin for Usage
impl UnsafeUnpin for Usage
impl UnwindSafe for Usage
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
Source§impl<R, P> ReadPrimitive<R> for P
impl<R, P> ReadPrimitive<R> for P
Source§fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
ReadEndian::read_from_little_endian().impl<T> Scalar for T
Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.