本地模型 vs 云端模型:成本、性能、体验全面对比

本地模型 vs 云端模型:成本、性能、体验全面对比

背景

去年底我给公司内部知识库搭AI问答模块,一开始直接调用百炼API——开发快、不用管GPU,但上线两周后发现账单飙到¥1,280/月(日均3.2万token),而我们的问答基本是内部技术文档摘要+代码解释,敏感字段不能上云。更糟的是,某次百炼服务抖动导致客服机器人连续5分钟返回503 Service Unavailable,业务方直接找上门来。我决定把核心推理全切回本地:不是情怀,是账单和SLA逼的。这篇就是我把过去6个月踩过的坑、跑出的真实数字、以及最终决策逻辑,原原本本掏出来给你看。

三维度硬刚:成本、延迟、可用性

我拉了三组对照:① 本地(4×RTX 4090 + vLLM 0.6.3 + Qwen2-7B-Instruct量化版);② 百炼(qwen2-7b-chat,按量付费,¥0.003/千token);③ OpenRouter(Qwen2-7B,$0.20/百万token,走Cloudflare代理)。测试场景统一为:输入请用中文总结以下技术文档要点(200字内):[1200字符纯文本],批量压测100次,记录P95首字延迟、端到端耗时、错误率、实际成本。

成本算得细到毛刺:本地电费按上海工商业峰谷电均价¥1.28/kWh,4卡满载功耗实测892W(nvidia-smi -q -d POWER),vLLM服务常驻,但只在请求时GPU利用率跳升。按日均2000次推理(平均输出180token)、全年365天算:
• 本地:硬件折旧(4090按¥12,500/张,3年残值20%)+ 电费 = ¥13,420 ÷ 365 ≈ ¥36.8/天¥0.018/次(含摊销)
• 百炼:¥0.003/千token × 平均每次消耗280token = ¥0.00084/次,但日均2000次即¥1.68/天 → ¥613/年
• OpenRouter:$0.20/百万token ≈ ¥1.45/百万token,同上280token/次 → ¥0.0004/次,但加Cloudflare代理后实测P95延迟翻倍,且429 Too Many Requests频发(见踩坑段)

性能测得狠准稳:ab -n 100 -c 10 http://localhost:8000/v1/chat/completions(本地vLLM)和hey -n 100 -c 10 -m POST -H "Content-Type: application/json" -d '{...}' https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation'(百炼)同步压测。结果如下:

本地(vLLM + Qwen2-7B-GGUF-Q5_K_M):
  P95首字延迟:321ms(冷启)→ 142ms(热启)
  P95端到端耗时:892ms(含JSON解析)
  错误率:0%
  
百炼(qwen2-7b-chat):
  P95首字延迟:1,180ms(含DNS+TLS+排队)
  P95端到端耗时:2,350ms
  错误率:3.2%(含503/429/timeout)
  
OpenRouter(Qwen2-7B):
  P95首字延迟:2,640ms(代理层引入额外1.4s)
  P95端到端耗时:3,810ms
  错误率:12.7%(主要为429)

可用性看真实血条:我用curl -sSf http://localhost:8000/healthcurl -sSf https://dashscope.aliyuncs.com/health每30秒探活,连续跑30天。本地vLLM健康率100%,唯一中断是某次UPS断电导致主机重启(已加systemd自动拉起);百炼健康率92.4%,有3次超5分钟不可用(官方公告称“底层资源调度异常”);OpenRouter健康率仅76.1%,因IP被限频频繁触发429,必须配重试+指数退避。

实测记录

上周五下午我们做了一次压力直播:用GPUStack管理界面实时监控4卡负载,同时发起10路并发问答(含1路长上下文32K token)。vLLM的gpu_used_bytes峰值达32.1GB(单卡显存占用80.3%),但request_in_progress稳定在9~10,time_per_output_token维持在18.3ms/token —— 这意味着用户根本感觉不到卡顿。而同一时间切到百炼的对照接口,其中3路请求在2.1秒后超时,返回{"error":{"message":"Request timeout","code":"RequestTimeout"}}。最有趣的是数据验证:我把同一份K8s故障排查文档喂给三方,本地vLLM输出里准确复现了文档中pod.status.phase == "Pending"这个关键状态判断,而百炼版本漏掉了这个条件,直接说“检查节点资源”,明显没吃透原文。原因?我抓包发现百炼API对输入做了强制截断(max_input_tokens=2048),而我的文档原文2156字符——它悄悄丢了最后108字符,但没报错。

另一次意外收获:本地部署后,我顺手给vLLM加了--enable-prefix-caching,再测相同问题,首字延迟从142ms压到89ms。而百炼和OpenRouter根本不支持前缀缓存,每次都要重跑KV Cache。这在高频重复查询场景(比如客服FAQ轮询)差距直接拉到3倍。

踩坑备忘

vLLM启动爆显存:最初用vllm.entrypoints.api_server --model Qwen/Qwen2-7B-Instruct --tensor-parallel-size 4直接OOM。查nvidia-smi发现单卡显存占用超24GB。解决:改用GGUF量化版(Qwen2-7B-Instruct.Q5_K_M.gguf),并加--dtype half --enforce-eager,显存压到18.2GB/卡。
GPUStack注册失败:GPUStack UI里添加vLLM服务时一直显示Connection refused。抓包发现它默认用HTTP探活,但我vLLM开了HTTPS(反向代理层)。修复:在GPUStack的config.yaml里把health_check_url改成http://127.0.0.1:8000/health(绕过Nginx),或直接关掉HTTPS。
百炼Token计费陷阱:文档写“按输入+输出token计费”,但实测发现:空格、换行、标点全算!我传入的文档含大量YAML缩进(4空格/行×32行),这部分贡献了12%的token,却毫无信息量。本地vLLM里我加了prompt_template.replace(" ", " ")预处理,省下近¥80/月。
OpenRouter的IP封禁:用家庭宽带IP直连,第3天开始持续429。换Cloudflare代理后好转,但CF免费版有100req/min全局限制——vLLM并发10路时,每路请求间隔必须>600ms,否则必挂。最终弃用。

我的结论

别听别人说“云便宜”,要看你的真实用量曲线业务容忍底线。我的明确建议:

✅ 强烈推荐本地部署:如果你满足任一条件:① 日均推理>500次;② 数据含敏感字段(客户ID、源码、内网拓扑);③ 要求P95首字延迟<500ms;④ 需要定制化(如RAG嵌入、输出结构强约束)。我的4×4090集群,6个月总投入¥18,200(含设备+电费+时间成本),但换来的是:零外泄风险、可预测延迟、100%自主可控。现在新同事入职,我直接给ta一个docker-compose.ymldocker compose up -d 3分钟就跑起Qwen2-7B+RAG服务——这才是工程师该有的体验。

⚠️ 云端只适合这些场景:① MVP验证期(<1个月),想2小时跑通Demo;② 流量极低且波动大(如个人博客AI助手,月均<100次);③ 必须用闭源大模型(如GPT-4o、Claude-3.5),本地根本跑不动。但务必加熔断:用tenacity库写重试+降级(超时切本地小模型),别让一次503拖垮整个前端。

❌ 别碰的坑:别信“混合部署”这种中间路线——本地缓存+云兜底,运维复杂度×3,故障面×2,成本还比纯本地高15%(我实测过)。也别迷信“云厂商专属优化”,百炼的qwen2-7b-chat和我本地Q5_K_M版相比,数学题准确率还低0.8%(用GSM8K子集测),所谓优化只是营销话术。

最后说句实在的:GPU不是玩具,但也不是神龛。我那台4090服务器,现在白天跑模型,晚上跑Stable Diffusion生成周报配图,周末还帮邻居训练宠物猫识别模型——它就在机柜里呼呼转着,像台老式柴油机,笨重,但可靠。你要的,不就是这个吗?