Packages
nous
0.14.3
0.17.0
0.16.6
0.16.5
0.16.4
0.16.3
0.16.2
0.16.1
0.16.0
0.15.8
0.15.7
0.15.6
0.15.5
0.15.4
0.15.3
0.15.2
0.15.1
0.15.0
0.14.3
0.14.2
0.14.1
0.14.0
0.13.3
0.13.2
0.13.1
0.13.0
0.12.17
0.12.16
0.12.15
0.12.14
0.12.13
0.12.12
0.12.11
0.12.9
0.12.7
0.12.6
0.12.5
0.12.3
0.12.2
0.12.0
0.11.3
0.11.0
0.10.1
0.10.0
0.9.0
0.8.1
0.8.0
0.7.2
0.7.1
0.7.0
0.5.0
AI agent framework for Elixir with multi-provider LLM support
Current section
Files
Jump to
Current section
Files
lib/nous/usage.ex
defmodule Nous.Usage do
@moduledoc """
Tracks resource usage for agent runs.
Usage tracking helps monitor costs and performance across agent executions.
You can aggregate usage from multiple agent runs to track total consumption.
## Example
usage = Usage.new()
usage = Usage.inc_requests(usage)
usage = Usage.add_tokens(usage, input: 100, output: 50)
IO.inspect(usage.total_tokens) # 150
"""
@type t :: %__MODULE__{
requests: non_neg_integer(),
tool_calls: non_neg_integer(),
input_tokens: non_neg_integer(),
output_tokens: non_neg_integer(),
total_tokens: non_neg_integer()
}
@enforce_keys []
defstruct requests: 0,
tool_calls: 0,
input_tokens: 0,
output_tokens: 0,
total_tokens: 0
@doc """
Create a new empty usage tracker.
## Example
usage = Usage.new()
# %Usage{requests: 0, total_tokens: 0, ...}
"""
@spec new() :: t()
def new, do: %__MODULE__{}
@doc """
Add two usage trackers together.
Useful for aggregating usage across multiple agent runs.
## Example
usage1 = %Usage{requests: 1, total_tokens: 100}
usage2 = %Usage{requests: 2, total_tokens: 200}
total = Usage.add(usage1, usage2)
# %Usage{requests: 3, total_tokens: 300}
"""
@spec add(t(), t()) :: t()
def add(%__MODULE__{} = u1, %__MODULE__{} = u2) do
%__MODULE__{
requests: u1.requests + u2.requests,
tool_calls: u1.tool_calls + u2.tool_calls,
input_tokens: u1.input_tokens + u2.input_tokens,
output_tokens: u1.output_tokens + u2.output_tokens,
total_tokens: u1.total_tokens + u2.total_tokens
}
end
@doc """
Increment request count by 1.
## Example
usage = Usage.new() |> Usage.inc_requests()
# %Usage{requests: 1, ...}
"""
@spec inc_requests(t()) :: t()
def inc_requests(%__MODULE__{} = usage) do
%{usage | requests: usage.requests + 1}
end
@doc """
Increment tool call count.
## Example
usage = Usage.new() |> Usage.inc_tool_calls(3)
# %Usage{tool_calls: 3, ...}
"""
@spec inc_tool_calls(t(), non_neg_integer()) :: t()
def inc_tool_calls(%__MODULE__{} = usage, count \\ 1) do
%{usage | tool_calls: usage.tool_calls + count}
end
@doc """
Add token counts from options.
## Options
* `:input` - Number of input tokens (default: 0)
* `:output` - Number of output tokens (default: 0)
## Example
usage = Usage.new()
usage = Usage.add_tokens(usage, input: 50, output: 30)
# %Usage{input_tokens: 50, output_tokens: 30, total_tokens: 80}
"""
@spec add_tokens(t(), keyword()) :: t()
def add_tokens(%__MODULE__{} = usage, opts) do
input = Keyword.get(opts, :input, 0)
output = Keyword.get(opts, :output, 0)
%{
usage
| input_tokens: usage.input_tokens + input,
output_tokens: usage.output_tokens + output,
total_tokens: usage.total_tokens + input + output
}
end
@doc """
Create usage from OpenAI API usage format.
Converts the usage object from OpenAI responses to our format.
## Example
openai_usage = %{
prompt_tokens: 100,
completion_tokens: 50,
total_tokens: 150
}
usage = Usage.from_openai(openai_usage)
# %Usage{input_tokens: 100, output_tokens: 50, total_tokens: 150}
"""
@spec from_openai(map()) :: t()
def from_openai(openai_usage) when is_map(openai_usage) do
%__MODULE__{
requests: 1,
input_tokens: Map.get(openai_usage, :prompt_tokens, 0),
output_tokens: Map.get(openai_usage, :completion_tokens, 0),
total_tokens: Map.get(openai_usage, :total_tokens, 0)
}
end
end