Trace File Formats
Many trace files are formatted in ways that need to be specially handled to create an accurate replay. This guide covers all trace file formats currently supported by GuideLLM, along with the format-agnostic and format-specific data arguments.
Detailed use of the replay profile and file-based datasets as a whole is explained in Trace Replay Benchmarking.
Supported Formats
These are passed to the --data argument as kind=format:
trace_synthetic: A trace format that does the bare minimum needed to complete a fully functioning trace replay benchmark with synthetic prompt generationmooncake: The trace format used by the serving platform Mooncake, as defined in https://doi.org/10.48550/arXiv.2407.00079weka: The trace format used by WEKA's Augmented Memory Grid, as specified in the original research repository
Loading Trace Data
Trace replay always uses --profile kind=replay. Choose a format (trace_synthetic, mooncake, or weka) and a source type from one of the other deserializer kinds (json_file, huggingface, etc). For example:
trace_synthetic with local json_file:
guidellm run \
--backend kind=openai_http,target=http://localhost:8000 \
--profile kind=replay \
--data kind=trace_synthetic,source.kind=json_file,source.path=replay.jsonl,time_scale=1.0
WEKA dataset from huggingface:
guidellm run \
--backend kind=openai_http,target=http://localhost:8000 \
--profile kind=replay \
--data kind=weka,source.kind=huggingface,source.source=semianalysisai/cc-traces-weka-no-subagents-051226,load_kwargs.split=train
Mooncake dataset from huggingface
--backend kind=openai_http,target=http://localhost:8000 \
--profile kind=replay \
--data kind=weka,source.kind=hf,source.src=valeriol29/mooncake-traces,load_kwargs.name=mooncake
Format-Agnostic Data Arguments
All trace formats can accept the following optional data arguments:
| Argument | Default | Description |
|---|---|---|
timestamp_column | "timestamp" | Column name for timestamps in the trace file |
prompt_tokens_column | "input_length" | Column name for prompt token counts in the trace file |
output_tokens_column | "output_length" | Column name for output token counts in the trace file |
time_scale | 1.0 | Scale remaining relative timestamps after wait and pack caps |
max_wait | unset | Maximum gap in original trace seconds between consecutive requests in one session |
max_session_wait | unset | Maximum idle in original trace seconds from the previous session's last request to this session |
min_concurrent_sessions | unset | Pack sessions so at least this many overlap during steady state |
copies | 1 | Sequential full-dataset replays; pass k+1 starts at pass k's last scheduled request |
copy_offset | 1.0 | Where the next copy starts relative to the prior span: 0 at the start, 1 at the end, >1 a gap |
These are passed through the --data argument like below:
guidellm run \
--backend kind=openai_http,target=http://localhost:8000 \
--profile kind=replay \
--data "kind=trace_synthetic,source.kind=json_file,source.path=replay.jsonl,timestamp_column=ts,prompt_tokens_column=input_tokens,output_tokens_column=generated_tokens,time_scale=1.0,max_session_wait=30"
trace_synthetic can be thought of as the format-agnostic option, only looking for the timestamp, prompt token count and output token count columns and ignoring all other features contained in a dataset. While primarily used for testing, trace_synthetic may be used as a fallback for trace formats not currently supported by GuideLLM.
trace_synthetic and mooncake replay each row as an independent, single-request conversation. Rows are sorted by timestamp and keep their offsets from the first request in the trace. Prompts are generated as rows are consumed, and Mooncake hash IDs remain shared across rows within one copies pass. Use max_session_wait to cap gaps between these independent requests; max_wait only caps gaps within multi-request conversations, such as WEKA sessions.
Raise parallelism with min_concurrent_sessions, wait caps, and time_scale first. Use copies only when that packed pass is too short for the benchmark (max_duration / max_requests). By default (copy_offset=1) copies replays the entire packed dataset back-to-back: the next pass starts at the previous pass's last request timestamp. copy_offset=0 starts at the prior pass's first timestamp; values between 0 and 1 interpolate; values above 1 add a gap. Hash-id formats (mooncake, weka) use a separately salted global token-block table per pass so later passes do not reuse earlier tokens and inflate prefix-cache hits.
Format-Specific Data Arguments
mooncake
The Mooncake format expects an additional column for prefix-based cache hash IDs. During prompt generation, hash IDs sharing the same previous ID are required to represent distinct blocks of token ids.
| Argument | Default | Description |
|---|---|---|
hash_ids_column | "hash_ids" | Column name for lists of hash IDs in the trace file |
hash_id_block_size | 512 | Amount of tokens represented by one hash ID |
weka
NOTE: Warm tool_tokens/system_tokens prefixes and hash-id LCP splitting of flattened agents are not implemented. Declared type: "subagent" groups and tool-call events (stop: tool_use, input_types: ["tool_result"]) are replayed.
The WEKA format expects a column with conversation UUIDs that is not wrapped within another column. The timestamp, input token length, output token length and hash IDs columns must all be wrapped inside one JSON column (ex. "requests"), in the form of a list of JSON objects.
Similar to Mooncake, WEKA uses prefix-based cache hash IDs. The original specification for the trace requires hash IDs to be 1 or greater, and for trailing hash IDs to be dropped if there are not enough input tokens to fill the hash ID block size. To accommodate for datasets which may not follow the specification exactly (ex. semianalysisai/cc-traces-weka-no-subagents-051226), GuideLLM will accept any non-negative integer as a valid hash ID, and will drop partially filled hash IDs if they exist.
GuideLLM will generate prompts starting from the first conversation. When the conversation ends, the next conversation will be used. Relative timestamps are offsets from the earliest request in the dataset, so later conversations can start later than the first.
Hash IDs follow the per-row hash_id_scope field:
"global"or omitted: hash IDs share one token-block table across conversations, matching Mooncake. The same hash ID in a later conversation reuses the earlier token block so prefix-cache hit rate stays close to the original trace. Eachcopiespass uses a separately salted global table."local": hash IDs apply only within that conversation. The table is discarded after the conversation is emitted. Local isolation also applies independently on eachcopiespass.
Declared type: "subagent" entries become isolated child chains. Each child spawns from the preceding parent API turn with a fresh history (history_context="new") and the following parent turn waits for every sibling spawned since that turn (history_context="last"). Multiple subagents listed between the same parent turns therefore run in parallel; the parent resumes only after all of them complete. Request-list order is preserved at every nesting level (it is the spawn/join topology) and is not sorted by timestamp.
Inner request timestamps follow the spec when they are relative to spawn, and published Hugging Face corpora when they are already absolute: if the first inner t is less than the subagent entry's spawn t, inner times are treated as spawn_t + inner_t; otherwise they are left as-is. Conversation timestamps are then absolute_t minus the earliest API request time in the dataset.
A single agent's consecutive turns are still serialized. If those turns overlap in time (t[i] + api_time[i] > t[i+1], or t[i+1] <= t[i] when api_time is absent), GuideLLM logs a debug message. Overlap between different subagents is intended parallelism and is not warned.
Tool-call events map onto GuideLLM's existing client tool-call pipeline. A request with stop: "tool_use" and user text input becomes a client_tool_call turn. The following request with input_types: ["tool_result"] (or, if input_types is absent, the next request after stop: "tool_use" on the same agent chain) becomes a tool_response_injection. When that injection row also has stop: "tool_use", it still sends tool results and keeps tools so the model may emit further tool calls. Traces do not contain real tool schemas or results. Pass tools and optionally tool_response_tokens the same way as synthetic data; otherwise GuideLLM uses the default synthetic tool definition and placeholder tool response. Chat handlers do not send the hash-id prompt as a user message on injection turns.
| Argument | Default | Description |
|---|---|---|
conversation_id_column | "id" | Column name for conversation UUIDs in the trace file |
hash_ids_column | "hash_ids" | Column name for lists of hash IDs in the trace file |
hash_id_block_size | 64 | Amount of tokens represented by one hash ID |
tools | None | OpenAI-format tool definitions for tool-call turns. When unset, the built-in placeholder tool is used |
tool_response_tokens | None | Average tokens for mocked tool results. When unset, a short placeholder ({"status": "ok"}) is used |
tool_response_tokens_stdev | None | Standard deviation for tool response token count |
tool_response_tokens_min | None | Minimum number of tokens for tool response |
tool_response_tokens_max | None | Maximum number of tokens for tool response |
Modified defaults:
| Argument | New Default |
|---|---|
timestamp_column | "t" |
prompt_tokens_column | "in" |
output_tokens_column | "out" |