Skip to content

Agentic multi-turn rollout: kernel, model wiring, engine resume API - #14

Merged
KJLdefeated merged 1 commit into
mainfrom
feat/agentic-rollout-engine
Jun 7, 2026
Merged

KJLdefeated merged 1 commit into
mainfrom
feat/agentic-rollout-engine

Conversation

@KJLdefeated

Copy link
Copy Markdown
Owner

Build the cross-turn KV-reuse path described in docs/AGENTIC_ROLLOUT_SPEC.md end-to-end, so a sequence can pause at turn end, accept an observation, and resume with only the new tokens prefilled (attending over the cached prefix).

Kernel

  • New launch_flash_attention_prefill_paged: a tile of new-chunk queries attends over the paged KV cache causally by absolute position. Same online-softmax math as paged decode; per-query (q_seq_idx, q_abs_pos) metadata with q_abs_pos<0 marking padding rows.
  • Fix Flash-Decode split-K NaN when num_splits > num_blocks (every short- context decode): empty splits computed expf(-inf - (-inf)) = NaN and poisoned the reduce. Empty splits now write neutral partials and the reduce skips them. Was blocking 100% of generation on the H100 box and is structurally on the path multi-turn resume hits every turn.

Model

  • qwen3_prefill detects any seq with num_cached_tokens>0 and routes the whole batch through the paged kernel via a cont_prefill flag; pure- fresh batches keep dense WMMA FA2. New d_q_seq_idx / d_q_abs_pos scratch buffers + host mirrors.

Engine

  • SeqStatus::PAUSED, SamplingParams::agentic; Sequence tracks next_turn_start / turn_count / asst_spans for per-turn token slicing and trainer mask building.
  • BlockManager::append_blocks_for grows a resumed seq's block table by delta only.
  • Scheduler::paused_ deque + resume(); postprocess routes agentic stops to PAUSED (KV + batch_slot retained) instead of FINISHED+delete; schedule_prefill takes a separate branch for resumed seqs that skips alloc_slot() and allocates only delta blocks.
  • LLMEngine::rollout_add / rollout_continue / rollout_run_turns / rollout_finish drive the full lifecycle.

Tests

  • test_chunked_prefill: weights-free spike + regression guard for the paged kernel (GQA, block boundaries, empty prefix, multi-seq+padding).
  • test_continued_prefill_model: 2/3-chunk + 1-token-resume prefill through the full 28-layer model matches a single full prefill; argmax identical, cos ~0.99998.
  • test_rollout_engine: end-to-end multi-turn rollout via the engine vs single-shot reference. Turn-1 tokens match generate(P, G1) exactly; all 12 turn-2 greedy tokens match generate(P+t1+O, G2).

Docs

  • agentic_rl_plan.md (roadmap) + docs/AGENTIC_ROLLOUT_SPEC.md (live spec with progress table; calls out the split-K decode bug and why it was load-bearing for the agentic path).

Build the cross-turn KV-reuse path described in docs/AGENTIC_ROLLOUT_SPEC.md
end-to-end, so a sequence can pause at turn end, accept an observation, and
resume with only the new tokens prefilled (attending over the cached prefix).

Kernel
- New launch_flash_attention_prefill_paged: a tile of new-chunk queries
  attends over the paged KV cache causally by absolute position. Same
  online-softmax math as paged decode; per-query (q_seq_idx, q_abs_pos)
  metadata with q_abs_pos<0 marking padding rows.
- Fix Flash-Decode split-K NaN when num_splits > num_blocks (every short-
  context decode): empty splits computed expf(-inf - (-inf)) = NaN and
  poisoned the reduce. Empty splits now write neutral partials and the
  reduce skips them. Was blocking 100% of generation on the H100 box and
  is structurally on the path multi-turn resume hits every turn.

Model
- qwen3_prefill detects any seq with num_cached_tokens>0 and routes the
  whole batch through the paged kernel via a cont_prefill flag; pure-
  fresh batches keep dense WMMA FA2. New d_q_seq_idx / d_q_abs_pos
  scratch buffers + host mirrors.

Engine
- SeqStatus::PAUSED, SamplingParams::agentic; Sequence tracks
  next_turn_start / turn_count / asst_spans for per-turn token slicing
  and trainer mask building.
- BlockManager::append_blocks_for grows a resumed seq's block table by
  delta only.
- Scheduler::paused_ deque + resume(); postprocess routes agentic stops
  to PAUSED (KV + batch_slot retained) instead of FINISHED+delete;
  schedule_prefill takes a separate branch for resumed seqs that skips
  alloc_slot() and allocates only delta blocks.
- LLMEngine::rollout_add / rollout_continue / rollout_run_turns /
  rollout_finish drive the full lifecycle.

Tests
- test_chunked_prefill: weights-free spike + regression guard for the
  paged kernel (GQA, block boundaries, empty prefix, multi-seq+padding).
- test_continued_prefill_model: 2/3-chunk + 1-token-resume prefill
  through the full 28-layer model matches a single full prefill; argmax
  identical, cos ~0.99998.
- test_rollout_engine: end-to-end multi-turn rollout via the engine vs
  single-shot reference. Turn-1 tokens match generate(P, G1) exactly;
  all 12 turn-2 greedy tokens match generate(P+t1+O, G2).

Docs
- agentic_rl_plan.md (roadmap) + docs/AGENTIC_ROLLOUT_SPEC.md (live
  spec with progress table; calls out the split-K decode bug and why it
  was load-bearing for the agentic path).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 7, 2026 04:53
@KJLdefeated
KJLdefeated merged commit a6c024c into main Jun 7, 2026
1 check passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Implements an end-to-end “agentic” multi-turn rollout flow with cross-turn KV reuse, enabling sequences to pause at turn boundaries, accept observation tokens, and resume generation using a continued-prefill path that attends over the cached prefix.

Changes:

  • Adds a paged, cache-reading causal prefill attention kernel (launch_flash_attention_prefill_paged) and wires it into Qwen3 prefill when any sequence resumes with num_cached_tokens > 0.
  • Introduces engine/scheduler support for pausing/resuming sequences (SeqStatus::PAUSED, SamplingParams::agentic, rollout_* API, resumed scheduling + delta block growth).
  • Adds kernel/model/engine regression tests plus supporting build plumbing and documentation/spec updates, and fixes split-K decode NaNs for empty splits.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/kernels/attention.cu Adds paged continued-prefill kernel; fixes split-K empty-split NaN behavior; adds launcher for cache-reading prefill.
include/kernels/attention.cuh Declares the new cache-reading continued-prefill launcher API.
src/model/qwen3.cu Routes prefill through paged continued-prefill path when resuming; adds/query metadata buffers; integrates new kernel at layer forward.
include/model/qwen3.h Adds continued-prefill metadata buffers + cont_prefill flag to the model struct.
include/model/sampling_parmas.h Adds SamplingParams::agentic, SeqStatus::PAUSED, and per-turn bookkeeping on Sequence.
include/engine/scheduler.h Adds paused queue + resume/take_paused plumbing; continued-prefill scheduling branch for resumed sequences.
include/engine/block_manager.h Adds delta-only block growth helpers for resumed sequences (blocks_needed_for, append_blocks_for).
include/engine/llm_engine.h Adds rollout_add/continue/run_turns/finish API driving multi-turn lifecycle.
tests/kernels/test_chunked_prefill.cu Weights-free kernel-level regression validating continued-prefill behavior vs golden reference (incl. multi-seq + padding).
tests/models/test_continued_prefill_model.cu Model-level validation that chunked/continued prefill matches full prefill logits (argmax/cosine).
tests/models/test_rollout_engine.cu End-to-end engine test for multi-turn rollout equivalence to single-shot reference generation.
tests/models/test_llmengine.cu Tweaks benchmark parameters/comments related to realistic bench data dependency.
Makefile Registers new kernel/model tests in the make-based test targets.
CMakeLists.txt Registers new kernel/model tests in the CMake build.
docs/AGENTIC_ROLLOUT_SPEC.md Adds/updates implementation spec and progress tracking for the agentic rollout path and prerequisites.
agentic_rl_plan.md Adds roadmap document describing the agentic RL pivot plan and sequencing.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +108 to +113
t.turn_idx = s->turn_count - 1;
t.new_tokens.assign(s->token_ids.begin() + it->second, s->token_ids.end());
int64_t last = t.new_tokens.empty() ? -1 : t.new_tokens.back();
t.hit_eos = (last == config.eos);
t.truncated = !t.hit_eos;
s->next_turn_start = s->size(); // mark turn collected
Comment thread src/kernels/attention.cu
Comment on lines +1595 to +1604
if (num_q <= 0) return;
const float scale = 1.0f / sqrtf((float)head_dim);

// 8 warps per (query, head): split the query's KV range across warps, then
// merge with a shared-memory reduction — same shape as paged decode.
constexpr int NUM_WARPS = 8;
dim3 grid(num_q, H_q);
dim3 block(32 * NUM_WARPS);
size_t smem = (2 * NUM_WARPS + NUM_WARPS * 128) * sizeof(float);

@KJLdefeated
KJLdefeated deleted the feat/agentic-rollout-engine branch June 7, 2026 14:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants