ALLM.Pipeline.LLMCallLog (allm_pipeline v0.1.0)

Copy Markdown View Source

Per-step collector for full LLM-call inputs/outputs.

The Executor calls activate/0 in the step process before execute/2 and drain/0 after; a host's LLM engine's generate_structured/4 calls record/1 for each call. The active collector pid lives in the step process's dictionary and is resolved from child tasks via the same :"$callers" walk the host engine uses for engine injection, so a future Task.async/Task.async_stream fan-out still records into the right step.

Lifecycle

  1. activate/0 — start an empty Agent collector and stash its pid in the current process's dictionary. No-op (returns :ok, stashes nothing) when logging is disabled.
  2. record/1 — append one captured call entry. Resolves the collector via the current process dict, then the :"$callers" ancestor chain. No-op when no collector is reachable (logging off, or record/1 called outside an activated step).
  3. drain/0 — read the pid from the current process dict only (the step process that called activate/0), return entries in chronological order, stop the agent, and delete the dict key.

Configuration

Logging is on by default, governed by an explicit config key on this module:

config :allm_pipeline, ALLM.Pipeline.LLMCallLog, enabled: true

Set enabled: false to make activate/0 and record/1 zero-cost no-ops.

Summary

Types

One logical LLM call's captured input/output.

Functions

Start a collector in the current process and stash its pid in the process dictionary. No-op when logging is disabled. Always returns :ok.

Drain the current step's collector: return its entries in chronological order, stop the agent, and delete the dict key. Returns [] when no collector is active on the current process.

Whether LLM-call logging is enabled (default true).

Append entry to the active collector for the current step.

Types

entry()

@type entry() :: %{optional(atom()) => term()}

One logical LLM call's captured input/output.

Built by LLMEngine.generate_structured/4; the map carries the redacted messages, the schema_name, the requested model / adapter / params, and — depending on outcome — the raw response_text / usage / finish_reason / served_model, or an error string. The exact keys are owned by the recorder; this module treats entries as opaque maps.

Functions

activate()

@spec activate() :: :ok

Start a collector in the current process and stash its pid in the process dictionary. No-op when logging is disabled. Always returns :ok.

drain()

@spec drain() :: [entry()]

Drain the current step's collector: return its entries in chronological order, stop the agent, and delete the dict key. Returns [] when no collector is active on the current process.

enabled?()

@spec enabled?() :: boolean()

Whether LLM-call logging is enabled (default true).

Reads :enabled from config :allm_pipeline, ALLM.Pipeline.LLMCallLog.

record(entry)

@spec record(entry()) :: :ok

Append entry to the active collector for the current step.

Resolves the collector pid via the current process dict, then the :"$callers" ancestor chain. No-op when none is reachable.