Skip to content

[RFC]: Next-phase roadmap: prefill-only execution, reuse and scheduling #150

Open

Description

@twu3202

Motivation

Decision models here only prefill. A request is one forward pass per prompt with no decoding, and the answer comes from a few label rows or a small head.

vLLM and SGLang now serve /v1/systemone too. They are built for hundreds of model architectures, and they answer decisions through the same engine they use for text generation (details under Anything else). A server that only does decisions has much more room at the system level.

Batching across requests helps less here than in a generation server:

  • Agent clients send one request at a time. System1-Agents does this, with a 5 s deadline per decision by default. Bulk users, such as tagging at ingest time, are the exception.
  • Batching changes the numbers unless every kernel is batch-invariant.
  • Models differ in heads, prompt layouts and limits, and some define how their questions are grouped in one prompt. A batcher has to keep each model's layout and limits.

What helps more is to skip work that repeats, make each prefill fast, and schedule with the cost known before running. Requests repeat in three ways:

  1. One state, many questions.
    • A System1-Agents browser step asks 2–6 questions, with 58–110 click targets on the larger pages, at 2K–17K input tokens.
    • Open-Jev scores each candidate as its own sequence, so every candidate repeats the context and the question.
    • TypeSafe's API allows up to 255 options per question.
  2. The same questions over many states. Guardrails, routers and taxonomies apply one fixed block of instructions and options to every message or document.
  3. The same state again. An agent asks new questions about the page it just looked at, or a voice agent asks again as the transcript grows.

Where things stand:

This proposes an order for the execution, reuse and scheduling work in #125, plus items past its milestones: branch batching, scheduling by cost, and a cross-request cache. The items are directions with a first step, not commitments. Each one gets its own issue or PR, with measurements, when it starts.

Proposed Change

1. Find the repeated work in real interactions

We don't yet know how much repeats in real agent use:

  • how often a state is asked about again;
  • how much of it changes between steps;
  • how often an image comes back;
  • how many questions share a state.

Record episodes from System1-Agents' browser, desktop and tool fronts, and measure these from the requests themselves. The served HTTP path carries no images yet, so screenshot reuse is measured on the in-process paths. The traces become frozen request plans for #116's serving matrix, and they decide which caches in section 4 are worth building.

First step: a trace format and a replay script under benchmarks/. Related: F6, A7, #87.

2. Run each request's repeated work once

This is case 1, in two stages.

  1. Land qwen3_5: add a GEMM handle with one algorithm per weight shape #98 → qwen3_5: run prompts that share prefixes once per prefix #99, which decider: reuse request prefixes with conservative auto selection #113 and omnijev: reuse the prefix within a request #134 build on, and move Open-Jev onto forward_shared ([RFC]: Reuse shared observations across decision questions — community help wanted #85).
  2. Run all branches of a prefix in one pass instead of one at a time:
    • the GDN layers start each branch from the shared snapshot;
    • attention reads the prefix K/V;
    • the readout runs on the GPU for all rows.

The goal is the same bits as running each branch alone. That needs:

It adds backend operations, so the design goes to #85 first, with measured numbers. Related: F3, within-request F4.

3. Scheduling for prefill-only work

A request's cost can be estimated once it is prepared, mostly from its uncached tokens and images. That allows:

  • Per-request admission. Admit, queue and account per request, with all its questions, rather than per question. Today Cua-S1 admits one question at a time.
  • Early refusal. When the client's deadline can't be met, refuse at admission with 503 and Retry-After, so the client finds out at once.
  • Shortest job first, with aging, when a queue forms.
  • Cache-aware order. Once section 4 exists, prefer requests whose prefix state is already cached.

This builds on #109 and #149. Batching across requests stays opt-in per model, needs section 5, and gets its own issue as #125 asks. Related: F2, cross-request F4.

4. Keep state across requests

This is case 3, and case 2 for models whose prompt starts with the fixed block. It generalizes JEV-VL's cache into a prefix-state cache in the shared executor, which owns retained prefix state for request-local reuse (#85). Where cross-request budgets live is part of the design.

  • Checkpoints sit where the state or a fixed leading block ends, at a 64-token boundary, so a state that grows can reuse the old one.
  • Keys cover:
    • the token IDs up to the checkpoint and their positions;
    • the model and adapter revision;
    • the processor settings;
    • an image identity computed from decoded pixels;
    • the precision and GEMM mode.
  • Memory has byte budgets, with eviction by compute saved per byte.
    • Each checkpoint holds 49 MiB of GDN and conv state on 4B/9B (147 MiB on 27B), plus 32 KiB (64 KiB) of K/V per token.
    • That is about 146 MiB (340 MiB) for a 3K-token state.
  • Only exact hits are used.

Section 1's traces decide its size. It gets a design issue before any code. Related: M7, F3, F5.

5. Repeatable answers

Reuse, packing, caching and scheduling should not change a model's output.

For comparison, the pplx-decider v1.2 card says its results are bit-stable only with one request per call. Related: F1, F6.

6. Easy to adopt

Related: F6, F7, F9.

Order

Phase Work
1 Section 1; the first stage of section 2; the declarations in section 5
2 Branches in one pass; scheduling on top of #149
3 The cross-request cache; cross-request batching where models allow it; the FP8 pilot

Not planned

  • Decoding or chat.
  • Lossy reuse, such as CacheBlend-style blending or approximate GDN state rebuilds.
  • Generic image-token pruning. On Qwen2.5-VL-3B, keeping 30% of tokens with FastV takes ScreenSpot-V2 from 81.5 to 38.6 (FocusUI).
  • Perceptual-hash caching. A checked checkbox can change the answer while barely changing a perceptual hash.

Questions

  1. Should this become the next phase of [Tracking]: System1-Omni roadmap: models, features, and agent integration #125, or stay a separate issue linked from it?
  2. Which comes first: branch batching (section 2) or the cross-request cache (section 4)? I'd let section 1's traces decide.
  3. Should batch-invariant execution be declared per model or per deployment?
  4. As backend operations are added, should the ABI keep one global version?

I'll start with section 1, and with Open-Jev in section 2. The rest is open.

Feedback Period

One week, until 2026-10-26.

CC List

Anything else

Who sends these requests
Use Typical request Case Latency
Agent steps (System1-Agents browser) 2–6 questions; 58–110 click targets on the larger pages; 2K–17K input tokens 1, 3 5 s client deadline
Guardrails (TypeSafe cookbook) 4 yes/no and 1 score question on every message, with one set for inputs and another for outputs 2 on either side of an LLM call
Routers (vLLM Semantic Router) 6 signals per prompt; 128 questions on one ticket in tests 1, 2 —
Voice turn-taking (convoai-jev-vad) 3–4 yes/no questions over ~2.1K–2.5K tokens, asked again on every transcript change 2, 3 ~275 ms p50 measured on Jev
Many checks per document (jevbench#47, a benchmark fixture) 37 states × 21 questions 1, 2 throughput
Reranking (TypeSafe cookbook) one question per (query, passage), after a BM25 shortlist 2 —
Tagging (typesafe-sdk-js#10, Scour) a fixed ~6K-token MITRE taxonomy block on every call; 54 questions over 1.1M documents a month, 88% of the input tokens 2 at ingest time

Published latencies are around 100 ms:

  • Jev: about 0.12 s p50 on OpenRouter, read on 10-19;
  • pplx-decider v1.2: 96 ms median on one GB200.
How vLLM and SGLang serve the same cases

Before submitting a new issue

Activity

  1. hsliuustc0106 commented on Oct 24, 2026

    @hsliuustc0106
    Contributor

    lgtm, any progress?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions