本地跑一个大语言模型早就不是停留在PPT上的概念了。各种开源模型权重放开之后越来越多团队和开发者把自己关进机房、拿着消费级显卡折腾本地化部署。我最早接触这套东西是因为某公司需要一个能长时间跑在离线环境里的问答服务数据不出内网还得支撑几十个同事同时用。试了一圈工具之后发现Ollama、vLLM、LMDeploy 配合 ModelScope 的组合基本覆盖了从“个人玩玩”到“产线服务”的完整梯度。这篇文章就把我自己实际落地过程里的选型判断、部署步骤、参数调整和踩过的坑拆开讲清楚希望能帮你少走点弯路。1. 项目内容拆解本地化部署到底要解决什么问题很多人以为本地化部署就是把模型文件下载下来、跑一个推理脚本。真上手之后你会发现链路远比想象的长模型从哪儿下、怎么下载更快、用什么引擎跑、显存够不够、并发来的时候会不会卡死、要不要做量化、之后怎么对外提供接口这些问题没有一个统一的答案。这个标题里出现的几个工具本质上分别对应了这条链路上的不同角色。1.1 一个模型从下载到推理链路里有哪些卡点先看一张逻辑链路模型本地化部署大体是这样的获取模型权重通常从 HuggingFace 或 ModelScope 下载国内网络环境下 ModelScope 明显更顺手。选择合适的推理引擎引擎负责把模型加载进显存、执行 Attention 计算、管理 KV Cache、生成 Token。封装服务接口推理引擎之上需要暴露 HTTP API要么兼容 OpenAI 格式要么自定义格式方便上层应用调用。资源调度与优化包括量化、张量并行、连续批处理Continuous Batching、KV Cache 管理这些手段。这四个环节里推理引擎是核心。Ollama、vLLM、LMDeploy 都是引擎但设计目标截然不同。Ollama 追求开箱即用的用户体验适合单机跑个聊天机器人vLLM 主打高吞吐和并发靠 PagedAttention 解决显存碎片问题LMDeploy 是国产团队做的推理方案对懒人很友好自带量化工具在国内模型生态上适配得很早。1.2 四种工具各管哪一段这四个关键词要分清它们不是同一层的替代品。ModelScope模型下载和托管平台类似国内的 HuggingFace。不只是下载模型它还有整套 Python SDK、命令行工具以及支持脚本一键微调的功能。Ollama一个把 llama.cpp、llama 系列模型封装得非常简单的本地推理工具。模型格式是 GGUF量化支持非常好资源占用低唯一的缺点是性能与扩展性不如 vLLM。vLLM一个高吞吐推理引擎核心卖点是 PagedAttention把显存里的 KV Cache 分页管理配合 Continuous Batching 让吞吐量大幅提升。适合在线服务要求相对高一些。LMDeploy一款支持多模型、多硬件、多场景的推理部署工具包内置 TurboMind 高性能引擎同时提供量化、单机多卡、服务化等功能对 LLM 部署链路的支持特别完整。很多人一上来就纠结选哪个其实答案取决于你要干什么。只给自己用Ollama 最省事给部门做内部工具vLLM 性能上限最高想快速在国产加速卡或受限环境下跑起来LMDeploy 往往更稳。1.3 如何根据场景选择第一套方案我把个人接触过的典型场景分成三类。第一类是个人开发者和学生想在自己电脑上跑一个 7B 或更小的模型来学习、测试绝大多数用的是 Ollama。原因很简单安装一条命令模型拉取一条命令聊天接口一条命令几乎没有配置负担。第二类是小型团队做内部应用需要几个人并发调用同时要兼容现有业务系统的 API我建议直接上 vLLM。虽然启动参数比 Ollama 多但换来的是吞吐量保障和完整的 OpenAI 接口兼容。第三类是拥有多张显卡、甚至需要批量跑模型试验的团队LMDeploy 的收益更明显。它把模型转换、量化、部署一体化Tensor Parallel 和 KV Cache 量化配置都封装好了能省掉一堆手工处理的时间。我建议第一套方案永远不要追求“最强性能”而是追求“最快跑通”。先用 Ollama 把模型和服务验证一遍确认模型本身符合需求再切到 vLLM 或 LMDeploy 做生产化改造。这样做的好处是能快速判断模型效果不至于在部署细节里耽误太多时间。2. 部署前准备硬件、系统和模型获取在碰任何工具之前先把底层的硬件和模型文件理清楚。这一步没做好后面所有引擎都会出现各种诡异的错误。2.1 硬件与系统依赖清单先说结论显存大小决定你能跑什么规模的模型内存大小决定你能不能顺利加载权重。以 7B Int8 量化模型为例权重文件大约 6-7GB加载后显存占用还会超过 8GB因为需要额外的 KV Cache 和激活值。所以跑 7B 级别一张 16GB 显存的显卡是舒服的起点。14B 级别至少要 24-32GB。如果是 70B 或者更大的模型又要上多卡并行推荐使用两张或更多的 24GB 及以上的显卡。操作系统方面Ollama 对 Windows 的适配很好vLLM 则更推荐 Linux毕竟很多 CUDNN 层面的优化和内存管理在 Linux 下更稳定。我实际部署的教训是如果是新装机器直接用 Ubuntu 20.04 或 22.04 的干净环境能少掉至少一半的问题。依赖方面统一梳理如下NVIDIA 驱动版本建议不低于 470CUDA 版本建议不小于 11.8。vLLM 和 LMDeploy 都会自动检测显卡环境但不同版本对 PyTorch 2.x 有要求建议提前装好 Python 3.10 及以上。ModelScope SDK 是纯 Python 包依赖少安装非常简单。如果你不在本机装 CUDA Toolkit也可以因为很多推理引擎会自带 CUDA 运行时。但这样遇到驱动和库冲突时排查会很麻烦。我的经验是宁可在环境上多花一小时也不要在问题出现后再花一晚上。2.2 ModelScope 下载模型的两个姿势ModelScope 相比 HuggingFace在国内的网络环境下优势很明显下载速度基本能跑满带宽。这里讲两种最常用的加载方式。第一种直接用 Python SDK 下载。在终端安装依赖pip install modelscope然后执行from modelscope import snapshot_download model_dir snapshot_download(qwen/Qwen2.5-7B-Instruct, cache_dir/data/models) print(model_dir)cache_dir可以指定模型存放目录。如果不指定默认会放到~/.cache/modelscope下。这个命令会一次性把模型仓库里所有文件同步下来包括权重文件、配置、分词词典等等。第二种用 CLI 下载适合脚本化操作modelscope download --model qwen/Qwen2.5-7B-Instruct --local_dir /data/models/qwen2.5-7b注意--local_dir和--cache_dir的区别--local_dir直接指定最终存放目录--cache_dir则是缓存目录之后复制出来用。我更喜欢用--local_dir下载完目录结构一目了然。下载前我建议先确认模型 ID 是否存在。ModelScope 的模型命名规则一般是组织名/模型名在网站搜索页可以看到。如果使用snapshot_download时模型名称不对会直接报 404 或者弹出文件列表。2.3 模型命名与目录规划这一点看起来不起眼但实际部署时经常被坑。同一个模型在 ModelScope 上的仓库里可能同时包含多个文件比如pytorch_model.bin、safetensors、gguf。要区分清楚。下载的时候如果你不看文件列表可能全量拉下来多花数倍时间。我给一个建议的目录结构/models /base_models /qwen2.5-7b-instruct /config.json /model.safetensors.index.json /model-00001-of-00002.safetensors /model-00002-of-00002.safetensors /tokenizer.json /tokenizer_config.json /engine_models /qwen2.5-7b-instruct-awq /qwen2.5-7b-instruct-gptq-int4基础权重和量化权重分开放避免混合。实际操作里我发现有人把 GGUF 文件和 HuggingFace 格式权重混在一个目录下Ollama 或 vLLM 会把它当成异常目录处理。保持目录纯洁度比什么都重要。3. Ollama五分钟跑通聊天的极简路线Ollama 的火爆不是没道理。它做了当年 Docker 做过的事——把各种纷繁复杂的推理引擎细节全藏起来让用户只面对可执行命令和模型名。3.1 安装与模型拉取Ollama 支持 macOS、Windows、Linux。最简单的安装方式curl -fsSL https://ollama.com/install.sh | sh装完之后先跑一个轻量模型试试比如 llama3.2:ollama run llama3.2首次运行会自动下载模型之后进入交互式对话界面。到这里一个能聊天的模型就在本地跑起来了。用国内网络时模型下载接口可能出现连接慢的问题。Ollama 的下载域名是registry.ollama.ai有些网络环境下载速度不稳定。如果你遇到下载卡住我建议从 ModelScope 下载对应 GGUF 模型文件然后通过Modelfile手动导入。比如先下载某个模型仓库里的 GGUF 文件到本地然后新建一个ModelfileFROM ./qwen2.5-7b-instruct-q4_k_m.gguf接着执行ollama create qwen2.5-7b-q4 -f Modelfile之后运行ollama run qwen2.5-7b-q4这套操作的本质是绕过 Ollama 的模型下载层直接用本地文件。适用于网络受限或者需要修改推理参数的场景。3.2 Ollama 的推理参数怎么调Ollama 默认的推理参数对多数场景已经够用但还是有调优空间。最直接的方式是修改Modelfile。参数文件可用的几个关键字段TEMPLATE设定模型使用的提示词模板。PARAMETER temperature控制采样随机性值越小越稳定适合问答值越高越发散适合对话。PARAMETER top_p核采样默认 0.9。PARAMETER num_ctx上下文长度默认只有 2048如果任务需要长上下文建议显存允许时改为 8192 或更大。PARAMETER stop设定终止符。一个实际可用的Modelfile示例FROM qwen2.5-7b-instruct PARAMETER temperature 0.7 PARAMETER top_p 0.85 PARAMETER num_ctx 8192 PARAMETER stop |im_end|创建并运行ollama create qwen2.5-7b-tuned -f ./Modelfile ollama run qwen2.5-7b-tuned我实测下来把num_ctx调大能明显改善长文本对话的连贯性但代价是 KV Cache 显存成比例上升。显存不够时宁可损失一点上下文长度也不要让模型 OOM。另外Ollama 支持同时为一个模型创建多个变体比如一个短上下文版、一个长上下文版按需切换。3.3 自定义 Modelfile 做微调如果你的业务有特殊的提示词前缀比如给 AI 一个系统人设可以在Modelfile里固化。例如FROM qwen2.5-7b-instruct SYSTEM 你是一个严谨的技术文档助手回答问题时先给出结论然后补充解释。 PARAMETER temperature 0.3这样的模型一跑起来就直接带着你的人设进入对话无需每次调用都重复传 system prompt。不过要注意SYSTEM的作用范围取决于模型是否支持 system prompt。对于不支持SYSTEM字段的基座模型最后的生成效果可能不可控。4. vLLM高并发生产级推理的部署细节当你确定模型本身可用并且需要并发支持时就应该考虑 vLLM。它解决的问题很核心同样一块显卡Ollama 可能只能同时跑十几个并发请求vLLM 能跑到上百吞吐量可能是数十倍的差距。4.1 安装 vLLM 与兼容性说明vLLM 的安装没有想象中麻烦但需要注意 Python 和 CUDA 环境兼容。官方推荐 Python 3.10CUDA 12.1。安装pip install vllm如果安装了多个 CUDA 版本建议用虚拟环境打包避免互相污染。我常用的创建方式python -m venv /data/venv/vllm source /data/venv/vllm/bin/activate pip install --upgrade pip pip install vllmvLLM 体积较大它会自动安装对应版本的 PyTorch一般不需要手动装 PyTorch否则可能产生依赖冲突。另外vLLM 对模型格式有明确要求。它通常直接跑 HuggingFace 格式的safetensors权重不支持 GGUF。所以从 ModelScope 下载模型时务必选safetensors版本而不是 Ollama 专用的 GGUF 文件。4.2 用 OpenAI 兼容接口启动模型vLLM 自带一个 OpenAI 兼容的 API 服务启动命令如下python -m vllm.entrypoints.openai.api_server \ --model /data/models/qwen2.5-7b-instruct \ --served-model-name qwen2.5 \ --port 8000 \ --tensor-parallel-size 1 \ --gpu-memory-utilization 0.9启动后可以通过http://localhost:8000/v1/chat/completions发送请求可以直接用 OpenAI 的 Python SDK 调用。from openai import OpenAI client OpenAI(base_urlhttp://localhost:8000/v1, api_keyEMPTY) response client.chat.completions.create( modelqwen2.5, messages[ {role: system, content: 你是一个技术助手。}, {role: user, content: 解释一下什么是 KV Cache} ], temperature0.7 ) print(response.choices[0].message.content)这里要注意--served-model-name这个参数。它定义在 API 请求里你要使用的模型名。如果不设置默认使用路径末尾的名字。这个字段只影响 API 路由的对应关系不影响模型权重。4.3 吞吐量与显存控制的关键参数vLLM 的性能优势除了引擎本身更多来自参数的合理配置。第一个关键参数是--gpu-memory-utilization。默认值 0.9表示 vLLM 会将可用显存的 90% 用于模型权重和 KV Cache。如果你的显卡还要跑其他任务最好降低这个值比如 0.7否则容易显存不足。第二个关键参数是--max-model-len。它决定模型最大接受序列长度默认值会根据模型配置决定。如果设为过大的值比如 32768KW Cache 会吃掉大量显存。建议根据实际业务调整例如--max-model-len 8192第三个关键参数是--enforce-eager。默认情况下 vLLM 会使用 CUDA Graph 加速首次启动时会话不少时间去 capturing。如果你的显存很小或图形依赖出问题加上它可以用 eager 模式牺牲一点性能来换取兼容性。第四个是并发数相关参数--max-num-seqs单批最多 token 数量默认 256。--max-parallel-loading-workers模型加载时的并发 worker 数。我不建议一上来就把并发开得很大因为并发高时调度和显存碎片问题会同步变严重。比较好的方式是先跑默认配置用压测工具发 50 个并发观察响应时间和显存曲线再去逐渐调大--max-num-seqs。5. LMDeploy量化推理与国内环境友好方案LMDeploy 是另一套完整的部署工具我对它的定位是“一台服务器上解决所有推理部署问题”。它的安装、量化、服务化、多卡并行整体都很顺手特别适合不喜欢折腾的人。5.1 LMDeploy 的安装与 TurboMind 引擎安装 LMDeploypip install lmdeployLMDeploy 会自带的 Python 包解析模型权重并把模型转换成自己的 TurboMind 格式。在第一次加载时它会自动转换并缓存所以第一次启动会慢一些第二次之后就快了。启动服务可以用这条命令lmdeploy serve api_server /data/models/qwen2.5-7b-instruct \ --server-name 0.0.0.0 \ --server-port 8000 \ --tp 1 \ --cache-max-entry-count 0.8这条命令会开启一个 OpenAI 兼容接口。LMDeploy 同样支持v1/chat/completions格式所以客户端代码可以和 vLLM 无缝切换。LMDeploy 的一大亮点是 KV Cache 的量化。它能对 KV Cache 做 8bit 或 4bit 量化从而节省更多显存给长上下文和更大 batch。相关配置是--kv-quantization参数常用的有fp8、int8和int4。例如lmdeploy serve api_server /data/models/qwen2.5-7b-instruct \ --kv-quantization fp8加了fp8之后显存占用会显著下降。如果你的 GPU 支持 FP8比如部分较新显卡这也是最大的性能红利之一。5.2 一键启动服务与 kv cache 配置除了 API 服务LMDeploy 还提供了命令行聊天模式非常方便用来快速验证模型lmdeploy chat /data/models/qwen2.5-7b-instruct它会进入一个交互式的对话界面可以直接看到模型的输出。这比写 Python 脚本验证要快得多。如果你需要把服务包装成自己的内部接口也可以用 Python 启动from lmdeploy import pipeline, TurbomindEngineConfig engine_config TurbomindEngineConfig( cache_max_entry_count0.6, session_len8192, tp1 ) pipe pipeline(/data/models/qwen2.5-7b-instruct, backend_configengine_config) for output in pipe([请介绍一下模型量化, 什么是连续批处理]): print(output.text)这里cache_max_entry_count的含义是显存中允许 KV Cache 占用的比例。默认值是 0.5代表只允许用一半显存。如果你有 48GB 显存且模型只占 8GB建议把它调高到 0.8 或 0.9以便支撑更大并发。如果模型本身很大就要调低避免 KV Cache 溢出。LMDeploy 的session_len对应上下文长度也需要根据显存去调。实际操作中我发现单纯调大session_len并不明智因为长上下文场景下碎片和调度开销都会增加。5.3 效果对比与量化取舍LMDeploy 自带的量化工具lmdeploy lite auto_awq可以将模型量化到 4bit显著减小显存占用。举个实操例子lmdeploy lite auto_awq /data/models/qwen2.5-7b-instruct \ --dest-path /data/models/qwen2.5-7b-awq \ --quant-dtype awq-w4g16 \ --calib-dataset ptb \ --calib-samples 128这一步会用 ptb 数据集做校准量化后的模型体积能降低一半左右。量化后可以用同样的方式部署lmdeploy serve api_server /data/models/qwen2.5-7b-awq量化的取舍在于精度损失。对于一般对话任务AWQ 4bit 量化后的表现几乎无感但对代码生成、数学推理等精度高度敏感的任务我建议只用 AWQ 或 GPTQ 的 4bit不要用极端的 2bit 量化。我的习惯是先拿测试集在原始模型上跑一遍结果再量化后跑一遍对比确保误差在可接受范围。LMDeploy 与 vLLM 的对比大致可以这样看对比项vLLMLMDeploy引擎核心PagedAttention 分页 KV CacheTurboMind自研算子库安装复杂度中依赖较多低整体封装度高模型格式HuggingFace safetensorsHF safetensors自动转换量化支持支持 AWQ/GPTQ内置 AutoAWQ、KV Cache 量化OpenAPI 兼容优秀良好多卡并行优秀优秀国内模型适配好极好用户反馈效率高吞吐压测峰值更强便于快速部署吞吐也不错两种选谁取决于你团队的使用习惯。如果你们已经跑了很多 Python 深度学习代码vLLM 更像是一个基础设施如果你们需要尽快把服务端起来减少心智负担LMDeploy 会让开发效率高很多。6. 性能优化与踩坑实录到了这一节才是把方案真正落到能跑生产环境的关键。我把自己实际部署中碰到过的典型问题都整理在下面供你排查。6.1 显存不足与OOM排查显存不足几乎是最常见的问题。表现形式多样要么启动时报 CUDA OOM要么跑了一会儿进程直接被杀。我的排查路径如下先确认模型权重占了多少显存。观察模型下载目录中的文件大小加上 KV Cache 估算基本就是总占用。用nvidia-smi查看当前显卡占用。如果写入了模型看占用是否超过 90%超过就先调整--gpu-memory-utilization。看hidden_states大小。即使是 FP16 加载7B 模型推理过程中激活值也可能增大几倍尤其当num_ctx很大时。一个可操作的技巧把max-model-len或session_len降到 4096把 batch size 减小再看是否还 OOM。如果还 OOM就要考虑量化lmdeploy lite auto_awq /data/models/qwen2.5-7b-instruct --dst-path /data/models/qwen2.5-7b-awq-4bit我实测过7B 模型从 FP16 变成 AWQ 4bit 后显存占用可以降低约 50%-60%对于 8GB 显卡来说能跑的空间从捉襟见肘变成游刃有余。另外使用多卡时容易忽略tensor-parallel-size设置。两张 24GB 显卡如果tp设成 1只会用一张卡另一张闲置如果设成 2显存总量翻倍但通信开销会增加。70B 模型建议至少两张卡7B 单卡就够了。6.2 并发高时响应变慢怎么解决很多人在本地测试时单路请求没问题一上并发就觉得“模型变慢了”。其实模型本身没问题问题多半出在批处理策略和显存利用率上。先说我推荐的做法别在应用层做复杂的排队让推理引擎自己去调度。vLLM 和 LMDeploy 都支持 Continuous Batching意思是新请求来了之后如果当前 batch 有空位就插进去而不是等前一批全部跑完。这个特性默认开启不需要额外配置。但要注意如果不限制采取措施的显存上限高并发时 KV Cache 会急剧膨胀导致部分请求被挤出去重新排队。所以参数调整方向是把--gpu-memory-utilization调高到 0.85 及以上给 KV Cache 更多空间。把--max-num-seqs从 256 调高到 512 或更高如果总请求数大。如果并发请求中长文本比例很高适当减少--max-model-len增加起飞 token 数。还有一种情况是前处理阶段瓶颈。比如 tokenizer 多线程没有开够。部分推理服务有--tokenizer-workers参数在并发场景下把 tokenizer 的 worker 数设为 4 或 8能明显提升吞吐。6.3 模型权重的坑下载失败、目录不完整、混用格式很多人会在 ModelScope 下载时忽略一个细节有些模型仓库内包括了原始权重、样本数据、微调脚本等多个目录导致下载耗时长。其实很多情况下你只需要safetensors文件和 tokenizer 相关文件。可以手动挑选文件列表比如modelscope download --model qwen/Qwen2.5-7B-Instruct \ --local_dir /data/models/qwen2.5 \ --include *.json *.py *.safetensors *.model *.txt *.md这样能过滤掉无关大文件节省时间。另外我碰到过一次服务启动后 tokenizer 一直打印警告原因是模型目录里同时存在新旧两个版本的tokenizer_config.json。后来删掉旧版本问题消失。遇到类似奇怪报错时第一件事检查目录文件是否干净看是否有重复或残留文件。用 Ollama 时也容易踩一个坑GGUF 文件本身可能是分片拆多个文件的用 Modelfile 导入时一定要保证路径指向完整的分片目录不能只指向第一个文件。否则会出现在生成长输出时中断的情况。7. 后续扩展与我的实际体会到这里一个从「模型下载」到「并发服务」的完整路径就已经清楚了。Ollama 解决的是“快速验证和低门槛使用”vLLM 解决的是“高并发和高吞吐”LMDeploy 解决的是“一站式部署和量化落地”ModelScope 则是所有模型来源的稳定底座。四个工具不是互相替代而是可以组合使用的在 Ollama 上迭代提示词和模型选择在 vLLM 或 LMDeploy 上做上线部署用 ModelScope 管理模型的版本和分发。我自己实际跑过最舒服的一次操作是先用 ModelScope 拉取 Qwen 系列模型然后用 Ollama 以 GGUF 形式快速验证模型回答质量确认模型之后再用 LMDeploy 加载原始权重做量化最后用 vLLM 承接正式 API 服务。整个流程下来几乎没有遇到无法解决的阻碍最大的坑反而是目录和格式管理。关于性能我再强调一次别迷信工具营销里的“数倍提升”实际部署中收益最大的永远是显存规划。无论用哪个引擎先把模型显存占比、可用 KV Cache 空间、期望并发这三个变量算清楚再决定要不要量化、要不要开长上下文。另外所有参数都要对标你自己的业务数据做压测网上传的参数仅供参考。最后分享一个小技巧部署完之后不要急着丢给测试人员。先把服务启动日志里的关键参数记录在一个 README 里包括模型名、量化方式、最大上下文、GPU 显存使用率、并发上限。下次环境重装或者扩容时这份记录能至少帮你节省半天的时间。本地化部署这件事看起来是跟机器打交道实际上是对需求的拆解能力。想清楚自己要什么选路径就简单多了。