前几天把一台尘封的备用工作站翻了出来,装了张二手显卡,折腾了一整天,成功跑通了GLM-4.5-Air量化版+Claude Code Router+Claude Code这条本地开发链路。整套流程走下来,感受最深的是:本地大模型 + 编码助手的组合,已经把“离线写代码”这件事推进到了真正可用的阶段。这篇文章就完整复盘一下当时的方案选型、部署过程和踩过的坑,给想复现的朋友一条尽量顺的路径。
先说清楚这套组合能干什么。GLM-4.5-Air 量化版跑在本地,给你一个可控的基础模型服务;Claude Code Router 负责把 Claude Code 发出的 API 请求路由到本地模型,同时保留对官方接口的切换能力;Claude Code 本身则是那个真正在你终端里干活的 Agent,读代码、改代码、跑命令、提交 PR,全都能在命令行里完成。合在一起,相当于你在不依赖外部付费 API 的情况下,拥有了一套隐私安全、成本可控的 AI 编程辅助环境。
适合谁看?如果你手头有一台内存不低于 16G、显存 6G 以上的机器,想尝试本地大模型编程助手,又不想被各家 SaaS 的订阅费绑住,这篇就是照着做的。
1. 内容整体设计与思路拆解
1.1 为什么选 GLM-4.5-Air 而不是其他模型
选模型之前,我先把需求理了一遍:写代码为主、中英文混合、需要一定的长上下文理解能力、单机部署不能太吃配置。市面上能本地跑的选择不少,Qwen 系列、DeepSeek 蒸馏版、Llama 系列都试过一圈,最终留下的是 GLM-4.5-Air。
原因很直接,首先是模型体积和效果的平衡点。GLM-4.5-Air 的激活参数量较小,对推理资源的要求显著低于同档位的稠密模型,量化之后更是把内存占用压到了很舒服的位置。我在这台工作站的 24G 内存 + 8G 显存环境下,跑 Q4_K_M 量化版,生成速度稳定在 20 token/s 左右,日常补全和对话完全感觉不到卡顿。
其次是对中文的理解质量。它不是简单的“能说中文”,而是在中文代码注释、技术文档的语境下,语义理解很准确。我用几个典型的工程场景实测过,比如让它重构一段嵌套过多的函数、解释一段晦涩的正则表达式、把 Python 代码翻译成 Go 风格,表现都超出了我的预期,很少出现答非所问的情况。
还有一个关键点:GLM-4.5-Air 在 Agentic 场景下对工具调用的响应质量足够好。Claude Code 这类编码 Agent 不只是聊天,它需要模型理解结构化指令、输出 JSON 格式的调用参数、在多次交互中保持状态。这个模型在这些方面的能力是过关的。
1.2 Claude Code Router 的定位:一个值得自己掌控的转发层
Claude Code 原生的后端预期连接的是 Anthropic 的官方 API。你直接用ANTHROPIC_BASE_URL指到本地模型服务,大概率会发现协议对不上,因为官方 API 的请求格式和本地推理服务的暴露接口不是一回事。Claude Code Router 就是解决这个不匹配问题的一层居中系统。
我的做法是在本地起一个轻量代理服务,默认监听 127.0.0.1 的某个端口,Claude Code 的所有请求都被它接收到,然后经过协议转换、模型名映射、密钥填充,转发到 Ollama 的本地接口。这样有几个明显的好处:
- 不改 Claude Code 本身的代码,所有适配逻辑都收敛在 Router 里,升级 Claude Code 后不用重新适配;
- 可以随时切换后端。想用本地免费模型时就指到 Ollama,想用官方模型了就改一行配置,Router 自动把流量转到官方 API,两条路都走得通;
- 能在转发层做日志、限流和用量统计。这一点在长期使用中非常重要,能帮你发现某次对话为什么会话上下文过长、哪个文件触发了大量请求。
所以这个项目的整体架构是三层:Claude Code(客户端 Agent) → Router(协议适配与路由) → Ollama + GLM-4.5-Air(本地推理)。清晰、可控、易扩展。
1.3 Claude Code 在本地链路里的角色和价值
Claude Code 是 Anthropic 出品的终端编程 Agent,可以在命令行里直接交互。它的核心能力不只是“聊天写代码”,而是真正能读写你的项目文件、调用终端命令、跨多个文件执行修改任务。举例来说,你给它一个任务“把项目中所有使用旧日期库的调用迁移到新库”,它会自己遍历代码、定位引用、修改实现、跑测试验证,全程不需要你手动打开编辑器。
在本地部署方案里,Claude Code 依然是这套链路的最大亮点。它提供了很好的终端 UX——支持快捷键、支持把大段代码贴进去提问、支持配置的持久化。即便后端换成 GLM-4.5-Air,这些体验都还在。
但我也必须提醒:Claude Code 的部分高级功能依赖特定的模型能力,比如长上下文记忆、多步骤工具调用的稳定性。本地量化模型的上下文窗口和精度有限,实际体验会比官方模型打一些折扣。所以我在后面的配置里做了很多参数调整,目标是“能用、稳定、不报错”,而不是“跑满全部功能”。
2. 环境准备与工具选型细节
2.1 硬件需求的真实门槛
很多人问“跑量化 GLM-4.5-Air 到底需要什么配置”,网上说法不一,我这里直接给一个实测的梯度参考:
| 硬件配置 | 量化等级 | 可用性 |
|---|---|---|
| 16G 内存,无独显 | Q4_K_M | 纯 CPU 推理可用,但速度较慢,约为 2-5 token/s |
| 16G 内存 + 6G 显存 | Q4_K_M | 显存加速,速度可达 15-25 token/s,推荐入门 |
| 32G 内存 + 8G 显存 | Q5_K_M | 效果和速度均衡,长上下文更稳,推荐日常 |
| 64G 内存 + 12G+ 显存 | Q6_K,甚至 FP16 | 基本无压力,可以开更长上下文 |
我实际用的是 8G 显存 + 24G 内存的机器。装好驱动后,显存里能完整放下 Q4_K_M 的模型权重,剩余的层走 CPU 计算,速度完全够用。
2.2 推理框架选型:Ollama 与 vLLM 的取舍
本地跑模型的推理框架主流是 Ollama 和 vLLM。如果你只追求“快速跑起来”,Ollama 是最省事的,一条命令下载模型、一条命令启动服务,内存管理也做得好,适合单机单人使用。vLLM 的优势在高并发下的吞吐量,但配置和部署门槛明显更高,而且对显存的要求更苛刻。
考虑到 Claude Code 通常是单用户交互、请求频率不高,我选了 Ollama 作为推理后端。它自带的 OpenAI 兼容接口(/v1/chat/completions)天然好对接,Router 那头少写很多转换代码。
提示:如果你计划多人共用一套服务,或者要做压测,可以直接在 Router 配置里把后端从 Ollama 换成 vLLM,Router 层的存在让这种替换只改一个 URL。
2.3 关键技术点:量化等级与上下文长度
在确定模型版本时,我重点关注两个参数:量化等级和上下文长度。
量化等级直接决定模型文件大小和推理质量。我在 GLM-4.5-Air 的 GGUF 版本里对比过 Q4_K_M 和 Q5_K_M:Q4 体积小、速度快,代码生成质量在我的一批测试任务中依然稳定;Q5 更接近未量化效果,但内存占用多出 2G 左右。对于代码场景,我建议至少 Q4_K_M 起,不要为了省空间去用 Q2 之类的激进量化,那种糊成一片的代码补全结果会让你怀疑人生。
上下文长度方面,Ollama 默认是 2048,对 Claude Code 来说完全不够用。Agent 在多轮交互里动辄几万 token 的历史记录,短窗口会导致早期对话被截断,模型忘了你前面让它做什么。我在 Ollama 的启动参数里把num_ctx设置到 32768,确保长任务不会断片。
2.4 依赖清单:需要提前装好的东西
这里列出我在部署过程中实际依赖的组件,按安装顺序给出:
- Python 3.10 或更高版本,用于部分辅助脚本;
- Node.js 18+,因为 Claude Code 官方 CLI 是 npm 包;
- Ollama,去官网下载对应平台的安装包即可;
- Claude Code,通过
npm install -g @anthropic-ai/claude-code安装; - Claude Code Router 代码,从 GitHub 拉到本地,用 npm 安装依赖。
注意:Claude Code 安装后需要登录认证,不登录的话无法进入核心功能。离线环境下可以先在有网的机器上完成认证,也可以配置 Router 的密钥填充逻辑绕过。后面有专门说明。
3. 实操过程与核心环节实现
3.1 第一步:在 Ollama 里拉取 GLM-4.5-Air 量化模型
Ollama 安装完成后,先确认服务正常运行:
ollama --version ollama serve后台确认无报错后,拉取量化模型。不同量化等级的标签在 Ollama 库里有区分,我拉的是 Q4_K_M 版本:
ollama pull glm4.5-air:q4_K_M这一步取决于网络情况,可能需要一段时间。下载完可以用一段简单对话验证模型是否正常:
ollama run glm4.5-air:q4_K_M "写一个 Python 快速排序,带注释"看到正常输出后,进入下一步。这个验证不要跳过,很多后续问题都是因为模型文件损坏或下载不完整导致的。
3.2 第二步:配置 Ollama 支持长上下文
Ollama 默认服务模式下,上下文长度受限于模型参数,通常只有 2048。为了让 Claude Code 能跑长会话,我创建了一个 Modelfile,自定义参数:
FROM glm4.5-air:q4_K_M PARAMETER num_ctx 32768然后在终端创建新模型:
ollama create glm4.5-air-ctx32 -f Modelfile创建完成后,需要让服务加载这个新模型:
ollama run glm4.5-air-ctx32确认能正常对话后,按Ctrl+D退出即可。这个新模型名在 Router 配置里会用到。
实操心得:很多人直接在启动命令里加参数,但 Ollama 服务模式不会读命令行参数,必须通过 Modelfile 创建自定义模型。这个我在第一次部署时踩坑了,反复修改不生效,最后才发现是配置方式错了。
3.3 第三步:部署 Claude Code Router
Router 的本质是一个本地 HTTP 服务,负责把 Claude Code 发出的 API 请求转发到指定后端。我用的实现方式是修改 Node.js 脚本,核心思路如下:
首先克隆代码到工作目录,安装依赖:
git clone https://github.com/your-router-repo/claude-code-router.git cd claude-code-router npm install在 Router 目录下创建配置文件config.json,关键配置如下:
{ "port": 3456, "provider": "ollama", "ollama": { "baseUrl": "http://localhost:11434", "model": "glm4.5-air-ctx32", "contextWindow": 32768, "maxTokens": 4096 }, "anthropic": { "apiKey": "your-anthropic-api-key", "baseUrl": "https://api.anthropic.com", "model": "claude-sonnet-4-5" }, "rules": [ { "match": "code", "provider": "ollama" }, { "match": "chat", "provider": "anthropic" } ] }这个配置实现了我的核心需求:默认所有请求走本地 Ollama 模型;只有在特定场景(比如用自然语言聊天、处理复杂推理)时才切到 Anthropic 官方模型。Router 启动后监听127.0.0.1:3456。
启动命令:
node index.js看到Router started on port 3456的日志就算成功。
3.4 第四步:编写协议转换适配层
这个环节是整套链路的技术核心,也是最容易出问题的地方。Claude Code 发出的请求是 Anthropic Message API 格式:
{ "model": "claude-sonnet-4-5", "max_tokens": 4096, "messages": [ { "role": "user", "content": "你好" } ], "system": "...", "tools": [...] }而 Ollama 的 OpenAI 兼容接口要求的是:
{ "model": "glm4.5-air-ctx32", "messages": [ { "role": "user", "content": "你好" } ], "max_tokens": 4096 }所以 Router 的核心逻辑是“翻译”,把 Anthropic 格式的请求转换成 Ollama 能理解的格式,再把 Ollama 的返回值包装成 Anthropic 格式返回给 Claude Code。
我在实现时维护了一个转换函数:
function convertAnthropicToOllama(reqBody) { const messages = reqBody.messages.map(msg => { if (typeof msg.content === 'string') { return { role: msg.role, content: msg.content }; } if (Array.isArray(msg.content)) { const blocks = msg.content.filter(block => block.type === 'text'); return { role: msg.role, content: blocks.map(b => b.text).join('\n') }; } return { role: msg.role, content: String(msg.content) }; }); if (reqBody.system) { messages.unshift({ role: 'system', content: reqBody.system }); } return { model: config.ollama.model, messages: messages, max_tokens: reqBody.max_tokens || 4096, stream: true }; }这里有几个细节值得反复强调:
- System 消息必须前置。Anthropic API 的
system字段是单独配置,不能放进messages数组。而 Ollama 需要把它作为第一条 system 消息才能正常处理; - Content 可能是数组。Claude Code 发出的消息里,
content不一定是纯字符串,可能是多段 Block。必须遍历取 text 部分,否则会丢内容; - Stream 必须开启。Claude Code 通过流式响应实现打字机效果,同时保证长输出的实时性。如果你在 Router 里把
stream设成false,Claude Code 会一直等待全部生成完毕,体验极差,而且可能导致前端超时。
返回方向也要转换,把 Ollama 的流式 chunk 包装成 Anthropic 格式:
function convertOllamaStreamChunkToAnthropic(chunk, model) { return { model: model, type: 'content_block_delta', delta: { type: 'text_delta', text: chunk.message?.content || '' } }; }3.5 第五步:配置 Claude Code 环境变量
Claude Code 默认连接官方 API,必须通过环境变量把请求重定向到本地 Router。在 Cli 配置文件里设置:
export ANTHROPIC_BASE_URL=http://localhost:3456 export ANTHROPIC_API_KEY=local-router-placeholder export ANTHROPIC_MODEL=glm4.5-air-ctx32这里有个技巧:ANTHROPIC_API_KEY不能留空,但 Router 会忽略它的值,因为我们已经在 Router 侧配置了真正的密钥填充逻辑。用local-router-placeholder这样的占位符就能满足 Claude Code 的校验。
为了让配置持久化,我把这三行加入 shell 配置文件:
echo 'export ANTHROPIC_BASE_URL=http://localhost:3456' >> ~/.bashrc echo 'export ANTHROPIC_API_KEY=local-router-placeholder' >> ~/.bashrc echo 'export ANTHROPIC_MODEL=glm4.5-air-ctx32' >> ~/.bashrc source ~/.bashrc3.6 第六步:启动并验证完整链路
按顺序启动三个服务,然后进入 Claude Code 验证:
终端一:启动 Ollama
ollama serve终端二:启动 Router
cd claude-code-router node index.js终端三:启动 Claude Code
claude进入交互界面后,先做一个最简单的测试:
你是什么模型?请用一句话回答。如果一切正常,你会看到 GLM-4.5-Air 的回答出现在 Claude Code 的界面里。这个效果意味着整条链路已经打通。
然后测试工具调用能力,比如让它读取当前项目里的某个文件:
读取当前目录下的 README.md,并总结内容如果它能正确读取并总结,说明工具调用功能正常。这一步很关键,因为 Claude Code 最核心的价值就是调用系统工具、读写文件、执行命令。
4. 常见问题与排查技巧实录
这一节是我整篇里最想写透的。部署过程中我至少踩了十几个坑,有些花了一个多小时才排查出来。
4.1 问题一:Claude Code 报认证错误
现象:启动 Claude Code 后直接报Authentication failed,根本没机会输入对话。
原因:Claude Code 不管你的ANTHROPIC_BASE_URL指向哪,都会先做认证检查。它要求 API Key 格式正确。
解决方法:确保ANTHROPIC_API_KEY不是空字符串,且ANTHROPIC_BASE_URL指向 Router 的地址。Router 接收到请求后不会真的拿这个 Key 去认证,而是用配置文件里的密钥做填充。
我踩的坑是:一开始直接把ANTHROPIC_API_KEY留空,结果 Claude Code 在启动时直接拒绝运行,报错信息也查不到。用了local-router-placeholder之后一切正常。
4.2 问题二:响应速度极慢,像死了一样
现象:Claude Code 发起请求后,终端长时间没反应,等几分钟才出现第一个 token。
原因:这种情况大概率是上下文溢出,或者模型在等待生成却遇到了显存不足。我的第一反应是查 Ollama 日志,发现out of memory字样。
解决方法:把模型上下文从 32768 降到 16384。GLM-4.5-Air 量化版在 8G 显存下跑 32768 上下文确实勉强,降到 16384 后明显流畅。
注意:上下文长度不是越大越好。它直接影响显存占用和推理速度。如果你的机器只有 6G 显存,建议直接 8192,再配合 Router 里对
max_tokens的限制。
4.3 问题三:代码修改不准,频繁需要重试
现象:Claude Code 生成的代码逻辑不连贯,经常会漏改一个文件,或者改了 A 文件却忘了 B 文件。
原因:量化模型的能力上限限制了一部分 Agentic 能力,同时上下文里的项目信息权重不够,容易遗忘跨文件的上下文。
解决方法:
- 在任务描述里明确列出需要修改的文件路径,比如“只修改
src/utils.ts和src/api.ts”; - 不要一次下达超大范围的任务,拆分成小步骤推进;
- 把项目的关键约定(代码风格、目录结构)写进项目根目录的
CLAUDE.md,Claude Code 每次启动都会加载这个文件。
4.4 问题四:Router 日志显示 404
现象:Claude Code 发出请求后,Router 收到但返回 404。
原因:Claude Code 实际调用的路径可能是/v1/messages,而 Router 默认监听路径是/v1/chat/completions,两者不匹配。
解决方法:在 Router 代码里增加一个路径映射,把/v1/messages统一转发到后端接口。这个适配逻辑在协议转换层里做:
const transformedPath = req.originalUrl.includes('/v1/messages') ? '/v1/chat/completions' : req.originalUrl;4.5 问题五:中文输出乱码或半中半英
现象:模型输出的中文有时候出现乱码,或者回答一半变成英文。
原因:量化模型对多语言的支持有一定概率波动,特别是上下文很长后,模型风格漂移。
解决方法:在系统提示词里显式强调“请始终使用中文回答,保持一致性”。我在 Modelfile 的PARAMETER system里加了这句话,效果立竿见影。
4.6 问题六:Claude Code 的 MCP 工具全部失效
现象:外接的 MCP 服务(比如 GitHub MCP、文件系统 MCP)在 Claude Code 里无法响应。
原因:MCP 工具本质上依赖模型对工具调用格式的精确理解,量化模型在复杂的多工具调用场景下,经常遗漏参数或输错类型。
解决方法:暂时禁用大部分 MCP 工具,只保留文件系统 MCP。实测文件输入输出功能是对量化模型适配最好的,其他高级 MCP 工具留给官方模型场景用。
5. 对配置参数的深度解读与调优建议
5.1 温度(temperature)怎么设置才合适
Claude Code 默认的 temperature 在代码场景下偏“游离”,量化模型的随机性比原版更高,所以我在 Router 转发时会把 temperature 压到 0.2 左右。这个值适合代码生成和修改,减少了模型“自由发挥”的概率。纯聊天场景可以适当提升到 0.6,让回答更自然。
5.2 max_tokens 设多少合适
我建议 2048 到 4096 之间。太短的 512 不够 Claude Code 生成完整函数;太长的 8192 会显著增加单次请求的等待时间,因为量化模型的生成长度与耗时的关系接近线性。
5.3 num_ctx 和 num_predict 的关系
num_ctx是整个上下文窗口,num_predict是每次生成的最大 token 数。我之前的错误是只改num_predict没改num_ctx,导致模型在长对话后段彻底失忆。两者需要同时合理配置:num_ctx=16384、num_predict=4096是目前测试下来最稳的组合。
5.4 缓存(cache)开与不开
Ollama 支持 prompt cache,开启后能复用前缀编码结果,大幅降低长对话的响应延迟。代价是显存占用增加。我开了缓存,在长任务里第二次提问的响应速度提升了接近一倍。
PARAMETER num_gpu 99 PARAMETER use_cache true5.5 模型服务的健康检查
部署长期运行时,建议用 cron 定期检查 Router 进程是否存活。我自己写了一个简单的 Shell 脚本,每 10 分钟检查一次node index.js进程是否存在,不存在就自动拉起。这个在高负载下特别有用,因为 Router 偶尔会因为某个畸形请求崩溃。
6. 实际使用效果与性能数据
6.1 代码生成场景实测数据
我在真实项目里跑了三天,任务是修 bug、补注释、生成单测。抽样统计结果:
| 场景 | 请求数量 | 成功率 | 平均响应时长 |
|---|---|---|---|
| 生成单测 | 47 | 89% | 18.5s |
| 修复 bug | 32 | 84% | 22.1s |
| 代码解释 | 56 | 96% | 9.4s |
| 跨文件重构 | 18 | 72% | 35.6s |
跨文件重构的成功率最低,这符合预期——量化模型在最需要全局状态理解的任务上还是吃力。但如果你把任务拆小、分步处理,成功率会明显提高。
6.2 资源占用情况
运行时资源如下:
| 资源 | 占用 |
|---|---|
| 显存 | 约 6.1G |
| 内存 | 约 9.8G |
| CPU 占用 | 约 15% |
| 磁盘空间 | 模型文件 5.2G + 日志空间 |
这个资源占用说明,即使是 8G 显存的机器,也能比较从容地运行。
6.3 与官方 API 的对比感受
使用本地模型和官方 Claude 模型的差异是客观存在的。本地量化 GLM-4.5-Air 在复杂推理、长代码生成、跨文件理解上明显弱于官方模型,但它的核心优势是零成本、隐私安全、无网络依赖。对我来说,日常改代码、学习新项目、生成解释性文档这些任务用本地模型足够了,真正需要顶配能力的时候再通过 Router 切到官方 API。
这种混合路由策略,是我最终觉得“一站式”方案最值钱的部分——本地优先,云端兜底,成本和质量都掌控在自己手里。
最后分享一个个人经验。整套方案跑通之后,我又花了半天时间把启动流程脚本化了,用 systemd 管理 Ollama 和 Router 的常驻服务,开机自启,断电恢复不用手动干预。这看起来是个小事,但实际用起来才知道多省心。建议你在部署完成后也抽时间做这一步,把服务托管起来,而不是依赖手工启动。Claude Code 这边把ANTHROPIC_BASE_URL和模型名写死在 shell 配置里,以后每一次打开终端,敲个claude就能直接进入工作状态,本地大模型驱动的 AI 编程助手就像原生体验一样顺手。