返回 文章 apply CMS 文章

Cactus Needle 3:8-29MB 端侧自动化基础模型,工具调用超越 10 倍大模型

一个 8-29MB 的端侧基础模型,用极小体积在工具调用上击败 10 倍大模型,让手机、手表、机器人离线完成结构化操作。

端侧AI小模型工具调用结构化提取
成长分 / 100 76 综合收获、行动、留存与影响

Cactus Needle 3:8-29MB 端侧自动化基础模型,工具调用超越 10 倍大模型
为什么值得读了解如何用 8-29MB 的二进制模型在移动端实现工具调用、结构化提取和嵌入,替代云端大模型。

掌握 Needle 3 的阶梯式架构、置信度门控与工具设计原则,可直接用于端侧 AI 产品开发。

关键洞察
  1. Needle 3 是单一 8-29MB 二进制模型,基于 Simple Attention Network,牺牲通用聊天能力换取移动端工具调用和提取任务的极致效率。
  2. 模型提供工具调用、结构化提取和文本嵌入三种能力,输出带类型的 JSON,解码语法保证可解析。
  3. 智能阶梯架构让开发者从 2 层到 20 层子网络中选择,4 层微调一个 epoch 即可匹配 DeepSeek V4 Flash。
转成行动

深入阅读

正文与原文对照

原文保真覆盖:全文原文字符:11368

工具调用

只要给出你的应用所暴露的函数,Needle 就会选出合适的函数,并根据用户所说的内容填好每个参数。一次提出两件事,就会按顺序得到两次调用;提出任何工具都不涵盖的请求,则得到一个空列表,而不是瞎猜。

结构化提取

声明一个结构,交给它杂乱的文本,就能拿回带类型的字段:发票、预订、通知、表单皆可。解码语法保证输出可被解析。提取能力也能很好地泛化到分类问题上。

文本嵌入

同一个模型还能为句子返回向量,因此应用可以在本地完成搜索、匹配和路由:找到你想要的那条笔记,挑出与请求最接近的工具,合并重复的提醒。

在产品中的表现如下:

智能家居

从按按钮变成和房子对话。“把卧室灯调暗,再把门锁上”会变成两次调用,离线执行,无需与网关往返。

机器人

给扫地机或小型机器人下达细致的指令:“打扫厨房,但别进卧室”“干完活就回充电座”。每条指令都会变成它能执行的一系列动作。

手机

一个在设备上直接行动而不只是回答问题的助手:用上周末的照片做一本相册、打开某个网站、调暗屏幕、在你的文件里找到租约。

可穿戴设备

在手腕上把通知读成结构化数据:把一条刷卡提醒拆成商户、金额和日期;把一条消息变成回复;把一条投诉变成情绪标记。

AR 眼镜

根据一句简短的请求完成导航和周边搜索,整个过程无需手机或网络。

汽车

根据车内的请求控制空调、媒体、导航和通话,工具集被固定下来,因此能撑过一整趟长途驾驶的对话量。

电脑

用自然的英语控制你面前的这台机器:起草邮件、启动计时器、复制地址、打开标签页。

搜索与匹配

数据不出设备的嵌入:对笔记、消息和文档做语义搜索;把一条查询匹配到数百个工具中最接近的那个;在手表上合并近似重复的提醒。

模型

智能阶梯(Intelligence laddering)。Needle 3 的每一层都是一个容量单调递增的子网络。开发者可以在 2 层(2L)子网络到 20 层(20L)之间选择合适的规模。每个子网络都适合微调,例如 4L 在下游任务上微调一个 epoch 后,就能与 DeepSeek V4 Flash 持平。智能阶梯产出 9 至 29 MB 的 CQ2 位二进制文件,支持各类微型设备。

输入

文本提示,外加工具定义或提取模式(schema)

输出

包含工具调用或提取结果的结构化 JSON

模型

29-121M 阶梯式简单注意力网络(Laddered Simple Attention Networks),CQ2 量化

训练

360B 词元的专有结构化数据集

速度

在 Raspberry Pi 5 上,解码 400-4k 词元/秒,预填充 1-10k 词元/秒

图 1

阶梯式简单注意力网络

图 1. 该架构每个词元消耗的 MFLOPs,比相同配置的 Transformer 少 2 倍以上。

图 2

图 2. Needle 3 在移动端工具调用上击败了 10 倍于自身规模的模型,在提取任务上与 2-3 倍于自身规模的模型持平。Needle 3 的子网络(20、16、8 和 4 层)通过已发布的 CQ2 位二进制文件运行,基线模型在 vLLM 下以 f16 运行,DeepSeek V4 Flash 通过其云端 API 调用。折线连接的是 Needle 系列模型。

快速上手

安装 Python 包。推理引擎会从 Hugging Face 下载一次并缓存,无需再构建其他东西。

pip install cactus-needle

Needle 通过阅读你的工具描述来决定调用什么、如何填写参数,所以把它们写好就是成败的关键。

简单方式:给函数加上装饰器。函数签名提供参数类型,文档字符串就是工具描述,run() 负责完成整个闭环:模型选出调用,Needle 执行你的函数,把结果回填给模型,并返回最终响应,已执行的工具结果以 results 的形式附在其中。

按模式路由:当描述无法穷举所有说法时,可以给工具设置 triggers,即与每条请求进行匹配的正则表达式。一旦匹配,解码就被限制在匹配到的工具上,并且必须发起调用,这样请求就会到达你指定的工具,而不是被拒绝或误路由,而且即使置信度低于下限,调用也会发出。一次匹配会限制整个回合,所以兜底规则应当排除其他工具所拥有的名词,例如 ^(?![\s\S]*\b(lights?|doors?)\b)[\s\S]*\b(turn|switch)\b[\s\S]*\b(on|off)\b;这样“打开风扇并调暗厨房的灯”仍然能同时触达两个工具。

python

from typing import Literal

@needle.tool(triggers=[r"\b(turn|switch|power|flip)\b.*\b(on|off)\b", r"\btoggle\b"])
def control_device(device: str, action: Literal["on", "off", "toggle"]):
    "Switch or toggle any named smart-home device."
    return {"device": device, "action": action}

agent = needle.Needle(tools=[control_device, get_weather])
agent.complete("toggle the garage door")
# function_calls [{"name": "control_device", "arguments": {"device": "garage door", "action": "toggle"}}]

提取:要从文本中提取结构化数据,请声明结构并调用 extract()。传入一个 Pydantic 模型,就能拿回带类型的对象。

每个回合返回一个 JSON 对象:

json

{
  "type": "call",
  "success": true,
  "error": null,
  "error_code": null,
  "function_calls": [ { "name": "set_lights", "arguments": { "room": "living room", "on": true, "brightness": 30 } } ],
  "reasoning": "'living room' -> room; 'dim' -> on true, brightness 30",
  "confidence": 0.94,
  "prefill_tps": 4300.0,
  "decode_tps": 850.0,
  "peak_ram_mb": 28.5
}

置信度门控与路由:每个响应都带有一个来自校准头的 confidence 分数,引擎已经应用了 0.1 的下限。低于该下限时,调用会被扣留到 suppressed_calls 中,而 function_calls 为空。高于下限时,如何根据分数路由由你决定:分数高就立即执行,居中就展示调用并询问用户,空结果则视为拒绝。带有 triggers 的工具对匹配的请求总是会产生调用,因此该分数就是告诉你应当直接运行还是先确认的依据。

python

r = agent.complete(user_text)
calls = r["function_calls"]
held = r["suppressed_calls"]

if calls and r["confidence"] >= 0.7:
    execute(calls)                                   # sure: act
elif calls or held:
    confirm(calls or held, r["reasoning"])           # unsure: show the call, ask
else:
    say("I can't do that here")                      # nothing to do: refuse

编写工具:模型会按字面意思读取模式,所以一个范围窄、描述朴素的工具胜过一个宽泛的工具。每个动作一个工具,用它所涵盖的动作来描述(“打开或关闭某个房间的灯”),而不是用类别来描述。枚举选项要以用户的说法命名(action: ["increase", "decrease"]),并把同义词放在描述中。当请求可能略去某个必填参数时,给它设置 default;没有默认值且请求中也没有依据的必填参数会被扣留,而不是被猜测。把取值格式写进描述里("City, ST"、"e.g. T-1042")。对必须始终到达某个工具的意图添加 triggers,并让每个回合的工具集保持精简,因为每多一个工具,就多一分误路由的可能。

微调:Python 包是最快捷的途径。先在冻结的基座模型全部 20 层上做 LoRA,再对任意子网络做 4 位 .cact,它能在同一个引擎上运行。

这些指南讲得更深入:设计工具、置信度、提取、微调、Python 参考、支持的设备、.cact 格式以及移植 Needle。源码在 GitHub 上。

Cactus Platform

Needle 的设计初衷就是可定制。它的容量是一架阶梯,哪怕只有 2 层的子网络,在针对某个产品的工具微调后,也能在比完整模型所需小得多的设备上以最佳状态运行。把容量限制在一个狭窄而明确的任务上,正是它能在该任务上达到前沿水平精度的原因:在 DroidCall 上微调能把每个子网络提升 18 到 36 个点,从 4 层起,微调后的子网络就超过了 DeepSeek V4 Flash,参数量从 29M 起步(图 3)。

图 3

在平台上微调后的每个子网络

图 3. 在平台上微调前后的每个 Needle 3 子网络,基座和微调后的模型都采用强制调用评分,对比对象是通过云端 API 调用的 DeepSeek V4 Flash。

Cactus Platform 提供完整路径:Cactus 数据集、已发布模型背后的 2 位量化、评估设计与跟踪、全深度微调和数据集管理,全部运行在我们的基础设施和训练流水线上,无需自己搭建。

部署

每个部署目标都附带一个小于 1 MB 的预构建引擎,启动时加载 needle3.cact 权重。needle build 会获取对应平台的引擎,并把权重放在它旁边,可以是完整的 20 层,也可以是任意更小的子网络:

每个目标对应一个文件夹;needle build --platform 会下载它,并把 needle3.cact 放在引擎旁边。

目标 平台文件夹 包含内容
macOS macos-arm64 needle CLI、libneedle.a、needle.h
Linux linux-x86_64, linux-arm64, linux-armv7, linux-riscv64, linux-mipsel needle CLI、libneedle.a、needle.h
Windows windows-x86_64, windows-arm64 needle.exe、libneedle.a、needle.h
Android android-arm64, android-armv7, android-riscv64 needle CLI、libneedle.a、needle.h
iOS ios-arm64, ios-sim-arm64 libneedle.a、needle.h
tvOS、watchOS tvos-arm64, watchos-arm64 libneedle.a、needle.h
浏览器 wasm needle.js、needle.wasm、needle.h
WASI 组件 wasm-component needle.component.wasm、needle.wit

sh

# engine, header and weights for this Mac
needle build --platform macos-arm64
# an 8-layer subnetwork for a Pi
needle build --platform linux-arm64 --layers 8 --out ./pi
# a tuned archive
needle build --lora adapter.safetensors --out tuned.cact