用 llama.cpp 跑 System One 模型 Julia-1

决策模型我已经折腾一阵了,先是闭源的 Jev,再是本地开源的 Laya。2026 年 10 月 2 日,ggml-org 发了博客《New in llama.cpp: Decision Models》,说 llama.cpp server 正式支持决策模型,接口是 /v1/systemone。博客里挂了一组模型:Julia-1、Laya、Kev-4B、lev、OpenJev。Julia-1 最小,官方写 144M,基于 mmBERT-small;我本机下的 Q8_0 大约 160MB。

聊天模型和决策模型差在输出形态。聊天模型一个字一个字往外蹦,就算只要一个分类结果,也常先写一段话,程序还得再解析。决策模型读一遍输入,直接给选项打概率,答案落在你给的选项里。接口对齐 TypeSafe 的 Jev / System One,题型是 choice、score、noul。官方用途写得很宽:路由、审核、看 agent 某步成不成都行。我这次只干两件事,把它在本机跑通,再和已经在跑的 Laya 比一比。

Homebrew 跑不通

官方示例是 llama serve -hf ggml-org/Julia-1-GGUF。我本机命令是 llama-server,第一次直接跑:

1
llama-server -hf ggml-org/julia-1-gguf

模型下载完就报 unknown pre-tokenizer type: 'mmbert':运行时太旧,认不出 mmBERT 的 tokenizer。Homebrew 是 llama.cpp 0.2.0,升到稳定版 0.5.0(build 11146)还是同一句错。llama update 只对 llama.app 安装有效,Homebrew 用不了;而官方博客偏偏建议从 llama.app 更新。brew install llama.cpp --HEAD 也过不去,本机 Xcode.app 还是 26.4,公式要求 27。

nightly 修好,还有 PATH 坑

后来改用 GitHub Releases 里的 macOS arm64 nightly,我用的是 b11398,解压到工具目录后版本变成 0.5.0-dev (build 11398)。起服务时绑本机并加 API key:

1
2
3
llama-server -hf ggml-org/julia-1-gguf \
--host 127.0.0.1 --port 18080 \
--api-key julia-local-test

curl http://127.0.0.1:18080/health -H "Authorization: Bearer ***" 返回 {"status":"ok"} 才算起来了。调用走 /v1/systemone,不走聊天接口。还有一件事官方点名过:选项要写描述,别只丢空标签。他们举过例子,Julia-1 在标签为空时会把“被扣了两次款”分到 shipping;补上 payments / delivery / bugs 这类描述后,billing 概率能到大约 0.99。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
curl http://127.0.0.1:18080/v1/systemone \
-H "Authorization: Bearer ***" \
-H "Content-Type: application/json" \
-d '{
"state": "Customer message: I was charged twice for my order last week and nobody has replied.",
"questions": {
"route": {
"type": "choice",
"instructions": "Which team should handle this?",
"criteria": {
"billing": "payments, charges, refunds, invoices",
"shipping": "delivery, tracking, lost or late parcels",
"technical": "bugs, errors, login problems"
}
},
"angry": {
"type": "noul",
"instructions": "Is the customer angry?"
}
}
}'

装好 nightly 之后还有一个更隐蔽的坑。包装脚本已经放进 ~/.local/bin,交互终端里再跑却继续报 mmbert。type -a llama-server 一看,PATH 里 Homebrew 还在前面;.zshrc 里有一行硬编码,把 /opt/homebrew/bin 写在了 ~/.local/bin 前面。处理办法是 brew unlink llama.cpp,再把 ~/bin 和 ~/.local/bin 挪到 Homebrew 前面,然后 hash -r,确认 llama-server --version 已经是 build 11398。模型文件没坏,坏的是终端还在打旧二进制。

和本机 Laya 比一轮

我这边一直跑的是 127.0.0.1:9410 上的 Laya MLX,权重 typed-decisions,接口同样是 /v1/systemone。两边请求形状一致,所以做了 7 个用例、交错 5 轮,奇偶轮交换先后。测的时候机器交换分区很重,数字是当前负载下的墙钟时间,不是空载成绩;官方速度表测的是 NVIDIA RTX PRO 6000,也不能和本机 Mac 直接横比。

速度结果很清楚:

  • Laya:p50 106.8ms,p95 480.5ms,mean 171.3ms
  • Julia-1:p50 24.9ms,p95 134.1ms,mean 51.0ms

按中位数大约快 4 倍,35 次请求两边都没有失败。主选项一致 5/7,同题连打 5 轮两边都很稳。工具类中文请求都选 coding,退款意图都选 refund,无害的 ls 都放行。

真正拉开差距的是简单寒暄 Hello, what time is it?:Laya 判成 fast,Julia 判成 deep_reasoning,而且还很笃定。拿它做本地助手路由的话,这句话会被送进重模型通道。危险的 git 强推命令也不一样:Laya 风险分偏高但动作偏松,倾向 allow;Julia 动作更严,倾向 deny,风险分反而偏低。所以两边都不能单独当硬闸门,不可逆操作还得靠确定性规则先拦一层。

观感上 Julia 的概率经常拉到 0.9 以上,Laya 更软、margin 更小。官方也说过阈值要按模型单独校准。他们对“Hi, quick question about my account”这类含糊工单举例,Julia-1 大约 0.25,Kev-4B 大约 0.80。

怎么用

博客末尾那些 tips,对照本机结果看,最值钱的还是两条:选项必须写描述,置信度阈值要用自己的样例按模型定。其余几条也成立,比如小模型先把接口跑通、真要看图再上 OpenJev,多题可以一起发,GGUF 也能指定 :Q8_0。

日常本地路由我还是继续用 Laya。Julia-1 更适合旁路和影子对比,或者对延迟极敏感、又能接受偶尔过判的场景。只想体验 /v1/systemone 的话,Julia-1 很合适,160MB 量级,起得快;至少在我测的这几天,Homebrew 稳定版跟不上,nightly 才是能跑通的路。官方推 llama.app,Homebrew 用户就按 nightly 处理。排查时如果还报 mmbert,先跑 type -a llama-server,看自己到底打到了哪个二进制。

官方原文:https://huggingface.co/blog/ggml-org/decision-models-in-llamacpp

结论也不复杂。Julia-1 证明决策模型已经能直接落进 llama.cpp 生态;速度上它赢,稳着做日常分流我还是选 Laya;选项要写描述,阈值要按模型校准;真正危险的动作,别把最后一道闸交给任何一个小模型独自判断。