Create a run trace
Usage
gr_trace(run_id = NULL, meta = list())
# S3 method for class 'gr_trace'
as.data.frame(x, row.names = NULL, optional = FALSE, ...)Arguments
- run_id
Optional identifier; generated when omitted.
- meta
Named list of run-level metadata.
- x
A
gr_trace.- row.names
Optional row names for the result.
- optional, ...
Ignored; part of the
as.data.frame()generic.
Value
A gr_trace. It is an environment, so it accumulates by reference:
pass the same trace to several calls and they all record into it. Fields:
run_id, started, meta, steps, calls, cached, tokens_in,
tokens_out, errors, budget_stop, stop_reason, spent_usd.
cached counts the calls answered from a gr_cache() or a
gr_replay_client() rather than the network, so calls - cached is what
the run paid for.
budget_stop is TRUE once a limit stopped the run, and stop_reason
says which: "calls" for max_calls, "cost" for max_cost_usd (see
gr_options()). spent_usd is what the calls so far cost, the figure
max_cost_usd is checked against. A call to a model with no registered
price adds nothing to it, so gr_trace_cost() is the full account.
as.data.frame() on a trace returns one row per request; see below.
One row per request
as.data.frame(trace) has one row for each request the run made, in the
order they were made, and none for local steps such as segmentation:
stepThe step's number in
trace$steps, where the full record is.documentThe document the request was about, when the run recorded one: the file name, web address or
"<inline text>".recipeThe recipe the request belonged to, when recorded.
stageWhat the request was for, such as
"map.answer"or"reduce".model,ok,cachedThe model, whether a usable reply came back, and whether it came from a
gr_cache()or agr_replay_client().tokens_in,tokens_outThe size of the prompt and the reply.
usdWhat the request cost, 0 when it came from a cache.
NAwhen the model has no registered price, as ingr_trace_cost(), whose total the column adds up to.secondsHow long the request took, retries included.
NAfor a trace written by a version of readgpt that did not time requests.errorThe error, or
NA.prompt,replyThe messages sent, each as
"[role] text", and the text that came back.
Examples
tr <- gr_trace(meta = list(purpose = "demo"))
cl <- gr_mock_client(function(m, p) "an answer")
ch <- gr_segment(readgpt_example(), list(method = "sentence", max_tokens = 150))
#> Using cached ingestion for this document + settings.
#> Segmenting with 'sentence' (cap 150 tokens, overlap 0).
invisible(gr_read(ch, "What was revenue?", cl, "map_reduce", trace = tr))
#> Reading with 'map_reduce' (all|N+logN|tree) over 5 chunk(s).
print(tr)
#> <gr_trace run_20260924000658.747_3116bd> 7 steps, 6 model calls, 1079 in / 36 out tokens, 0 error(s)
#> steps: map.answer x5, preflight x1, reduce x1
#> cost: $0.0026 across gpt-5.6-terra
# One row per request, with what each cost and how long it took.
reqs <- as.data.frame(tr)
reqs[, c("step", "stage", "tokens_in", "tokens_out", "usd", "seconds")]
#> step stage tokens_in tokens_out usd seconds
#> 1 2 map.answer 196 6 0.000464 0.000
#> 2 3 map.answer 206 6 0.000484 0.000
#> 3 4 map.answer 183 6 0.000438 0.001
#> 4 5 map.answer 189 6 0.000450 0.000
#> 5 6 map.answer 160 6 0.000392 0.000
#> 6 7 reduce 145 6 0.000362 0.000