Spark-X2.5-4B 是个较新的模型,vLLM 上游还没直接注册它的架构,必须配合官方 Spark 插件才能加载。本文记录 Linux + RTX 3060 12GB 环境下用 vLLM 跑通它的全过程,重点是版本兼容性那几个坑和最终的显存调优。
| 项目 | 值 |
|---|---|
| GPU | NVIDIA GeForce RTX 3060,12288 MiB(SM86) |
| vLLM | 0.27.1 |
| transformers | 5.14.1 |
| Spark-plugin | 最新版 |
| flashinfer-cubin | 0.6.16.post3 |
| 模型路径 | /data/vllm/Spark-X2.5-4B |
- *
1. 环境准备
1.1 先解决 pip 下载慢
一开始用阿里云源,vLLM 那个 316 MB 的包只有 111 kB/s,ETA 快 47 分钟。换清华源后直接 31.3 MB/s,9 秒下完。永久换源,省得每次加 -i:
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
pip config set global.trusted-host pypi.tuna.tsinghua.edu.cn
pip config set global.timeout 1201.2 安装 vLLM 与 Spark 插件
pip install vllm克隆并安装 Spark 插件(用 --no-deps,别让它把 vLLM 的依赖版本改掉):
git clone https://github.com/XHToken/Spark-plugin.git
cd Spark-plugin
pip install -e . --no-deps1.3 下载模型
建议先把模型下完再启动服务,边启动边下载很容易超时失败。
export HF_ENDPOINT=https://hf-mirror.com
pip install -U huggingface_hub
hf download XHToken/Spark-X2.5-4B --local-dir /data/vllm/Spark-X2.5-4B下完确认目录里有 config.json、model.safetensors(或分片文件)、tokenizer.json 这些,缺文件后面启动会报找不到权重。
- *
2. 版本兼容踩坑记录
这一段是整个部署最耗时的地方。vLLM、transformers、Spark 插件三者互相死锁,得一个个拆。
坑 1:transformers 5.17.0 导致 RoPE 解析报错
AttributeError: 'float' object has no attribute 'get'
File ".../spark2_5_config.py", line 69, in __init__
super().__init__(**kwargs)transformers 5.x 对 RoPE 参数做了破坏性重构,新增 rope_parameters 字段、废弃了独立的 rope_scaling。Spark 插件还是按旧结构读,拿到的却是个 float。
坑 2:vLLM 0.29.0 拒绝 transformers v4
想降级到 transformers==4.57.0 绕开坑 1,结果:
ImportError: Support for Transformers v4 is deprecated and was removed in vLLM v0.24.0.
Please upgrade to Transformers v5: pip install --upgrade transformersvLLM 从 v0.24.0 起强制要求 transformers v5。0.29.0 这条路走不通,得降 vLLM 版本。
坑 3:vLLM 0.23.0 的 WeightsMapper 不认新参数
TypeError: WeightsMapper.__init__() got an unexpected keyword argument 'orig_to_new_stacked'
File ".../spark2_5.py", line 329, in Spark2_5ForCausalLMorig_to_new_stacked 是较新版本才有的参数,0.23.0 的 WeightsMapper 没有。
坑 4:最终落到 vLLM 0.27.1
pip uninstall vllm transformers -y
pip install "vllm==0.27.1" "transformers==5.14.1"0.27.1 既有 orig_to_new_stacked,又支持 transformers v5。换到这个组合后,前面那些配置解析报错全部消失。
坑 5:flashinfer-cubin 版本不匹配
RuntimeError: flashinfer-cubin version (0.6.12) does not match flashinfer version (0.6.16.post3).
Please install the same version of both packages.vLLM 0.27.1 依赖 flashinfer-python 0.6.16.post3,但环境里残留了旧的 cubin 0.6.12。麻烦在于:官方给的 flashinfer install-cubin-wheel 命令自身也会 import flashinfer,同样卡在这个版本检查上,形成死循环。而清华源上 flashinfer-cubin 最新只有 0.6.13,没有需要的版本。
解决办法是用 pip download -vvv 拿到真实下载地址,发现文件其实托管在 GitHub Releases:
https://github.com/flashinfer-ai/flashinfer/releases/download/v0.6.16.post3/flashinfer_cubin-0.6.16.post3-py3-none-any.whl用 aria2c 多线程拉下来(16 连接,约 1.6 MiB/s,9 分钟):
aria2c -x 16 -s 16 --continue=true \
"https://github.com/flashinfer-ai/flashinfer/releases/download/v0.6.16.post3/flashinfer_cubin-0.6.16.post3-py3-none-any.whl"本地安装:
pip install ./flashinfer_cubin-0.6.16.post3-py3-none-any.whl💡 没有 aria2c 就用wget -c或curl -L -C -断点续传,GitHub 直连不稳,多试几次或者挂代理。
- *
3. 显存调优
12GB 显存跑 4B 模型不算紧张,但前提是 max-model-len 得压住。
第一次失败:默认 max-model-len 太大
模型默认 max_model_len 是 1048576(1M tokens),KV cache 要 36.48 GiB,远超 12GB:
ValueError: To serve at least one request with the model's max seq len (1048576),
36.48 GiB KV cache is needed, which is larger than the available KV cache memory (2.03 GiB).
Based on the available memory, the estimated maximum model length is 45264.注意可用 KV cache 只有 2.03 GiB —— 因为启动命令漏了 --gpu-memory-utilization,vLLM 用了默认值。
第二次失败:32768 差一点点
加上 --gpu-memory-utilization 0.92 --max-model-len 32768 后,需要 1.6 GiB,可用 1.56 GiB,差 0.04 GiB:
max seq len (32768), 1.6 GiB KV cache is needed,
which is larger than the available KV cache memory (1.56 GiB)
Based on the available memory, the estimated maximum model length is 31616.最终可用配置
取一个明显小于 31616 的整数,给系统留余量:
vllm serve /data/vllm/Spark-X2.5-4B \
--trust-remote-code \
--port 8000 \
--tensor-parallel-size 1 \
--gpu-memory-utilization 0.92 \
--max-model-len 28672 \
--enable-prefix-caching按上面的数据推算,28672 约对应 1.4 GiB KV cache,低于实测可用的 1.56 GiB,有约 0.16 GiB 余量。
- *
4. 启动与验证
看到这两行日志就是起来了:
INFO ... Application startup complete.
INFO ... API server: HTTP server started服务监听在 http://0.0.0.0:8000,所有 API 路由已注册。
确认模型已加载
curl http://localhost:8000/v1/models测一次实际推理
curl -X POST "http://localhost:8000/v1/chat/completions" \
-H "Content-Type: application/json" \
--data '{"model": "/data/vllm/Spark-X2.5-4B","messages": [{"role": "user", "content": "你好,请用一句话介绍你自己。"}],"max_tokens": 128}'返回正常 JSON、内容字段里有模型生成的文字,就说明整条链路通了。
检查显存占用
nvidia-smi看 Memory-Usage 那一列:
- 在 11.0~11.5 GiB 之间 →
--gpu-memory-utilization 0.92被充分利用,正常 - 接近 11.8 GiB → 余量偏紧,后续长上下文推理可能 OOM
- *
5. 参数说明与后续优化
--enable-prefix-caching 是什么
vLLM 的自动前缀缓存(Automatic Prefix Caching,APC)。它把已处理过的提示词 KV Cache 块缓存下来,新请求的前缀如果和旧请求相同,直接复用,跳过重复的预填充计算。实现上是按块管理 KV Cache、每块用哈希标识,新请求进来先算块哈希,命中就复用。
- 适合:长文档问答(同一份文档反复问不同问题)、多轮对话(后续轮次复用历史 KV Cache)
- 限制:只加速预填充阶段,不加速解码;输入提示词很短且各不相同的话提升有限
如果还要更长上下文或更高并发
- FP8 KV Cache:
--kv-cache-dtype fp8,存储精度从 bf16 降到 fp8,显存占用减半。但 RTX 3060(SM86)对 fp8 原生支持有限,可能走软件模拟反而更慢;另外有报告说非 Hopper 架构上用 FP8 KV cache 出现过输出乱码。 - 关闭 CUDA Graph:
--enforce-eager。vLLM 默认编译 CUDA Graph 加速推理,这部分本身也占显存,关掉能释放出来,代价是推理变慢。适合"就差一点点就能启动"的场景。 - INT4/INT8 量化:理论上显存需求会大幅下降(INT4 约 2.2 GB,INT8 约 4.5 GB),但 Spark-X2.5-4B 目前没有 vLLM 能直接加载的量化权重 —— 现有的量化版本是 LiteRT-LM / MLX / GGUF 格式,vLLM 都不认。要量化得用
llm-compressor自己处理。 - *
6. 总结
整个过程的核心难点就是 vLLM + transformers + Spark 插件三者的版本兼容性,最终可用组合:
| 组件 | 版本 |
|---|---|
| vLLM | 0.27.1 |
| transformers | 5.14.1 |
| Spark-plugin | 最新 |
| flashinfer-cubin | 0.6.16.post3 |
建议把这套组合冻结下来:
pip freeze > requirements-lock.txt⚠️ 后面升级其中任何一个组件,都可能再次触发新的兼容性问题。要升级就先在虚拟环境里试,别直接动生产环境。
评论 (0)