做本地推理的人大概都接受过一个默认前提:模型得先装进显存,装不进去就装内存,内存也不够就只能换更小的模型。于是「能不能跑得动」变成了一道纯粹的硬件算术题——参数越大,需要的卡越多。
Colibri 做的事情,是把这道题的前提换掉。它是一个纯 C 写的极简推理引擎,零外部依赖:不链接 BLAS,运行时不需要 Python,也不需要 GPU。而它宣称能跑的模型,从 744B 一直到 2.8T 参数。作为参照,项目诞生时用的开发机是 25GB 内存、12 核 CPU。
💡 一句话概括它的主张:模型不需要「装进」高速内存,它需要被「放置(placed)」。
一、重新算一遍稀疏性这笔账
以 744B 的 GLM-5.2 为例,拆开看每一层到底需要什么:
总参数 744B
每 token 激活参数 约 40B
其中的路由专家 约 11GB(随 token 变化)
稠密部分(注意力 / 共享专家 / 嵌入层) 约 17B
→ int4 常驻内存 约 9.9GB
路由专家数量 19456 个,约 370GB
结论很干脆:真正必须常驻高速内存的只有约 9.9GB,剩下的 370GB 不需要同时在场,只需要「在需要那一刻到达」。于是 Colibri 把存储、内存、显存统一成一层推理层级(AI memory tiering),把权重调度做成了一件类似 JIT 编译器的事——为权重而生的 JIT。
启动时的实际输出长这样:
./coli chat
ready in 32s · resident 9.9 GB
二、构建与权重转换
引擎在 c/ 目录下按模型系列分发,coli 启动器读 config.json 自动选对应二进制,命令行接口完全一致。
以下命令均按项目文档整理:
git clone https://github.com/JustVugg/colibri && cd colibri/c
./setup.sh # 检查 gcc / OpenMP、构建并自测
make -C c glm # GLM-5.2 / 5.3 (744B)
make -C c glm53 # GLM-5.3-Flash (321B)
make -C c kimi_k3 # Kimi K3 (2.8T)
make -C c deepseek_v41 # DeepSeek V4.1 Flash (552B)
make -C c qwen38 # Qwen3.8-Flash-Next (仅 CPU)
make -C c olmoe # OLMoE (7B,适合先跑通链路)
权重有两种来源:直接下载社区已经转换好的容器,或者自己转。自转可以分片断点续传,不需要一次性腾出全部磁盘空间。
./coli convert --model /nvme/glm52_i4 # 自转,可断点续传
⚠️ 先小后大:不要一上来就转 2.8T 的 Kimi K3。建议先用 OLMoE(7B,磁盘约 7GB)把 setup、convert、chat 整条链路跑通,确认本机 gcc 与 I/O 正常,再去碰几百 GB 的权重。
三、专家调度机制的五个关键点
这一层是项目最值得读的部分,全部优化都要求「端到端可复现」,不允许悄悄改变模型精度或路由语义。
| 机制 | 作用 | 环境变量 |
|---|---|---|
| 路由热度驱动调度 | 决定哪些专家留在内存 | 自动(.coli_usage) |
| 学习化固定热存储 | 记录实际路由到的专家并固定最热的 | 自动 |
| 路由前瞻线程 | 提前一层预取下一层专家,71.6% 可预测 | PILOT=1 |
| 异步 I/O 重叠 | 算常驻专家时并行加载缺失专家 | PIPE=1(默认开) |
| 批量联合去重 | 批量位置对每个唯一专家只读一次 | 自动 |
有一个工程细节值得单独说:每个专家的三个矩阵在磁盘上相邻存放,因此一次 pread 就能读完整个专家。这不是算法创新,但它是把随机读变成顺序读的关键——对磁盘而言,读 3 次小片段和读 1 次连续片段的代价差很远。
另外,开启直接 I/O 可以绕过页缓存,在有 DRAM 缓存的盘上收益明显:
DIRECT=1 COLI_MODEL=/nvme/glm52_i4 ./coli chat
四、本机调优的三条命令
不用猜配置,引擎自带测量工具:
COLI_MODEL=/nvme/glm52_i4 ./coli plan # 只读:查看规划出的 VRAM / RAM / 磁盘放置
COLI_MODEL=/nvme/glm52_i4 ./coli doctor # 只读:就绪检查
COLI_MODEL=/nvme/glm52_i4 ./coli tune # 测量并保存本机最快安全配置
如果手上正好有两块 SSD,可以让两块盘同时供数:
COLI_MODEL=/fast/glm52_i4 \
COLI_MODEL_MIRROR=/second/glm52_i4 \
COLI_DISK_WEIGHTS=9,3 \
./coli chat
./c/coli mirror plan --model /fast/glm52_i4 --mirror /second/glm52_i4 --budget-gib 200
./c/coli mirror stage --model /fast/glm52_i4 --mirror /second/glm52_i4 --budget-gib 200
./c/coli mirror verify --model /fast/glm52_i4 --mirror /second/glm52_i4
mirror 三步是分开的,因为 stage 要写入几百 GB,中途失败可以重跑,而 verify 会逐块校验两份副本一致——这一步别省,读到损坏的专家矩阵不会报错,只会让输出变得难以解释。
服务化用 coli serve(无头 API + 仪表盘)或 coli web(自动开浏览器):
./coli serve --model /nvme/glm52_i4
五、各硬件档位的真实数字
项目把实测数据公开得很坦率,包括不体面的那部分。整理如下:
| 硬件配置 | 解码速度 | 说明 |
|---|---|---|
| 6 × RTX 5090 全专家常驻 | 5.8 - 6.8 tok/s | TTFT 约 13s |
| 128GB 纯 CPU 桌面 | 约 1.8 tok/s | 预热后 |
| 单 RTX 5070 Ti | 1.07 tok/s | GPU 常驻管线 |
| 25GB 开发机 | 0.05 - 0.1 tok/s | 冷启动,诚实基线 |
有个容易被忽略的维度:首轮预填充的代价极高。在 RTX 5080 加两块 NVMe 的配置上,3324 token 的预填充约 90 秒,8.3k token 的首轮接近 4 分钟——但后续轮次回落到 6 到 9 秒,3k 上下文解码约 1.6 tok/s。这意味着多轮对话的体感远好于单次长文输入,长上下文一次性投喂是这个架构最脆弱的场景。
显存也不是完全没用,CUDA=1 可以把专家层放进 VRAM。在两张 8GB 卡的 Qwen3.6 上,这一项把速度从 1.44 拉到 10.05 tok/s,7 倍,且输出与 CPU 路径位级一致。
六、该有的怀疑
第一,冷启动基线是真的冷:25GB 开发机上 0.05 tok/s 意味着一个 token 二十秒,这个档位只能用来验证「链路能通」,不能用来和模型对话。
第二,可移植性被牺牲了:每个模型系列需要一个独立的 C 文件,加新模型是写代码。这和 llama.cpp 那种「一种格式到处跑」的路线是两种哲学,别指望拿它当通用运行时。
第三,磁盘寿命与带宽是隐藏成本:几百 GB 的权重反复流式读取,对 SSD 是持续压力,这也是双盘镜像和 DIRECT=1 存在的理由。
第四,速度和质量的取舍没有免费选项:项目明确承诺所有优化都必须可复现、不改变路由语义,这一点值得肯定,但也就意味着它不会用近似专家跳过之类的手段来换取速度。
结语
Colibri 的价值不在于它比 GPU 集群快——它显然不快。它的价值在于把一个被当作物理定律的约束降级成了工程取舍:「这个模型我跑不动」从此不再是一句终局判断,而是一句可以追问「愿意等多久、愿意牺牲多少延迟」的工程判断。
对于做本地推理、模型评测、或者单纯想亲手验证巨型 MoE 行为的人来说,先用 7B 的 OLMoE 把链路跑通,再决定要不要为 744B 腾出三四百 GB 磁盘,是成本最低的进入路径。