feat(graph)!: native Dynamo trace replay -- Graph IR agentic workload lane with unified segment store and session routing - #1132
Closed
ajcasagrande wants to merge 1 commit into
Closed
feat(graph)!: native Dynamo trace replay -- Graph IR agentic workload lane with unified segment store and session routing#1132ajcasagrande wants to merge 1 commit into
ajcasagrande wants to merge 1 commit into
Conversation
ajcasagrande
requested review from
FrankD412,
debermudez,
ganeshku1,
ilana-n,
lkomali and
matthewkotila
as code owners
July 8, 2026 02:22
Try out this PRQuick install: pip install --upgrade --force-reinstall git+https://github.com/ai-dynamo/aiperf.git@58028d5ba1cb33b0e135e18f1cc8833556a3639eRecommended with virtual environment (using uv): uv venv --python 3.12 && source .venv/bin/activate
uv pip install --upgrade --force-reinstall git+https://github.com/ai-dynamo/aiperf.git@58028d5ba1cb33b0e135e18f1cc8833556a3639eLast updated for commit: |
This comment has been minimized.
This comment has been minimized.
ajcasagrande
marked this pull request as draft
July 13, 2026 18:10
ajcasagrande
force-pushed
the
ajc/aiperf-graph-ir
branch
from
July 17, 2026 18:38
5f5cdf7 to
4a537d4
Compare
… lane with unified segment store and session routing Add a first-class agentic benchmarking lane built on Graph IR: a typed, validated intermediate representation of multi-turn, multi-agent conversation graphs that AIPerf ingests, lowers, and replays against an inference endpoint with recorded structure and timing preserved. Ingest and lowering - Graph IR schema and structural validation (node/edge typing, replay-output and branch rules, trie prompt convention) with actionable gate errors. - Adapters lower weka, dynamo, and dag_jsonl traces into Graph IR; parallel adapter variants (dynamo/weka trace_parallel) scale large-corpus parses. - Native lowering builds graphs directly without a source trace. Unified segment store - A single interned segment store per build (content pool + per-node manifests) is the sole graph store shape; the worker opens it lazily from the dataset broadcast and materializes each node's request payload from interned content, layering run-level endpoint options while keeping per-node dispatch overrides and stream settings winning. - Trie-based content interning deduplicates shared prefixes; a theoretical-prefix-cache accumulator emits the infinite-cache prefix hit rate without carrying hash ids through the request path. Runtime, timing, and routing - Async dataflow graph runtime dispatches nodes over the credit system with a cooperative duration deadline; replay timing honors recorded per-node delays and synthesis scaling. - Session routing keeps a trace's turns sticky to one worker; recorded dynamo session-identity headers are stripped when routing is active or uniquified per replay instance so concurrent instances never share a server session. - Graph first-token anchoring emits a per-credit FirstToken for post-TTFT observation independent of prefill-limit gating. Records pipeline and metrics - The records/post-processor pipeline routes records by record type through a per-request RecordsMessage envelope (producers emit typed records, observers act on them), reconciled with origin/main's route-by-record-type refactor. - Context-overflow records bypass the perf accumulators and error tracker but still advance the success counter and forward only the context_overflow_count metric so the submission-rate gate stays correct. Surface and tests - CLI/schema surface: graph_format auto-detection/override, synthesis config (--synthesis-max-osl), and phase autodefaults for graph/dag corpora. - GraphIRReplayStrategy with a phase-teardown hook that detaches observers and closes sticky trace lifecycles between phases. - Reference documentation for the schema, ingest/build pipeline, runtime, segment store, worker materialization, and troubleshooting, plus unit/integration/component test suites and fidelity tooling. Signed-off-by: Anthony Casagrande <acasagrande@nvidia.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ajcasagrande
force-pushed
the
ajc/aiperf-graph-ir
branch
from
July 17, 2026 18:49
4a537d4 to
58028d5
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Tip
Q: How does this compare to AIPerf - AgentX?
A: This branch contains more Dynamo specific functaionality than AgentX, but also includes a graph-native alternative implementation of core AgentX concepts, which may be based on this runtime in the future. TBD.
Summary
Native Dynamo trace replay: point AIPerf at a recorded Dynamo capture (
.jsonl/.jsonl.gz, segmentedtrace.NNNNNN.jsonl.gzfiles, or a directory of them) and replay it faithfully against any OpenAI-compatible endpoint — recorded topology, pacing, token lengths, prefix-cache structure, and session identity included. No conversion step:aiperf profile \ --model my-model \ --url http://localhost:8000 \ --endpoint-type chat \ --input-file ./captures/trace.jsonl.gz \ --streaming \ --tokenizer builtin \ --random-seed 1234 \ --num-dataset-entries 50 \ --num-conversations 50 \ --concurrency 8 \ --concurrency-ramp-duration 60 \ --workers-max 8 \ --session-routing dynamo_headers \ --benchmark-duration 600 \ --artifact-dir ./artifacts/dynamo-replay \ --ui simpleThe capture is auto-detected as
dynamo_trace(pass--graph-format dynamo_traceto force it explicitly).--concurrency-ramp-durationperforms a lane-level ramp on the graph replay plane: replay lanes park at phase start and are admitted 1 →--concurrencyover the ramp window, spreading load onto a cold server.Dynamo replay rides a new general agentic-workload lane (Graph IR): LLM workflows represented as dataflow graphs (LLM nodes wired by static edges, reading and writing channels) instead of flat request lists or linear conversations. The same lane also ingests
weka_trace, hand-authored native graph YAML/JSONL, and legacydag_jsonlfiles.Dynamo trace replay
dynamo.request.trace.v1records lower per session-tree (root + descendants linked viaagent_context.parent_trajectory_id), so independent trees never share causality edges; schema-less uploader marker lines are tolerated; mixed multi-file captures group cross-file trees correctly.--synthesis-idle-gap-cap), interval-order causality edges enforce recorded finished-before relations, and recorded output lengths pin per-request generation caps.--session-routing dynamo_headersstampsX-Dynamo-Session-ID/parent headers;--session-routing dynamo_nvextemitsnvext.session_controlbody metadata, withcontract=openmatching the released Dynamo v1.2.x contract (open once, then baresession_id) andcontract=bind(default) matching >= v1.3.0-dev re-bind-per-turn.Build plane at a glance
flowchart LR subgraph sources["Workload sources"] dynamo["dynamo_trace<br/>.jsonl / .jsonl.gz capture"] weka["weka_trace<br/>.json / dir / HF corpus"] native["native<br/>graph YAML / JSONL"] dag["dag_jsonl<br/>legacy DAG files"] end subgraph ingest["Ingest: aiperf.dataset.graph"] ctx["GraphParseContext<br/>run knobs, tri-state idle-gap cap"] adapters["graph_adapter registry<br/>parse(path, ctx)"] ir["ParsedGraph IR<br/>LlmNodes + edges + channels"] end subgraph build["GraphStoreBuilder"] store["unified segment store<br/>content-addressed, mmap"] sidecar["graph_meta sidecar"] end dynamo --> adapters weka --> adapters native --> adapters dag --> adapters ctx --> adapters adapters --> ir ir --> store ir --> sidecar store --> bc["DatasetMetadata.graph +<br/>GraphSegmentClientMetadata<br/>broadcast"] sidecar --> bcSupporting infrastructure (Graph IR lane)
Ingest / IR (
aiperf.dataset.graph)ParsedGraphschema, parser, structural and semantic validators, and adapters loweringdynamo_trace,weka_trace, native YAML/JSONL, anddag_jsonlonto one IR.(trace_id, node_ordinal, phase_variant)with agraph_metasidecar; graph runs broadcastDatasetMetadata.graph+GraphSegmentClientMetadata(mandatory sidecar, no stub conversations).GraphParseContext;GraphStoreBuilderowns the store build; trie emission splices content-parent segment chains for corpus-scale CPU bounds.Runtime (
aiperf.graph){scope}:{turn}node ids, per-trajectoryx_correlation_id, instance-keyed sticky sessions with whole-tree co-placement.model,max_tokens,raw_tools,extra_headers,extra_body, theoretical prefix-cache counts).sequenceDiagram participant TM as TimingManager<br/>graph_ir_replay participant R as StickyCreditRouter participant W as Worker participant SR as session_routing plugin participant S as Inference server TM->>TM: replay recorded pacing<br/>idle-gap warp, t* window TM->>R: credit (trace instance, x_correlation_id) R->>W: route (instance pinned to ONE worker) W->>W: materialize payload from unified store<br/>fill dynamic slots from ancestor responses W->>SR: headers() / transform_body() at serialization SR-->>W: session identity (headers or nvext body) W->>S: HTTP request S-->>W: streamed response W->>W: capture reply into dynamic pool W-->>TM: credit return (unblocks dependent nodes)Timing
graph_ir_replaystrategy with a scenario-scoped t* snapshot window, extended-warmup cache-pressure stage with a profiling handoff, and warmup failure aborts.--num-dataset-entries,--max-context-length,--allow-dataset-wrap, sampling strategies) behind a fail-loud wrap-guard; single-pass semantics for bare graph runs.Session routing
session_routingplugin category (--session-routing) unifying router-affinity signaling (dynamo_headers,dynamo_nvext,smg_routing_key,session_id_header) at the request-serialization chokepoint, with per-request lineage/finality facts fromSessionTreeRegistry, wired into both the linear and graph planes.x-dynamo-session-id; pair runs with--session-routing dynamo_headersto restore stamping (now available for any dataset and endpoint).Fidelity gates
dag_jsonlbyte-parity vs the legacy plane, golden store digests, and live mock-server E2E runs.Documentation
User guides (rendered on this branch):
Reference internals:
🤖 Generated with Claude Code