Packages
langchain
0.8.1
0.9.2
0.9.1
0.9.0
0.8.14
0.8.13
0.8.12
0.8.11
0.8.10
0.8.9
0.8.8
0.8.7
0.8.6
0.8.5
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.0
0.6.3
0.6.2
0.6.1
0.6.0
0.5.2
0.5.1
0.5.0
0.4.1
0.4.0
0.4.0-rc.3
0.4.0-rc.2
0.4.0-rc.1
0.4.0-rc.0
0.3.3
0.3.2
0.3.1
0.3.0
0.3.0-rc.2
0.3.0-rc.1
0.3.0-rc.0
0.2.0
0.1.10
0.1.9
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
Elixir implementation of a LangChain style framework that lets Elixir projects integrate with and leverage LLMs.
Current section
Files
Jump to
Current section
Files
lib/telemetry.ex
defmodule LangChain.Telemetry do
@moduledoc """
Telemetry events for LangChain.
This module defines telemetry events that other applications can attach to.
It provides a standardized way to emit events for various operations in the
LangChain library without implementing tracing functionality.
## Event Naming
Events follow the convention: `[:langchain, component, operation, stage]`
## Core Events
* `[:langchain, :llm, :call, :start]` - Emitted when an LLM call starts
* `[:langchain, :llm, :call, :stop]` - Emitted when an LLM call completes
* `[:langchain, :llm, :call, :exception]` - Emitted when an LLM call raises an exception
* `[:langchain, :llm, :prompt]` - Emitted when a prompt is sent to an LLM
* `[:langchain, :llm, :response]` - Emitted when a response is received from an LLM
* `[:langchain, :llm, :response, :non_streaming]` - Emitted when a non-streaming response is received from an LLM
* `[:langchain, :llm, :response, :streaming]` - Emitted when a streaming response is received from an LLM
* `[:langchain, :chain, :execute, :start]` - Emitted when a chain execution starts
* `[:langchain, :chain, :execute, :stop]` - Emitted when a chain execution completes
* `[:langchain, :chain, :execute, :exception]` - Emitted when a chain execution raises an exception
* `[:langchain, :message, :process, :start]` - Emitted when message processing starts
* `[:langchain, :message, :process, :stop]` - Emitted when message processing completes
* `[:langchain, :message, :process, :exception]` - Emitted when message processing raises an exception
* `[:langchain, :tool, :call, :start]` - Emitted when a tool call starts
* `[:langchain, :tool, :call, :stop]` - Emitted when a tool call completes
* `[:langchain, :tool, :call, :exception]` - Emitted when a tool call raises an exception
## Usage
To attach to these events in your application:
```elixir
:telemetry.attach(
"my-handler-id",
[:langchain, :llm, :call, :stop],
&MyApp.handle_llm_call/4,
nil
)
def handle_llm_call(_event_name, measurements, metadata, _config) do
# Process the event
IO.inspect(measurements)
IO.inspect(metadata)
end
```
"""
@doc """
Emits a telemetry event with the given name, measurements, and metadata.
## Parameters
* `event_name` - The name of the event as a list of atoms
* `measurements` - A map of measurements for the event
* `metadata` - A map of metadata for the event
## Examples
iex> LangChain.Telemetry.emit_event([:langchain, :llm, :call, :start], %{system_time: System.system_time()}, %{model: "gpt-4"})
"""
@spec emit_event(list(atom()), map(), map()) :: :ok
def emit_event(event_name, measurements, metadata) do
:telemetry.execute(event_name, measurements, metadata)
end
@doc """
Emits a start event and returns a function to emit the corresponding stop event.
This is useful for span-like events where you want to measure the duration of an operation.
## Parameters
* `event_prefix` - The prefix for the event name as a list of atoms
* `metadata` - A map of metadata for the event
## Returns
A function that accepts additional metadata to be merged with the original metadata
and emits the stop event with the duration measurement.
## Examples
iex> stop_fun = LangChain.Telemetry.start_event([:langchain, :llm, :call], %{model: "gpt-4"})
iex> # Do some work
iex> stop_fun.(%{result: "success"})
"""
@spec start_event(list(atom()), map()) :: (map() -> :ok)
def start_event(event_prefix, metadata) do
start_time = System.monotonic_time()
start_system_time = System.system_time()
emit_event(event_prefix ++ [:start], %{system_time: start_system_time}, metadata)
fn additional_metadata ->
end_time = System.monotonic_time()
duration = end_time - start_time
emit_event(
event_prefix ++ [:stop],
%{duration: duration, system_time: System.system_time()},
Map.merge(metadata, additional_metadata)
)
end
end
@doc """
Wraps a function call with start and stop telemetry events.
## Parameters
* `event_prefix` - The prefix for the event name as a list of atoms
* `metadata` - A map of metadata for the event
* `fun` - The function to execute
## Returns
The result of the function call.
## Examples
iex> LangChain.Telemetry.span([:langchain, :llm, :call], %{model: "gpt-4"}, fn ->
...> # Call the LLM
...> {:ok, "response"}
...> end)
"""
@spec span(list(atom()), map(), (-> result)) :: result when result: any()
def span(event_prefix, metadata, fun) do
stop = start_event(event_prefix, metadata)
try do
result = fun.()
stop.(%{result: result})
result
rescue
exception ->
stacktrace = __STACKTRACE__
emit_event(
event_prefix ++ [:exception],
%{system_time: System.system_time()},
Map.merge(metadata, %{
kind: :error,
error: exception,
stacktrace: stacktrace
})
)
reraise exception, stacktrace
end
end
# LLM Events
@doc """
Emits an LLM call start event.
"""
@spec llm_call_start(map()) :: (map() -> :ok)
def llm_call_start(metadata) do
start_event([:langchain, :llm, :call], metadata)
end
@doc """
Emits an LLM prompt event.
"""
@spec llm_prompt(map(), map()) :: :ok
def llm_prompt(measurements, metadata) do
emit_event([:langchain, :llm, :prompt], measurements, metadata)
end
@doc """
Emits an LLM response event.
"""
@spec llm_response(map(), map()) :: :ok
def llm_response(measurements, metadata) do
emit_event([:langchain, :llm, :response], measurements, metadata)
end
# Chain Events
@doc """
Emits a chain execution start event.
"""
@spec chain_execute_start(map()) :: (map() -> :ok)
def chain_execute_start(metadata) do
start_event([:langchain, :chain, :execute], metadata)
end
# Message Events
@doc """
Emits a message processing start event.
"""
@spec message_process_start(map()) :: (map() -> :ok)
def message_process_start(metadata) do
start_event([:langchain, :message, :process], metadata)
end
# Tool Events
@doc """
Emits a tool call start event.
"""
@spec tool_call_start(map()) :: (map() -> :ok)
def tool_call_start(metadata) do
start_event([:langchain, :tool, :call], metadata)
end
@doc """
Emits a tool call event.
"""
@spec tool_call(map(), map()) :: :ok
def tool_call(measurements, metadata) do
emit_event([:langchain, :tool, :call], measurements, metadata)
end
# Memory Events
@doc """
Emits a memory read start event.
"""
@spec memory_read_start(map()) :: (map() -> :ok)
def memory_read_start(metadata) do
start_event([:langchain, :memory, :read], metadata)
end
@doc """
Emits a memory write start event.
"""
@spec memory_write_start(map()) :: (map() -> :ok)
def memory_write_start(metadata) do
start_event([:langchain, :memory, :write], metadata)
end
# Retriever Events
@doc """
Emits a retriever get relevant documents start event.
"""
@spec retriever_get_relevant_documents_start(map()) :: (map() -> :ok)
def retriever_get_relevant_documents_start(metadata) do
start_event([:langchain, :retriever, :get_relevant_documents], metadata)
end
end