Skip to content

standalone-indexer: hash a vLLM cache_salt into its sequence's first block - #53

Merged
Shang-Pin merged 1 commit into
cpu-medium-host-tierfrom
salt-hash
Oct 19, 2026
Merged

Shang-Pin merged 1 commit into
cpu-medium-host-tierfrom
salt-hash

Conversation

@Shang-Pin

Copy link
Copy Markdown

Summary

vLLM mixes a request's cache_salt into the hash of the sequence's first block and publishes it in that block's BlockStored extra_keys. The normalizer kept only 64-hex MM ids, which caused two problems:

This change:

  • In a BlockStored with no parent, a bare string in block 0 that is neither an MM id nor the event's lora_name is the salt. vLLM's key order is lora + mm + [cache_salt only when start_token_idx == 0] + prompt_embeds.
  • The salt joins block 0's MM ids as cache_salt_extra_hash(salt). A 64-hex salt parses like an MM id; any other salt hashes to its XXH3-64. A salted block therefore hashes as xxh3(tokens LE ++ sorted(mm ids + salt) LE, seed), with no new hash scheme.
  • Non-root events, other blocks, and extra_keys_to_block_mm_infos (used by lib/llm) are unchanged. Unsalted traffic hashes exactly as before.
  • The deepapi probe hashes the salt the same way, behind the per-model kv_probe_cache_salt flag (deepinfra/backend PR linked below). Tests pin hash vectors shared with deepapi's tests.

Known gap, same as for images: /kv_recover TreeDumps carry token-only hashes, so salted blocks restored at startup stay plain until evicted.

Validation

  • cargo test -p dynamo-kv-router --lib: 555 passed on both lines (rustc 1.93.1). This includes 5 new zmq_wire tests:
    • salt hashed into the first block only;
    • ignored on non-root events;
    • a LoRA name is not taken as a salt;
    • salt plus image in the same block;
    • fixed vectors cross-checked with Python xxhash.

Rollout

Roll per model, together with the deepapi flag: indexer images first, then i models -n <model> feature-flags kv_probe_cache_salt.

🤖 Generated with Claude Code

…block

vLLM mixes a request's cache_salt into the hash of the sequence's first
block and publishes it in that block's BlockStored extra_keys, but the
normalizer kept only 64-hex MM ids. Salted and unsalted chains with the same
tokens then shared tree edges while carrying different engine hashes: the
tree keeps one engine hash per edge position, so the second chain's children
were rejected as ParentBlockNotFound, and probes scored salted prefixes as
reusable by anyone.

In a BlockStored with no parent, a bare string in block 0 that is neither an
MM id nor the event's LoRA name is the salt. It joins that block's MM ids as
cache_salt_extra_hash(salt): a 64-hex salt parses like an MM id, any other
salt is its XXH3-64. Non-root events and other blocks are unchanged, as is
extra_keys_to_block_mm_infos for existing callers.

deepapi's probe hashes the salt the same way under the per-model
kv_probe_cache_salt flag; the tests pin vectors shared with it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@Shang-Pin
Shang-Pin deployed to external_collaborator October 19, 2026 20:44 — with GitHub Actions Active
@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Oct 19, 2026
@Shang-Pin
Shang-Pin marked this pull request as ready for review October 19, 2026 21:46
@Shang-Pin
Shang-Pin merged commit 9554bb9 into cpu-medium-host-tier Oct 19, 2026
14 of 26 checks passed

This branch was successfully deployed

1 active deployment
external_collaborator — bfaa04b8 Deployed Oct 19, 2026 by Shang-Pin via ok-to-test #61
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant