Skip to main content

Collector

info

Added in version 0.79.0

The Collector allows you to inspect the internal state of BAML function calls, including raw HTTP requests, responses, usage metrics, and timing information.

Syntax​

from baml_py import Collector

collector = Collector(name="my-collector")
result = b.MyFunction("input", baml_options={"collector": collector})

print(collector.last.usage)
print(collector.last.raw_llm_response)

Collector Properties​

PropertyTypeDescription
logsList[FunctionLog]All function calls (oldest to newest)
lastFunctionLog | nullMost recent function log
usageUsageCumulative total usage across all tracked requests

Collector Methods​

MethodDescription
clear()Clears all logs

FunctionLog Properties​

PropertyTypeDescription
idstringRequest ID
function_namestringName of the function
log_type"call" | "stream"How the function was called
timingTimingRequest timing information
usageUsageToken usage (aggregated from all calls)
callsLLMCall[]Every call made (including retries/fallbacks)
selected_callLLMCall?The call used for parsing the response
raw_llm_responsestring | nullRaw text from the LLM
tagsMap[str, any]User-provided metadata

Usage Properties​

PropertyTypeDescription
input_tokensint | nullCumulative input tokens
output_tokensint | nullCumulative output tokens
cached_input_tokensint | nullCached input tokens (for providers with caching)

Examples​

Basic Logging​

from baml_client import b
from baml_py import Collector

collector = Collector(name="my-collector")
res = b.ExtractResume("...", baml_options={"collector": collector})

# Access the last request
print(collector.last.id)
print(collector.last.usage)
print(collector.last.raw_llm_response)

# Access raw HTTP response
print(collector.last.calls[-1].http_response)

Tags​

Attach custom metadata to function calls:

from baml_client import b
from baml_client.tracing import trace, set_tags
from baml_py import Collector

@trace
async def run_with_tags():
# Parent trace tags
set_tags(parent_id="p123", run="xyz")

collector = Collector(name="tags-collector")

# Per-call tags
await b.TestFunction(
"hi",
baml_options={"collector": collector, "tags": {"call_id": "first"}},
)

# Tags are merged
print(collector.last.tags) # {'parent_id': 'p123', 'run': 'xyz', 'call_id': 'first'}

Multiple Collectors​

from baml_client import b
from baml_py import Collector

collector_a = Collector(name="collector-a")
collector_b = Collector(name="collector-b")

# Use both collectors for the same call
res = b.ExtractResume("...", baml_options={"collector": [collector_a, collector_b]})

# Both have the same logs
assert collector_a.last.usage.input_tokens == collector_b.last.usage.input_tokens

# Use only collector_a for another call
res2 = b.TestFunction("another call", baml_options={"collector": collector_a})

# collector_a has 2 logs, collector_b has 1
assert len(collector_a.logs) == 2
assert len(collector_b.logs) == 1

Accessing SSE Responses (Streaming)​

from baml_client import b
from baml_py import Collector

async def run():
collector = Collector(name="stream-collector")

stream = b.stream.ExtractResume("...", baml_options={"collector": collector})
async for chunk in stream:
print(chunk)

# Access raw SSE responses
log = collector.last
if log and log.selected_call:
sse_responses = log.selected_call.sse_responses()
if sse_responses:
for sse in sse_responses:
print(f"Raw: {sse.text}")
parsed = sse.json()
if parsed:
print(f"JSON: {parsed}")

Cached Token Tracking​

For providers with prompt caching (Anthropic, OpenAI, Google, Vertex):

from baml_client import b
from baml_py import Collector

async def run():
collector = Collector(name="cache-tracker")

# First call - content cached by provider
res = await b.TestCaching(large_content, "Question 1", baml_options={"collector": collector})

# Second call - uses cached tokens
res2 = await b.TestCaching(large_content, "Question 2", baml_options={"collector": collector})

first_log = collector.logs[0]
second_log = collector.logs[1]

print(f"First call cached tokens: {first_log.usage.cached_input_tokens}")
print(f"Second call cached tokens: {second_log.usage.cached_input_tokens}")
print(f"Total cached tokens: {collector.usage.cached_input_tokens}")

LLMCall Properties​

PropertyTypeDescription
client_namestrName of the client used
providerstrProvider of the client
timingTimingRequest timing
http_requestHttpRequestRaw HTTP request
http_responseHttpResponse | nullRaw HTTP response (null for streaming)
usageUsage | nullToken usage
selectedboolWhether this call was used for parsing

Timing Properties​

PropertyTypeDescription
start_time_utc_msintStart time in milliseconds since epoch
duration_msint | nullDuration in milliseconds

HttpRequest Properties​

PropertyTypeDescription
urlstrRequest URL
methodstrHTTP method
headersobjectRequest headers
bodyHTTPBodyRequest body

HttpResponse Properties​

PropertyTypeDescription
statusintHTTP status code
headersobjectResponse headers
bodyHTTPBodyResponse body

HTTPBody Methods​

MethodReturnsDescription
text()stringBody as string
json()objectBody as JSON object

SSEResponse Properties​

Property/MethodTypeDescription
textstringRaw text of the SSE data field
json()object | nullParse as JSON (null if invalid)

See Also​