返回博客
·AI技术

本地部署 LLM:从 Ollama 到 vLLM,生产环境的三个真实坑

从显存估算到并发调优,本地部署大语言模型在生产环境的真实踩坑记录和解决方案。

#LLM#vLLM#Ollama#本地部署#量化

# 本地部署 LLM:从 Ollama 到 vLLM,生产环境的三个真实坑

背景

去年开始,公司内部有个需求:把一些敏感的业务问答从云端 API 移到本地,避免数据外泄。我负责选型和部署,三个月下来,踩了至少五个坑,三个是硬件相关的,两个是工程相关的。

选型过程

候选方案:Ollama、vLLM、llama.cpp、Text Generation WebUI。

最终选了 vLLM 做推理服务,Ollama 做本地开发调试。为什么?因为 vLLM 的 PagedAttention 在吞吐量和延迟上确实领先,Ollama 胜在简单。

坑一:显存估算完全不准

我的第一版估算:A100 80G,跑 70B 模型应该够。结果:

# 实际显存占用(70B 模型,bf16)

model_weights: 140GB # 光权重就 140G

activation_cache: 20GB # KV cache 开销

total: ~160GB+

一个 70B 模型在 A100 80G 上根本跑不起来,哪怕 quantize 到 4bit 也要 40GB 左右。我花了两天时间才搞清楚:**模型大小 × 2(bf16)× 1.2( overhead)÷ quantize_factor = 最低显存需求**。

解决方案:

  • 70B 模型要么用 2×A100 80G,要么 quantize 到 4bit 用单卡
  • 我们最终选了 4×A100 80G 跑 70B bf16,效果最好
  • 开发环境用 Ollama + 4bit quantized 模型,单张 RTX 4090 能跑
  • 坑二:并发和吞吐量的 balance

    vLLM 默认配置在生产环境会 OOM。问题出在 max_num_seqs 和 tensor_parallel_size 的交互上。

    # 我们的生产配置(4×A100)

    from vllm import EngineArgs, LLMEngine

    engine_config = EngineArgs(

    model="meta-llama/Meta-Llama-3-70B-Instruct",

    tensor_parallel_size=4,

    max_model_len=8192,

    max_num_seqs=256, # 这个值很关键

    gpu_memory_utilization=0.9, # 别设太高,留一点余量

    swap_space=16, # CPU swap,防止 OOM

    )

    max_num_seqs 设太大,GPU 显存不够 KV cache;设太小,吞吐量上不去。我们实测发现 256 是个甜点——高峰期 200 QPS 下,P99 延迟能保持在 2s 以内。

    坑三:量化后的质量衰减

    quantize 是必须的(显存和速度的 balance),但 4bit 量化对某些模型的影响比你想象的大。

    我们测了三个模型:

    | 模型 | bf16 准确率 | 4bit 准确率 | 下降 |

    |------|------------|------------|------|

    | Llama-3-70B-Instruct | 82.3% | 79.1% | -3.2% |

    | Qwen2.5-72B-Instruct | 85.1% | 83.4% | -1.7% |

    | DeepSeek-V3 | 81.7% | 77.8% | -3.9% |

    Qwen2.5 对量化的容忍度最好,DeepSeek-V3 最差。我的建议:**量化前先跑一轮 benchmark,别直接上生产**。

    工程上的小坑

    坑四:冷启动时间

    vLLM 启动一个大模型需要 5-10 分钟。在 K8s 环境下,这个延迟意味着:

  • HPA 扩容时,新 pod 就绪时间很长
  • 滚动升级期间,服务不可用窗口变大
  • 解决方案:用 readiness probe 而不是 liveness probe,确保模型加载完再 traffic。

    readinessProbe:

    httpGet:

    path: /health

    port: 8000

    initialDelaySeconds: 300 # 5分钟

    periodSeconds: 30

    坑五:API 兼容性

    vLLM 的 API 接口和 OpenAI 兼容,但有些细节不一致:

  • `stop_sequences` 参数在 vLLM 里叫 `stop`
  • streaming 模式下,`choices[0].delta` 的结构略有不同
  • `max_tokens` 在 vLLM 里上限受 `max_model_len` 限制
  • 我们之前用 OpenAI SDK 调云端 API,切到 vLLM 本地部署后,花了半天时间做适配。建议写一个适配层,不要直接调 SDK。

    硬件选型建议

    如果你也在做类似的项目,我的建议:

  • **开发环境**:Ollama + RTX 4090(24G),跑 7B-14B 量化模型,够用
  • 2. **小规模生产**(<100 QPS):2×A100 80G,跑 70B 4bit 量化

    3. **大规模生产**(>500 QPS):4×H100 80G,跑 70B bf16,延迟和吞吐都有保障

    4. **预算有限**:考虑云端推理服务(如 Together AI、Replicate),别自己搭

    一句话总结

    本地部署 LLM 不是"装个 Docker 就跑"的事。显存估算、并发调优、量化权衡、工程化部署,每个环节都有坑。但一旦跑起来,数据安全和延迟可控的收益是值得的。