Repository navigation
Conversation
Add --dynamo-traces, which reads Dynamo frontend request_end rows (dynamo.request.trace.v1, *.jsonl.gz) from local files and writes the same schema v2 manifest as the prompt-chain source. - Rows are windowed by request_received_ms, not file name, and attempts sharing an x_request_id collapse to the last one that finished. - Sessions link by the strict-prefix rule on the block hashes, within one model, block size, principal and agent session. - Prompts are cut where chains diverge or end; each segment is a user block sized trace_block_size x hashes, the partial tail is a final block, and an extension carries the previous tail, a live reply, then new content. - An optional join on x_request_id (--analytics-table or --analytics-rows-jsonl) fills principal and alias. - Docs list the fidelity lost against prompt chains.
…eply live A continuation now repeats the blocks emitted for the previous request, so the third and later turns keep earlier replies and tails instead of re-cutting the shared prefix into plain user segments. A previous reply that does not fit in the extension is generated at the size that fits, since a live block always replays the whole real reply.
There was a problem hiding this comment.
Review completed against the latest diff
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
Dynamo appends a hash for the partial last block when the prompt length is not a multiple of the block size, so a row has ceil(length / block size) hashes. Such rows were dropped as malformed. The partial hash is now split off: linking and segment cuts use full blocks only, and the partial hash seeds the tail block.
There was a problem hiding this comment.
2 issues found
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="src/batchbench/export_plans.py">
<violation number="1" location="src/batchbench/export_plans.py:257">
P3: The `link_parents` docstring and the `by_principal` name still say records link within a principal, but grouping now uses `link_key`, which for Dynamo traces also includes model, block size and session. Update the docstring to say "within a link key (the principal for chain records)" and rename the dict to `by_link_key`.</violation>
<violation number="2" location="src/batchbench/export_plans.py:901">
P3: `--principal-id` with `--dynamo-traces` but no analytics join drops every record, because principal comes only from the join. Raise an ExportError here, as `--served-by` does, instead of reporting an empty export.</violation>
</file>
There was a problem hiding this comment.
1 issue found across 3 files (changes from recent commits).
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="src/batchbench/dynamo_traces.py">
<violation number="1" location="src/batchbench/dynamo_traces.py:169">
P2: `record_from_trace` accepts extra hashes when `request.input_tokens` is large enough to cover them, producing blocks inconsistent with `replay.input_length`. Check the hash count against `ceil(input_length / trace_block_size)` and count excess hashes as `malformed_hashes`.</violation>
</file>
- A branch in a trajectory starts with the blocks already sent for the longest prefix it shares with an earlier request, so it replays the same bytes, live replies included. - Segments are found in one pass over the chain instead of one index search per cut. - Rows with more hashes than ceil(input_length / block size) are malformed, whatever input_tokens says. - The model prefilter is used only for ASCII names, which no writer escapes. - --principal-id with --dynamo-traces needs an analytics join. - Docstrings name link keys and both ClickHouse readers.
Repeated earlier replies were kept live, so one request could carry dozens of live blocks. They now repeat as plain assistant blocks under the seed they were sent with. The agent replays an already-sent seed with the same bytes, live reply included, so the replay is unchanged within a trajectory and each request has at most one live block.
A clamped reply was one generated block, so when it spanned a segment cut no rendering was recorded there and a later branch lost the shared prefix. It is now one generated block per remaining piece.
There was a problem hiding this comment.
All reported issues were addressed across 4 files (changes from recent commits).
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
There was a problem hiding this comment.
0 issues found across 1 file (changes from recent commits).
Auto-approved: Adds an internal-only Dynamo request-trace input to batchbench-export-plans, with tests and docs; no production serving or request-path impact.
View guided diff | Turn on auto-fix | Re-trigger cubic
Adds a second input to
batchbench-export-plans:--dynamo-traces <dir|file|glob>reads therequest_endrows a Dynamo frontend writes with request tracing enabled (dynamo.request.trace.v1, gzipped JSONL) and writes the same schema v2 manifest as the prompt-chain source. With this, replays of Dynamo-served models don't need a separate gateway capture.How it works
request_received_ms(--start/--end, plus the link window before--startfor link targets).x_request_idare attempts of one request. The exporter keeps the last attempt that finished and counts the others.input_sequence_hashes. Rows link only within one model, block size, principal and agent session id. Rows with differenttrace_block_sizeare never linked or merged.ceil(input_length / trace_block_size)hashes. The exporter splits off the partial hash, so it is never used for linking or cutting; it only seeds the tail block. Rows that hash only full blocks also load. A row with more hashes than that counts asmalformed_hashes.userblock withseed= the segment's last hash andtokens=trace_block_size× its hash count, so shared prefixes replay with identical bytes.userblock, not overhead. That keeps the replayed prompt at the recorded length, which matters when block sizes run to thousands of tokens. Sooverhead_tokensis 0.liveassistant block of the previousoutput_tokens, then the new content. Only the newest reply islive. Earlier replies repeat as plain assistant blocks under their original seeds, and the agent replays an already-sent seed with the same bytes, real reply included. A reply that would not fit in the extension is generated (split where segments end) rather than replayed live, because a live block always replays the whole real reply.live_clampedcounts these; it is typical for reasoning models, whoseoutput_tokensinclude reasoning that clients don't send back.reset_beforeclears the agent's cache, so generated blocks come out the same from their seeds, but copies of earlier replies are generated rather than real.--analytics-table(needs--clickhouse-url) or--analytics-rows-jsonljoins onx_request_id(--analytics-id-column, defaultx_request_id). The analytics side is bounded by time, and the id is compared as a string. A match supplies the principal (user_id, elseapi_key_id) and the alias (in trajectorymetadata). Without a join, the exporter runs on the traces alone, and--principal-idis rejected.docs/export-plans.mddocuments the source, the join, and the fidelity lost compared with prompt chains: no roles, no tools array, template overhead merged and double counted, block granularity, large blocks hiding divergence and splitting sessions, approximate reply length, nostream/max_tokens, and timing that starts at Dynamo.link_parentsnow groups by alink_keyproperty (the principal, for chain records). It also finds candidate parents with a set intersection, because trace chains run to thousands of hashes. The behaviour is unchanged for chain records.Testing
python -m unittest discover -s tests: 37 tests pass, including the existing ones. The new tests generate cumulative hashes in the test, in the production ceil shape. They cover shared prefixes, divergent branches, partial tails (ceil, floor and exact shapes, plus a turn that fills the previous partial block), three-turn sessions, branch reuse, a 1056-token block size, two block sizes with colliding hashes, a row received before its file's upload time, a truncated file, retried attempts, and rows with and withoutx_request_id, joined and unjoined.batchbench-agentwith both live blocks replayed.