LangChain.TokenUsage (LangChain v0.13.0)

Copy Markdown View Source

Contains token usage information returned from an LLM.

Example

%TokenUsage{
  input: 30,
  output: 15,
  raw: %{
    "total_tokens" => 29
  }
}

Input is the tokens from the prompt. Output is the completion or generated tokens returned.

Refer to the raw token usage information for access to LLM-specific information that may be available.

Combining usage

Two different questions call for two different combinations, and the caller knows which one it is asking:

  • add/2 combines several readings of the same message, as a streamed response produces. Each reading is a snapshot of the message so far, so the combination keeps the largest count per field.

  • add_total/2 combines the final usage of different messages into a running total for a conversation. Each operand is already settled for its own message, so the combination sums them.

Summary

Functions

Combines two readings of the same message into one.

Adds one completed message's usage to a running total across messages.

Extracts token usage information from a LangChain.Message or LangChain.MessageDelta struct's metadata. Returns nil if no token usage information is found.

Build a new TokenUsage and return an :ok/:error tuple with the result.

Build a new TokenUsage and return it or raise an error if invalid.

Sets the token usage information on a LangChain.Message or LangChain.MessageDelta struct in the metadata under the :usage key.

Sets the token usage information on a LangChain.Message or LangChain.MessageDelta struct when wrapped in an :ok,:error tuple in the metadata under the :usage key.

Return the total token usage amount. The total is the sum of input and output.

Types

t()

@type t() :: %LangChain.TokenUsage{input: term(), output: term(), raw: term()}

Functions

add(usage, usage)

@spec add(t() | nil, t() | nil) :: t() | nil

Combines two readings of the same message into one.

A streamed response reports usage more than once, and each reading is a snapshot of the message so far rather than a description of one delta's share. Anthropic opens with the input classes on message_start and closes with a total on message_delta; Gemini repeats the running totals on every chunk; OpenAI-shaped providers answer with a single snapshot on a usage-only terminal chunk. Combining snapshots keeps the larger of the two readings per field.

Token counts are counters, so a count never decreases while a message is being generated. Providers differ in how completely each reading repeats the picture: some report every class every time, some report only the classes that changed, and some normalize an unreported class to zero. Keeping the larger reading is correct under all three -- a fuller reading advances the total, and a partial one cannot erase a class it never meant to describe.

The raw maps are merged the same way, at every depth, so map-valued usage details such as prompt_tokens_details and completion_tokens_details advance per-key rather than the later map replacing the earlier one. A detail reported as a list of per-modality objects, the shape Gemini uses for promptTokensDetails, offers no key to advance against and is taken from the later usage whole.

Keeping the larger count is sound for a primitive counter. A raw key holding a value derived from other counts within a single reading, such as a total_tokens an adapter computes as input + output, is only meaningful alongside the reading it came from and does not survive the merge intact. Read the total from total/1 rather than from raw.

To total usage across different messages, use add_total/2.

If both arguments are nil, returns nil. If one argument is nil, returns the non-nil argument.

Example

iex> alias LangChain.TokenUsage
iex> opening = TokenUsage.new!(%{input: 25, output: 1, raw: %{"input_tokens" => 25}})
iex> closing = TokenUsage.new!(%{output: 15, raw: %{"output_tokens" => 15}})
iex> combined = TokenUsage.add(opening, closing)
iex> {combined.input, combined.output}
{25, 15}
iex> combined.raw
%{"input_tokens" => 25, "output_tokens" => 15}

add_total(usage, usage)

@spec add_total(t() | nil, t() | nil) :: t() | nil

Adds one completed message's usage to a running total across messages.

Use this, rather than add/2, whenever the two operands are totals for different messages. Each assembled message's usage is already final for that message, so the values are summed, at every depth of the raw map.

If both arguments are nil, returns nil. If one argument is nil, returns the non-nil argument.

Example

iex> alias LangChain.TokenUsage
iex> first = TokenUsage.new!(%{input: 100, output: 20})
iex> second = TokenUsage.new!(%{input: 150, output: 35})
iex> total = TokenUsage.add_total(first, second)
iex> {total.input, total.output}
{250, 55}

get(arg1)

@spec get(any()) :: t() | nil

Extracts token usage information from a LangChain.Message or LangChain.MessageDelta struct's metadata. Returns nil if no token usage information is found.

Example

iex> message = %LangChain.Message{metadata: %{usage: %LangChain.TokenUsage{input: 10, output: 20}}}
iex> LangChain.TokenUsage.get(message)
%LangChain.TokenUsage{input: 10, output: 20}

iex> message = %LangChain.Message{metadata: %{}}
iex> LangChain.TokenUsage.get(message)
nil

new(attrs \\ %{})

@spec new(attrs :: map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()}

Build a new TokenUsage and return an :ok/:error tuple with the result.

new!(attrs \\ %{})

@spec new!(attrs :: map()) :: t() | no_return()

Build a new TokenUsage and return it or raise an error if invalid.

set(message, usage)

@spec set(any(), nil | t()) :: any()

Sets the token usage information on a LangChain.Message or LangChain.MessageDelta struct in the metadata under the :usage key.

Example

iex> message = %LangChain.Message{metadata: %{}}
iex> token_usage = %LangChain.TokenUsage{input: 10, output: 20}
iex> LangChain.TokenUsage.set(message, token_usage)
%LangChain.Message{metadata: %{usage: %LangChain.TokenUsage{input: 10, output: 20}}}

set_wrapped(message, usage)

@spec set_wrapped(
  {:ok, %{metadata: nil | map()}} | {:error, any()} | any(),
  nil | t()
) ::
  {:ok, %{metadata: %{usage: t()}}} | {:error, any()} | any()

Sets the token usage information on a LangChain.Message or LangChain.MessageDelta struct when wrapped in an :ok,:error tuple in the metadata under the :usage key.

total(usage)

@spec total(t()) :: integer()

Return the total token usage amount. The total is the sum of input and output.

A count a provider never reported is nil and contributes nothing to the total. Anthropic's closing message_delta event, for one, carries only output_tokens, so a usage built from it alone has no input count.