pub struct TokenTrackingLLM<L: BaseChatModel> { /* private fields */ }Expand description
LLM wrapper with token statistics
Wraps any BaseChatModel, accumulating prompt / completion token usage automatically,
preferring the real usage returned by the LLM, falling back to tiktoken estimates.
v0.20.1: implements BaseChatModel itself, so a tracked LLM can be plugged
directly into framework agents (e.g. FunctionCallingAgent::new); every
chat/stream/bind_tools call inside the agent loop is counted, and
get_usage/estimate_cost reflect the cumulative agent-run usage.
Implementations§
Source§impl<L: BaseChatModel> TokenTrackingLLM<L>
impl<L: BaseChatModel> TokenTrackingLLM<L>
Sourcepub fn new(llm: L, counter: Arc<dyn TokenCounter>) -> Self
pub fn new(llm: L, counter: Arc<dyn TokenCounter>) -> Self
Wraps an LLM with a custom counter.
Sourcepub fn for_openai(llm: L) -> Result<Self, TokenCounterError>
pub fn for_openai(llm: L) -> Result<Self, TokenCounterError>
Wraps with a Tiktoken (cl100k_base) counter
Sourcepub fn with_metrics_sink(self, sink: Arc<dyn MetricsSink>) -> Self
pub fn with_metrics_sink(self, sink: Arc<dyn MetricsSink>) -> Self
Attaches an observability sink: after each call that reports usage the
wrapper exports a TokenUsage event (real when the provider reports it,
otherwise the tiktoken estimate). The sink is shared across wrappers
rebuilt by bind_tools/with_temperature/with_max_tokens.
Sourcepub fn with_cost_tracker(self, tracker: Arc<CostTracker>) -> Self
pub fn with_cost_tracker(self, tracker: Arc<CostTracker>) -> Self
Attaches a CostTracker (B3): every counted call is priced under the
model’s provider/id and aggregated on the shared tracker. Share one
Arc<CostTracker> across models/runs to get per-run or per-session
totals. The tracker keeps working when the model has no price entry
(tokens/calls counted, cost 0).
Sourcepub fn with_provider(self, provider: impl Into<String>) -> Self
pub fn with_provider(self, provider: impl Into<String>) -> Self
Declares the provider slug ("openai", "anthropic", …) used when
looking up prices. Defaults to None (model-only table lookup).
Sourcepub async fn chat(
&self,
messages: Vec<Message>,
config: Option<RunnableConfig>,
) -> Result<LLMResult, L::Error>
pub async fn chat( &self, messages: Vec<Message>, config: Option<RunnableConfig>, ) -> Result<LLMResult, L::Error>
Calls the LLM and counts tokens.
Inherent method (kept for backward compatibility); delegates to
Self::chat_tracked. When the model is reached through
dyn BaseChatModel (e.g. inside an agent), the trait chat takes over —
both count through the same helper, so the two paths never diverge.
Sourcepub async fn get_usage(&self) -> TrackerTokenUsage
pub async fn get_usage(&self) -> TrackerTokenUsage
Returns the cumulative usage
Sourcepub async fn estimate_cost(&self, pricing: &ModelPricing) -> f64
pub async fn estimate_cost(&self, pricing: &ModelPricing) -> f64
Estimates the cost (USD)
Trait Implementations§
Source§impl<L> BaseChatModel for TokenTrackingLLM<L>
impl<L> BaseChatModel for TokenTrackingLLM<L>
Source§fn chat<'life0, 'async_trait>(
&'life0 self,
messages: Vec<Message>,
config: Option<RunnableConfig>,
) -> Pin<Box<dyn Future<Output = Result<LLMResult, Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn chat<'life0, 'async_trait>(
&'life0 self,
messages: Vec<Message>,
config: Option<RunnableConfig>,
) -> Pin<Box<dyn Future<Output = Result<LLMResult, Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn stream_chat<'life0, 'async_trait>(
&'life0 self,
messages: Vec<Message>,
config: Option<RunnableConfig>,
) -> Pin<Box<dyn Future<Output = Result<Pin<Box<dyn Stream<Item = Result<StreamChunk, Self::Error>> + Send>>, Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn stream_chat<'life0, 'async_trait>(
&'life0 self,
messages: Vec<Message>,
config: Option<RunnableConfig>,
) -> Pin<Box<dyn Future<Output = Result<Pin<Box<dyn Stream<Item = Result<StreamChunk, Self::Error>> + Send>>, Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn bind_tools(
&self,
tools: Vec<ToolDefinition>,
) -> Option<Box<dyn BaseChatModel<Error = Self::Error> + Send + Sync>>
fn bind_tools( &self, tools: Vec<ToolDefinition>, ) -> Option<Box<dyn BaseChatModel<Error = Self::Error> + Send + Sync>>
Source§impl<L> BaseLanguageModel<Vec<Message>, LLMResult> for TokenTrackingLLM<L>
impl<L> BaseLanguageModel<Vec<Message>, LLMResult> for TokenTrackingLLM<L>
Source§fn model_name(&self) -> &str
fn model_name(&self) -> &str
Source§fn temperature(&self) -> Option<f32>
fn temperature(&self) -> Option<f32>
Source§fn max_tokens(&self) -> Option<usize>
fn max_tokens(&self) -> Option<usize>
Source§fn with_temperature(self, temp: f32) -> Selfwhere
Self: Sized,
fn with_temperature(self, temp: f32) -> Selfwhere
Self: Sized,
Source§fn with_max_tokens(self, max: usize) -> Selfwhere
Self: Sized,
fn with_max_tokens(self, max: usize) -> Selfwhere
Self: Sized,
Source§impl<L> Runnable<Vec<Message>, LLMResult> for TokenTrackingLLM<L>
impl<L> Runnable<Vec<Message>, LLMResult> for TokenTrackingLLM<L>
Source§fn invoke<'life0, 'async_trait>(
&'life0 self,
input: Vec<Message>,
config: Option<RunnableConfig>,
) -> Pin<Box<dyn Future<Output = Result<LLMResult, Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn invoke<'life0, 'async_trait>(
&'life0 self,
input: Vec<Message>,
config: Option<RunnableConfig>,
) -> Pin<Box<dyn Future<Output = Result<LLMResult, Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn stream<'life0, 'async_trait>(
&'life0 self,
input: Vec<Message>,
config: Option<RunnableConfig>,
) -> Pin<Box<dyn Future<Output = Result<Pin<Box<dyn Stream<Item = Result<LLMResult, Self::Error>> + Send>>, Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn stream<'life0, 'async_trait>(
&'life0 self,
input: Vec<Message>,
config: Option<RunnableConfig>,
) -> Pin<Box<dyn Future<Output = Result<Pin<Box<dyn Stream<Item = Result<LLMResult, Self::Error>> + Send>>, Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn batch<'life0, 'async_trait>(
&'life0 self,
inputs: Vec<Input>,
config: Option<RunnableConfig>,
) -> Pin<Box<dyn Future<Output = Result<Vec<Output>, Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn batch<'life0, 'async_trait>(
&'life0 self,
inputs: Vec<Input>,
config: Option<RunnableConfig>,
) -> Pin<Box<dyn Future<Output = Result<Vec<Output>, Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn batch_as_completed<'life0, 'async_trait>(
&'life0 self,
inputs: Vec<Input>,
config: Option<RunnableConfig>,
) -> Pin<Box<dyn Future<Output = Result<Vec<(usize, Output)>, Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn batch_as_completed<'life0, 'async_trait>(
&'life0 self,
inputs: Vec<Input>,
config: Option<RunnableConfig>,
) -> Pin<Box<dyn Future<Output = Result<Vec<(usize, Output)>, Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn transform<'life0, 'async_trait>(
&'life0 self,
input: Pin<Box<dyn Stream<Item = Result<Input, Self::Error>> + Send>>,
config: Option<RunnableConfig>,
) -> Pin<Box<dyn Future<Output = Result<Pin<Box<dyn Stream<Item = Result<Output, Self::Error>> + Send + '_>>, Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn transform<'life0, 'async_trait>(
&'life0 self,
input: Pin<Box<dyn Stream<Item = Result<Input, Self::Error>> + Send>>,
config: Option<RunnableConfig>,
) -> Pin<Box<dyn Future<Output = Result<Pin<Box<dyn Stream<Item = Result<Output, Self::Error>> + Send + '_>>, Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Auto Trait Implementations§
impl<L> !RefUnwindSafe for TokenTrackingLLM<L>
impl<L> !UnwindSafe for TokenTrackingLLM<L>
impl<L> Freeze for TokenTrackingLLM<L>where
L: Freeze,
impl<L> Send for TokenTrackingLLM<L>
impl<L> Sync for TokenTrackingLLM<L>
impl<L> Unpin for TokenTrackingLLM<L>where
L: Unpin,
impl<L> UnsafeUnpin for TokenTrackingLLM<L>where
L: UnsafeUnpin,
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
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> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
Source§impl<I, O, R> RunnableExt<I, O> for R
impl<I, O, R> RunnableExt<I, O> for R
Source§fn pipe<O2, R2>(self, other: R2) -> RunnableSequence<Input, O2>
fn pipe<O2, R2>(self, other: R2) -> RunnableSequence<Input, O2>
Source§fn into_sequence(self) -> RunnableSequence<Input, Output>
fn into_sequence(self) -> RunnableSequence<Input, Output>
RunnableSequence from this runnable as a single step. Read moreSource§fn with_fallbacks<R>(
self,
fallbacks: Vec<R>,
) -> RunnableWithFallbacks<Input, Output>
fn with_fallbacks<R>( self, fallbacks: Vec<R>, ) -> RunnableWithFallbacks<Input, Output>
Source§fn with_retry(self, retry_config: RetryConfig) -> RunnableRetry<Input, Output>where
Input: Clone,
fn with_retry(self, retry_config: RetryConfig) -> RunnableRetry<Input, Output>where
Input: Clone,
Source§fn configurable_alternatives<K, R>(
self,
which: impl Into<String>,
default_key: impl Into<String>,
alternatives: Vec<(K, R)>,
) -> RunnableConfigurable<Input, Output>
fn configurable_alternatives<K, R>( self, which: impl Into<String>, default_key: impl Into<String>, alternatives: Vec<(K, R)>, ) -> RunnableConfigurable<Input, Output>
Source§fn configurable_fields(self) -> RunnableConfigurableFields<Input, Output>
fn configurable_fields(self) -> RunnableConfigurableFields<Input, Output>
config.configurable (Python’s Runnable.configurable_fields). Read moreSource§impl<M> StreamingStructuredOutputExt for Mwhere
M: BaseChatModel,
impl<M> StreamingStructuredOutputExt for Mwhere
M: BaseChatModel,
Source§fn stream_structured_output<'life0, 'life1, 'async_trait, T>(
&'life0 self,
schema: Value,
prompt: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Pin<Box<dyn Stream<Item = Result<T, StructuredOutputError>> + Send>>, StructuredOutputError>> + Send + 'async_trait>>
fn stream_structured_output<'life0, 'life1, 'async_trait, T>( &'life0 self, schema: Value, prompt: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<Pin<Box<dyn Stream<Item = Result<T, StructuredOutputError>> + Send>>, StructuredOutputError>> + Send + 'async_trait>>
Source§impl<M> StructuredOutputExt for Mwhere
M: BaseChatModel,
impl<M> StructuredOutputExt for Mwhere
M: BaseChatModel,
Source§fn with_structured_output<'life0, 'life1, 'async_trait, T>(
&'life0 self,
schema: Value,
prompt: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<T, StructuredOutputError>> + Send + 'async_trait>>where
T: 'async_trait + DeserializeOwned + Serialize + Send + Sync + 'static,
Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn with_structured_output<'life0, 'life1, 'async_trait, T>(
&'life0 self,
schema: Value,
prompt: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<T, StructuredOutputError>> + Send + 'async_trait>>where
T: 'async_trait + DeserializeOwned + Serialize + Send + Sync + 'static,
Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
T. Read more