ByteNoteByteNote

字节笔记本

2026年6月8日

零 API 费用的本地 Coding Agent:4090 + Codex + LM Studio 实战

API中转
¥120

6 月 1 号那天我做了一个决定:把 ChatGPT 的 Codex 从云端切到本地。

原因很简单。5 月份的账单看了之后有点肉疼——不是 ChatGPT Plus 的 20 刀,是 Codex 跑 agent loop 时消耗的 token 量。一个稍微复杂的任务,模型在后台来回调用工具、读文件、改代码、跑测试,几十轮下来 token 就烧掉了。单次 API 调用几分钱不痛不痒,但 agent 的调用方式是循环式的,一天烧几十万 token 很正常。

更让我不舒服的是另一种感觉:不安全感。

云端 API 的价格随时可能变。OpenAI 已经改过一次计费方式了——从"按条消息"变成"按 token 用量",上下文越长、修改轮次越多,扣得越多。谁知道下次改什么?

本地跑模型,token 无限,价格为零。只要电费和硬件折旧,想怎么烧怎么烧。

但"本地跑模型"这五个字,说起来轻巧,做起来全是坑。这篇文章就是我踩过来之后,把所有该知道和不该踩的东西整理出来。

先说硬件:你的 4090 到底能干什么

我手上是一张 RTX 4090 D,24GB GDDR6X 显存,显存带宽 1008.4 GB/s。

这三个数字决定了你能跑什么模型、跑多快、能不能用。

24GB 显存决定了模型的上限。装不下的模型要么跑不了,要么部分溢出到系统内存,推理速度断崖式下降。Qwen3.6 35B A3B 的 Q4 量化版大约 20GB,能完整装进 24GB。Nemotron 3 Nano Omni 的 Q4 版本 26GB,装不下,溢出到 CPU 之后速度从 120 tok/s 掉到 10-20 tok/s,基本不可用。

1008.4 GB/s 带宽决定了推理速度。这是显存到 GPU 计算核心之间的数据传输速度。LLM 推理不是计算密集型任务,是内存带宽密集型任务——每生成一个 token,要把模型权重从显存搬到计算单元,算完就扔掉,下一个 token 再搬一次。搬运速度直接决定生成速度。

一个直观的理解方式:GPU 像一条高速公路,带宽是公路宽度,算力是车速。12B 的小模型只有 7GB,货太少,公路没跑满,81 tok/s。35B 的 MoE 模型虽然更大,但每次只激活 3B 参数对应的数据,反而能把带宽利用率拉满,跑到 120+ tok/s。

这就是为什么"更大的模型反而更快"这个看似反直觉的结论会成立。

还有一个小细节:我的 4090 D 插在 PCIe x4 通道上,不是标准的 x16。对推理影响不大——数据主要在 GPU 显存内部流转,不经过 PCIe。但如果以后做多 GPU 推理,x4 会成为瓶颈。

35B A3B 这三个字母是什么意思

选模型这件事,我纠结了很久。27B 稠密还是 35B A3B?Gemma 4 12B QAT 还是 Qwen3.6?

先说 A3B。

MoE 的字面意思是"专家混合"(Mixture of Experts)。35B A3B 这个模型内部有大量"专家"子网络,总参数 35B。但每次处理一个 token,有一个"路由器"决定只激活哪些专家。A3B 的意思就是每次只激活约 3B 参数。

打个比方:35B A3B 像一个有 35 个专家的公司,每次来了一个任务,路由器判断"这是个前端问题",只叫 3 个前端专家开会,其余 32 个人继续待命。27B 稠密模型则像一个 27 人的公司,每次来了任务,27 个人全部开会。

对 agent loop 来说速度才是质量的一部分。RTX 4090 上实测,35B A3B 约 120 tok/s,27B 稠密约 35 tok/s。前者快 3 倍。agent 一次任务要发出 20 到 50 次工具调用,每次消耗数百 token。35 tok/s 的模型每步要等 30 秒以上,120 tok/s 几乎实时。一个是日常能用的工具,一个是吃灰的。

纯编码质量的差距确实存在——27B 稠密在 SWE-bench 上约 77.2%,35B A3B 约 72%。但 agent loop 里大部分任务是聚焦的单一操作(读文件、改 bug、跑命令),MoE 的路由完全够用。质量损失在这个场景下可以忽略。

我的结论:用 Codex 跑 agent loop 选 35B A3B,没有悬念。

QAT:为什么 7GB 的模型能接近满精度效果

Gemma 4 12B QAT 是我在测试过程中用的模型,值得单独说。

QAT 是 Quantization-Aware Training,量化感知训练。普通量化是模型训练完之后再压缩——就像运动员退役后强行减重,模型没见过压缩后的误差,质量会损失。QAT 是在训练过程中就模拟量化误差,让模型提前适应——就像从训练开始就按比赛体重级别练。

同样 4bit 压缩,QAT 版本比普通 Q4 质量损失极小。Google 官方说 12B QAT 的性能接近体积两倍的 26B 模型。Unsloth 测试显示 KL 散度低 29 倍。7.15GB 的体积,跑出来的效果接近需要 24GB 的 bf16 满精度版。

我在 LM Studio 里跑这个模型,81 tok/s,GPU 在推理时飙到 97%,温度 58°C。速度不错,但 12B 的 coding 能力和 35B A3B 不在一个量级。它更适合做多模态任务(分析截图、理解文档),和 coding agent 互补。

LM Studio 还是 Ollama

Apple Silicon 用户普遍选 LM Studio,因为它原生支持 MLX 格式——MLX 走 Apple Silicon 的 Metal GPU,绕开 CPU-GPU 数据搬运,比 GGUF 在 Mac 上快得多。

Windows + NVIDIA 的情况不太一样。两个都能用,选择逻辑也不同。

LM Studio 的优势在于模型管理体验。内置模型搜索和下载,加载后直接开 Local Server,默认端口 1234,Codex CLI 一配就能连。Ollama 的优势在于生态更成熟,很多 agent 框架默认集成 Ollama 支持。

我选 LM Studio 的原因很简单:它的 Local Server 管理更方便,而且 Codex 配置只需要一个 config.toml 就搞定。

配置过程两步。

第一步,在 ~/.codex/config.toml 里加:

toml
[model_providers.lm_studio]
name = "LM Studio"
base_url = "http://localhost:1234/v1"
wire_api = "chat"

[profiles.qwen36]
model_provider = "lm_studio"
model = "qwen/qwen3.6-35b-a3b"

第二步,启动 Codex:

bash
codex --profile qwen36

这里有个坑。 模型名称格式不同:Ollama 用 模型名:tag 格式(如 qwen3.6:35b-a3b),LM Studio 用 vendor/model-name 格式(如 qwen/qwen3.6-35b-a3b)。直接把 Ollama 的名字粘到 LM Studio 的配置里会找不到模型。

[此处插入截图:LM Studio 模型加载页面,显示 Qwen3.6 35B A3B 的 Vision、Tool Use、Reasoning 三个能力标签]

三个能力标签,缺一不可

LM Studio 里加载 Qwen3.6 35B A3B 之后,会显示三个能力图标。

Vision — 能看图,可以把截图扔给它分析。对 coding agent 来说这意味着它能理解 UI 截图、报错页面截图。

Tool Use — 能调用工具。Codex 的文件读写、命令执行全靠这个。没有这个能力,coding agent 就是空谈。

Reasoning — 有思考模式。复杂任务先在脑子里推理再回答。就是你在输出里看到的"Thought for X seconds"。

这三个能力缺一个都不行。Vision 让它看,Tool Use 让它动手,Reasoning 让它在动手之前先想清楚。

Thinking Preservation 是 Qwen3.6 的一个额外特性:可以在多轮对话中保留推理上下文。对 Codex 这种多步骤工具调用场景很关键——每一步的推理不是独立的,需要记得前面几步做了什么、发现了什么。

实际跑起来是什么感受

LM Studio 开启 Local Server,Codex 启动,连接本地模型。

第一感受是延迟。云端的 Claude Code 响应几乎是即时的,本地模型有一个明显的启动延迟——LM Studio 需要先加载模型到显存。加载完毕之后,单次推理的延迟取决于 tok/s。

120 tok/s 意味着什么?模型每秒输出 120 个 token。一段 500 字的回答大约需要 10-15 秒。和云端 Claude Sonnet 的体验差距不大,但和云端 o1 pro 的深度推理模式没法比——那种可能要想一分钟,本地模型没那个深度。

第二感受是 GPU 的占用。任务管理器里 GPU 利用率在推理时飙到 97%,温度 58°C,显存用了 10GB 左右(跑 12B QAT 的情况)。如果是 35B A3B,显存会用到 20GB,带宽打满,这才是 4090 的正常工作状态。

[此处插入截图:任务管理器 GPU 97%、58°C 运行中状态]

第三个感受是"终于不用看账单了"。这种感觉很难用数字衡量,但它影响你的使用方式。云端跑 agent loop 时,每次模型开始一个长时间推理,我心里都会默算一下"这一轮又要烧多少 token"。本地跑没有这个问题。模型想多久就想多久,不花钱。

几个踩过的坑

上下文窗口默认 4096。 LM Studio 加载模型后,上下文长度默认只有 4096 token。Qwen3.6 支持最大 262,144 token,你现在只开了 1.6%。做 coding agent 时 4096 太短了,模型很快就会忘记前面的代码。建议改成 32768。

[此处插入截图:LM Studio 上下文设置,4096 改为 32768]

Windows 任务管理器的 GPU 利用率是骗人的。 空闲时显示 3-4%,推理时显示 97%。但这个 3D 栏不是 CUDA 计算负载——Windows 把 CUDA Compute 归类到了"3D"这个桶里。3% 不代表 GPU 没在工作,97% 才是推理时的真实负载。想看准确的 CUDA 占用,用 nvidia-smi

模型会"心算"而不是调用工具。 我让 Gemma 4 12B 算 1234 × 5678,它没有调用计算器工具,而是自己想了 11 秒直接给出答案。答案是对的,但它走的是推理路径,不是工具调用路径。对 coding agent 来说,工具调用的可靠性比心算更重要——你希望它调用 grep 找文件,而不是"凭记忆"告诉你文件在哪里。

采样参数不用动。 Top K、Top P、最小 P、重复惩罚——这些参数控制的是模型"怎么选下一个词"。简单说就是抽奖池的大小和筛选规则。coding 场景用默认值就好,代码生成不需要太多创意。

PCIe x4 而不是 x16。 这是我后来用 GPU-Z 发现的。对单 GPU 推理影响不大,但如果以后做多 GPU,会成为带宽瓶颈。Resizable BAR 已启用,这对推理有小幅提速。

本地和云端不是二选一

我现在的实际用法是混合模式。

日常编码任务、读文件、改 bug、跑测试——本地 Qwen3.6 35B A3B 通过 Codex 执行。速度快,零成本,不依赖网络。

复杂架构决策、需要深度推理的 bug 追踪、涉及大量跨模块重构的任务——切到云端 Claude Code 或 o1 pro。质量差距在复杂任务上是真实的。

这和 Karpathy 的"LLM 顾问委员会"思路一致:不同模型各有所长,按任务复杂度分配。不是"本地替代云端",是"本地承接日常,云端兜底困难"。

适合谁

有独立显卡的开发者,RTX 4090 或 4080 最理想,24GB 显存是跑 35B 量级模型的门槛。16GB 显存的卡能跑但选择少,12B 以下的小模型 coding 能力有限。

Apple Silicon 大内存用户,M5 Max 128GB 跑 35B A3B 6bit 大约 35-50 tok/s,比 4090 慢但可用。M1/M2/M3 的 16GB 版本不建议跑本地 coding agent——上下文窗口受限,速度难以支撑多步骤工具调用。

不想看账单的人。agentic 工作流的 token 消耗是指数级的,本地模型的边际成本趋近于零。

愿意折腾的人。本地模型不 plug-and-play,需要选模型、装环境、配参数、踩坑。但一旦配好,它是你的,不受任何平台限制。

结尾

从开始折腾到现在,大概一周时间。这周里我装了三个模型,踩了五个坑,配通了 Codex + LM Studio 的本地工作流,跑了几十个任务。

最真实的感受不是"快"或"省钱",是"安心"。

安心地让模型跑一个需要 50 轮工具调用的任务,不用担心 token 计价器在背后加速。安心地在本机完成所有开发工作,代码和模型都不离开这台机器。

这种安心感,是云端 API 给不了的。

[此处插入截图:Codex 终端运行中的 agent loop,本地模型在执行任务]

分享: