
这半年来我把日常开发用的LLM从云端API逐渐迁到了本地GPU服务器上。Self-hosting不是一个新概念但在software development这个场景里它带来的收益远比我预想的大代码不再经手第三方服务、高频调用的费用直线下降、上下文长度和模型行为完全可控。这篇文章是我自己完整折腾一遍后的记录覆盖硬件选型、推理引擎、模型对比、编辑器接入、Agent工作流、RAG知识库以及一串实打实踩过的坑。如果你也在犹豫要不要把代码模型搬到本地这篇文章应该能帮你少走不少弯路。1. 先用算账的方式聊聊为什么开发场景更适合本地LLM1.1 代码开发比聊天更吃上下文也更吃隐私很多人把“代码补全”和“对话问答”混为一谈但实际上软件开发的LLM调用模式和普通聊天完全不同。日常聊天一次几百token而代码场景里一个函数可能有几百行一次代码审查要喂进整个文件一个Agent任务可能要读完十几个文件再开始改代码。这么算下来单次调用的token数量是聊天场景的几十倍。token量大带来的第一个问题是上下文窗口。云端服务虽然也有长上下文但真把32K、64K的内容塞进去之后生成速度和费用都会变得很难看而且很多模型在超长上下文下的表现会明显退化。第二个问题是隐私。代码就是公司的资产把核心业务代码通过API发给第三方做评估在很多团队里是过不了合规这关的。本地部署最大的优势就是推理发生在你自己的机器上请求不出内网这从源头上消掉了“代码被外部服务留存”这个隐患。第三个问题是延迟和稳定性。代码补全这种交互需要的是低延迟、稳定的返回。公网API的延迟取决于你的网络路径和服务端当前的负载高峰期响应变慢、偶发断连都是家常便饭。而本地模型只要显存够用、服务进程稳定响应时间是可控的不会因为“隔壁租户”在跑大任务而连累你。1.2 费用账本API年费对比一块显卡的折旧我自己用的一个折中方案是这样的50人不到的研发团队平均每天通过IDE插件调用约8000次补全每次平均消耗约800 token加上海量的一次性代码审查和对话任务日均token量为1600万左右。如果全用云端API按会员包月或按量付费一年下来的账单非常可观而一台双卡RTX 4090的服务器用三年折旧加上电费和机房托管总成本大约只有同等级别API年费的40%到60%。这里的关键点是聊天用户按量付费没问题因为频率低、单次短但开发工具是高频请求单日token量很容易冲到千万级别这种量级下本地算力就会体现规模效应。当然自托管不是零成本GPU折旧、电力、模型更新、调优的人力都是成本。如果你的团队只是偶尔用AI辅助写脚本直接买API更划算。这个取舍每个人要自己算一遍。1.3 到底谁需要自托管我并不是建议大家一上来就全部本地化。根据这几个月的经验真正适合自托管的典型场景有这么几类代码和数据敏感不能出内网的团队。每日token消耗量很高API账单已经成了固定开支的团队。需要自定义模型行为比如要微调、要换掉某个模型、要控制上下文窗口大小的场景。网络环境不稳定依赖公网API会直接影响开发效率的场景。如果你的情况不在这个列表里老老实实先用云端API等量上来了再迁移也不迟。2. 硬件与软件栈把显存、推理引擎和模型选型一次性说清2.1 显存估算公式与硬件门槛决定本地部署方案的第一件事是显存而不是GPU型号有多新。显存占用的估算可以套一个很粗的公式模型参数量B× 每个参数的字节数 权重大致占用。以7B模型为例FP16半精度下每个参数占2字节纯权重就要约14GB加上推理时的KV Cache和激活值实际单卡至少需要24GB才跑得舒服。如果显存不够就只能做量化。INT8下每个参数约1字节INT4量化后降到0.5到0.6字节14B模型在INT4下权重只有8GB左右12GB到16GB的消费级显卡就能带起来。我个人的观察是代码补全和常规代码生成任务对INT4量化并不敏感但在复杂逻辑推理和长文本重构上量化后的模型还是能感到一丝“降智”。我的原则是能用FP16就用FP16显存不够再退而求其次。KV Cache对显存的影响也很容易被低估。上下文长度和显存占用是二次方关系32K上下文的KV Cache在7B模型上就能吃掉好几个GB。所以选显卡时不要只盯着“能不能塞下权重”要多算一层长上下文的余量。2.2 推理引擎选型vLLM、llama.cpp、Ollama怎么挑推理引擎现在有不少选择但真正值得盯着的就这么几个Ollama、llama.cpp特别是它的llama-server、vLLM以及少数人用的Hugging FaceTGI。它们各自解决不同的问题Ollama安装简单模型一条命令下载自动支持OpenAI兼容接口适合个人开发者快速起步。llama.cpp llama-serverGGUF量化格式的源头CPU和Mac上表现很好单机内部使用很稳。vLLM吞吐量最强带连续批处理continuous batching和PagedAttention适合做多用户共享的生产级服务。团队里多人同时用我强烈建议直接上vLLM。TGIHugging Face出品和HF生态集成好但如果要我在TGI和vLLM之间选我会选vLLM因为它的社区更活跃、API兼容性更好。选型逻辑其实很简单个人用Ollama足够团队共用直接vLLM如果是MacBook本地跑测试llama.cpp或Ollama一条命令就能解决。不要做选择题做到一半又回头纠结先用Ollama跑通流程再平滑切换到vLLM这个路径最省时间。2.3 模型选型代码模型横向对比模型选型是自托管里最值得花时间的部分。我自己测试和长期使用下来目前主流的本地代码模型大致可以分为三档模型参数规模特点适用场景DeepSeek-Coder6.7B / 33B训练数据覆盖多语言代码生成与补全扎实常规代码补全、单文件生成CodeLlama7B / 13B / 34BMeta出品生态成熟指令跟随一般兼容性测试、微调底模Qwen2.5-Coder0.5B / 7B / 14B / 32B中文和英文代码都强工具调用支持好代码生成、Agent、中文注释场景Phi-3 / Phi-4 系列3.8B / 14B小参数高表现资源占用低轻量补全、老显卡运行Stable Code3B轻量快速专注补全低资源环境个人强烈建议从14B这个档位起步。7B在补全上够用但一旦涉及“多文件重构”“解释整段业务逻辑”这类任务表现会出现明显的天花板。32B档位在代码审查和复杂重构上确实更强但对显存的要求也直线上升32B模型在INT4下都需要20GB左右显存才能跑出可用速度。入门用户不要一上来就追最大模型先把服务跑通、把流程接顺再根据实际需求升级参数规模。3. 部署实操两条可复制的落地路径3.1 用Ollama快速起步一条命令跑出OpenAI兼容接口我个人建议第一步永远是用Ollama把整个流程跑通因为它把模型下载、进程管理、接口暴露都封装好了。Linux或macOS上装好之后核心就三条命令curl -fsSL https://ollama.com/install.sh | sh ollama pull qwen2.5-coder:14b OLLAMA_HOST0.0.0.0:8080 ollama serveollama pull会从模型仓库拉取GGUF格式的模型之后ollama serve启动服务。默认端口是11434我习惯改成8080因为这个端口在IDE插件和脚本配置里更常见。如果你改动服务端口就设置环境变量OLLAMA_HOST比如0.0.0.0:8080表示监听本机所有网卡局域网内其他机器也能访问。验证服务是否起来直接请求一下接口curl http://127.0.0.1:8080/v1/models如果返回了包含qwen2.5-coder:14b的JSON列表说明服务已经就绪。此时你拥有的是一个标准的、兼容OpenAI调用格式的本地接口任何原本对接OpenAI的工具只需要把base_url改成http://127.0.0.1:8080/v1就能接上。3.2 用vLLM搭生产级服务吞吐量的质变当团队多人同时用或者你需要跑Agent批量任务时Ollama会慢慢暴露出并发能力不足的问题。这时候就该切到vLLM。vLLM是Python生态建议在干净的conda环境里装pip install vllm启动命令同样很简单vllm serve Qwen/Qwen2.5-Coder-14B-Instruct \ --port 8000 \ --max-model-len 32768 \ --gpu-memory-utilization 0.9 \ --tensor-parallel-size 1几个参数值得展开说说--max-model-len最大上下文长度我设的是32K。注意设得越大KV Cache吃掉显存越多OOM概率也越高。--gpu-memory-utilization显存利用率上限我习惯设0.9留出10%余量给CUDA上下文和突发峰值。不要设到0.98你会后悔的。--tensor-parallel-size使用多少张卡做张量并行。单卡就用1多卡显存不够跑大模型时再调大。vLLM和Ollama最大的区别在于连续批处理机制当请求并发变高时vLLM会把多个请求动态组合进一个batch里GPU利用率明显高单卡QPS能比Ollama高出好几倍。我们团队实际从Ollama切到vLLM之后同样的硬件配置IDE补全的平均等待时间从4秒降到了1秒左右。3.3 量化与显存优化小显卡到底能跑多大模型如果你的显卡只有12GB或者16GB又实在想跑14B甚至更大大小的模型那只能靠GGUF量化或者vLLM的权重量化。GGUF量化里我最常用的是Q4_K_M它在体积和效果之间比较平衡14B模型量化后大约8GB到9GB16GB显卡还能余出空间处理上下文。量化后的实际效果因任务而异。纯补全和短函数生成问题不大但一旦任务涉及复杂推理、多步骤规划量化模型返回的质量会有肉眼可见的下降。如果你有24GB显存我建议直接跑FP16或INT8把量化带来的损失降到最低。另外一个小显存跑大模型的技巧是把--max-model-len往下压。如果模型默认支持32K你显存不够可以压到16K或8KKV Cache占用的显存会大幅下降。开发场景里大多数补全和对话任务根本用不到长上下文压到16K的体验损失很小。4. 工作流接入从编辑器补全到终端Agent与RAG4.1 把Continue配置成本地模型客户端服务跑起来之后最重要的事是把日常编辑器接上。Continue是VS Code和JetBrains里做得比较好的插件它支持把任意OpenAI兼容端点作为模型来源。安装插件后打开配置文件~/.continue/config.json加入一个模型{ models: [ { title: Local Qwen Coder, provider: openai, model: qwen2.5-coder:14b, apiBase: http://127.0.0.1:8080/v1, apiKey: ollama } ] }这里有个小细节本地服务本身不校验API Key但Continue要求apiKey字段非空随便填一个占位符就行。配置完成后编辑器里按快捷键就能呼出对话面板选中一段代码按CtrlI就可以让模型解释或改代码。自动补全方面Continue会请求服务端的/completions接口本地模型的补全速度直接取决于服务端的吞吐量。4.2 Aider与Cline本地模型做Agent任务的实操IDE里的对话只是第一步真正有生产力的是让模型直接操作代码库、批量修改文件。Aider是终端里的AI编程工具它支持OpenAI兼容服务启动方式如下aider --model openai/qwen2.5-coder:14b \ --openai-api-base http://127.0.0.1:8080/v1 \ --openai-api-key ollama注意模型名前面加openai/前缀因为Aider需要识别它为OpenAI兼容模型。运行之后你可以让Aider“把utils.py里所有硬编码的数据库地址改成配置文件读取”它会自己搜索相关代码、生成diff并应用。本地模型在Aider里能不能跑得好取决于两件事模型本身具备工具调用能力以及服务端支持对应schema。实测下来Qwen2.5-Coder的tool calling支持比较完整跑Aider这类Agent工具比较稳。IDE里同样可以用Cline这类Agent插件和Aider的区别在于它是图形化的文件修改能看到每一次对文件的diff。配置方式类似把Base URL填成http://127.0.0.1:8080/v1模型名填本地的就行。我建议先用Aider在终端里跑通一个简单的重构任务再上Cline这种图形化工具排查问题时更容易定位。4.3 RAG与本地知识库检索让模型更懂你的项目和文档代码补全和对话远不是自托管LLM的终点。社区里讨论很多的“LLM Wiki知识库”本质上就是把项目的设计文档、代码注释、内部规范先做文本切块再用embedding模型向量化存到向量库里供检索。用户提问时先检索出相关的文档片段连同用户问题一起交给LLM生成回答这就是RAG。它能让本地模型在回答项目特有问题上表现得像“懂这个项目的老员工”而不只是“懂通用代码的应届生”。一个实际的例子有人把本地ERP系统的产品手册和业务字段说明做成向量库用户用自然语言问“某个单据的审批流在哪配置”系统通过Semantic Kernel从向量库检索到对应文档再让本地LLM组织成完整回答。这种方案对模型的要求反而不高14B模型完全够用真正要用心的是切块策略和检索质量。我自己在用Semantic Kernel搭这类服务时会这样连接本地模型from semantic_kernel import Kernel from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion kernel Kernel() kernel.add_service( OpenAIChatCompletion( service_idlocal, ai_model_idqwen2.5-coder:14b, api_keyollama, base_urlhttp://127.0.0.1:8080/v1 ) )向量库我建议优先用Qdrant或pgvector。embedding模型不必用太大的本地部署场景里bge-small等轻量模型在中文文档上的表现就不错。RAG真正要花时间调的是chunk size和检索top_k切得太碎会丢失语义切得太长会浪费上下文top_k一次也别取太多否则上下文塞满LLM反而会迷失。5. 密钥管理与安全实践自托管不是免死金牌5.1 密钥泄露的主要来源与自托管优势聊到“使用LLM时如何防止密钥等鉴权信息泄露”很多人的第一反应是环境变量、不要硬编码。这些当然对但自托管还有一个常被忽略的优势你的请求根本不会携带第三方平台的密钥。使用云端API时客户端代码里必然存在一个API Key哪怕放在环境变量里也意味着任何一个能读到环境变量的进程都能冒用你的身份消耗配额。本地服务则没有这个模型级的密钥外部请求不需要分发“LLM密钥”安全面直接少了一块。但这不代表本地部署完全没有密钥管理问题。模型服务本身可能没有鉴权如果你把端口暴露在公网或公司共享网络里任何人都能发起请求消耗你的GPU资源。还有一种更隐蔽的泄密路径你在代码里把数据库密码、云服务AccessKey写进了Prompt然后交给模型去“分析”或“整理”这些敏感信息可能被记录在vLLM的日志、Ollama的历史记录或者Agent工具的对话存档里。所以开发环境里应当建立硬规矩任何密钥都不能通过对话内容发给模型不管是云端还是本地。5.2 本地服务的鉴权与访问控制本地推理服务本身不带完善的用户体系这就需要在前面加一层访问控制。我的做法是服务端口只监听内网同时用nginx做反向代理在代理层加上Basic Auth或Bearer Token。这样至少能挡住绝大多数未授权的访问。如果必须通过公网访问不要直接把Ollama或vLLM的端口暴露出去务必在代理层开启鉴权并限制来源IP。自托管之后安全责任全部回到自己手里这一点意识必须清晰。一些具体措施可以整理成清单部署时挨个核对模型服务只监听内网地址不监听0.0.0.0除非你一定要让局域网内其他机器访问。用反向代理统一暴露服务在代理层加Key校验。禁止把任何密钥写入代码、Prompt、模型历史记录。.env文件加入.gitignore用git-secrets或类似工具拦截密钥提交。定期检查模型服务日志看有没有可疑的调用来源。6. 性能数字与故障排查实录6.1 吞吐量、延迟这些指标怎么看判断自托管服务性能主要看两个指标首token延迟TTFT和生成速度tokens/s。TTFT决定了“代码补全的等待时间”生成速度决定了“长文本生成会不会等到天荒地老”。我用RTX 4090配合24GB显存跑Qwen2.5-Coder-14B时INT4量化下生成速度大约在40到60 tokens/sTTFT在几百毫秒到一两秒之间日常补全和对话完全够用。换到vLLM之后多人并发时吞吐量还能再上一个台阶。有一点要提醒单看生成速度容易忽视并发。Ollama在单用户下速度不慢但几个用户同时请求时其他请求会排队体验明显下降。vLLM的连续批处理能尽量填满GPU计算单元所以团队场景我坚持用vLLM。评测时不要只测单请求的tokens/s要加上并发条件下的p95延迟那个数字才是真实体验。6.2 常见错误速查表下面这些是我和团队在实际使用中遇到最多的问题整理成速查表方便直接对照排查错误现象可能原因解决方法llm request failed: provider rejected the request schema or tool payload.本地模型不支持工具调用或客户端发送了模型不认识的tools参数换支持tool calling的模型如Qwen2.5-Coder在客户端关闭function callingcontext window exhausted或上下文溢出请求内容超过--max-model-len调大--max-model-len注意显存减少RAG检索片段数量CUDA out of memory显存不够KV Cache占满降低上下文长度换成量化模型调低--gpu-memory-utilizationconnection refused服务没启动或端口不匹配检查ollama serve/vllm serve进程检查配置里的base_url端口返回结果不稳定长文本越写越乱上下文过长、模型能力不够或SQL查询结果塞满上下文检索结果做摘要大段数据库结果分页或先聚合再让LLM生成热搜里那个“Dify的SQL查询内容太多导致LLM返回不稳定”的问题本质就是上下文灌得太满。SQL查询结果几百行直接塞给LLM模型生成的注意力全被无关数据打散输出自然不稳定。解决方式是在RAG链路里先对数据库查询做聚合或截断比如先跑COUNT(*)看总量、只返回前50行或者让一个小模型先把结果总结成精华再交给大模型生成最终回答。这比单纯换更大的模型更有效。7. 最后分享几点实际使用中的个人体会前面讲完技术和排错最后说一下自己这几个月的体验变化。最开始我只是想省API的钱真正跑起来之后才发现可控性才是最大的收益模型升级不用等平台上下文窗口自己定服务挂了可以自己排查而不是干等供应商。我个人目前的主力配置是32GB显存的单卡服务器跑Qwen2.5-Coder-14BIDE补全和简单重构都交给它复杂的多文件重构会让Aider配合人工确认效果已经很接近我之前用的云端方案。如果你也想尝试我的建议很直接从Ollama加14B模型起步先接入Continue用一周习惯这个手感后再研究vLLM和RAG。不要一开始就上32B甚至更大的模型部署复杂度会分散你对工作流本身的关注。真正贴着开发流程跑一段时间你自然会知道瓶颈在哪里。自托管LLM这条路没有标准答案硬件、模型、流程都要适配自己的团队但一旦跑顺体验是真的回不去了。