colibri 实测:大模型不装内存、改「摆放」,我在 16GB M4 上摸清了它的真实边界

16GB 内存的 MacBook 能不能跑 744B 的大模型?这个问题我以前的答案都是「装不下,别想了」。10 月底在 GitHub Trending 上看到一个叫 colibri 的项目(JustVugg/colibri,Apache-2.0,写作时 46,000+ star,11 月 2 日还在日榜上),它的回答方式不太一样:模型不用装进内存,而是像工具间里的扳手一样摆放好——每个 token 只用到大模型很小一部分(路由专家),这部分留在磁盘上,路由器点到谁就读谁;常驻内存的只有稠密部分(注意力、共享专家、embedding)。GLM-5.2 有 744B 参数,每个 token 激活约 40B,其中逐 token 变化的路由专家只占约 11GB——这个数字一算出来,「内存不够」这件事就变成了「磁盘够不够、读得快不快」。

我花了一个上午在 M4/16GB 的 MacBook Pro 上把它跑了起来,实测了三块东西:机型适配规划器对一个 16GB Mac 的真实裁决、两个决策引擎 Laya 与 GLiNER2.5-Decide 的端到端推理和同题对比、以及一个 2B 对话模型从 GGUF 导入到生成、再到给中文工单打分的全流程。也确认了一个反直觉的结论:对 16GB Mac 来说,colibri 时代真正的瓶颈不是 RAM,是磁盘容量。下面按顺序讲,所有数据都来自我这次的真实运行,没跑到的部分我会明说。

colibri 是什么:一条和 llama.cpp 不同的路线

先交代背景。colibri 是纯 C 写的 MoE 推理引擎,零依赖,13 个引擎覆盖 13 个模型家族:GLM-5.2/5.3(744B)、Kimi K3(2.8T)、DeepSeek V4 Flash(284B)、MiMo-V2.6(309B/1.02T)、Qwen3.6-35B、Qwen3-Coder-30B、OLMoE,还有一个画图的 Qwen-Image-2.1 和三个决策模型。它可以直接读市面上已发布的 GGUF 文件(从 IQ1_S 到 Q8_0、MXFP4),不做二次量化。

和 llama.cpp 的区别在资源模型上。llama.cpp 的思路是「把模型尽量塞进内存/显存」,塞不下就报错或换页;colibri 的思路是把「哪些权重放哪里」当作一个显式的规划问题:稠密部分常驻 RAM,路由专家留在磁盘,通过一个会学习使用习惯的专家缓存减少重复读盘;有 GPU 时 GPU 拿最热的专家和稠密层。官方的说法是「权重放在哪里只改变速度,不改变模型产出」——同样的路由决策、同样的权重,算出同样的 token。

这份定位决定了它的受众:不是比拼 tok/s 的极客,而是「内存小但磁盘可以大」的普通设备。这正好戳中我这类 16GB 用户。

实测一:规划器对 16GB Mac 的真实裁决

安装走的是官方 release 的 macOS arm64 预编译包(4.4MB,我核对了 SHA256,与官方 SHA256SUMS.txt 一致)。解包出来是 13 个按模型家族命名的引擎二进制加一组 Python 脚本,最大的一个 colibri(GLM 引擎)不到 900KB——「tiny engine, immense model」这句 slogan 不是吹的。

跑起来第一步是问规划器:我这台机器能跑什么。命令一行:

Bash
python3 c/coli setup --list

这是我在 17.2GB 内存的 M4 上拿到的真实输出(节选):

Plaintext
 * qwen36-35b                    23 GB  tight      runs with a small expert cache (needs 10 GB, runs best with 20 GB)
   qwen3-coder-30b               19 GB  tight      runs with a small expert cache (needs 8 GB, runs best with 18 GB)
   deepseek-v4-flash-reap        85 GB  needs-disk needs 88 GB free for the download; 65 GB free there
   glm-5.3                      419 GB  needs-disk needs 430 GB free for the download; 65 GB free there
   glm-5.2                      429 GB  needs-disk needs 440 GB free for the download; 65 GB free there
   kimi-k3                     1561 GB  needs-ram  needs 32 GB of RAM (dense part 20 GB plus the expert cache); this machine has 17.2 GB

这张表值得逐行看,因为我第一次看的时候理解错了两行:

  • qwen36-35b 和 qwen3-coder-30b 标的是 tight:内存下限(10GB/8GB)过了,但「跑得舒服」的线(20GB/18GB)没到,所以会以小专家缓存运行,速度打折。
  • glm-5.3 和 glm-5.2 没有倒在内存上。GLM-5.2 的内存下限是 16GB,我这台 17.2GB 过线了——规划器没有报 needs-ram。它死在第二行:needs-disk,下载要 430/440GB,我只剩 65GB。
  • kimi-k3(2.8T)才是真正的 needs-ram:光稠密部分就要 20GB。

这就是我说的反直觉结论:在 colibri 的盘算里,我这台 16GB Mac 跑不动 744B 模型的原因不是「内存不够」(那是 2024 年的直觉),而是「磁盘不够」。内存墙变成了磁盘墙。对外接大容量 NVMe 的 Mac mini/Studio 用户,这条路是通的;对内置 512GB 硬盘还剩 65GB 的笔记本,744B 只能留在纸面上。顺带一提,Kimi K3 开源时我算过它的部署成本,当时的结论是「没 64GB 内存别碰」;colibri 把内存线拉低到了 32GB,但 1.56TB 的下载量摆在那里——瓶颈只是换了个位置。

实测二:决策引擎 Laya 端到端——一次前向算完一组问题

colibri 有个我很喜欢的子模式叫 System One:POST /v1/systemone 接收一个状态和一组带类型的封闭问题(choice 选择、score 打分、noul 是非),一次前向返回每个选项的概率和置信度。因为不生成文本,答案不可能越出你的选项列表,「模型不确定」是一个可以设阈值的数字。请求格式与 TypeSafe 的 Jev API 兼容,官方说现有 Jev 客户端不改代码、换个 base URL 就能切过来——JEV 决策模型我去年测过,当时只能走 OpenRouter 的云端 API,colibri 把这条路搬到了本地。

我测了原生决策模型 Laya(Convai Innovations,Apache-2.0,842MB 下载)。coli plan --model ~/Models/laya 给出的资源画像:421M 参数、磁盘 843MB、以 f32 运行约占 1.7GB 内存,没有 KV cache、没有需要流式读取的专家,内存占用不随使用增长——这是决策模型和对话模型在引擎里的本质区别。

启动服务后我用客服工单分流的经典场景试它(这也是官方文档的示例请求):

Bash
curl -s http://127.0.0.1:8000/v1/systemone -H 'Content-Type: application/json' -d '{
  "state": "Hi, we were billed twice for March. Please refund the duplicate today or we will cancel our plan.",
  "questions": {
    "department": {"type": "choice", "instructions": "Which department should handle this?",
                   "criteria": {"billing": "invoices, payments, refunds",
                                "technical": "bugs, outages, system errors", "other": "everything else"}},
    "urgency": {"type": "score", "instructions": "How urgent is this?",
                "criteria": ["not urgent", "soon", "blocking"]},
    "churn_risk": {"type": "noul", "instructions": "Does the user threaten to cancel or leave?"}}}'

三个问题一次请求算完,M4 CPU 上实测返回:

Json
{"answers": {
  "department": {"type": "choice", "choice": "billing",
                 "probabilities": {"billing": 0.986516, "technical": 0.007975, "other": 0.005509},
                 "confidence": 0.979774},
  "urgency": {"type": "score", "score": 1.772169, "confidence": 0.71661},
  "churn_risk": {"type": "noul", "noul": 0.879019}},
 "usage": {"input_tokens": 164, "output_tokens": 0, "cost": 0}}

两个细节让我对这引擎多了几分信任:一是我跑出的三个概率与官方文档贴的示例逐位一致(billing 0.986516),同样的输入得到完全确定的输出——决策模型要的就是这种可复现性;二是输出 0 token、成本 0,纯打分不生成。我又换了一个代码评审场景(「340 行、8 个文件、没有测试,CI 绿但没人覆盖这条路径」),它给 merge 的概率只有 0.466、置信度 0.199——低置信度本身就是有效信号,正好拿去触发人工复核。

延迟方面,我连发 5 次同样的两问请求,耗时稳定在 0.70-0.73 秒/次(含 HTTP 开销),引擎进程实测 RSS 1.76GB,与 plan 宣称的 1.7GB 对得上。作为对照,我还确认了 /v1/chat/completions 在决策模型上会被正确拒绝(HTTP 400 并提示走 /v1/systemone)——接口边界干净,不会出现「决策模型开始编故事」的意外。

说实话,决策模型不是什么新物种——但「本地、免 API Key、一次前向、概率可校准」这个组合,对做工单路由、内容审核初筛这类场景是实打实能省钱的,比调一个生成式大模型拼 JSON 稳定得多。

随后我把第二个原生决策模型 GLiNER2.5-Decide(fastino,约 1.95GB 下载,486M 参数、f32 约占 1.9GB 内存)拉起来做了同题对比。延迟上它更快:同样两问的请求连发 5 次稳定在 0.43-0.47 秒(Laya 是 0.70-0.73 秒)。但真正有意思的是分歧:同一句「340 行、8 个文件、没有测试」的评审请求,Laya 给的是 merge 0.466(置信度 0.199),GLiNER 给的是 request changes 0.431(置信度 0.147)——两个模型选了相反的结论,而且都老老实实承认自己不确定。风险判断的分歧更大:Laya 说 0.043(不危险),GLiNER 说 0.477(接近五五开)。这个实验让我确信一件事:决策模型的输出不能单模型独断,低置信度阈值 + 双模型交叉复核才是正确用法——而这恰好只有本地部署才能做得这么便宜,云端 API 每次调用都要钱。

实测三:GGUF 导入 + 2B 对话模型真跑 + 给中文工单打分

决策模型证明引擎活着,但大家最关心的还是对话。我选了 LFM3-VL-2B 的官方 GGUF(Q4_K_M,约 1.1GB)——这个模型上个月我用 llama.cpp 测过全家族,正好当对照组。colibri 的 GGUF 支持是「原位读取」:coli import 只在旁边写一个模型目录(config、tokenizer、chat template 和指向 GGUF 的 gguf.json),不复制不转换,秒级完成:

Bash
python3 c/coli import ~/Models/lfm3vl/LFM3-VL-2B-Q4_K_M.gguf
# colibri model directory ready: .../LFM3-VL-2B-Q4_K_M.colibri  (lfm3, 24 layers, mode link)
python3 c/coli serve --model ~/Models/lfm3vl/LFM3-VL-2B-Q4_K_M.colibri --port 8000

服务约 2 秒就绪,暴露 OpenAI 兼容的 /v1/chat/completions 和 Anthropic 兼容的 /v1/messages。引擎进程实测 RSS 约 1.3GB。解码速度我连测多轮:150-800 token 的生成统一折算在 17.4-18.7 tok/s(M4 CPU,Q4_K_M,含少量提示词处理开销)。官方在 i5-13500 桌面 CPU 上测得 31.6-34.5 tok/s——桌面 DDR5 平台反而比 M4 笔记本快接近一倍,这个对照提醒我们:小模型解码速度基本被内存带宽锁死,「芯片代次新」不等于「解码快」。

然后是我这次最大的踩坑:--no-think 对 LFM3-VL-2B 不生效。LFM3 家族默认开思考链(上次用 llama.cpp 测时也遇过,当时传 enable_thinking=False 就关掉了),这次我在 coli serve 加了 --no-think,实测 150/300/400/800 四档 max_tokens 全部被 reasoning_content 吃光、content 恒为空串,800 token 时思考已写到 2409 字符还没停。源码注释里也写着 LFM3 的模板「<think> always written」。如果你的 OpenAI 客户端只读 content,会以为模型坏了——在 colibri 修掉这个问题之前,接 LFM3 这类思考模型请直接把 reasoning_content 展示出来,或者换非思考模型。

最后测了一个我认为是 colibri 最被低估的功能:对话模型也能走 /v1/systemone——引擎不让它写字,而是读出每个选项的概率。我用中文工单试了两问(「App 在 iOS 18 上白屏,该分派给谁、多严重」):

Json
{"answers": {
  "queue":    {"type": "choice", "choice": "ios_client",
               "probabilities": {"ios_client": 0.720136, "backend": 0.034611, "other": 0.245253},
               "confidence": 0.580204},
  "severity": {"type": "score", "score": 1.449992,
               "probabilities": {"0": 0.197335, "1": 0.155338, "2": 0.647327}}},
 "usage": {"input_tokens": 79, "output_tokens": 11, "cost": 0}}

分派给 iOS 客户端组(0.72)、严重程度偏「高」(0.647),都对;11 个输出 token 是花在收尾上的。中文场景能用,置信度 0.58 也如实反映了它的犹豫。同一个端点、同一个请求格式,小到 421M 的专用决策模型、大到 2B 的对话模型都能接——这套「封闭问题」抽象是我认为 colibri 比裸跑模型更值得关注的资产。

踩坑记录(都是我亲手踩的)

  1. 模型下载器单流直连 huggingface.co。我的网络直连 HF 已经超时(40 秒无响应),colibri 的 setup 下载走 Python 的 huggingface_hub,好在它认 HF_ENDPOINT 环境变量——HF_ENDPOINT=https://hf-mirror.com python3 c/coli setup ... 就能切到镜像。但单流下载在限速网络下依然慢,我是用 curl 并行把权重先拉下来、再让 --model 指向本地目录的。国内读者装模型建议照抄这条路径。
  2. 预编译包别在解包目录里直接用。coli 这个 Python 入口按「自己所在目录」解析引擎二进制路径,官方 start-here.sh 的正常流程会把预编译产物放进仓库的 c/ 目录;我一开始在 release 解包目录里直接跑,引擎找不到。把 13 个二进制拷进 c/ 后一切正常。
  3. --list 的两档内存语义要看懂:needs 10 GB, runs best with 20 GB 的意思是低于下限直接不启动,介于两者之间能跑但以小专家缓存运行(tight)。别把 tight 理解成「跑不了」,也别把下限理解成「推荐值」。
  4. coli plan 对纯稠密小模型有一条吓人的警告。LFM3-VL-2B 的 plan 输出里有一句「1.1 GB of weights do not fit the RAM budget of 4.8 GB」——1.1 明明小于 4.8,实际运行也完全正常。这是提示文案的粗糙边角,看到别慌,以实际 RSS 为准。
  5. Metal 后端我只验证了存在性,没测性能。macOS 预编译包里 colibri、inkling、kimi_k3 三个引擎带了 Metal 后端(运行时编译 shader,不用装 Xcode),COLI_METAL=1 开启。但这三个引擎对应的模型(GLM-5.2/Inkling/K3)我都因为磁盘装不下没下载,Metal 的实际收益我没有数据。qwen36 引擎(跑 Qwen3.6/LFM3-VL)不在 Metal 名单里,我的 plan 输出也明说 M4 被检测到但「reported only and drives no automatic tier」。

不建议使用的场景

  • 把它当低延迟推理服务器。专家从磁盘读的设计决定了首 token 延迟和磁盘速度强相关,官方自己的基准里 GLM-5.2 在普通笔记本上冷启动是 0.05-0.1 tok/s——那是「能跑」不是「能用」。要服务化吞吐,还是 vLLM 那条路线。
  • 磁盘剩余空间小于下载体积 + 20% 时硬上。needs-disk 的判断已经把余量算进去了,强行用 --model-dir 绕过检查只会把系统盘塞爆。
  • 指望决策模型的结果单模型独断。我这次同题对比里,Laya 和 GLiNER2.5-Decide 在代码评审场景给出了相反结论(merge 0.466 vs request changes 0.431),风险判断差距更大(0.043 vs 0.477)。两个模型都以英文为主,Laya 官方标注 English——中文分流要么换支持中文的模型(比如用 LFM3-VL-2B 打分,实测可行),要么先把状态翻译成英文,并且务必设置信度阈值 + 人工复核兜底。
  • 离线后端选型困难症:如果你只是想要一个「开箱即用的本地 AI 桌面应用」,Hob 那类带界面的一体化产品门槛低得多。colibri 的价值在「给大模型一个精确的资源规划」加 OpenAI/Anthropic 兼容端点,它默认没有面向终端用户的完整聊天界面。

写在最后

colibri 给我的最大启发不是某个数字,而是资源模型的转换:当「每个 token 只激活 5% 的参数」成为大模型的常态,「装不装得下」就从内存问题变成了摆放问题。16GB Mac 的真正天花板在磁盘容量和磁盘速度,这两样恰好都是可以外接扩展的。我的 65GB 剩余空间装不下 744B,但如果哪天我挂一块 2TB 的 NVMe,GLM-5.2 就在纸面可行名单里——速度大概要以「秒/词」计,那是另一篇实测的事了。

本次真跑的内容:机型规划器真实输出、Laya 与 GLiNER2.5-Decide 两个决策引擎的端到端推理(含延迟、内存与同题分歧实测)、LFM3-VL-2B 的 GGUF 导入、对话生成与中文 System One 打分。744B 级别的磁盘流式性能我没有实测条件(磁盘不够),相关数字均来自官方文档基准并已注明出处。如果你也想在 16GB 机器上试,我的建议是从决策模型或 2B 级小模型起步,先把 --list 跑一遍再说。

推荐阅读

  • Lightpanda 实测:给 AI Agent 换个不吃内存的无头浏览器,我在 M4 上和 Chrome 真刀真枪比了一轮

    GitHub 4 万 star 的 Zig 无头浏览器 Lightpanda,专为 AI Agent 抓网页而生。我在 16GB M4 Mac 上实测:与 Chrome headless 同页对比,峰…

  • unslop 实测:用免费模型把「一眼 AI 生成」的界面改成有设计感的页面

    GitHub 三天 3500+ star 的 unslop 技能,专治 AI 生成界面的紫渐变、发光、emoji 图标和乱间距。我用 opencode 加免费模型真实跑了一遍:从安装、造重 slop …

  • TokenEconomizer 实测:微软开源的编码 Agent 省钱插件,我在 opencode 上跑通了仓库手册注入,也踩了三个坑

    微软研究院开源的 TokenEconomizer 给编码 Agent 加了经验复用层:从历史会话蒸馏仓库事实,下个会话开头直接注入。我在 opencode 上做了 15 个会话对照实测:token 变…

  • Bernstein 实测:给 CLI 编码 Agent 加一层可离线验证的编排,四组破坏实验测出审计链的真正边界

    Bernstein 是 10 月 29 日登上 Hacker News 首页的开源 Agent 治理层,调度器里没有 LLM。我在 16GB M4 MacBook 上从装包测到 Ed25519 回执:…