use serde::{Deserialize, Serialize};
use serde_with::{serde_as, skip_serializing_none};
#[serde_as]
#[skip_serializing_none]
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct Usage {
pub prompt_tokens: Option<i32>,
pub prompt_tokens_details: Option<PromptTokensDetails>,
pub completion_tokens: Option<i32>,
pub completion_tokens_details: Option<CompletionTokensDetails>,
pub total_tokens: Option<i32>,
}
impl Usage {
pub fn compact_details(&mut self) {
if self.prompt_tokens_details.as_ref().is_some_and(|d| d.is_empty()) {
self.prompt_tokens_details = None;
}
if self.completion_tokens_details.as_ref().is_some_and(|d| d.is_empty()) {
self.completion_tokens_details = None;
}
}
}
#[serde_as]
#[skip_serializing_none]
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct PromptTokensDetails {
#[serde(default, deserialize_with = "crate::support::zero_as_none")]
pub cache_creation_tokens: Option<i32>,
#[serde(default, deserialize_with = "crate::support::zero_as_none")]
pub cached_tokens: Option<i32>,
#[serde(default, deserialize_with = "crate::support::zero_as_none")]
pub audio_tokens: Option<i32>,
}
impl PromptTokensDetails {
pub fn is_empty(&self) -> bool {
self.cache_creation_tokens.is_none() && self.cached_tokens.is_none() && self.audio_tokens.is_none()
}
}
#[serde_as]
#[skip_serializing_none]
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct CompletionTokensDetails {
#[serde(default, deserialize_with = "crate::support::zero_as_none")]
pub accepted_prediction_tokens: Option<i32>,
#[serde(default, deserialize_with = "crate::support::zero_as_none")]
pub rejected_prediction_tokens: Option<i32>,
#[serde(default, deserialize_with = "crate::support::zero_as_none")]
pub reasoning_tokens: Option<i32>,
#[serde(default, deserialize_with = "crate::support::zero_as_none")]
pub audio_tokens: Option<i32>,
}
impl CompletionTokensDetails {
pub fn is_empty(&self) -> bool {
self.accepted_prediction_tokens.is_none()
&& self.rejected_prediction_tokens.is_none()
&& self.reasoning_tokens.is_none()
&& self.audio_tokens.is_none()
}
}