Exclude partial prompt blocks from prefix cache replay

This commit is contained in:
2026-07-24 00:35:48 +08:00
parent ab952b47e7
commit 5a4011ca12
9 changed files with 25 additions and 8 deletions

View File

@@ -275,6 +275,13 @@ def materialize(args: argparse.Namespace, *, tokenizer: Any | None = None) -> di
identity_collisions += int(previous != witness)
prompt_kind = "synthetic_missing_prompt_fallback"
synthetic_fallback_requests += 1
# vLLM only inserts complete physical blocks into the prefix cache.
# Keep the final partial block identity in selected-remapped.jsonl
# for exact token/block validation, but never expose it as a
# cacheable Frontier block. Otherwise an exact repeated prompt can
# report ceil(ISL / 16) cached blocks, exceeding ISL and leaving the
# request permanently unschedulable.
cacheable_block_ids = block_ids[: isl // TARGET_BLOCK_SIZE]
parent = row.get("parent_chat_id")
if args.validate_parents and parent not in (None, "", -1, "-1"):
parent_blocks = parent_sequences.get(parent)
@@ -290,7 +297,7 @@ def materialize(args: argparse.Namespace, *, tokenizer: Any | None = None) -> di
# unaligned block. So we require a contiguous common prefix and
# only tolerate a bounded mismatch confined to the parent tail.
common = 0
for a, b in zip(block_ids, parent_blocks):
for a, b in zip(cacheable_block_ids, parent_blocks):
if a != b:
break
common += 1
@@ -305,7 +312,7 @@ def materialize(args: argparse.Namespace, *, tokenizer: Any | None = None) -> di
)
parent_prefix_common_blocks += common
parent_tail_nonreused_blocks += len(parent_blocks) - common
parent_sequences[row_identity(row, source_index)] = block_ids
parent_sequences[row_identity(row, source_index)] = cacheable_block_ids
if first_selected_timestamp is None:
first_selected_timestamp = ts
@@ -318,7 +325,9 @@ def materialize(args: argparse.Namespace, *, tokenizer: Any | None = None) -> di
"num_prefill_tokens": isl,
"num_decode_tokens": osl,
"session_id": sid,
"block_hash_ids": "|".join(str(value) for value in block_ids),
"block_hash_ids": "|".join(
str(value) for value in cacheable_block_ids
),
}
)
row_vector_digest.update(
@@ -329,7 +338,7 @@ def materialize(args: argparse.Namespace, *, tokenizer: Any | None = None) -> di
isl,
osl,
sid,
block_ids,
cacheable_block_ids,
],
separators=(",", ":"),
).encode()
@@ -343,7 +352,7 @@ def materialize(args: argparse.Namespace, *, tokenizer: Any | None = None) -> di
"input_length": isl,
"output_length": osl,
"session_id": sid,
"runtime_block_ids": block_ids,
"runtime_block_ids": cacheable_block_ids,
"body": {
"model": args.served_model,
"prompt": request_prompt,
@@ -375,7 +384,7 @@ def materialize(args: argparse.Namespace, *, tokenizer: Any | None = None) -> di
prefill_tokens += isl
decode_tokens += osl
source_blocks += len(original_hashes)
target_blocks += len(block_ids)
target_blocks += len(cacheable_block_ids)
if request_count == 0:
raise ValueError("rho/window selected no requests")
@@ -419,6 +428,7 @@ def materialize(args: argparse.Namespace, *, tokenizer: Any | None = None) -> di
"paired_row_vector_sha256": row_vector_digest.hexdigest(),
"source_block_size": source_block_size,
"target_block_size": TARGET_BLOCK_SIZE,
"prefix_cache_blocks": "complete 16-token blocks only; final partial block excluded",
"workload_mode": workload_mode,
"mapping": (
"real prompt tokens: BLAKE2b-128(parent runtime identity, exact 16-token block); "

View File

@@ -2,8 +2,9 @@
from __future__ import annotations
import math
import csv
import json
import math
import sys
import tempfile
import unittest
@@ -124,15 +125,21 @@ class StrictRemapTest(unittest.TestCase):
manifest = materialize(args)
request = json.loads((output / "real_requests.jsonl").read_text())
mapped = json.loads((output / "selected-remapped.jsonl").read_text())
with (output / "frontier.csv").open(newline="") as stream:
frontier_row = next(csv.DictReader(stream))
self.assertEqual(manifest["source_block_size"], 512)
self.assertEqual(manifest["workload_mode"], "prefill_only")
self.assertEqual(manifest["target_16_blocks"], math.ceil(513 / 16))
self.assertEqual(manifest["target_16_blocks"], math.floor(513 / 16))
self.assertEqual(request["input_length"], 513)
self.assertEqual(request["output_length"], 1)
self.assertEqual(request["body"]["max_tokens"], 1)
self.assertEqual(len(request["runtime_block_ids"]), math.floor(513 / 16))
self.assertEqual(mapped["output_length"], 1)
self.assertEqual(len(mapped["hash_ids_16"]), math.ceil(513 / 16))
self.assertEqual(
len(frontier_row["block_hash_ids"].split("|")), math.floor(513 / 16)
)
def test_real_prompt_tokens_preserve_parent_and_four_to_one_contract(self) -> None:
tokenizer = CharacterTokenizer()