我在家里有几台低功耗小设备,常年只干一件事:读个温度、开个灯、记条日志。以前想让它们听懂点自然语言,基本得上云端走一轮 LLM API, latency 高不说,还得担心断网。最近看到 Cactus Needle 2 的 README 写得挺狂:45M 参数、单个 14MB 二进制、完整会话只要 28MB 内存,就能跑工具调用。我心想,这要是真的,树莓派级别的硬件也能本地当个小 agent 了。
先上 GitHub 看了眼:Apache-2.0,6,987 stars,今天还在提交。版本已经发到 v2.0.5。试玩成本不高,pip install cactus-needle 就行。于是我在一台老设备上跑了起来。
<img class="alignnone size-full wp-image-NEEDLE_ARCH" src="
” alt=”Needle 2 的 Simple Attention Network 架构图” width=”1800″ height=”1300″ />
安装本身没坑,第一次运行会从 Hugging Face 拉一个 engine 下来缓存。项目 README 说离线部署也有文档,这对想彻底断网跑的人比较友好。真正有意思的是它的设计:没有传统 FFN,用 Hadamard MLP 替代;KV 缓存做了 256 token 的滑动窗口,但工具描述会被 pin 住不丢;权重用 CQ2 2-bit 量化,直接 baked 进引擎,推理时不解压。官方给的数字是 500 tok/s 左右能出现在树莓派 5 上,普通手机 300–700 tok/s。
我照着 README 写了个最简单的天气工具:
import needle
@needle.tool
def get_weather(city: str):
"Get the current weather for a city."
return {"city": city, "temp_c": 27, "sky": "clear"}
agent = needle.Needle(tools=[get_weather])
print(agent.run("what's it like in Lagos right now?")["results"])
跑出来的结果是结构化的 JSON tool call,不是聊天文本。这跟我预期一致:Needle 不做通用对话,它只负责把输入映射成工具调用。如果你的需求是让小设备执行固定动作,这种减法反而省心。
<img class="alignnone size-full wp-image-NEEDLE_TERMINAL" src="
” alt=”Needle 2 本地安装与工具调用终端示例” width=”900″ height=”560″ />
让我有点意外的是它的输出约束。模型通过你声明的 schema 编译出一个 byte-level grammar,每个 token 都被限制,所以基本不会产出 malformed 的调用。它还带一个 calibrated confidence score,低于阈值会走“escalate”而不是硬猜。这套设计放在端侧很合理:宁可不执行,也别乱执行。
官方 benchmark 我也去看了。Mobile-Actions 上 Needle 2 拿 63.7%,同期 FunctionGemma 270M 64.0%、LFM2.5 230M 69.1%、Apple FM 57.6%。考虑到 Needle 只有 45M 参数、14MB 体积、2-bit 量化,跟人家 f16 打平到这种程度已经够意思。BFCL v4 整体 42.6%,well-formed 率 93.4%,说明它调用格式确实稳。
<img class="alignnone size-full wp-image-NEEDLE_FRONTIER" src="
” alt=”Needle 2 与同类小模型的规模与性能对比” width=”1800″ height=”1040″ />
但限制也很硬。256 token 的上下文窗口基本告别了复杂多轮对话;没有自由文本 fallback,问它超出工具范围的问题只会返回空调用;训练数据是闭源的,想深究为什么某些词识别不好,只能自己微调。README 很诚实地说:这不是聊天模型,是端侧工具调用模型。
我目前的感觉是,Needle 2 适合两类场景:一是在智能家居、可穿戴设备这类算力紧张的硬件上跑本地 intent parser;二是当做一个轻量级“工具路由层”,把简单请求本地解决,复杂请求再交给大模型。它的 LoRA 微调流程也做得比较完整,导出后还是一个 .cact 单文件,部署成本没增加。
最后列一下我踩到的小坑:第一次启动等 engine 下载要有耐心;Apple Silicon 训练要用 pip install "cactus-needle[metal]";如果要跑在完全没网的机器上,得提前把 engine 和 .cact 文件一起拷过去。整体来说,这是一个方向感很清晰的实验:不追大参数,只把“工具调用”这一件事压到足够小。我在本地跑通之后,已经想把它接到家里的几个传感器脚本后面试试了。