Skip to content

Recipes Integration.zh

sikkatu edited this page Nov 2, 2026 · 3 revisions

English | Русский | 中文

配方集成

sikkatu/recipes 的生产启动器带有一个可选开关,可在不改变配方普通行为的前提下 接入持久化缓存。

工作原理

启动器(recipes/rtx-pro-6000/mimo-v2.6-pro-hotsplit 中的 scripts/run-tp4-uva.sh、 scripts/run-tp4-hotsplit.sh)包含一个 KV-PERSIST 块:

KV_PERSIST="${KV_PERSIST:-0}"
if [ "$KV_PERSIST" = "1" ]; then
  ... 派生缓存身份命名空间 ...
  MODEL_ARGS=(--model "/models/$KV_PERSIST_NAMESPACE")
  MODEL_ARGS+=(--kv-transfer-config "$KV_TRANSFER_CONFIG")
  MODEL_ARGS+=(--enable-prompt-tokens-details)
  MODEL_ARGS+=(--block-size "$KV_PERSIST_BLOCK_SIZE")
fi
  • 默认关闭 —— KV_PERSIST 未设置或为 0 时,配方行为与之前完全一致:无连接器、 无命名空间重挂载、无新参数。普通运行不需要 MODEL_DIR,也不需要安装 kv-persistence。
  • 开启(KV_PERSIST=1)时该块做四件事(评审修正,第 19 轮):
    1. 缓存身份命名空间 —— MODEL_DIR 挂载到 /models/<命名空间>(而非 /model)。 LMCache 以 model_config.model(--model 的值)为每个 L2 对象做键,因此固定的 /model 路径会让所有部署共享一个命名空间:不同版本、KV dtype 或几何配置 可能读到彼此的 KV 块。使用命名空间路径后,每个身份拥有独立命名空间,不兼容的部署 得到安全的缓存未命中 —— 前提是命名空间从引擎的实际参数派生(评审修正: 实际的 KV_CACHE_DTYPE、MAX_MODEL_LEN、block size、TP size 作为 KVP_* 覆盖传递给 CLI,auto 先解析为模型的实际 dtype)。命名空间优先取自 python3 -m kvpersist.cli model-name(已验证的身份哈希,需找到 kv-persistence 克隆 KVP_REPO_ROOT 或 ~/kv-persistence),否则由 KV 兼容性字段的确定性哈希 生成(config.json、权重索引 + shard 大小、tokenizer 文件、chat template、kv dtype、 max-model-len、block size、TP size)。 因此 KV_PERSIST=1 必须设置 MODEL_DIR。
    2. --kv-transfer-config —— LMCache 连接器(与 kv-persistence 自身启动器相同的 JSON)。
    3. --enable-prompt-tokens-details —— 没有它就不会上报 usage.prompt_tokens_details, cached_tokens(唯一机器可读的复用计数器)不可用,且 kv-persistence 的验收测试 (scripts/test-recovery.sh)永远无法 PASS。
    4. 固定 --block-size(默认 16,通过 KV_PERSIST_BLOCK_SIZE 覆盖)—— kv-persistence 的身份门禁(verify-engine-identity.sh)需要一个可验证的引擎参数。 参数记录在 tp4.env.example / .ru / .zh(三种语言的名称、值和顺序一致): KV_PERSIST、KV_PERSIST_HOST、KV_PERSIST_PORT、KV_PERSIST_NAMESPACE、KV_PERSIST_BLOCK_SIZE。 ⚠️ KV_PERSIST_NAMESPACE(覆盖)—— 若手动设置,隔离保证由你自行负责: 启动器无法验证 namespace 是否与引擎的实际配置一致。仅在理解身份字段时使用覆盖。

启用 —— 完整流程

  1. 按 Quick Start 步骤 1–6 安装并启动缓存服务。
  2. 在配方的 tp4.env 中添加:
    KV_PERSIST=1
  3. 如常启动配方:
    bash scripts/run-tp4-uva.sh

块激活时启动器会打印两行确认: KV_PERSIST=1: attaching LMCache connector … 和 KV_PERSIST=1: cache-identity namespace -> /models/<hash> …。

复用前验证引擎身份

配方的块无法自动运行 kv-persistence 的 verify-engine-identity.sh(配方中未接入 kv-persistence 克隆路径),因此请在信任任何缓存复用之前手动运行:

bash ~/kv-persistence/scripts/verify-engine-identity.sh <容器名>

退出码 0 = 身份已验证(在该范围内允许缓存复用)。退出码 4 = MISMATCH(不得复用 缓存 —— 将 configs/mimo-v2.6-pro/identity.env.local 与引擎参数对齐后重跑)。 退出码 5 = INCONCLUSIVE(先修复值来源)。门禁比较容器的启动参数和被服务模型的 config.json;KV_PERSIST=1 时启动器固定了 --block-size 和命名空间挂载,因此所有 字段均可检查。门禁只读取引擎配置 —— 不改变生产行为。

两端的端口变量名

三个不同变量名指向同一端点(评审备注):

侧 主机 端口
缓存服务(kv-persistence configs/generic/lmcache-server.env) LMCACHE_HOST LMCACHE_PORT
缓存服务(kv-persistence configs/generic/cache.env 文档别名) KVP_LMCACHE_HOST KVP_LMCACHE_PORT
配方启动器(tp4.env) KV_PERSIST_HOST KV_PERSIST_PORT

配方侧是 vLLM 用来连接的;缓存侧是服务监听的。如果在缓存侧更改端口(LMCACHE_PORT), 必须在配方侧 KV_PERSIST_PORT 设置相同值 —— 否则 vLLM 找不到缓存,连接器会静默重试 一个死端点。主机同理。默认值一致(127.0.0.1:5555)。

两条路径,一个缓存 —— 相同与不同

kv-persistence/scripts/run-vllm-with-persist.sh(专用启动器)和配方的 KV_PERSIST=1 分支现在在所有决定缓存兼容性的地方保持一致:

参数 kv-persistence 启动器 配方 KV_PERSIST=1 配方普通运行
--model /models/<命名空间> /models/<命名空间> /model 或 MODEL_ID
--kv-transfer-config 是(LMCacheMPConnector) 是(相同 JSON) 无
--enable-prompt-tokens-details 是 是 无
--block-size 16(固定) 16(固定,经 KV_PERSIST_BLOCK_SIZE) 不传(引擎默认)
MAX_NUM_SEQS 2 2 2(env;用户实测:速度不受影响,默认值更方便)
KV_CACHE_DTYPE auto(解析为模型 dtype) auto(解析为模型 dtype) auto(env)
MAX_MODEL_LEN 1048576 1048576 1048576(env)
身份门禁 自动(不匹配则拒绝) 手动提醒 无
专用启动器还会自动运行身份门禁并在不匹配时拒绝挂载缓存;配方分支只提醒你手动
运行。任何身份字段(含 dtype 字符串)的值差异都是安全的缓存未命中 —— 命名空间
哈希改变,两条路径只是停止共享缓存块。它们绝不会读取错误的 KV;只是不再复用。若想
在两条路径间复用,请保持值完全一致。

禁用 / 回滚

删除 KV_PERSIST=1 行(或设为 0)并重新启动。这就是全部回滚:配方设计上不被触碰, NVMe 上的缓存数据在禁用期间只是被忽略。

启动顺序

缓存服务必须在启动器接入之前运行。顺序:先 start-cache.sh,后配方启动器。如果 vLLM 启动时服务未运行 —— 移除 KV_PERSIST=1 并使用普通配方(或启动缓存后重新启动) —— 绝不要让 vLLM 在生产中重试一个死连接器。

选择哪个启动器

启动器 适用场景
run-tp4-uva.sh UVA 基线(已验证的配方路径)
run-tp4-hotsplit.sh 热/冷专家分离(动态/静态模式)
kv-persistence/scripts/run-vllm-with-persist.sh 需要自动身份门禁和完整 kv-persistence 工具链(preflight、benchmark、test-recovery)时

三者接受相同的 KV-PERSIST 参数(专用启动器从 kv-persistence 自身的配置读取)。 使用你今天运行的那个。

启动器块如何被测试

契约测试(文本检查)加上 sikkatu/recipes/tests/test_kv_persist_behaviour.py 中的行为测试:两个启动器用桩 docker/nvidia-smi/curl/python3 实际 执行,桩 python3 记录块传给它的 KVP_* 覆盖。覆盖范围:命名空间跟随引擎的 实际参数(fp8 与 bfloat16 产生不同命名空间)、auto 解析为模型的有效 dtype、 CLI 失败以真实错误中止启动(无静默 fallback)、KV_PERSIST_NAMESPACE 覆盖被 遵守、普通运行(KV_PERSIST=0)不派生任何命名空间、KV_PERSIST_BLOCK_SIZE 同时 到达 CLI 与 --block-size、model_name 前缀在两个启动器间稳定(两条路径都是 mimo-pro/<hash>)。kv-persistence 另有 tests/unit/test_launcher_namespace_coherence.py,执行 run-vllm-with-persist.sh 的真实默认值表达式 —— 回退到 basename $MODEL_DIR 会让测试失败。

配方中没有的东西

缓存服务器本身、容量策略、身份固定和管理工具位于 kv-persistence;其 wiki 是设置、持久化 验证和回滚的参考。注意恢复验收(scripts/test-recovery.sh)仍需在 GPU 主机上实际 运行 —— 诚实状态见 kv-persistence 的 docs/final-report.md。配方的契约测试验证 启动器包含该机制;它们本身并不能证明真实的 NVMe 恢复。

Clone this wiki locally